Giter Site home page Giter Site logo

livotovlabs / 3dsview Goto Github PK

View Code? Open in Web Editor NEW
109.0 13.0 51.0 283 KB

Android UI component to process banking 3D Secure (MasterCard SecureCode / Verified By Visa) payment authorizations in Android apps.

License: Apache License 2.0

Java 100.00%
webview android android-apps visa payment-authorizations java

3dsview's Introduction

3DSView (D3SView :) , aka 3D Secure WebView

Self-contained UI component to process banking 3D Secure (MasterCard SecureCode / Verified By Visa) payment authorizations in Android apps.

Why exactly "D3S" ? Simply because Java does not allow to have number as a first character in a package and class names :)

Component have to be used instead of a WebView and handles the complete payment authorization process from redirecting user to an ACS banking server web UI and to grabbing authorization results and parameters, intercepting post events and parsing the code.

Simply add it to your layout just instead of a WebView, invoke only two methods and then you have 3DS auth implemented.

Component can be used in activity, fragment or in any other part of your layout, both declaratively (in xml files) or programmatically by creating an instance in the source code. Only make sure to give it sufficient space on the screen to display the banking ACS web page.

Status

  • Current stable version: Download
  • Current development version: n/a

Get It

  • Maven repository: jCenter
  • Group: eu.livotov.labs.android
  • Artifact ID: 3DSView
implementation 'eu.livotov.labs.android:3DSView:x.y.z@aar'

What's new (1.1.2.9)

  • Latest pull requests merged
  • Code reading

Installation

Release versions are available from jCenter repository, so just add the "implementation" statement to your project. For snapshots, please add our bintray snapshots repository url first: https://dl.bintray.com/livotovlabs/maven

dependencies {
    implementation 'eu.livotov.labs.android:3DSView:x.y.z@aar'
}

Alternatively you may download the source code and build it on your own.

Quick Usage

  1. Build your own or download precompiled 3dsview.jar from releases section and put it to the libs folder of your app project.
  2. Add eu.livotov.labs.android.d3s.D3SView to your layout file (or create and add it programmatically)
  3. In corresponding Activity or Fragment, configure the instance of D3SView by calling DS3View#setAuthorizationListener(D3SViewAuthorizationListener).
    • This adds a listener to receive authorization results and progress messages.
    • You will receive authorization MD and PaRes values there as well, when 3DSecure completes.
  4. Invoke the D3SView#authorize(String, String, String) method by passing MD, PaReq and ACS url values, you receive from your card payment gateway and listen for authorization completion event in your callback.
    • Specifying postback url is optional but recommended, the library will use a sensible default value if not set.
  5. Once user completes the authorization at the ACS server, your callback method will be automatically called with the 3DS response data, which you may then pass to your processing backend server for payment finalization.

For a quick sample see the checkout the 3DSViewSample sub project in this repo.

Bugs, Suggestions, Ideas

Any ideas/bugs/etc, as well as pull requests, are welcome in the issues section.

Credits

Alex Askerov (@askerov), Mia Alexiou (@subsymbolic), Luke Korth (@lkorth), Christophe Beyls (@cbeyls), Owen O Byrne (@owenobyrne)

3dsview's People

Contributors

cbeyls avatar chrisleversuch avatar livotov avatar lkorth avatar mezpahlan avatar owenobyrne avatar sandyscoffable avatar shchurov avatar subsymbolic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

3dsview's Issues

3Ds with more than one page does not work

Hi, there!

onAuthorizationCompleted needs pause. Because payment does not have time to be processed.

@Override
    public void onAuthorizationCompleted(String md, String paRes) {
        mHandler.postDelayed(() -> mPresenter.onGetPaymentRezult(md), 1000);
    }

But basic problem with banks wich use more then one page. For example: - insert 3ds code and then another page with button "Continue". Proccesing is made only after pressed continue buuton

completeAuthorization called without required html form for 3D Secure with Continue button

