# Establish communication between SRCI and DCF
source: https://developer.mastercard.com/mastercard-checkout-solutions/tutorial/mobile/step3/index.md

## Step 3. Establish communication between SRCI and DCF {#step-3-establish-communication-between-srci-and-dcf}

In a web to web scenario the merchant web page can be used as a communication bridge between SRCI and DCF (e.g., via postMessage). Under these circumstances, the SRCI and DCF need not both be active at the same time; scripts running within the merchant web page can facilitate communication, maintain state, and orchestrate flow.

However, because of the communication limitations between native application code and WebViews, a different communication pattern must be utilized in app to web scenarios. During app to web flow, both the SRCI and DCF should be opened in individual WebViews and communication between the two should be real-time and direct (e.g., via postMessage).

The web view **srciWebView** created in the previous code samples will need to be able to handle the DCF being invoked. In a web application this would involve a pop-up window, with mobile the view controller / activity needs to handle web views for the SRCI and DCF within the same native view.

* For Android, your SRCI WebView will require **WebChromeClient** to handle creation of pop-ups.

WebChromeClient provides methods to create a separate WebView which can route to the DCF provider.

* For iOS, you should handle this by implementing **WKUIDelegate** and **WKNavigationDelegate**.

* Java
* Objective-C

```code
// Sample WebChromeClient implementation

srciWebView.setWebChromeClient(new WebChromeClient() {
  @Override public boolean onCreateWindow(final WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
    final WebView dcfWebView = new WebView(activity);
    dcfWebView.getSettings().setJavaScriptEnabled(true);
    dcfWebView.getSettings().setSupportZoom(true);
    dcfWebView.getSettings().setBuiltInZoomControls(true);
    dcfWebView.getSettings().setSupportMultipleWindows(true);
    dcfWebView.setLayoutParams(
        new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT));

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      CookieManager.getInstance().setAcceptThirdPartyCookies(dcfWebView, true);
    }

    view.addView(dcfWebView);

    WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
    transport.setWebView(dcfWebView);
    resultMsg.sendToTarget();

    // Set DCF webView logic for WebView
    dcfWebView.setWebViewClient(new WebViewClient() {
      @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // This should be the same shouldOverrideUrlLoading used in the srci WebView
        return WebCheckoutActivity.this.shouldOverrideUrlLoading(url);
      }

      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override
      public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        // This should be the same shouldOverrideUrlLoading used in the srci WebView
        return shouldOverrideUrlLoading(view, request.getUrl().toString());
      }
    });

    // DCF WebChromeClient provides a way to handle all popups using HitTestResult
    dcfWebView.setWebChromeClient(new WebChromeClient() {
      @Override public void onCloseWindow(WebView window) {
        // Remove the DCF view from the Activity's views when closing
        view.removeView(dcfWebView);
      }

      public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture,
          Message resultMsg) {
        WebView.HitTestResult result = view.getHitTestResult();

        if (result.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
          //If the user has selected an anchor link, open in browser
          Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(result.getExtra()));
          startActivity(browserIntent);
          return false;
        }
        return true;
      }
    });
    return true;
  }
}
```

```objective-c
// Sample WKUIDelegate, WKNavigationDelegate implementation

- (WKWebView *) webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {

    _dcfWebView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
    _dcfWebView.UIDelegate = self;
    _dcfWebView.navigationDelegate = self;
    _receiveNavigationForDCFPopupCount = 0;

    [self.view addSubview:_dcfWebView];
    [self setConstraintsForView:_dcfWebView];
    [self.view addSubview:_indicatorView];
    [self.view bringSubviewToFront:_indicatorView];
    [_indicatorView show];

    [self.view addSubview:_dcfWebView];
    [self setConstraintsForView:_dcfWebView];

    return _dcfWebView;
}

- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    if (_dcfWebView != nil) {
        _receiveNavigationForDCFPopupCount += 1;
        if (_receiveNavigationForDCFPopupCount == 2) {
            [_indicatorView hide];
            [_indicatorView removeFromSuperview];
        }
    } else {
        [_indicatorView hide];
        [_indicatorView removeFromSuperview];
    }
}
```

### Returning control to the merchant app {#returning-control-to-the-merchant-app}

The DCF provider (e.g., the Mastercard DCF) will notify a successful checkout or a user-cancelled action,
which you will need to handle.
For this to work you will need to define a suitable URL scheme for links to the application
so that control can return to the application.
* Java
* Objective-C

```java
// Sample shouldOverrideUrlLoading() implementation on WebViewClient.
// The intent scheme should be defined in the merchant application AndroidManifest.xml
// to receive intent from SRCI.

@Override private boolean shouldOverrideUrlLoading(String url) {
  String urlScheme = URI.create(url).getScheme();

  Log.d(TAG, "Navigating to: " + url);

  if (urlScheme.equals(INTENT_SCHEME)) {
    handleIntent(url);

    return true;
  } else {

    return false;
  }
}

private void handleIntent(String intentUriString) {
  try {
    Intent intent = Intent.parseUri(intentUriString, Intent.URI_INTENT_SCHEME);
    String intentApplicationPackage = intent.getPackage();
    String currentApplicationPackage = getApplication().getApplicationInfo().packageName;
    Uri intentUri = Uri.parse(intentUriString);
    String transactionId = intentUri.getQueryParameter(QUERY_PARAM_TRANSACTION_ID);
    String status = intentUri.getQueryParameter(QUERY_PARAM_STATUS);

    if (STATUS_CANCEL.equals(status)) {
      finish();
    } else if (intentApplicationPackage != null &&
        intentApplicationPackage.equals(currentApplicationPackage)) {
      intent.putExtra(COMMERCE_TRANSACTION_ID, transactionId);
      intent.putExtra(COMMERCE_STATUS, status);
      intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

      startActivity(intent);
    } else {
      throw new IllegalStateException(
          "The Intent is not valid for this application: " + intentUriString);
    }
  } catch (URISyntaxException e) {
    Log.e(TAG,
        "Unable to parse Intent URI. You must provide a valid Intent URI or checkout will not work.",
        e);

    throw new IllegalStateException(e);
  }
}
```

