React Native


Overview

This guide will walk you though an easy and straight forward solution to accept payments within your React Native app. This guide requires the use of a Web View component for a secure integration with Moyasar.

On this page


Before Starting

Please first go through Mobile Payments to get some understanding of the different implementation methods required to proceed here.

Setting Environment

If you already have a React Native project, you can skip to the next part or follow the official React Native guide Setting up the development environment.

Add the WebView Component

New versions of React Native do not provide the WebView components out of the box, instead you need to install something like react-native-webview to use this functionality.

Please follow the Getting Started guide of React Native WebView and make sure that your application compiles before proceeding to the next section.

Showing Payment Form

As we have mentioned in the main guide you can host the payment form and payment logic at your backend server (web application), since this will just make integration much easier and straight forward.

Hosted Payment Page

If you are following this method, please implement the payment form using this guide.

Now using the react-native-webview library before, you can show a webview and navigate to the payment page as follows:

return (
    <WebView source={{ uri: 'https://my-app.io/pay/34143125' }} style={{ height: '100%' }} />
);

Managed Payment Page

If you need to manage the page within application, prepare your form by following Web Payments guide, e.g.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Checkout</title>
    <link rel="stylesheet" href="https://cdn.moyasar.com/mpf/1.5.0/moyasar.css">
    <script src="https://polyfill.io/v3/polyfill.min.js?features=fetch"></script>
    <script src="https://cdn.moyasar.com/mpf/1.5.0/moyasar.js"></script>
</head>

<body style="margin: 2rem;">
    <div class="payment-form"></div>
    <script>
        Moyasar.init({
            element: '.payment-form',
            language: 'ar',
            amount: 100,
            currency: 'SAR',
            description: 'React Native Payment Demo',
            publishable_api_key: 'pk_live_TKHGYUq2iuyet2qyteyuifnjj',
            callback_url: 'https://payments.local/return'
        });
    </script>
</body>
</html>

Now you need to show the webview component and load the earlier HTML as follows:

function PaymentPage() {
    const formHtml = getEarlierHtml();
    
    return (
        <WebView 
            style={{ height: '100%' }}
            originWhitelist={['*']}
            source={{ html: formHtml, baseUrl: 'https://payments.local' }} />
    );
}

The param originWhitelist={['*']} is required in order to raw HTML, and you can find reasoning for why we chose https://payments.local as the baseUrl here.

Saving Payment ID

If you have read through the advanced configurations for Moyasar Payment Form, you know that you can handle on_complete event and read the new payment object before redirecting the user away.

If you hosting the page on your server, you can easily follow the Web Payments guide and see how to save payment ID.

But for managed pages, you have to communicate this information from within the WebView component back to your app. This can be achieved by onMessage event handler on the WebView component. To accomplish this, add the following to you raw HTML in the initialization object:

Moyasar.init({
    // Other parameters
    on_complete: function (payment) {
        return new Promise(function (resolve, reject) {
            window.ReactNativeWebView.postMessage(JSON.stringify(payment));
            resolve();
        });
    }
});

You can notice that we have used JSON.stringify(payment) to serialize the payment object before sending it, this is required since since postMessage can only send string messages. You can learn more here.

Now from your React Native app, you can just handle onMessage event and listen for incoming strings.

return (
    <WebView 
        style={{ height: '100%' }}
        originWhitelist={['*']}
        source={{ html: formHtml, baseUrl: 'https://payments.local' }}
        onMessage={event => {
            const payment = JSON.parse(event.nativeEvent.data);
            const paymentId = payment.id;
            // TODO: Save payment here...
        }} />
);

Handling Return

After the user has entered their credit card info or succeeded with other methods, they will be redirect to the callback_url we have provided before.

In react-native-webview we can handle the onShouldStartLoadWithRequest event watch for our return URL. Here is an example:

function PaymentPage() {
    function handleNavigationChanges(request) {
        if (request.url.includes('payment.local/return')) {
            // Parse Payment ID and status from URL

            // Hide the WebView and proceed with App logic

            return false; // We are done, prevent navigation
        }

        return true; // Allow navigation
    }

    return (
        <WebView 
            style={{ height: '100%' }}
            originWhitelist={['*']}
            source={{ html: formHtml, baseUrl: 'https://payments.local' }} />
    );
}

If we find payment.local/return within our URL, this indicates that the user is back, we can parse info or ignore them if we have saved the payment before.

Moyasar will always redirect the user with the id, status and message query params, for example:

https://payments.local/return?id=7cbc8071-1854-4055-974e-6ed3abba4f28&status=paid&message=Success

Note that message is a human readable message and is not intended for your app instead for your user. If you need a reliable info use status field.


Last Modified : Jun 2021