In this case the 3D Secure page that is loaded into the WebView first asks your to press a "next" button. Once next is pressed the bank sends a USSD to the phone associated with your card. You then reply to the USSD, and the Webview shows a "CONTINUE" button. Once you press "continue" the redirect is caught. However the html that is sent to completeAuthorisation contains a pre-auth link with PaReq, TermUrl, MD, rather than the required form with MD & PaRes. Attached is the html that is caught.
continueHtml.txt

PDS2 (3-D Secure v2)

I've got a working version of the library that I've (accidentally) included in #26 (as I committed to master on my own fork, and there was already a PR from master into this repository).

This supports the fallback to 3-D Secure v1. Feel free to change! ๐Ÿ˜„

Lint warnings

After using 3DSView, I am getting the following Lint warnings.

  • AddJavascriptInterface: addJavascriptInterface Called - WebView.addJavascriptInterface should not be called with minSdkVersion < 17 for security reasons: JavaScript can use reflection to manipulate application
  • SetJavaScriptEnabled: Using setJavaScriptEnabled - Using setJavaScriptEnabled can introduce XSS vulnerabilities into you application, review carefully.
  • WrongConstant: Incorrect constant - Must be one or more of: Pattern.UNIX_LINES, Pattern.CASE_INSENSITIVE, Pattern.COMMENTS, Pattern.MULTILINE, Pattern.LITERAL, Pattern.DOTALL, Pattern.UNICODE_CASE, Pattern.CANON_EQ

Are there any fixes for these warnings?

3-D Secure v2: Issue with Monzo in the UK

Steps to reproduce:

  1. Submit a payment using a Monzo card that gets 3-D Secure v2 challenged
  2. Break out of app containing 3DSView library to go to Monzo app and accept the payment
  3. Return to original app

What happens:

Term URL is hit, and onAuthorizationCompleted3dsV2() is not called with parameters (cres etc)

What should happen:

onAuthorizationCompleted3dsV2() should be called, meaning the payment can be completed

Regex matcher prematurely captures blank value

Whilst using the library we noticed a bug in one of the regex patterns that caused certain ACS web pages to not display and hence 3DS transactions aborted. Upon investigation we noticed a change in the way certain ACS web pages were being presented around 8th October 2020.

The regex in question is: private static Pattern valuePattern = Pattern.compile(".*? value=\\\"(.*?)\\\"", Pattern.DOTALL); when combined with an ACS web page that starts off like this:

