Summary
This doc outlines the steps to integrate PhonePe PG for custom checkout experience.
Authorization
This API is used to generate access token which will be used to make further API calls, below are the steps for the same:
API DETAILS:
POST https://api-preprod.phonepe.com/apis/pg-sandbox/v1/oauth/token
Request Details
Request Headers
Header Name | Header Value |
---|---|
Content-Type | application/x-www-form-urlencoded |
Request Parameters
Parameter Name | Description |
---|---|
client_id | Client ID shared by PhonePe |
client_version | In case of simulator, client_version value should be 1. In case of production, use the value as received in credentials email. |
client_secret | Client secret shared by PhonePe |
grant_type | client_credentials |
Send the above Headers and payload to the below API using HTTP POST method :
POST – https://api-preprod.phonepe.com/apis/pg-sandbox/v1/oauth/token
Sample CURL :
curl --location 'https://api-preprod.phonepe.com/apis/pg-sandbox/v1/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=V2SUBUAT_2403281706165571071834' \
--data-urlencode 'client_version=1' \
--data-urlencode 'client_secret=MWQyMjUxMmMtM2RlYi00ZTQwLTg1ZjUtOTI1NDFlOGY1YWNk' \
--data-urlencode 'grant_type=V2PGTESTUAT'
NOTE : Above CURL has only the dummy data, please refer to the request headers and parameters table above to generate the payload and headers.
Sample Response from the API :
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVzT24iOjE3MTIyNTM2MjU2NDQsIm1lcmNoYW50SWQiOiJWMlNVQlVBVCJ9.7aVzYI_f_77-bBicEcRNuYx093b2wCsgl_WFNkKqAPY",
"encrypted_access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVzT24iOjE3MTIyNTM2MjU2NDQsIm1lcmNoYW50SWQiOiJWMlNVQlVBVCJ9.7aVzYI_f_77-bBicEcRNuYx093b2wCsgl_WFNkKqAPY",
"expires_in": null,
"issued_at": 1711629025,
"expires_at": 1712253625,
"session_expires_at": 1712253625,
"token_type": "O-Bearer"
}
Use the above access token to initiate the payment process as specified below :
Initiate Payment
This API is used to initiate the payment :
API Details :
POST https://api-preprod.phonepe.com/apis/pg-sandbox/payments/v2/pay
Request Details
Request Headers
Header Name | Header Value |
---|---|
Content-Type | application/json |
Authorization | O-Bearer <merchant-auth-token> |
Request Parameters
Parameter Name | Data Type | Description | Mandatory (Yes/No) | Constraints |
merchantOrderId | STRING | Unique merchant order id generated by merchant | Yes | Max Length = 63 charactersNo Special characters allowed except underscore “_” and hyphen “-“ |
amount | LONG | Order amount in paisa | Yes | Min Value = 1 |
expireAfter | LONG | Order expiry in seconds. If not passed default value will be used. | No | Min Value = 300, Max Value = 5184000 |
metaInfo | OBJECT | Merchant defined meta info to store additional information.same data will be returned in status and callback response | No | |
metaInfo.udf1-4 | STRING | Merchant defined additional information | No | Max length = 256 characters |
constraint | STRING | Different type of constraints that must be applied to the payment. | No | |
constraints.type | STRING | Type of constraint to apply | No | Values Allowed = [ACCOUNT] |
deviceContext.deviceOS | STRING | device OS required only in case of UPI_INTENT | No | Values Allowed = [IOS, ANDROID] |
deviceContext.merchantCallBackScheme | STRING | Merchant Callback Scheme. Required only in case targetApp = PHONEPE and deviceContext.deviceOS = IOS | No | |
paymentFlow | OBJECT | Additional details required by this flow | Yes | |
paymentFlow.type | STRING | Type of payment flow | Yes | Valued Allowed = [PG_CHECKOUT] |
paymentMode | OBJECT | Object containing details for mode of payments | Yes | |
paymentMode.type | STRING | Type of payment mode | Yes | Values Allowed = [UPI_INTENT, UPI_COLLECT, UPI_QR, NET_BANKING, TOKEN, CARD] |
merchantUrls.redirectUrl | STRING | Url where user will be redirected after completing the payment. Mandatory only for [NET_BANKING, TOKEN, CARD] Payment Mode | Yes | Valid Http url. |
Sample Request Body:
Pay using UPI_INTENT
{
"merchantOrderId": "TX123456",
"amount": 1000,
"expireAfter": 1200,
"metaInfo": {
"udf1": "<additional-information-1>",
"udf2": "<additional-information-2>",
"udf3": "<additional-information-3>",
"udf4": "<additional-information-4>",
"udf5": "<additional-information-5>"
},
"constraints": [
{
"type": "ACCOUNT"
"accountNumber": "420200001892",
"ifsc": "ICIC0000041"
}
],
"deviceContext": {
"deviceOS": "IOS",
"merchantCallBackScheme": ""
},
"paymentFlow": {
"type": "PG",
"paymentMode" : {
"type" : "UPI_INTENT",
"targetApp" : "PHONEPE" // PHONEPE, GPAY, PAYTM, null
}
}
}
Extra parameters for UPI INTENT
Field Name | Data Type | Mandatory | Description |
---|---|---|---|
targetApp | application/json | No | Target app to use. Allowed Values = [PHONEPE, GPAY, PAYTM] |
Pay using UPI_COLLECT
{
"merchantOrderId": "TX123456",
"amount": 1000,
"expireAfter": 1200,
"metaInfo": {
"udf1": "<additional-information-1>",
"udf2": "<additional-information-2>",
"udf3": "<additional-information-3>",
"udf4": "<additional-information-4>",
"udf5": "<additional-information-5>"
},
"constraints": [
{
"type": "ACCOUNT"
"accountNumber": "420200001892",
"ifsc": "ICIC0000041"
}
],
"paymentFlow": {
"type": "PG",
"paymentMode" : {
"type" : "UPI_COLLECT",
"details" : {
"type" : "VPA",
"vpa" : "abcd@ybl"
},
"message" : "some message from merchant to populate"
}
}
}
Extra parameters for UPI COLLECT
Field Name | Data Type | Mandatory | Description |
---|---|---|---|
collectPaymentDetails | Object | Yes | Object containing collect payment details |
collectPaymentDetails.type | String | Yes | Type of collect payment details. Allowed Values = [VPA, PHONE_NUMBER] |
collectPaymentDetails.vpa | String | Yes | VPA against which collect request need to be raised (Use when type = VPA) |
collectPaymentDetails.phoneNumber | String | Yes | Phone number against which collect request need to be raised (Use when type = PHONE_NUMBER) |
message | String | Yes | Message to show in collect request |
Pay using UPI_QR
{
"merchantOrderId": "TX123456",
"amount": 1000,
"expireAfter": 1200,
"metaInfo": {
"udf1": "<additional-information-1>",
"udf2": "<additional-information-2>",
"udf3": "<additional-information-3>",
"udf4": "<additional-information-4>",
"udf5": "<additional-information-5>"
},
"constraints": [
{
"type": "ACCOUNT"
"accountNumber": "420200001892",
"ifsc": "ICIC0000041"
}
],
"paymentFlow": {
"type": "PG",
"paymentMode" : {
"type" : "UPI_QR"
}
}
}
Pay using NET_BANKING
{
"merchantOrderId": "TX123456",
"amount": 1000,
"expireAfter": 1200,
"metaInfo": {
"udf1": "<additional-information-1>",
"udf2": "<additional-information-2>",
"udf3": "<additional-information-3>",
"udf4": "<additional-information-4>",
"udf5": "<additional-information-5>"
},
"constraints": [
{
"type": "ACCOUNT"
"accountNumber": "420200001892",
"ifsc": "ICIC0000041"
}
],
"paymentFlow": {
"type": "PG",
"paymentMode" : {
"type" : "NET_BANKING",
"bankId" : "HDFC",
"merchantUserId": ""
},
"merchantUrls": {
"redirectUrl": "<redirectUrl>"
}
}
}
Extra parameters for NET_BANKING
Field Name | Data Type | Mandatory | Description |
---|---|---|---|
bankId | String | Yes | Bank id from where payment will be completed. |
Pay using TOKEN
{
"merchantOrderId": "TX123456",
"amount": 1000,
"expireAfter": 1200,
"metaInfo": {
"udf1": "<additional-information-1>",
"udf2": "<additional-information-2>",
"udf3": "<additional-information-3>",
"udf4": "<additional-information-4>",
"udf5": "<additional-information-5>"
},
"constraint": [
{
"type": "ACCOUNT"
"accountNumber": "420200001892",
"ifsc": "ICIC0000041"
}
],
"paymentFlow": {
"type": "PG",
"paymentMode" : {
"type" : "TOKEN",
"authMode": "3DS",
"tokenDetails": {
"encryptedToken": "<encryptedToken>",
"encryptionKeyId": 122,
"expiry": {
"month": "12",
"year": "2029"
},
"panSuffix": "<panSuffix>",
"cardHolderName": "Dummy Name",
"cryptogram": "<cryptogram>",
"encryptedCvv": "<encryptedCvv>"
},
"merchantUserId": "dummyUser"
},
"merchantUrls": {
"redirectUrl": "<redirectUrl>"
}
}
}
Extra parameters for TOKEN
Field Name | Data Type | Mandatory | Description |
---|---|---|---|
authMode | String | Yes | Defaults to 3DS |
tokenDetails.encryptionKeyId | Integer | Yes | KeyId of key which merchant uses to encrypt card number & cvv. |
tokenDetails.encryptedToken | String | Yes | Encrypted TOKEN number which merchant passes to process card transaction. |
tokenDetails.encryptedCvv | String | Yes | Encrypted CVV of the card with which payment is being initiated. |
tokenDetails.cryptogram | String | Yes | The cryptogram fetched from the gateway where the card was tokenized. |
tokenDetails.panSuffix | String | Yes | Last four digits of cardNumber |
tokenDetails.cardHolderName | String | No | Card Holder Name |
tokenDetails.expiry.month | String | Yes | Token expiry month |
tokenDetails.expiry.year | String | Yes | Token expiry year |
merchantUserId | String | No |
Pay using CARD
{
"merchantOrderId": "TX123456",
"amount": 1000,
"expireAfter": 1200,
"metaInfo": {
"udf1": "<additional-information-1>",
"udf2": "<additional-information-2>",
"udf3": "<additional-information-3>",
"udf4": "<additional-information-4>",
"udf5": "<additional-information-5>"
},
"constraint": [
{
"type": "ACCOUNT"
"accountNumber": "420200001892",
"ifsc": "ICIC0000041"
}
],
"paymentFlow": {
"type": "PG",
"paymentMode" : {
"type": "CARD",
"authMode": "3DS",
"cardDetails": {
"encryptedCardNumber": "<encryptedCardNumber>",
"encryptionKeyId": 1,
"cardHolderName": "Dummy Name",
"expiry": {
"month": "12",
"year": "2029"
},
"encryptedCvv": "<encryptedCvv>"
},
"merchantUserId": "dummyUser"
},
"merchantUrls": {
"redirectUrl": "<redirectUrl>"
}
}
}
Response from the API :
Response Headers:
Header Name | Header Value |
---|---|
Content-Type | application/json |
Response Payload:
Case 1: Success Response
Http Response Code: 200
UPI_INTENT
{
"orderId": "OMO123456789",
"state": "PENDING",
"expireAt": 1703756259307,
"intentUrl" : "ppe://url"
}
UPI_COLLECT
{
"orderId": "OMO123456789",
"state": "PENDING",
"expireAt": 1703756259307
}
UPI_QR
{
"orderId": "OMO123456789",
"state": "PENDING",
"expireAt": 1703756259307,
"intentUrl": "ppe://url",
"qrData": ""
}
NET_BANKING / CARD / TOKEN
{
"orderId": "OMO123456789",
"state": "PENDING",
"expireAt": 1703756259307,
"redirectUrl": ""
}
Case 2: Order with same merchant order id is already present and not in CREATED state
Http Response Code: 400
{
"code": "BAD_REQUEST",
"message": "Please check the inputs you have provided."
}
Case 3: Internal Server Error
Http Response code: 500
{
"code": "INTERNAL_SERVER_ERROR",
"message": "There is an error trying to process your transaction at the moment. Please try again in a while."
}
Response Field Details:
Field Name | Data Type | Description |
---|---|---|
orderId | String | PG generated internal order id |
state | String | State of the order created, Expected value is CREATED |
expiryAt | Long | Order expiry date in epoch |
redirectUrl | String | Url where merchant is supposed to redirect user to complete payment |
intentUrl | String | Intent url (Present in case of UPI_INTENT or UPI_QR) |