React Native

Quickstart guide for adding Trustly UI to React Native mobile apps

The Trustly Lightbox Javascript library allows you to quickly build a bank authorization workflow in your React Native app. Integrating the Select Bank Widget and/or the Trustly Lightbox provides a powerful user experience that results in bank authorization data which can be used with other Trustly APIs.

💻

Example App

Prefer running an example project? Checkout our React Native Example on Github.

OAuth Background

Banks that use OAuth login pages often have strict security policies which prohibit user access to their login urls from inside Webviews. Trustly has added functionality to our client libraries in order to make OAuth handling simpler, but some additional integration steps must be taken in order to properly handle these OAuth flows via secure in-app browser components.

For more information visit the OAuth Guide

Prerequisites

  1. Add react-native-webview to your application (or alternative webview package)
npm install react-native-webview --save
  1. Add react-native-inappbrowser to your application (or alternative in-app browser package)
npm install react-native-inappbrowser-reborn --save
  1. Configure a deep link for your application. See the documentation provided by React Native on Linking. Typically a deep link (or URL scheme) in your application will look like: my_app://.

Steps to Integrate with OAuth Support

The following steps will guide you to successfully implement the Trustly Lightbox from a React Native app. There are primarily 4 steps to building this integration successfully:

👍

Checklist

  1. Launch the Lightbox in a Webview
  2. Setup window message listener
  3. Open the OAuth login URL
  4. Notify the Lightbox to proceed on user return

Launching the Lightbox in React Native

In addition to the standard variables required to load the Lightbox, the establishData passed into the Trustly Lightbox methods must include a metadata object with two key properties:

  1. urlScheme which is the URL you want the user to return to after completing an OAuth or “App-to-App” user flow. e.g my_app:// or my_app://path/success
  2. integrationContext which can be one of two valid strings, either InAppBrowser or InAppBrowserNotify. InAppBrowserNotify works by posting a message to the Webview element and generally performs better with React Native apps. InAppBrowser works by triggering a window.open event with a target url to be opened with a secure in-app browser.

See the example below, but note several required fields in the establishData are omitted for simplicity. For a complete list of required fields, see Establish Data.

const establishData = {
  accessId: 'YOUR_ACCESS_ID',
  merchantId: 'YOUR_MERCHANT_ID',
  metadata: {
    urlScheme: "YOUR_APP://",
    integrationContext: "InAppBrowserNotify",
  }
};

🚧

Multi-platform Users

Note that the presence of the integrationContext property will break the default web browser behavior of the Lightbox. If your web page containing the Trustly Lightbox serves both web browser users and mobile app users, the web page should add these metadata properties dynamically. A suggested approach to handle this is demonstrated in the Trustly Webview Example app.

With these properties included in the establishData object, you are ready to render the Lightbox in a webview. Depending on your application architecture, you may open a separately hosted web page or raw html. In either case, there are several packages for implementing a Webview. In our example we will be using the react-native-webview package to open a URL of myapp.com/checkout where the Trustly Lightbox is rendered.

import { WebView } from 'react-native-webview';

class TrustlyWebview extends Component () {
  render(){
    return (
      <WebView
        source={{ uri: 'https://myapp.com/checkout' }}
        javaScriptEnabled={true}
        startInLoadingState
      />);
  }  
}

Note: For this package, the prop javaScriptEnabled={true} must be passed in order for the Trustly Lightbox to be able to communicate with your app’s webview.

With this simple webview rendering our web page and the appropriate metadata properties in your establishData, the Lightbox will load normally, but behave differently when a user selects an OAuth-required bank. The next steps describe how to handle these behaviors.

Setup Window Message Listener

When a user selects an OAuth-enabled bank, navigating directly to the bank's login URL within the webview may result in errors. Instead, with the integrationContext parameter provided earlier, the Trustly Lightbox will simply provide a URL to be opened with the secure in-app-browser component. To simplify receiving this message in a React Native app, use the window.ReactNativeWebview.postMessage method by injecting a listener on the webview we constructed in the previous step:

import { WebView } from 'react-native-webview';

const postMessageForOauth = `
	window.addEventListener(
	"message",
	function (event) {
		var data = (event || {}).data || {}
		window.ReactNativeWebView.postMessage(event.data);
	},
	false
	);
`;

class TrustlyWebview extends Component () {
  render(){
    return (
      <WebView
        source={{ uri: 'https://myapp.com/checkout' }}
        javaScriptEnabled={true}
        injectedJavaScript={postMessageForOauth}
        startInLoadingState
      />);
  }  
}

Now the Trustly Javascript library is prepared to send your React Native app message events. The next step is to configure your app to listen for for these messages. For reference, an example of an OAuth login window message is below:

{
    "nativeEvent": {
        "canGoBack": true,
        "canGoForward": false,
        "data": "PayWithMyBank.ExternalBrowserIntegration|open|https://sandbox.paywithmybank.com/step/oauth/login/1024436793?ts=1691778330867&lbid=1691778325518|oauth:_FIOAuthWindow",
        "loading": false,
        "target": 3,
        "title": "Trustly",
        "url": "about:blank"
    }
}

Create a message handler function to filter and verify the messages your application may receive and pass it to the onMessage prop of the Webview component:

import { WebView } from 'react-native-webview';

const postMessageForOauth = `
	window.addEventListener(
	"message",
	function (event) {
		var data = (event || {}).data || {}
		window.ReactNativeWebView.postMessage(event.data);
	},
	false
	);
`;

  messageHandler = (message: any) => {
    const data = message.nativeEvent.data
    var [command, ...params] = data.split("|")
    
    // check for correct message content
    if(command.includes("ExternalBrowserIntegration")) {
      var messageUrl = params[1]
      // user selected an OAuth bank
      console.log("Trustly URL", messageUrl)
    }
  }

