Partner Checklist (Standard)
UAT Sign-Off Process
Once integration is complete, Partners must share their UAT instance for end-to-end flow verification.
All issues identified during UAT must be fixed and verified by the Partner’s integration POC in the UAT environment itself.
✅ Sign-Off Criteria:
- All mandatory use cases must be successfully validated.
- The integration POC will provide UAT Sign-Off only after complete verification.
- The Partner must acknowledge the sign-off to receive Production credentials.
API Wise Checklist
The following checklist ensures all required scenarios are validated during integration for smooth UAT closure:
Authorization API
- The
expires_atparameter in the response should be used to determine token validity. - Option 1:
- Check whether the token is active or expired before every API request.
- If active, the same token can be reused.
- If expired, call the Authorization API to regenerate a new token and use it.
- Option 2:
- Set up a scheduler to regenerate a new token by calling the Authorization API 3 to 5 minutes before expiry of the existing token.
⚠️ Avoid Unnecessary Authorization Calls!
Do not call the Authorization API before every request. Always check and rely on the token expiry time.
Payment API
Request
Common Parameters
- merchantOrderId → A unique
merchantOrderIdmust be passed for every request. - expireAfter → Order expiry in seconds. If not passed, the default value will be applied.
- For Custom Checkout → Min = 300, Max = 5184000 (in seconds)
- amount → The value must be passed in paise (multiply the amount in INR by 100).
- udf → User-defined fields should be passed in
metaInfoonly if required. Currently, 5 fields are supported. Use only the fields needed and remove unused fields instead of passing empty values. - paymentFlow.type → Must be passed as PG.
UPI Intent Parameters
ℹ️ Available UPI Apps!
Only list UPI apps that are available on the user’s device.
- paymentFlow.paymentMode.type → Set this value to
UPI_INTENT - paymentFlow.paymentMode.targetApp →
- For Android → pass the package name of the UPI app chosen by the user.
- For iOS → pass the static app name of the UPI app chosen by the user.
- deviceContext.deviceOS → Pass
ANDROIDorIOSbased on the platform. - deviceContext.merchantCallBackScheme → [iOS only] Pass the URL schema of the merchant app.
UPI Collect Parameters
ℹ️ Validate VPA Before API Call!
Always validate the VPA entered by the user with the UPI Address Validate API before invoking this API. If the VPA is invalid, display an appropriate error message to the user.
- paymentFlow.paymentMode.type → Set this value to
UPI_COLLECT. - paymentFlow.paymentMode.details.type →
Set this value to.VPA - paymentFlow.paymentMode.details.vpa → Pass the customer’s VPA as entered.
UPI QR – Parameters
- paymentFlow.paymentMode.type → Set this value to
UPI_QR.
📘 QR Code Generation Guidance!
Can use either the intentUrl or the qrData received in the response to generate a QR code image and display it on the checkout page.
Card – Parameters
📘 PCI DSS Compliance Requirement!
Must be PCI DSS compliant in order to process payments using the Custom Card Flow.
- paymentFlow.paymentMode.type → Set this value to
CARD - cardDetails.encryptedCardNumber → Pass the 16-digit card number entered by the customer. This must be RSA-4096 encrypted using the provided Public Key.
- cardDetails.encryptionKeyId → Pass the numeric Key ID associated with the provided Public Key.
- cardDetails.expiry.month → Pass the card expiry month.
- cardDetails.expiry.year → Pass the card expiry year (4 digits).
- cardDetails.encryptedCvv → Pass the 3-digit CVV entered by the customer. This must be RSA-4096 encrypted using the provided Public Key.
- paymentFlow.merchantUrls.redirectUrl → Pass the Merchant’s redirection URL. The UI control will be returned to this URL once the payment is completed by the customer.
Token – Parameters
📘 PCI DSS Compliance Requirement!
Must be PCI DSS compliant in order to process payments using the Custom Card Flow.
- paymentFlow.paymentMode.type → Set this value to
TOKEN - tokenDetails.encryptedToken → Pass the token number entered by the customer. This must be RSA-4096 encrypted using the provided Public Key.
- tokenDetails.encryptionKeyId → Pass the numeric Key ID associated with the provided Public Key.
- tokenDetails.expiry.month → Pass the expiry month of the tokenised card.
- tokenDetails.expiry.year → Pass the expiry year of the tokenised card (4 digits).
- tokenDetails.encryptedCvv → Pass the 3-digit CVV entered by the customer. This must be RSA-4096 encrypted using the provided Public Key.
- tokenDetails.cryptogram → Pass the cryptogram generated and returned by the card network or gateway during tokenisation.
- tokenDetails.panSuffix → Pass the last four digits of the original card number.
- paymentFlow.merchantUrls.redirectUrl → Pass the Merchant’s redirection URL where UI control will return once the payment is completed by the customer.
NetBanking – Parameters
📘 Listing Supported Banks!
Should fetch the list of supported banks and their respective Bank IDs. Only these banks must be shown on the checkout page and routed to PhonePe.
- paymentFlow.paymentMode.type → Set this value to
NET_BANKING - paymentFlow.paymentMode.bankId → Pass the bankId corresponding to the bank selected by the customer.
- paymentFlow.merchantUrls.redirectUrl → Pass the Merchant’s redirection URL where UI control will return once the payment is completed by the customer.
Response
- orderId → In the Payment API response, PhonePe provides the orderId parameter which is the PhonePe-generated Order ID for that transaction. Map this orderId with the merchantOrderId passed in the request.
- redirectUrl → In the Payment API response for Card, Token, and NetBanking, the redirectUrl parameter contains the bank’s redirection URL. Redirect the customer to this URL on the browser. Ensure the URL shared by PhonePe is used exactly as received, without modification or truncation.
- intentUrl → In the Payment API response for UPI Intent or UPI QR, the intentUrl parameter contains the intent URL. Launch this URL on the UI. Ensure the URL shared by PhonePe is used exactly as received, without modification or truncation.
Order Status API
- Do not perform strict deserialization of the response payload.
- Always rely on the root-level
stateparameter for payment status confirmation. - Possible Values of
state- COMPLETED → Transaction is successful.
- FAILED → Transaction has failed.
- PENDING → Transaction is still in progress.
Handling the PENDING Scenario
If the state = PENDING, there are two possible approaches:
- Option 1:
- Mark the transaction as Failed on the UI and show the Payment Failure page.
- Continue to reconcile the transaction on the server side until a terminal status (COMPLETED or FAILED) is received.
- If the transaction is later marked as COMPLETED, initiate a Refund.
- Note: For this approach, it is highly recommended to integrate the Refund API.
- Option 2:
- Mark the transaction as Pending on the UI and show the Payment Pending page.
- Continue to reconcile the transaction on the server side until a terminal status (COMPLETED or FAILED) is received.
- If the transaction is later marked as COMPLETED, proceed with order fulfilment.
Order Status API – Reconciliation [Mandatory]
For PENDING transactions, the Order Status API must be called at the following intervals:
- First status check at 20–25 seconds after transaction start.
- Then, every 3 seconds for the next 30 seconds.
- Then, every 6 seconds for the next 60 seconds.
- Then, every 10 seconds for the next 60 seconds.
- Then, every 30 seconds for the next 60 seconds.
- Finally, every 1 minute until the transaction reaches a terminal state (COMPLETED or FAILED), or until the expireAfter value (from the request) is reached.
Webhook Handling
- Do not perform strict deserialization of the response payload.
- Always rely on the root-level
payload.stateparameter for payment status confirmation. - Do not use the
typeparameter in the webhook response (this will be deprecated). Instead, use theeventparameter as the webhook event identifier. expireAtandtimestampparameters are provided as epoch timestamps in milliseconds.
Security Validation [Mandatory]
- On receiving a webhook, calculate the Authorization header value using the formula:
SHA256(username:password) - Compare the computed value with the Authorization header received in the webhook request.
- Only if both values match, update the payment status.
- If the values do not match, treat the webhook as fraudulent and ignore it.
- In case of a mismatch, the Order Status API should be used to fetch the real-time transaction status.
Webhook APIs
- Currently, Partner-level Webhook is supported (Merchant-level webhook is not supported).
- Use the Webhook API to configure the webhook URL by providing the following:
- Webhook URL
- Username (Partner-defined)
- Password (Partner-defined)
- List of webhook events
- Ensure that duplicate webhooks are not configured.
- PhonePe provides APIs to List, Update, and Delete webhook configurations. Use these appropriately based on your integration needs.
Refund API
📘 Refund Processing through API!
Refunds can be initiated either through the Dashboard or by using the API. The following details apply only when the refund is initiated through the API.
- merchantRefundId → Always pass a unique ID for each refund request.
- originalMerchantOrderId → Pass the merchantOrderId used in the original Payment API request for which the refund is to be processed.
- amount → Pass the refund amount in paise (multiply the rupee value by 100).
- Once a refund is initiated, the initial state will be
PENDING. - The updated refund status can be obtained through:
- Webhook (async notification), and
- Refund Status API (active polling).
- Mandatory → Both Webhook handling and Refund Status API implementation are required to ensure accurate refund reconciliation.
Refund Status API
- Do not perform strict deserialization of the response payload.
- Always rely on the root-level
stateparameter for refund status confirmation. - If the
state=PENDINGorCONFIRMED:- Continue polling the Refund Status API using the merchantRefundId until a terminal state (
COMPLETEDorFAILED) is reached. - Configure a Scheduler/Cron Job as per your convenience for reconciliation.
- Do not initiate another refund for the same transaction while the current refund is still in PENDING or CONFIRMED state.
- Continue polling the Refund Status API using the merchantRefundId until a terminal state (
- If the
state=COMPLETED:- The refund has been processed successfully.
- If the
state=FAILED:- The refund request has failed.
- A new refund request must be initiated with a unique merchantRefundId.
Here’s a polished documentation-style version of your TSP Headers section with structured formatting:
TSP Headers
Prerequisites
- Web: Each end merchant must have a unique domain name.
- Example:
- Merchant A →
https://abc.test.com - Merchant B →
https://def.test.com
- Merchant A →
- Example:
- Android/iOS: Each end merchant must have their own Android or iOS app with a unique package name (Android) or bundle identifier (iOS).
Payment API
Common Headers
- Authorization → Token generated using Partner Credentials.
- X-MERCHANT-ID → The MID provided by PhonePe for the end merchant. This value differs for each merchant, and the correct MID must always be passed.
- X-SOURCE → Must be set to
API. - X-SOURCE-PLATFORM → The TSP Name provided by the Integration Team.
- Note: For Production, the Integration Team will share this value when Production credentials are released.
- X-SOURCE-CHANNEL → Dynamic value based on the platform where the transaction is initiated. Possible values:
web,android,ios. - X-MERCHANT-IP → The IP address of the end merchant system from where the request is initiated.
Additional Headers for Web
- X-BROWSER-FINGERPRINT → Dynamically generate the browser fingerprint from the customer’s browser.
- USER-AGENT → Dynamically capture the User Agent of the customer’s browser.
- X-MERCHANT-DOMAIN → Dynamically capture the merchant’s domain from where the transaction is initiated.
Additional Headers for Android
- X-SOURCE-CHANNEL-VERSION → Android OS version.
- X-MERCHANT-APP-ID → Package name of the merchant’s Android app.
Additional Headers for iOS
- X-SOURCE-CHANNEL-VERSION → iOS version.
- X-MERCHANT-APP-ID → Bundle ID of the merchant’s iOS app.
Other APIs
- For Order Status, Refund, and Refund Status APIs → Both Authorization and X-MERCHANT-ID headers are mandatory.
- For Webhook APIs → Only Authorization header is required. The X-MERCHANT-ID header is not needed.