Giter Site home page Giter Site logo

Comments (17)

bobvse avatar bobvse commented on May 30, 2024 2

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.

nagashik avatar nagashik commented on May 30, 2024 1

any update about this issue?

from 3dsview.

bobvse avatar bobvse commented on May 30, 2024 1

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.

AamirAbro avatar AamirAbro commented on May 30, 2024 1

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.

rcpassos avatar rcpassos commented on May 30, 2024

@bobvse Any update? Thanks

from 3dsview.

rcpassos avatar rcpassos commented on May 30, 2024

@livotov Any update?

from 3dsview.

rcpassos avatar rcpassos commented on May 30, 2024

@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.

AamirAbro avatar AamirAbro commented on May 30, 2024

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.

bobvse avatar bobvse commented on May 30, 2024

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.

AamirAbro avatar AamirAbro commented on May 30, 2024

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.

sandyscoffable avatar sandyscoffable commented on May 30, 2024

@bobvse

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.

sandyscoffable avatar sandyscoffable commented on May 30, 2024

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:

  1. It had an option to skip processing on first start, which breaks things for certain providers
  2. 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.

rcpassos avatar rcpassos commented on May 30, 2024

@sandyscoffable is it works on Android 9?

from 3dsview.

sandyscoffable avatar sandyscoffable commented on May 30, 2024

Yes it works on Android 9

from 3dsview.

 avatar commented on May 30, 2024

@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 avatar sandyscoffable commented on May 30, 2024

@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.

livotov avatar livotov commented on May 30, 2024

Just FYI - @sandyscoffable 's PR is merged now

from 3dsview.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.