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
- Add react-native-webview to your application (or alternative webview package)
npm install react-native-webview --save
- Add react-native-inappbrowser to your application (or alternative in-app browser package)
npm install react-native-inappbrowser-reborn --save
- 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
- Launch the Lightbox in a Webview
- Setup window message listener
- Open the OAuth login URL
- 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:
urlScheme
which is the URL you want the user to return to after completing an OAuth or “App-to-App” user flow. e.gmy_app://
ormy_app://path/success
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 awindow.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 toInAppBrowser
, theonNavigationStateChange
prop should be used instead ofonMessage
and anavigationChangeHandler
should be created instead of themessageHandler
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.
Updated about 1 year ago