search

All-in-One SDK Integration for React Native platform

For merchants who have built their app on React Native platform - Paytm provides a bridge for you to conveniently integrate All-in-One SDK. In this document, we will highlight the steps required to integrate All-in-One SDK with React Native platform for your app. This platform helps you to build a seamless and responsive checkout experience for your application.

 

This integration will support the following two flows:

  • App Invoke Flow: In case the Paytm app is installed, it will be launched to complete the transaction and give the response back to your app.

  • Redirection Flow: In case the Paytm app is not installed, All-in-One SDK will open a web view to process transaction and give the response back to your app.

Overview of payment processing in React Native App

  1. On your mobile app, the user adds goods/services into the shopping/order cart and proceeds to checkout. You call Initiate Transaction API from your backend to generate transaction token.
    Within the Initiate Transaction API, you also get an option to include single or multiple payment sources for the users, thus, allowing you to make your own payment page with multiple payment sources.

  2. Launch the Hybrid app bridge to invoke Paytm All-in-One SDK with the transaction token received in step 1.

  3. If Paytm app is installed on user's phone, the payment will be completed on Paytm app using the user's saved credentials else transaction will be processed via web view within the All-in-One SDK(Paytm hosted redirection flow).

  4. Paytm processes the transaction with the user’s bank and returns the transaction response to your app.

  5. You call the Transaction Status API to verify the transaction response.

  6. Notify the payment status to the user and proceed with the order/service fulfilment.

Pre-requisites

  1. Create an account on Paytm as a merchant. Click how to create an account.

  2. Get the merchant Id and merchant key for the integration environment after creating the account.

  3. Go through the checksum logic to understand how to generate and validate the checksum.

  4. Get the staging android or iOS paytm app for integration testing on the merchant staging enviornment.

  5. Go through All-in-One SDK documentation before proceeding with integration.

  6. Call Initiate Transaction API from your backend to generate Transaction Token.

 

Please go through the following steps to integrate All-in-One SDK in your React Native app:

Android Project of React Native

  1. Add the below line to the ‘repositories’ section of your project-level build.gradle file.

    maven {
        url "https://artifactory.paytm.in/libs-release-local"
    }
  2. Add below line to ‘dependencies’ section of your app build.gradle.

    implementation 'com.paytm.appinvokesdk:appinvokesdk:1.5.3’
  3. Add AllInOneSDKManager and AllInOneSDKPackage in your project (see Appendix at the end of this document).

  4. In the pre-existing MainApplication class while creating an instance of ReactNativeHost there are a method getPackages(). In this method add AllInOneSDKPackage class in ReactPackage List.

  5. Update setResult method in AllInOneSDKPackage class as per your response requirement in the react native app.

  6. Call startTransaction method from your React Native app to invoke Paytm module.

For further queries visit the SDK based integration documentation.

Note: Add below line to ‘dependencies’ section of your app build.gradle in case of crash due to api calls as in my case it was crashing due to version mismatch of okhttp.

implementation "com.squareup.okhttp3:okhttp:4.2.1"
implementation "com.squareup.okhttp3:logging-interceptor:4.2.1"
implementation "com.squareup.okhttp3:okhttp-urlconnection:4.2.1"

React Native Code

  1. Import NativeModules from the react-native package.

    import { NativeModules } from 'react-native'
  2. Using NativeModule fetch the AllInOneSDKManager of Android project.

    const AllInOneSDKManager = NativeModules.AllInOneSDKManager;
  3. Start the process by calling AllInOneSDKManager.startTransaction with the appropriate parameters.

    AllInOneSDKManager.startTransaction(orderId, mid, txnToken, amount, callbackUrl, 
    isStaging, displayResult);
    • callbackUrl - this can be “” if static callback is required else you can send your custom callback URL.

    • displayResult - this is a react method which will receive a response from the startTransaction method.
       

      const displayResult = (result) => { setShowToast(result); }
      Attributes Description Mandatory

      orderid

      String(50)

      Unique reference ID for a transaction which is generated by merchant Special characters allowed in Order ID are: "@" "-" "_" ".". Yes

      mid

      String(20)

      This is a unique identifier provided to every merchant by Paytm. MID is part of your account credentials and is different on staging and production environment. Yes

      txnToken

      String

      Transaction token received from calling Initiate Transaction API (Note - pass same order id in SDK which was used for initiateTransaction). Yes

      amount

      String

      Amount in INR payable by the customer. Should contain digits up to two decimal points. The amount should not include any separator like (",") Yes

      callbackurl

      String(255)

      On completion of the transaction, Paytm payment gateway will send the response on this URL. This can be a static response URL as mentioned below:

      - Staging Environment: "https://securegw-stage.paytm.in/theia/paytmCallback?ORDER_ID=<order_id>"

      - Production Environment: "https://securegw.paytm.in/theia/paytmCallback?ORDER_ID=<order_id>"
      Yes

      IsStaging

      Boolean

      IsStaging is to define staging or production server (True for staging and False for production) Yes
  4. The callback will be received in the above “displayResult” as below string in case of transaction success or failure else it will receive a string message like onBackedPressed, networkError etc. You can handle this as per your requirement in the AllInOneSDKManger.setResult method which is in your react native android project.

    Sample Response:

    Bundle[
    {
        STATUS=TXN_SUCCESS,
        ORDERID="Order Id",
        CHARGEAMOUNT=0.00,
        TXNAMOUNT=1.00,
        TXNDATE=2020-07-21 19:00:05.0,
        MID="Merchant Id",
        TXNID="Transaction Value",
        RESPCODE=01,
        PAYMENTMODE=UPI,
        BANKTXNID="Bank transaction Id",
        CURRENCY=INR,
        GATEWAYNAME=ICICI,
        RESPMSG=Txn Success
    }]
  5. Verifying Payment

    1. You should validate the transaction response via a server-side request using the Transaction Status API. This API requires checksumhash in request and response. You must verify the Order ID and Amount with your data. The status should be treated as the final status of the transaction in all cases.

    2. Paytm provides payment response on both Callback URL and Webhook URL. Please refer to the sample response for different payment sources here.

 

