Comments (17)
Hello! I have a similar problem. I've debugged our payment process and found out that after a user had submitted his 3ds code, the onPageFinished() method was not invoked.
public void onPageStarted(WebView view, String url, Bitmap icon) {
final boolean stackedMode = !TextUtils.isEmpty(stackedModePostbackUrl);
if (!urlReturned && !postbackHandled.get()) {
if ((!stackedMode && url.toLowerCase().startsWith(postbackUrl.toLowerCase())) || (stackedMode && url.toLowerCase().startsWith(stackedModePostbackUrl.toLowerCase()))) {
if (!TextUtils.isEmpty(stackedModePostbackUrl)) {
if (postbackHandled.compareAndSet(false, true)) {
authorizationListener.onAuthorizationCompletedInStackedMode(url);
}
} else {
view.loadUrl(String.format("javascript:window.%s.processHTML(document.getElementsByTagName('html')[0].innerHTML);", JavaScriptNS));
}
urlReturned = true;
} else {
// super.onPageStarted(view, url, icon);
onPageFinished(view, url);
}
}
}
In some cases I was able to circumvent the problem by force invoking onPageFinished(). However, it does not fix the problem for all our users and is a hack IMO.
When I try to Debug-run the app on those devices that don't budge to this hack, everything works just fine as I step over each line. It seems like that Debug mode provides some necessary delays, that make code work correctly every the time. Maybe there's a way to add those delays manually in proper places, but I wasn't able to figure out where exactly. I appreciate any help you can provide!
from 3dsview.
any update about this issue?
from 3dsview.
Hope this helps someone. I have managed to work around this problem, but the solution is very hacky.
First of all, as I have moved my codebase to AndroidX, I now use WebViewClientCompat instead of WebViewClient. There I've extended onPageCommitVisible() method.
private AtomicBoolean isFirstStart = new AtomicBoolean(true); //first run
setWebViewClient(new WebViewClientCompat() {
/.../
@Override
public void onPageCommitVisible(WebView view, String url) {
Log.d("Threads", "on_page_commit_visible " + url);
if (!url.equals(postbackUrl) && !isFirstStart.get()) {
view.loadUrl(String.format("javascript:window.%s.processHTML(document.getElementsByTagName('html')[0].innerHTML);", JavaScriptNS));
}
isFirstStart.set(false);
super.onPageCommitVisible(view, url);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap icon) {
Log.d("Threads", "on_page_started " + url);
if (url.equals(postbackUrl)) {
Log.d("Threads", "geteaway_from_onStarted " + url);
return;
}
view.loadUrl(String.format("javascript:window.%s.processHTML(document.getElementsByTagName('html')[0].innerHTML);", JavaScriptNS));
super.onPageStarted(view, url, icon);
}
@Override
public void onPageFinished(WebView view, String url) {
Log.d("Threads", "on_page_finished " + url);
if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.LOLLIPOP_MR1 && !url.equals(postbackUrl)) {
view.loadUrl(String.format("javascript:window.%s.processHTML(document.getElementsByTagName('html')[0].innerHTML);", JavaScriptNS));
}
super.onPageFinished(view, url);
}
}
Processing is done in a separate thread now, using Handler. This may not be ideal, but it works for me. I have had to change onPageStarted and onPageFinished methods as well.
This is the gist of my solution. Though far from ideal, as I check for Md and PaRes each time a page is loaded, at least this way I have it in a separate thread and able to finish payment process the moment I get the params. I'm glad if this helps, but a proper solution is still needed.
private void completeAuthorizationIfPossible(String html) {
Log.d("Threads", "get_data_to_activity");
if (authorizationListener != null) {
authorizationListener.onGetResultString(html);
}
}
In Activity code:
webView.setAuthorizationListener(new D3SSViewAuthorizationListener() {
@Override
public synchronized void onGetResultString(String result) {
Runnable runnable = new Runnable() {
public void run() {
Log.d("Threads", "start_processing_thread");
Message msg = handler.obtainMessage();
Bundle bundle = new Bundle();
ConcurrentHashMap<String, String> map;
synchronized (this) {
map = completeAuthorizationIfPossible(result);
}
bundle.putSerializable("Map", map);
msg.setData(bundle);
handler.sendMessage(msg);
}
};
Thread thread = new Thread(runnable);
thread.start();
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
ConcurrentHashMap<String, String> map = (ConcurrentHashMap<String, String>) bundle.getSerializable("Map");
if (map != null && !paymentProcessed.get()) {
paymentProcessed.set(true);
Log.d("Threads", "map is ready");
webView.stopLoading();
/*** show you progress and hide webview ***/
// go to another step payment
} else {
Log.d("Threads", "map is null or pament is porocessed");
}
}
};
Thanks!
from 3dsview.
I have opened a bug on the Chrome bug tracker for this as well.
https://bugs.chromium.org/p/chromium/issues/detail?id=984741
from 3dsview.
@bobvse Any update? Thanks
from 3dsview.
@livotov Any update?
from 3dsview.
@bobvse I don't have the possibility to move my code base to AndroidX and I don't have the onGetResultString method in D3SSViewAuthorizationListener.
Thanks!
from 3dsview.
I have tried the code from @bobvse and it works but I think not all of the code is required for me just adding onPageCommitVisible
and isFirstStart
works -- in test environment at-least.
private AtomicBoolean isFirstStart = new AtomicBoolean(true);
@Override
public void onPageCommitVisible(WebView view, String url) {
Log.d("Threads", "onPageCommitVisible " + url);
if (!url.equals(postbackUrl) && !isFirstStart.get()) {
view.loadUrl(String.format("javascript:window.%s.processHTML(document.getElementsByTagName('html')[0].innerHTML);", JavaScriptNS));
}
isFirstStart.set(false);
super.onPageCommitVisible(view, url);
}
from 3dsview.
isFirstStart - flag to prevent the page from being processed the first time. You can not use it if you do not want.
Using it will only slightly improve performance.
from 3dsview.
These are the logs that I get on v72.0 where it works and v75.0 where it's failing.
on chrome v72.0
onPageStarted https://test.adyen.com/hpp/3d/validate.shtml
onPageFinished https://test.adyen.com/hpp/3d/validate.shtml
onPageStarted https://test.adyen.com/hpp/3d/authenticate.shtml;jsessionid=asdf.test103e
onPageFinished https://test.adyen.com/hpp/3d/authenticate.shtml;jsessionid=asdf.test103e
onPageStarted https://test.adyen.com/hpp/3d/www.google.com
onPageFinished https://test.adyen.com/hpp/3d/www.google.com
on chrome v75.0
onPageStarted https://test.adyen.com/hpp/3d/validate.shtml
onPageFinished https://test.adyen.com/hpp/3d/validate.shtml
onPageStarted https://test.adyen.com/hpp/3d/authenticate.shtml
onPageStarted https://test.adyen.com/hpp/3d/www.google.com
onPageFinished https://test.adyen.com/hpp/3d/www.google.com
from 3dsview.
isFirstStart - flag to prevent the page from being processed the first time. You can not use it if you do not want.
Using it will only slightly improve performance.
Be careful with that one ... I something similar and had to back it out here https://github.com/LivotovLabs/3DSView/pull/24/files
Basically, it broke processing for some providers that just provide a PARes on first page load, which the major PSP test environments don't simulate.
It sounds like you've done a fair amount of work here ... any chance of raising a PR?
I'm coming to the conclusion that I need a fallback solution, as this sort of thing has happened twice now (#20 and here).
The fallback would be to receive the PARes server side, and notify the app in some way, so at least the user wouldn't get the Google error page. This library is otherwise good, and provides a bit more of a slicker solution than merely doing this server side.
from 3dsview.
Ok - I've knocked this together:
#26
I got some inspiration from @bobvse, however I didn't like his/her solution for the following reasons:
- It had an option to skip processing on first start, which breaks things for certain providers
- I didn't like the amount of code that needed to go into the app - clearly that shouldn't be necessary. However I liked the threading idea, so the library creates threads for HTML processing and it does improve performance. 👍
from 3dsview.
@sandyscoffable is it works on Android 9?
from 3dsview.
Yes it works on Android 9
from 3dsview.
@sandyscoffable Using these changes, it fixed the issue in the test environment, but still causing issues in production, much more than before this fix was applied.
from 3dsview.
@sandyscoffable Using these changes, it fixed the issue in the test environment, but still causing issues in production, much more than before this fix was applied.
Can you describe the issues you are having?
from 3dsview.
Just FYI - @sandyscoffable 's PR is merged now
from 3dsview.
Related Issues (20)
- How to use D3sDialog HOT 1
- 3Ds with more than one page does not work HOT 3
- "Processing..." page displays instead of 3DSecure page HOT 1
- completeAuthorization called without required html form for 3D Secure with Continue button HOT 2
- Disallow auto-zoom in 3dsDialog
- Chrome version 71 - Android 8.1.0 HOT 1
- 405 Method now allowed HOT 1
- Certain bank cards don't work with this library HOT 1
- PDS2 (3-D Secure v2) HOT 1
- Migrate to androidX HOT 1
- Regex matcher prematurely captures blank value HOT 1
- Setup GH actions for automatic build, test and release of the library HOT 1
- Revise code, update project structure/configs/gradle files HOT 2
- Create unit tests to cover what we can cover here in this tiny lib HOT 1
- Migrate artefacts to mavenCentral or GitHub maven repo HOT 1
- 3-D Secure v2: Issue with Monzo in the UK HOT 2
- Google error 413. That's an error after confirm payment
- Webview not loading for stripe gateway HOT 1
- 3 D Secure
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from 3dsview.