Accept Payments

<html-block html=”

Server Side

“>

  1. Save the below Assigned apiEndPoint value at your server for the debit request.
String apiEndPoint = "/v4/debit";
  1. Construct the request body and encode in Base 64 at your server as follows:
HashMap<String, Object> data = new HashMap<>();
data.put("merchantId", “M2306160483220675579140”); //String. Mandatory
data.put("transactionId", “TX123456789”); //String. Mandatory. 
data.put("amount", 100); //Long. Mandatory

//Note: Don't pass this if you are passing userAuthToken.
data.put("merchantUserId", “U123456789”); //String. Mandatory. Needed for linking 

//Note : Used only for OTP linking flow.
data.put("userAuthToken", <userAuthToken>); //String. Optional. Needed for linking 

data.put("merchantOrderId", “OD1234”); //String. Mandatory
data.put("message", “Payment for order placed 001234”); //String. Optional
data.put("mobileNumber", “9xxxxxxxxx”); //String. Optional
data.put("email", “amit***[email protected]”); //String. Optional
data.put("shortName",  “Amit”); //String. Optional
data.put("subMerchant", “DemoMerchant”); //String. ONLY if a submerchant id has been allocated to you.

//Note : Used only for Open Intent flow.
data.put("paymentScope", "ALL_UPI_APPS"); // String. Mandatory

// transactionId length should be less than 38 characters.
// merchantOrderId length should be less than 48 characters.
// Put more info as intimated. Nesting is allowed

String base64Body = Base64(new GSON().toJson(data));
Parameter NameTypeDescriptionMandatory
merchantIdSTRINGUnique MerchantID assigned to the merchant by PhonePeYes
transactionIdSTRINGUnique TransactionID generated by the merchant to track request to PhonePe
transactionId length should be less than 38 characters.
Yes
merchantUserIdSTRINGUnique UserID generated by merchant. This is used to pre-login users authenticated on PhonePe. Un-authenticated users are redirected to PhonePe login page. Conversions are higher when this is provided. Avoid passing email/mobile number.
Skip this for guest users.
Note:
Don't pass this if you are passing userAuthToken.
Yes
userAuthTokenSTRINGUnique userAuthTokengiven to merchant in OTP flow. This is used to pre-login users authenticated on PhonePe. If not passed users will be redirected to PhonePe login page.
Note : Used only for OTP linking flow.

amountLONGTransaction amount in PaiseYes
merchantOrderIdSTRINGOrderID generated by the merchant
merchantOrderId length should be less than 48 characters.
No
subMerchantSTRING.Tag to categorize merchant transaction.
Skip this field if you don’t have multiple merchants tagged under one merchant id
No
mobileNumberSTRINGMobile number of the userNo
messageSTRINGShort message. This message is displayed to the user on completion of payment.No
emailSTRINGEmail address of the userNo
shortNameSTRINGUser’s name pre-filled for registration purpose.No
  1. Select one of the API keys shared with you and note it’s index. Refer this link for salt key value and salt index credentials. Construct the checksum at your server as follows:
String checksum = sha256(base64Body + apiEndPoint + salt) + ### + saltIndex;

<html-block html=”

App Side

“>

  1. Collect Base64 encoded payload, checksum, apiEndPoint and transactionId from your server.
  2. a. Initiate the payment process as follows:
TransactionRequest debitRequest = new TransactionRequestBuilder()
	.setData(base64Body)
	.setChecksum(checksum)
	.setUrl(apiEndPoint)
	.build();

//For Intent SDK call below fuction 

try {
    startActivityForResult(PhonePe.getTransactionIntent(/* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}

//For open Intent call below function, Other flows will remain as it is.  

try {
    startActivityForResult(PhonePe.getImplicitIntent(/* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}
  1. b. For server to server callback option, refer to below
Map<String, String> headers = new HashMap();
headers.put("X-CALLBACK-URL","https://www.demoMerchant.com");  // Merchant server URL
headers.put("X-CALL-MODE","POST");
headers.put("X-PROVIDER-ID","M2401563246873249082352"); // ONLY if x-provider-id has been allocated to you.
TransactionRequest debitRequest = new TransactionRequestBuilder()
	.setData(base64Body)
	.setChecksum(checksum)
	.setUrl(apiEndPoint)
	.setHeaders(headers)
	.build();

//For Intent SDK call below fuction 

try {
    startActivityForResult(PhonePe.getTransactionIntent(
    /* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}

//For open Intent call below function, Other flows will remain as it is.  

try {
    startActivityForResult(PhonePe.getImplicitIntent(/* Context */ this, debitRequest),DEBIT_REQUEST_CODE);
} catch(PhonePeInitException e){
}

If you get a blank screen with “Load more”, refer Troubleshooting.

  1. Override onActivityResult to listen to debit result:
private static int DEBIT_REQUEST_CODE = 777;
 
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
 
    if (requestCode == DEBIT_REQUEST_CODE) {
      
      /*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.*/
    }   
}
  • Inform your server about the completion of the transaction flow from your app.
  • Your 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 RESULT_CANCELED).
  • App should get the transaction status from the backend.
  • Based on the result inform the user about the success or failure status of the transaction.

<html-block html=”

Server Side

“>

  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 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 amount gets deducted but you receive payment in Pending in the Check Transaction Status . For such cases either you can show order failed immediately and refund the amount when pending changes to success using Refund API or show order placed according to your use case.
{“method”:”post”,”url”:”/v3/merchant/inline/pay”,”auth”:”required”,”results”:{“codes”:[{“status”:200,”language”:”json”,”code”:”{}”,”name”:””},{“status”:400,”language”:”json”,”code”:”{}”,”name”:””}]},”params”:[{“name”:”request”,”type”:”string”,”enumValues”:””,”default”:””,”desc”:”base64 encoded payload”,”required”:true,”in”:”body”,”ref”:””,”_id”:”5aba199d69b8720062f880e7″},{“name”:”Content-Type”,”type”:”string”,”enumValues”:””,”default”:”application/json”,”desc”:””,”required”:true,”in”:”header”,”ref”:””,”_id”:”5abb6da3ed190c001275720d”},{“name”:”X-VERIFY”,”type”:”string”,”enumValues”:””,”default”:””,”desc”:”SHA256(base64 encoded payload + \”/v3/merchant/inline/pay\” + salt key) + ### + salt index”,”required”:true,”in”:”header”,”ref”:””,”_id”:”5abb6da3ed190c001275720e”},{“name”:”X-CALLBACK-URL”,”type”:”string”,”enumValues”:””,”default”:””,”desc”:”Dynamic callback URI for server to server callback”,”required”:false,”in”:”header”,”ref”:””,”_id”:”5abc9548453c7f00958b1d2e”},{“name”:”X-CALL-MODE”,”type”:”string”,”enumValues”:””,”default”:””,”desc”:”HTTP mode to be used for server to server callback. Default Values are POST/PUT”,”required”:false,”in”:”header”,”ref”:””,”_id”:”5abc9548453c7f00958b1d2d”}],”apiSetting”:”5ecf9143b5bd210023b3b738″,”examples”:{“codes”:[]}}
https://mercury-uat.phonepe.com