SDKLess Integration (Android)

anchor image
Copied !
To support SDKLess integration, deviceContext has to be added to the request body of the v4/debit API call.
anchor image
Copied !
{ "merchantId": "MERCHANTUAT", "transactionId": "e474af20-a2a6-46c1-9a5d-73910ae86d0b", "merchantOrderId": "OD139924923", "merchantUserId": "user9999", "amount": 1000, "mobileNumber": "9999999999", "paymentScope": "PHONEPE", "deviceContext": { "phonePeVersionCode": "303391" } }
{ "request": "ewogICAgIm1lcmNoYW50SWQiOiAiTUVSQ0hBTlRVQVQiLAogICAgInRyYW5zYWN0aW9uSWQiOiAiZTQ3NGFmMjAtYTJhNi00NmMxLTlhNWQtNzM5MTBhZTg2ZDBiIiwKICAgICJtZXJjaGFudE9yZGVySWQiOiAiT0QxMzk5MjQ5MjMiLAogICAgIm1lcmNoYW50VXNlcklkIjogInVzZXI5OTk5IiwKICAgICJhbW91bnQiOiAxMDAwLAogICAgIm1vYmlsZU51bWJlciI6ICI5OTk5OTk5OTk5IiwKICAgICJwYXltZW50U2NvcGUiOiAiUEhPTkVQRSIsCiAgICAiZGV2aWNlQ29udGV4dCI6IHsKICAgICAgInBob25lUGVWZXJzaW9uQ29kZSI6ICIzMDMzOTEiCiAgICB9Cn0K" }
anchor image
Copied !
Sample Payload in JSON
{ "merchantId": "MERCHANTUAT", "transactionId": "e474af20-a2a6-46c1-9a5d-73910ae86d0b", "merchantUserId": "user9999", "amount": 100, "mobileNumber": "9999999999", "paymentScope": "ALL_UPI_APPS", "openIntentWithApp":"com.phonepe.app" }
{ "merchantId": "MERCHANTUAT", "transactionId": "e474af20-a2a6-46c1-9a5d-73910ae86d0b", "merchantUserId": "user9999", "amount": 100, "mobileNumber": "9999999999", "paymentScope": "ALL_UPI_APPS", "openIntentWithApp":"com.google.android.apps.nbu.paisa.user" }
{ "merchantId": "MERCHANTUAT", "transactionId": "e474af20-a2a6-46c1-9a5d-73910ae86d0b", "merchantUserId": "user9999", "amount": 100, "mobileNumber": "9999999999", "paymentScope": "ALL_UPI_APPS", "openIntentWithApp":"net.one97.paytm" }
Request Payload
{ "request": "eyAibWVyY2hhbnRJZCI6ICJNRVJDSEFOVFVBVCIsICJ0cmFuc2FjdGlvbklkIjogImU0NzRhZjIwLWEyYTYtNDZjMS05YTVkLTczOTEwYWU4NmQwYiIsICJtZXJjaGFudFVzZXJJZCI6ICJ1c2VyOTk5OSIsICJhbW91bnQiOiAxMDAsICJtb2JpbGVOdW1iZXIiOiAiOTk5OTk5OTk5OSIsICJwYXltZW50U2NvcGUiOiAiQUxMX1VQSV9BUFBTIiwgIm9wZW5JbnRlbnRXaXRoQXBwIjoiY29tLnBob25lcGUuYXBwIn0=" }

anchor image
Copied !

{ "success": true, "code": "SUCCESS", "message": "Your request has been successfully completed.", "data": { "redirectType": "INTENT", "redirectURL": "upi://pay?pa=MERCHANTUAT@ybl&pn=MERCHANT&am=1.00&mam=1.00&tr=e474af20-a2a6-46c1-9a5d-73910ae86d0b&tn=Payment+for+e474af20-a2a6-46c1-9a5d-73910ae86d0b&mc=5311&mode=04&purpose=00&utm_campaign=DEBIT&utm_medium=MERCHANTUAT&utm_source=e474af20-a2a6-46c1-9a5d-73910ae86d0b&mcbs=demoAppScheme" } }

Server Side

  1. Save the below-assigned apiEndPoint value at your server for the debit request.
Java
String apiEndPoint = "/v4/debit";
2. Collect the phonePeVersionCode from your app. 3. Call /v4/debit API with the above request payload. For more details, refer here 4. Select one of the API keys shared with you and note its index. Construct the checksum at your server as follows:
Java
String checksum = sha256(base64Body + apiEndPoint + saltKey) + ### + saltKeyIndex;
5. Initiate the payment process using Accept Payments API from the server and in the response you will receive the redirectURL which needs to be passed to the app side.

App Side

1. Check whether the PhonePe app is installed or not on the user’s device.
Java
public boolean doesPhonePeExist(Context context) { PackageInfo packageInfo = null; long phonePeVersionCode = -1L; try { packageInfo = getPackageManager().getPackageInfo(PHONEPE_PACKAGE_NAME,PackageManager.GET_ACTIVITIES); phonePeVersionCode = packageInfo.versionCode; } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, String.format("failed to get package info for package name = {%s}, exception message = {%s}", PHONEPE_PACKAGE_NAME, e.getMessage())); } if (packageInfo == null) { return false; } if (phonePeVersionCode > 94033) { return true; } return false; }
2. If the PhonePe app is installed on the user’s device, then you need to get the PhonePe app version code and give it to your server. 3. Once the merchant app receives the redirectUrl from the server, the deep linking option will be shown where the merchant has to handle the intent flow by using the below code:
anchor image
Copied !
Java
Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(redirectUrl)); i.setPackage(PHONEPE_PACKAGE_NAME); startActivityForResult(i, PHONEPE_REQUEST);
Note:
  • In this case, you will receive the intent URI in the “redirectURL” parameter in the response of the Accept Payment API response.
  • On loading this URL, the merchant will invoke the PhonePe app only and complete the payment.
  • Upon payment completion, the merchant will receive the UI callback in onActivityResult.
  • Once you receive the UI callback, It indicates that the payment flow is completed then you should check the payment status with the server.
Note:
  • You will get redirectURL in the response of the Accept Payment API response.
4. Override onActivityResult to listen to the debit result:
Java
private static final int PHONEPE_REQUEST = 123; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PHONEPE_REQUEST) { /*This callback indicates only about completion of flow. Inform your server to make the transaction status call to get the status. Update your app with the success/failure status.*/ } }
  • Inform your server about the completion of the transaction flow from your app.
  • Your server should make the Check Transaction Status API call to the PhonePe server to check the transaction status(Even for RESULT_CANCELED).
  • Get the result and notify your app.
  • Based on the result inform the user about the success or failure status of the transaction.
anchor image
Copied !
1. Refer to Check Transaction Status API for the server-to-server call to get the transaction status. The payment status can be Success, Failed, Pending, or any of the codes. For Pending, merchants should retry until the status changes to Success or Failed. 2. Refer to Refund API for the reconciliation. There could be cases where the amount gets deducted but you receive payment in Pending in the Check Transaction Status. For such cases either you can show the order failed immediately and refund the amount when pending changes to success using Refund API or show the order placed according to your use case.