Appendix

AllInOneSDKManager.java

package ;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.paytm.pgsdk.PaytmOrder;
import com.paytm.pgsdk.PaytmPaymentTransactionCallback;
import com.paytm.pgsdk.TransactionManager;
import org.json.JSONObject;
import java.util.Objects;

public class AllInOneSDKManager extends ReactContextBaseJavaModule implements ActivityEventListener {
    protected static final int REQ_CODE = 0;
    private Callback callback;
    public AllInOneSDKManager(ReactApplicationContext reactContext) {
        super(reactContext);
        reactContext.addActivityEventListener(this);
    }

    @NonNull

    @Override
    public String getName() {
        return "AllInOneSDKManager";
    }

    @ReactMethod
    public void startTransaction(String orderId, String mid, String txnToken, String amount, String callbackUrl, boolean isStaging, Callback call) {
        callback = call;
        if (orderId == null || mid == null || txnToken == null || amount == null || orderId.isEmpty() || mid.isEmpty() || txnToken.isEmpty() || amount.isEmpty()) {
            if (txnToken == null || txnToken.isEmpty()) {
                Toast.makeText(getReactApplicationContext(), "txnToken error", Toast.LENGTH_LONG).show();
            } 
            else {
                Toast.makeText(getReactApplicationContext(), "Please enter all field", Toast.LENGTH_LONG).show();
            }
            return;
        }

        String host = "https://securegw.paytm.in/";
        if (isStaging) {

            host = "https://securegw-stage.paytm.in/";

        }

        if (callbackUrl.isEmpty()) {
            callbackUrl = host + "theia/paytmCallback?ORDER_ID=" + orderId;

        }

        PaytmOrder paytmOrder = new PaytmOrder(orderId, mid, txnToken, amount, callbackUrl);
            TransactionManager transactionManager = new TransactionManager(paytmOrder, new PaytmPaymentTransactionCallback() {

                @Override
                public void onTransactionResponse(Bundle bundle) {
                    Log.d("LOG", "Payment Transaction is successful " + bundle);
                        setResult("Payment Transaction response " + bundle.toString(), call);
                }

                @Override
                public void networkNotAvailable() {
                    setResult("networkNotAvailable", call);
                }

                @Override
                public void onErrorProceed(String s) {
                    setResult(s, call);
                }

                @Override
                public void clientAuthenticationFailed(String s) {
                    setResult(s, call);
                }

                @Override
                public void someUIErrorOccurred(String s) {
                    setResult(s, call);
                }

                @Override
                public void onErrorLoadingWebPage(int iniErrorCode, String inErrorMessage, String inFailingUrl) {
                    setResult(inErrorMessage, call);
                }

                @Override
                public void onBackPressedCancelTransaction() {
                    setResult("onBackPressedCancelTransaction", call);
                }

                @Override
                public void onTransactionCancel(String s, Bundle bundle) {
                    setResult(s + " " + bundle.toString(), call);
                }

        });

        transactionManager.setShowPaymentUrl(host + "theia/api/v1/showPaymentPage");
        transactionManager.startTransaction(Objects.requireNonNull(getCurrentActivity()), REQ_CODE);

    }

    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
        if (requestCode == REQ_CODE && data != null) {
            setResult(data.getStringExtra("nativeSdkForMerchantMessage") + data.getStringExtra("response"), callback);
        //data.getStringExtra("nativeSdkForMerchantMessage") this return message if transaction was stopped by users<span>
        // data.getStringExtra("response") this returns the shared response if the transaction was successful or failure.
        }
    }

    @Override
    public void onNewIntent(Intent intent) {

    }

    private void setResult(String message, Callback call) {
        Log.e("log", message);
        if (call != null) {
            call.invoke(message);
        } 
        else {
            Toast.makeText(getReactApplicationContext(), "call is null", Toast.LENGTH_LONG).show();
        }
    }

}

AllInOneSDKPackage.java

package ;
import androidx.annotation.NonNull;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class AllInOneSDKPackage implements ReactPackage {
   @NonNull

   @Override
    public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new AllInOneSDKManager(reactContext));
        return modules;
    }
    
   @NonNull

   @Override
    public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}