Webhook Handling
PhonePe Payment Gateway uses Webhook (S2S Callbacks) to notify you about key events like payment completion or refund status. Here’s how it works:
- You need to provide a Webhook URL (a specific endpoint on your server) where these updates will be sent.
- To ensure secure communication, you should set up a username and password for authentication.
Webhook Setup
- Configure Webhook: Follow these steps to set up a new webhook for receiving event notifications.
- Log in to your PhonePe Business Dashboard.
- Set the environment mode using the Test Mode toggle located on the dashboard.
- For Sandbox (Testing): Ensure the toggle is switched ON.
- For Production (Live): Ensure the toggle is switched OFF.
- Navigate to Developer Settings from the side menu.
- Select the Webhook tab and click the Create Webhook button.
- In the configuration form, fill in the following details:
- Webhook URL: Your server’s endpoint URL to receive notifications.
- Username: Your authentication username.
- Password: Your authentication password.
- Description: A brief description for your reference.
- From the list of active events, choose:
pg.order.completed: Order reachesCOMPLETEDstate (capture successful).pg.order.failed: Order reachesFAILEDstate (authorization failed, capture failed, or cancelled).pg.transaction.failed: A transaction attempt fails while order is stillPENDING(e.g., authorization failure with retries remaining).
- Click Create to save and complete the configuration.
- Your webhook is now active.
- Authorization.
- Once configured, PhonePe Payment Gateway will send updates to your server using the provided username and password.
- These credentials will be used to create an Authorization header in the webhook response using SHA256 (username:password) method.
- Verification.
- For the incoming request, extract the header Authorization, verify it with the one which you have shared with us and accept the response if the Username and password match.
- If the hash matches the one sent by PhonePe Payment Gateway, the update is valid, and the response payload can be consumed.
- If it doesn’t match, the response should be ignored.
Response
Event: pg.transaction.authorized
{
"type": "PG_TRANSACTION_ATTEMPT_AUTHORIZED",
"event": "pg.transaction.authorized",
"payload": {
"merchantId": "M_001",
"merchantOrderId": "ORDER_123456",
"orderId": "OMO2506...",
"state": "PENDING",
"currency": "INR",
"amount": 10000,
"expireAt": 1750000000000,
"paymentDetails": [
{
"transactionId": "OMT2506...",
"paymentMode": "UPI_INTENT",
"state": "AUTHORIZED",
"amount": 0,
"currency": "INR",
"authAmount": 10000,
"authCurrency": "INR",
"payableCurrency": "INR",
"payableAmount": 0,
"feeCurrency": "INR",
"feeAmount": 0,
"timestamp": 1749999000000,
"instrument": {
"type": "ACCOUNT",
"processingRail": "UPI"
},
"rail": {
"type": "UPI"
}
}
]
}
}