class TrustlyWebview extends Component () {
  render(){
    return (
      <WebView
        source={{ uri: 'https://myapp.com/checkout' }}
        javaScriptEnabled={true}
        injectedJavaScript={postMessageForOauth}
        startInLoadingState
        onMessage={this.messageHandler}
      />);
  }  
}

🚧

Integration Context

If the IntegrationContext property was instead set to InAppBrowser, the onNavigationStateChange prop should be used instead of onMessage and a navigationChangeHandler should be created instead of the messageHandler function.

📘

Messages & OAuth Login URLs

Note that the message verification example above only verifies an expected portion of the data property of the message. If additional verification or filtering is required, be sure to account for URLs such as these in the data property of the message:

Sandbox
www.sandbox.paywithmybank.com/step/oauth/login/{transactionId}
https://sandbox.paywithmybank.com/step/oauth/login/{transactionId}
www.sandbox.trustly.one/step/oauth/login/{transactionId}
https://sandbox.trustly.one/step/oauth/login/{transactionId}

Production
www.paywithmybank.com/step/oauth/login/{transactionId}
https://paywithmybank.com/step/oauth/login/{transactionId}
www.trustly.one/step/oauth/login/{transactionId}
https://trustly.one/step/oauth/login/{transactionId}

Additionally, an epoch timestamp will be attached as a query parameter as demonstrated below:

www.trustly.one/step/oauth/login/{transactionId}?ts=1519211809934

Now your app’s webview is prepared to handle the window.postMessage event from within the Trustly Lightbox. The next step outlines the specifics of how the OAuth link contained in the message should be opened.

Opening The External Link

At this point, it may seem appropriate to open the external url in a new webview. However, many banks do not consider webviews secure for the purposes of entering user credentials and creating an authenticated user session. Therefore, OAuth login pages must be opened in a secure in-app browser.

For iOS, the secure in-app browser class ASWebAuthenticationSession is preferred. For Android Chrome Custom Tabs provide similar capabilities. Depending on your React Native toolchain there are several packages that provide abstractions for these APIs. In our example, we will be using the popular react-native-inappbrowser-reborn package.

import { InAppBrowser } from 'react-native-inappbrowser-reborn';

class TrustlyWebview extends Component () {
  
  openOAuthLink = async link => {
    try {
      await InAppBrowser.openAuth(link, '', { modalPresentationStyle: "fullscreen"})
        .then(response => {
        // handle user action in auth session
        
      });
    } catch (err) {
      console.log(err);
    }
  }
  
  messageHandler = (message: any) => {
    const data = message.nativeEvent.data
    var [command, ...params] = data.split("|")
    
    // check for correct message content
    if(command.includes("ExternalBrowserIntegration")) {
      var messageUrl = params[1]
      // user selected an OAuth bank
      console.log("Trustly URL", messageUrl)
      this.openOAuthLink(messageUrl)
    }
  }
  
  // render function ommitted for brevity

}

🚧

Note on Code Example

Usage of the InAppBrowser function has been greatly simplified for the purpose of this example. For best practices, see the guidance and API for the in-app browser package of your choosing.

At this point, upon opening the Trustly Lightbox and selecting an OAuth-required Bank (e.g. Chase) the user will see a new secure in-app-browser layer open over the Lightbox containing information regarding the chose bank’s OAuth experience and a button prompting them to “Continue to {Bank Name}”.

Upon clicking the link, the user will be able to authenticate with their bank’s mobile app or through the bank’s OAuth login web page. After a successful authentication, the user will be directed back to your app. However, the Trustly authorization process will not be complete until we handle the final step.

Return to the Lightbox

The final step is to listen for the user’s return and prompt Trustly to complete the authorization process.

To do this, we will handle the promise returned by the InAppBrowser.openAuth() function and notify the Trustly Lightbox that the user has returned from their OAuth session. Within this callback, we will add a simple function to inject Javascript which will call the Trustly.proceedToChooseAccount() function on the webview.

import { InAppBrowser } from 'react-native-inappbrowser-reborn';

class TrustlyWebview extends Component () {
  
  const postMessageForOauth = `
    window.addEventListener(
    "message",
    function (event) {
      var data = (event || {}).data || {}
      window.ReactNativeWebView.postMessage(event.data);
    },
    false
    );
  `;

	openOAuthLink = async link => {
	  try {
			await InAppBrowser.openAuth(link, '', { modalPresentationStyle: "fullscreen"})
				.then(response => {
					if (response.type === 'success') {
						// notify Trustly object of user return
			      this.webview.injectJavaScript('window.Trustly.proceedToChooseAccount();');
			    } else {
						console.log(response);
				});
	  } catch (err) {
	    console.log(err);
	  }
	}
	
	//messageHandler ommitted for brevity

	render(){
		return (
	    <WebView 
	      source={{ uri: 'https://myapp.com/checkout' }}
	      javaScriptEnabled={true}
        injectedJavaScript={postMessageForOauth}
	      startInLoadingState
        onMessage={this.messageHandler}
	    />);
	}  
}

Conclusions & Next Steps

That’s it! You have successfully handled OAuth scenarios for your Trustly integration. Your application will now appropriately load OAuth login pages from a secure in-app browser and the Trustly Lightbox will proceed smoothly when the OAuth session is complete. To see the code examples included in this guide in the context of a complete demo, see the Trustly React Native Example App on Github.