<!--[if lte IE 8]>
<html class="lt-ie9" lang="en"><![endif]--><!--[if IE 9]>
<html class="lt-ie10" lang="en"><![endif]--><!--[if gt IE 9]>
<html lang="en"><![endif]-->
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Processing</title>
    <link href="/Content/dist/css/template-e527b6106c.min.css" rel="stylesheet">
    <style>
        body {color: #000000;font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;font-size: 1.25em}.header, legend, h1, h2, h3, h4 {color: #000000}label {color: #000000}a,.btn-link {color: #000000;text-decoration: underline}a:visited,.btn-link:visited {color: #000000}a:hover,a:focus,.btn-link:hover,.btn-link:focus {color: #211f1f}a:active,.btn-link:active {color: #211f1f}a.btn-link {font-size: .95em}.btn-primary,.btn-primary:focus,.btn-primary:hover {background: #211f1f;color: #FFF;border: none;border-radius: 0}.btn-primary:active,.btn-primary:active:hover,.btn-primary:active:focus {background: #AB2C29}fieldset {border: 0}fieldset > legend {border-bottom: 0;font-size: 1.00em}:not(.lt-ie9) label.custom-radio [type=radio]:checked+span:before {background: #211f1f}.accordion.modal .modal-body .panel-group .expander {color: #211f1f}.accordion.modal .modal-body .panel-group .panel {background: #FFF}.field-validation-error {color: #AB2C29}.toast-top-full-width {display: none}
    </style>
</head>
<body>
<div class="threeds-one">
    <div class="container container-sticky-footer">
        <div class="header" id="HeaderLogos">
            <div class="row no-pad">
                <div class="col-12">
                    <img alt="Starling Logo" class="img-responsive header-logo pull-left" src="somelogo.png">
                    <img alt="Mastercard Identity Check logo" class="img-responsive header-logo pull-right" src="anotherlogo.png">
                </div>
            </div>
        </div>
        <div class="container">
            <div class="body" dir="LTR">
                <h1 class="screenreader-only">Processing</h1>
                <div class="row">
                    <div class="col-12">
                        <div id="Body1"><strong>Your payment is being processed.</strong><br><br>Please do not close this window or hit your Back button.
                        </div>
                    </div>
                </div>
                <div class="row">
                    <div class="col-12 processing">
                        <img src="/Content/images/loading.svg" alt="Loading Indicator" class="processing-img center-block content-block">
                        <br>
                        <p id="Processing-label" class="processing-text">Processing</p>
                    </div>
                </div>
                <div class="row">
                    <div class="col-12">
                        <div id="Body2"></div>
                    </div>
                </div>
            </div>
        </div>
        <form action="/Api/NextStep/ProcessRisk" autocomplete="off" data-ajax="true" data-ajax-begin="ccHelpers.ajax.onBegin"
              data-ajax-complete="ccHelpers.ajax.onComplete" data-ajax-failure="ccHelpers.ajax.onFailure" data-ajax-method="form"
              data-ajax-success="ccHelpers.ajax.onSuccess" id="ProcessRiskForm" method="post" name="ProcessRiskForm"><input
                id="TransactionId" name="TransactionId" type="hidden" value="some_value"><input id="DeviceId"
                                                                                                                  name="DeviceId"
                                                                                                                  type="hidden"
                                                                                                                  value="some_value"><input
                id="ProviderType" name="ProviderType" type="hidden" value="TM"><input id="ProviderId" name="ProviderId" type="hidden"
                                                                                      value="some_value"><input id="IssuerId" name="IssuerId"
                                                                                                              type="hidden"
                                                                                                              value="some_value">
        </form>
        <div class="hidden">
            <iframe title="hidden-iframe"
                    src="https://geoissuer.cardinalcommerce.com/DeviceFingerprintWeb/V2/Browser/Render?referenceId=some_reference&amp;orgUnitId=some_unit_id&amp;threatmetrix=true&amp;tmEventType=PAYMENT"
                    frameborder="0"></iframe>
        </div>
        <form class="nextstep-form" method="post">
            <input id="NextStepTransactionId" name="TransactionId" type="hidden" value="some_value">
            <input id="GroupId" name="GroupId" type="hidden" value="">
            <input id="Type" name="Type" type="hidden" value="">
            <input id="NextStepChoiceType" name="NextStepChoiceType" type="hidden" value="">
            <input id="NextStepIssuerId" name="IssuerId" type="hidden" value="some_value">
        </form>
        <div class="modal modal-clear" id="ProcessingModal" tabindex="-1" role="dialog" aria-labelledby="Processing-label"
             aria-hidden="true" data-keyboard="false" data-backdrop="static">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-body">
                        <div class="row">
                            <div class="col-12 processing">
                                <img id="ProcessingImage" src="/Content/images/loading.svg" alt="Loading Indicator"
                                     class="processing-img center-block content-block">
                                <p class="processing-text" id="Processing-label">Processing</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <input data-val="true" data-val-number="The field MessageVersion must be a number."
               data-val-required="The MessageVersion field is required." id="MessageVersion" name="MessageVersion" type="hidden" value="1">
        <form class="nextstep-form" method="post">
            <input id="NextStepTransactionId" name="TransactionId" type="hidden" value="some_value">
            <input id="GroupId" name="GroupId" type="hidden" value="">
            <input id="Type" name="Type" type="hidden" value="">
            <input id="NextStepChoiceType" name="NextStepChoiceType" type="hidden" value="">
            <input id="NextStepIssuerId" name="IssuerId" type="hidden" value="some_value">
        </form>
        <form method="POST" id="TermForm">
            <input type="hidden" id="PaRes" name="PaRes" value="">
            <input type="hidden" id="MD" name="MD" value="">
        </form>
    </div>
</div>
<script src="/Content/dist/js/template-34c97fbbe3.min.js"></script>
</body>

This is from Starling Bank in the UK but we noticed similar failures with Monzo and HSBC. The bug appears to be when using the above regex to parse this page and being confronted with the snippet at the end of the webpage:

<form method="POST" id="TermForm">
  <input type="hidden" id="PaRes" name="PaRes" value="">
  <input type="hidden" id="MD" name="MD" value="">
</form>

The values for the PaRes and MD seem to become populated as the user steps through / completes their 3DS interaction but on initial page load they are blank. The current valuePattern allows for empty values and we do not guard against these at present.

We patched this internally by modifying the regex. I'll share a PR shortly with the fix but I also wanted to explore creating some tests for this and in future the library in general. If you have any suggestions for how best to test the library that would be appreciated.

How to use D3sDialog

Not a single code snippet is available on how to use the D3SDialog

When I am using D3S Dialog, i want to show the Loading progress bar, when ever there is loading.

Especially after the 3D secure pin is entered and when a user click the submit button.

Note: I dont know the URL of the 3D secure page , which is created by ACS Server with multiple redirection

Migrate to androidX

Any plan to migrate legacy support package to use androidX ?
By moving the library to androidX, we can disable jetifier and make some improvement on the build speed.

Chrome version 71 - Android 8.1.0

Hi,

I'm using Android 8.1.0 and the Chrome Webview version is 71 and I'm not getting the md and paRes parameters from the D3SSViewAuthorizationListener on onAuthorizationCompleted, but if I use Chrome Webview version 70 it will work fine.

Can you help me?

Thanks.

"Processing..." page displays instead of 3DSecure page

Hey LivotovLabs,

Thanks for the library. I've been using this fine up until sometime within the past 3 weeks I get a "Processing..." page (attached) that appears for about a second and then disappears. Previously I would get a 3DSecure page that asks what kind of response I want to return (as it's a test server). This happens with both the 3DSView and the Dialog, same exact issue.