```objective-c
// Sample webView:decidePolicyForNavigationAction:decisionHandler

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {
        NSURL *url = navigationAction.request.URL;
        [UIApplication.sharedApplication openURL:url options:@{} completionHandler:nil];
        decisionHandler(WKNavigationActionPolicyCancel);
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}


- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {
    NSURL *callbackUrl = urlSchemeTask.request.URL;
    NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithURL:callbackUrl resolvingAgainstBaseURL:YES];
    MCSCheckoutResponse *checkoutResponse = [[MCSCheckoutResponse alloc] init];

    NSURLResponse *urlResponse = [[NSURLResponse alloc] init];
    [urlSchemeTask didReceiveResponse:urlResponse];
    [urlSchemeTask didFinish];

    for (NSURLQueryItem *item in [urlComponents queryItems]) {
        if ([item.name isEqualToString:@"oauth_token"]) {
            checkoutResponse.transactionId = item.value;
        } else if ([item.name isEqualToString:@"mpstatus"]) {
            checkoutResponse.status = item.value;
        }
    }

    [self dismiss];

    [_delegate checkoutCompletedWithResponse:checkoutResponse];
}


- (WKWebView *) webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {

    _dcfWebView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
    _dcfWebView.UIDelegate = self;
    _dcfWebView.navigationDelegate = self;
    _receiveNavigationForDCFPopupCount = 0;

    [self.view addSubview:_dcfWebView];
    [self setConstraintsForView:_dcfWebView];
    [self.view addSubview:_indicatorView];
    [self.view bringSubviewToFront:_indicatorView];
    [_indicatorView show];

    [self.view addSubview:_dcfWebView];
    [self setConstraintsForView:_dcfWebView];

    return _dcfWebView;
}
```

#### Defining a suitable URL scheme {#defining-a-suitable-url-scheme}

The above code samples rely on a suitable URL scheme being defined
such that when the checkout experience is complete, a redirect to the
native application can be made successfully.

The following details show how this may be done for Android and iOS.

##### Android - Sample AndroidManifest.xml on Merchant application (DPA) {#android---sample-androidmanifestxml-on-merchant-application-dpa}

If the url parameter passed to `shouldOverrideUrlLoading()` matches the defined intent scheme, then the checkout experience is complete or cancelled and the result should be returned to Merchant application.

The merchant application (DPA) should define an intent-filter to receive the intent message and this should match the callback URL sent by the SRCI.

```xml

<activity
    android:name=".presentation.activity.CartActivity"
    android:screenOrientation="portrait">

    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data
            android:host="commerce"
            android:path="/"
            android:scheme="fancyshop"/>
    </intent-filter>
</activity>
```

The example above has CartActivity on Merchant application receiving the intent scheme. The Merchant will define an URI similar to `intent://fancyshop/#Intent;package=com.fancyshop;scheme=fancyshop;end`

The intent can be configured to return transactionID or similar information to confirm successful checkout. This can be used by the merchant application (DPA) to process payment data and authorize the transaction.

##### iOS - Sample Merchant application plist configuration {#ios---sample-merchant-application-plist-configuration}

For an iOS merchant application (DPA), the scheme can be configured on the project preferences. The callbackUrl from the SRCI should return the same URI scheme similar to `fancyshop://`

![](https://static.developer.mastercard.com/content/mastercard-checkout-solutions/images/mobile_xcode_iOS_plist_config.png)

## Building for native mobile applications {#building-for-native-mobile-applications}

If you are building a native mobile application, you can still use the JavaScript SDK and build your user experience as a web page which you can then display within the mobile app via a WebView.

Note that to do so there are some issues to do with how to pass control between the windows within the WebView -- we provide some suggestions about how to handle this in the
[Mobile Integration](https://developer.mastercard.com/mastercard-checkout-solutions/tutorial/mobile/index.md) section.

The following web frameworks are supported:

|           OS / Browser            |                                                        Version                                                        |
|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| ChromeTab                         | v63+ **Requires additional Merchant Integration to launch in ChromeTab**                                              |
| Android Webview                   | v68+ **Requires additional Merchant Integration to launch in WebView**                                                |
| Safari (In-App) - Webview         | v11+ **Requires additional Merchant Integration to launch in Safari WebView**                                         |
| SafariViewController              | v11+ **Requires additional Merchant Integration to launch in Safari ViewController**                                  |
| Safari AsWebAuthenticationSession | v11+ **Note: WebAuthenticationSession is a launch mechanism to launch the checkout experience on the Safari browser** |

#### Building Screens for Click to Pay {#building-screens-for-click-to-pay}

To provide your consumers with Click to Pay Checkout experience, you must create the following screens:

* Consumer Identity Entry
* Consumer Assurance
* SRC Candidate List
* Payment Method and Cardholder Information Confirmation

Refer to [EMV Secure Remote Commerce User Interface Guidelines and Requirements PDF](https://3ds-ux-guidelines.emvco.com/), which provides reference examples of how screens can be built using SRC elements and components.
