React Native Platform - SDK Integration

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

This integration will support the following flows:

  • App Flow: In case the PhonePe app is installed, the bottom pop-up PhonePe payment page
    called QCLite flow will be launched. Once the customer completes the transaction, SDK gives
    the response back to the merchant app

  • Redirection Flow: In case the PhonePe app is not installed, an android web view will be launched
    to complete the transaction. Once the customer completes the transaction, SDK gives the
    response back to the merchant app

Follow the steps below to integrate PhonePe SDK in React Native app:

Android Project of React Native

  1. Add the below code to 'repositories' section of your project level build.gradle file
// Top-level build file where you can add configuration options common to all sub-projects/modules.

allprojects {
   repositories {
       google()
       maven {
			url  "https://phonepe.mycloudrepo.io/public/repositories/phonepe-intentsdk-snapshots"
       }
   }
}
//https://dash.readme.com/project/phonepe-docs/v1/docs/android-pg-sdk-integration Top-level build file where you can add configuration options common to all sub-projects/modules.

allprojects {
   repositories {
       google()
       maven {
			url  "https://phonepe.mycloudrepo.io/public/repositories/phonepe-intentsdk-android"
       }
   }
}
  1. Add the below line to the 'dependencies' section of your app build.gradle.
implementation 'phonepe.intentsdk.android.snapshot:IntentSDK:1.6.8-478638-SNAPSHOT@aar’
implementation 'phonepe.intentsdk.android.release:IntentSDK:1.6.8@aar’

🚧

For, SDK version 1.6.8

We have compileSdkVersion: 28, minSdkVersion: 21, targetSdkVersion: 28

  1. Add below lines of code inside application tag in the AndroidManifest.xml file
<!-- Keep it false in production environment-->
<meta-data
	android:name="com.phonepe.android.sdk.Debuggable"
	android:value="true"/>

<!-- Keep it false in production environment-->
<meta-data
	android:name="com.phonepe.android.sdk.isUAT"
	android:value="true"/>

<!-- The value will be the MID-->
<meta-data
   android:name="com.phonepe.android.sdk.MerchantId"
   android:value="MID"/>

<!-- Get the App Id from PhonePe-->
<meta-data
  android:name="com.phonepe.android.sdk.AppId"
  android:value="<your app id given by PhonePe>"/>
  1. Add PhonePeSDKManager and PhonePeSDKPackage in your project (see Appendix at the end
    of this document).

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

  3. Update onActivityResult method in PhonePeSDKPackage class as per your response
    the requirement in the react native app.

  4. Call startPaymentTransaction method from React Native app to invoke the PhonePe module.

React Native Code

  1. Import NativeModules and NativeEventEmitter from the react-native package
import { NativeModules, NativeEventEmitter } from 'react-native'
  1. Using NativeModule fetch the PhonePeSDKManager of Android project
const PhonePeSDKManager = NativeModules.PhonePeSDKManager;
  1. In react native app.js file implement the following piece of code to check whether the PhonePe
    app is installed or not
const eventEmitterPhonePeCheck = new
NativeEventEmitter(NativeModules.PhonePeModule.doesPhonePeExists());
this.eventListenerPhonePeCheck =
eventEmitterPhonePeCheck.addListener('EventReminderPhonePeCheck', (event) =>
{
	var display = event.CheckPhonePeInstalled;
	/* Display PhonePe option in the checkout page only if variable display returns true */
	console.log("Does PhonePe app is installed = "+display);
});

🚧

Note

  1. Install the PhonePe PreProd app. Refer to this link.

  2. If returns true then display the PhonePe option on the checkout page or if returns false then
    do not display the PhonePe option on the checkout page.

  1. Start the process by calling PhonePeSDKManager.startPaymentTransaction with the appropriate
    parameters
PhonePeSDKManager.startPaymentTransaction(base64EncodedBody, checksum, endpoint,
xCallbackUrl, uiCallbackHandler);
  • base64EncodedBody - pass the encoded payload request

  • checksum - pass the checksum value

  • endPoint - pass the endpoint

  • xCallbackUrl - This can be “” or else you can send your custom callback URL where you
    will receive the server to server callback response to your custom callback URL. Once
    the response is received you have to validate the checksum and invalid amount. Refer to this
    link for more details.

  • uiCallbackHandler - This is a react method that will receive a user interface callback
    response from the startPaymentTransaction method.

function uiCallbackHandler(data)
{
	/*This callback indicates only about completion of UI flow.
	Inform your server to make the transaction
	status call to get the status. Update your app with the
	success/failure status.*/
}

🚧