This whole process works fine on Web and I'm trying to get confirmation for iOS. Has anyone else run into this issue or am I alone?

image

Certain bank cards don't work with this library

A few of our customers have ran into the following error:

We have a 3-D Secure success rate of 91-92% on Android, and on our other platforms they are all solidly around 95% (this is on a volume of around 20,000 transactions since I made the change in the Android app).

It seems to be an issue confined to certain banks. The cards affected seem to be Co-op and perhaps Clydesdale Bank and Capital One ๐Ÿ™€

Here are a few IINs that seem to be affected: 498824, 557351

Update - reproduced issue

I've been able to reproduce the issue here. When the library loads it seems to fairly quickly show the above Google page in the screenshot (without any sort of intervention required).

The code that extracts the PaRes from the HTML doesn't appear to be called (as I had debug code to spit out the HTML if that was hit). There are the following cryptic log lines though which might offer a clue:

2019-01-11 12:55:07.033 10790-12869/com.scoffable W/chromium: [WARNING:spdy_session.cc(2876)] Received RST for invalid stream1
2019-01-11 12:55:07.079 10790-10790/com.scoffable I/chromium: [INFO:CONSOLE(1)] "Uncaught TypeError: Cannot read property 'innerHTML' of undefined", source: https://www.google.com/ (1)

The above error points to an issue with this line of code:

view.loadUrl(String.format("javascript:window.%s.processHTML(document.getElementsByTagName('html')[0].innerHTML);", JavaScriptNS));

So, still not 100% sure why this is happening, but it's definitely an issue. The employee who has an affected card is off today, so I can't reproduce again until they are back in the office.

405 Method now allowed

Hi,
I use 3Ds Dialog and after confirm, I have got the error "405 method not allowed" on the WebView
and have got a callback on Authorization Completed with md and pores are empty

p.s. Please help me!

Chrome for Android Update 75

I can't complete the 3D Secure process after the new Chrome for Android update since June 19, 2019.

Any suggestion?
Thanks.

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.