swiftflutterdart3d-secure

How to implement 3D Secure (Verified by Visa / MasterCard SecureCode) in Flutter?


The existing implementation 3DS is such that during checkout and payment stage, it involves redirecting the customer away from your app, to a bank / card issuer website where the customer can enter their previously set-up password to authenticate that they are indeed the card holder. The website will then redirect the customer back to your website with information needed to complete the transaction. How can I read the response of the bank server to the redirection? I tried to do this via the webview_flutter, but can only get URL redirects.

Widget _view3ds(PaymentAnswer answer) {
  final url = answer.model['AcsUrl'];
  return Scaffold(
    appBar: AppBar(
      title: const Text('Pay'),
    ),
    body: WebView(
      initialUrl: url,
      initialPostParameters: answer.paramPost3DS(),
      javascriptMode: JavascriptMode.unrestricted,
      onPageFinished: _pageFinished
    ),
  );
}

void _pageFinished(String url)  {
  print(url);
  url.response ??? // Is there a way to get to the server response? Maybe there is another plugin that allows this?
}

There is a swift code that works great:

/// Handle result from 3DS form
    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        let urlString = request.url?.absoluteString
        if (urlString == Constants.cloudpaymentsURL) {
            var response: String? = nil
            if let aBody = request.httpBody {
                response = String(data: aBody, encoding: .ascii)
            }
            let responseDictionary = parse(response: response)
            webView.removeFromSuperview()
            post3ds(transactionId: responseDictionary?["MD"] as! String, paRes: responseDictionary?["PaRes"] as! String)
            return false
        }
        return true
    }

Can i get something like this on pure flutter?


Solution

  • You need to understand the flows that are happening in your payment integration. Basically there is the app, the server and the payment gateway.

    Your app may initiate a payment to your server and your server may then redirect this call to payment gateway. Alternatively, your app may directly call a link on a payment gateway (this is implementation dependent). In either case, the call to the payment gateway will most likely be initiated with a callbackUrl parameter of some sort. This callbackUrl will be used by the payment gateway to notify you of any success or failure.

    In most cases if not all, the callbackUrl is a publicly accessible url and hence will most probably be the your servers (your application is not publicly accessible for the payment gateway to invoke any endpoints on). Note that you app still has no access to this data as the payment gateway calls your server directly. Your server will then execute an HTTP Redirect which will be reflected by the app going to a success or error page.

    This redirect url is the key. It should hold either a transactionId that u can later use to query the server for status or a general success/failure format with sufficient info for your next work.

    Also please understand that the above is only an example. You will have to figure out how the payment flow is implemented in your server.

    To obtain a handle onto the navigation functions of a WKWebView use the navigation delegate: https://developer.apple.com/documentation/webkit/wknavigationdelegate

    Specifically you will need to look at the delegate methods and choose an appropriate handle to capture the url. I would assume the following will help you:

    func webView(WKWebView, didReceiveServerRedirectForProvisionalNavigation: WKNavigation!)