Note

  • If data returns User Completed it indicates the payment has been completed.
  • If data returns User Cancelled it indicates the payment has been canceled just in case if the user presses the back button or aborts the transaction.
  • Inform merchant server about the completion of the transaction flow from merchant app

  • Merchant server should check the status with server to server callback or make the Check
    Transaction Status API call to the PhonePe server to check the transaction status (Even
    for User Cancelled callback)

  • The app should get the transaction status from the backend

  • Based on the result, the merchant must inform the user about the success or failure status
    of the transaction

🚧

Note

Kindly maintain the parameter order sequence

References

  • For Accept Payment API, Refer to this link.

  • Use the Check Transaction Status API to check the status of the payment transaction. Refer to
    this link.

  • For refund API, Refer to this link.

Appendix

PhonePeSDKManager.java

import android.app.Activity;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.phonepe.intent.sdk.api.PhonePe;
import com.phonepe.intent.sdk.api.PhonePeInitException;
import com.phonepe.intent.sdk.api.ShowPhonePeCallback;
import com.phonepe.intent.sdk.api.TransactionRequest;
import com.phonepe.intent.sdk.api.TransactionRequestBuilder;
import java.util.HashMap;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;

public class PhonePeSDKManager extends ReactContextBaseJavaModule implements
ActivityEventListener {
    /**
     * Global variables
     */
    private static int PHONEPE_REQUEST = 777;
    private Callback uiCallbackHandler;
    /**
     * Constructor
     * @param reactContext
     */
    public PhonePeSDKManager(@Nullable ReactApplicationContext reactContext) {
        super(reactContext);
        PhonePe.init(getReactApplicationContext());
        reactContext.addActivityEventListener(this);
    }
    @NonNull
    @Override
    public String getName() {
        return "PhonePeSDKManager";
    }
    /**
     * Method to set whether PhonePe app is installed or not and send the event to the React Code
     */
    @ReactMethod
    public void doesPhonePeExists() {
        try {
            PhonePe.isUPIAccountRegistered(new ShowPhonePeCallback() {
                @Override
                public void onResponse(boolean b) {
                    WritableMap params = Arguments.createMap();
                    params = Arguments.createMap();
                    params.putBoolean("CheckPhonePeInstalled", b);
                    sendEvent(getReactApplicationContext(), "EventReminderPhonePeCheck", params);
                }
            });
        } catch (PhonePeInitException e) {
            e.printStackTrace();
        }
    }
    /**
     * Method to send the event to the React native code
     * @param reactContext
     * @param eventName
     * @param params
     */
    private void sendEvent(ReactContext reactContext,
        String eventName,
        @Nullable WritableMap params) {
        reactContext
            .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
            .emit(eventName, params);
    }
    /**
     * Method to launch the PhonePe payment page from the React Native code
     * @param base64Body
     * @param checksum
     * @param endPoint
     * @param xCallbackUrl
     * @param uiCallbackHandler
     */
    @ReactMethod
    public void startPaymentTransaction(String base64Body, String checksum, String endPoint,
        String xCallbackUrl, Callback uiCallbackHandler) {
        TransactionRequest mTransactionRequest;
        this.uiCallbackHandler = uiCallbackHandler;
        HashMap < String, String > headers = new HashMap();
        headers.put("X-CHANNEL-ID", "phonepe_react_native_sdk");
        if (xCallbackUrl != null && xCallbackUrl.length() != 0 && !xCallbackUrl.isEmpty()) {
            headers.put("X-CALLBACK-URL", xCallbackUrl);
            headers.put("X-CALL-MODE", "POST");
            mTransactionRequest = new TransactionRequestBuilder()
                .setData(base64Body)
                .setChecksum(checksum)
                .setUrl(endPoint)
                .setHeaders(headers)
                .build();
        } else {
            mTransactionRequest = new TransactionRequestBuilder()
                .setData(base64Body)
                .setChecksum(checksum)
                .setHeaders(headers)
                .setUrl(endPoint)
                .build();
        }
        try {
            getReactApplicationContext().startActivityForResult(PhonePe.getTransactionIntent(mTransaction Request), 777, null);
        } catch (PhonePeInitException e) {}
    }
    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
        if (requestCode == PHONEPE_REQUEST) {
            if (resultCode == RESULT_OK) {
                this.uiCallbackHandler.invoke("User Completed");
            } else if (resultCode == RESULT_CANCELED) {
                this.uiCallbackHandler.invoke("User Cancelled");
            }
        }
    }
    @Override
    public void onNewIntent(Intent intent) {}
}

PhonePeSDKPackage.java

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 PhonePeSDKPackage implements ReactPackage {
    @NonNull
    @Override
    public List < NativeModule > createNativeModules(@NonNull ReactApplicationContext reactContext) {
        List < NativeModule > modules = new ArrayList < > ();
        modules.add(new PhonePeSDKManager(reactContext));
        return modules;
    }
    @NonNull
    @Override
    public List < ViewManager > createViewManagers(@NonNull ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}