SDK Integration

Step 1: Android SDK setup

Install PhonePe SDK using Android Studio. To add the SDK to the android app please follow the steps given below:

  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-android"
       }
   }
}
  1. Add the below line to the 'dependencies' section of your app build.gradle.
implementation 'phonepe.intentsdk.android.release:IntentSDK:1.6.5'
  1. Add meta-data in <application> tag of 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"/> 

<!-- Get the App Id from PhonePe-->
<meta-data
  android:name="com.phonepe.android.sdk.AppId"
  android:value="<your app id given by PhonePe>"/>

Step 2: SDK Initialization

  1. Initialize the PhonePe SDK in an Activity that gets launched before a user selects the PhonePe option on your checkout screen.

🚧

Note: Don't initialize in the Application class of your project.

PhonePe.init(this)
  1. Validate user’s phone number on PhonePe app:

Merchant app calls the SDK method validateUser(phoneNumber: String): String which internally checks whether the PhonePe app is installed or not as well as if the user is registered with the same phone number on both Merchant & PhonePe.

Merchant app calls the SDK method getPhonePeAppVersionCode(): long to get the installed PhonePe app version on the user’s device.

// add following code as part of Merchant app before displaying payment options
private void validatePhonePeUser() {
        try {
            PhonePe.validateUser(phoneNumber, phonePeUserStatus -> {
            //phonePeUserStatus values - VALID, INVALID
            long phonePeAppVersionCode = PhonePe.getPhonePeAppVersionCode();
            // returns -1 if app is not installed
            });
        } catch (PhonePeInitException e) {
            Log.d(“PhonePe.init() should be called before to initialize SDK”);
        }
}
  1. The Merchant app passes the above values to the Merchant backend to construct deviceContext to be sent in the v3/payment/options API call being made to PhonePe.
{
  "amount": 300,
  "merchantId": "MERCHANTUAT",
  "mobileNumber": "9999999999",
  "otpVerified": true,
  "deviceContext": {
    "phonePeUserStatus": "VALID",
    "phonePeVersionCode": 400922
  }
}

Based on the parameters, PhonePe decides to send payment options.

  1. The Merchant app passes the above values to the Merchant backend to construct deviceContext to be sent in the v3/inline/pay API call being made to PhonePe.
{
    "deviceContext": {
        "phonePeUserStatus": "VALID", 
    "phonePeVersionCode": 400922
    }
}

Post account selection on the checkout screen, the inline/pay API returns an intent url
( upi://pay ) which opens up the NPCI MPIN screen directly to process the payment.

  1. Card payments will continue to work via webview.
    Note: No changes are expected from the Merchant side for cards

Step 3: Handling callback from PhonePe

In order to receive server to server callbacks from the PhonePe server we recommend, merchants, pass X-CALLBACK-URL and X-CALL-MODE in the headers of the Accept Payment API. Before considering this response you need to validate the checksum and amount parameter. This will provide the payment status response as success/failure only. Based on payment status response, handling can be built at the merchant's end

  1. After the transaction is complete:
    Once the transaction is complete, you will get a Base64 Encoded JSON response along with the headers with checksum values. Find the below code snippet:
{
"response":"eyJzdWNjZXNzIjp0cnVlLCJjb2RlIjoiUEFZTUVOVF9TVUNDRVNTIiwibWVzc2FnZSI6IllvdXIgcGF5bWVudCBpcyBzdWNjZXNzZnVsLiIsImRhdGEiOnsidHJhbnNhY3Rpb25JZCI6IlRYMzIzMjE4NDk2NDQyMzQiLCJtZXJjaGFudElkIjoiTTIzMDYxNjA0ODMyMjA2NzU1NzkxNDAiLCJwcm92aWRlclJlZmVyZW5jZUlkIjoiUDE4MDYxNTEzMjMwOTM5MDA1NTQ5NTciLCJhbW91bnQiOjEwMDAsInBheW1lbnRTdGF0ZSI6IkNPTVBMRVRFRCIsInBheVJlc3BvbnNlQ29kZSI6IlNVQ0NFU1MiLCJwYXltZW50TW9kZXMiOlt7Im1vZGUiOiJBQ0NPVU5UIiwiYW1vdW50IjoxMDAwLCJ1dHIiOiI4MTY2MjY1MjE2MTYifV0sInRyYW5zYWN0aW9uQ29udGV4dCI6e319fQ"
}
{ 
    "headers": { 
        "x-verify":"2abaa82a4810c57dcd6aa52680dd772173b1e40770afe028131f31ddbe5487a8###1"
    }
}
  1. To calculate the checksum in the server to server callback response. Find the code snippet
Content-Type       application/json
X-VERIFY           SHA256(response + salt key) + ### + salt index
  1. To validate the amount, the merchant needs to compare the amount parameter received in the server to server callback response with the amount parameter passed in the Inline Pay API
  2. You need to validate the X-verify. Once both checksum and the amount parameters are validated, the order can be fulfilled based on the response. Note that completion of a transaction does not imply that payment is successful. Payment can be in a successful or failed state which needs to be derived from JSON response. Here is the code snippet:
{  
   "success":true,
   "code":"PAYMENT_SUCCESS",
   "message":"Your payment is successful.",
   "data":{  
      "transactionId":"TX32321849644234",
      "merchantId":"UATMERCHANT",
      "providerReferenceId":"P1806151323093900554957",
      "amount":1000,
      "paymentState":"COMPLETED",
      "payResponseCode":"SUCCESS",
      "paymentModes":[  
         {  
            "mode":"ACCOUNT",
            "amount":1000,
            "utr":"816626521616"
         }
      ],
      "transactionContext":{  
      }
   }
}
  1. When the back button is pressed by customer, SDK will return a UI callback to the App.You should take action as mentioned below

UI callbacks

Server to Server callbacks

Check Transaction Status API

Action

RESULT_OK

Success / Failure

Success / Failure

Take the decision based on response.

RESULT_CANCELLED

Success / Failure

Success / Failure

Take the decision based on response.

RESULT_CANCELLED

X

Payment Pending

Temporarily Mark transaction as payment failure.
Timeout is 10 minutes.
Call Check Transaction Status API after 10 to 15 minutes.
If response is failure then mark as failure transaction in the system.
If the response is successful then process the Refund.

RESULT_CANCELLED

X

Internal Server Error
Timed Out

Call Check Transaction Status API - Take decisions based on the response received.


Step 4: Validating the X-verify

Once the response is received, you need to validate the X-verify in order to ensure that the response received is not tampered with. In order to validate the X-verify, please follow the below steps:

  • Generate the checksum by using a SHA256 of the encoded body received in the response, salt key and salt index
  • The salt we would use will be appended with ### to the checksum value in the checksum attribute. Upon receiving this payload, you need to look at the salt_index in the checksum attribute after ### delimiter and use the appropriate salt_index to be able to calculate checksum at their end for the said payload. If it doesn't match, then you need to abort the request.
  • Salts are already pre-shared with you at the time of onboarding
  • If the value of any parameter is null, it will not be included in the calculation of the checksum.