Handle Webhooks with .NET SDK
Use callback verification to confirm that the callback you received from PhonePe is authentic.
Request
Request Parameters
| Parameter Name | Data Type | Mandatory (Yes/NO) | Description |
username | String | Yes | Your unique username configured for the callback URL |
password | String | Yes | Your unique password configured for the callback URL |
authorization | String | Yes | Value of the Authorization header under the callback response. |
responseBody | String | Yes | The response body received in the callback as a string |
Sample Request
string authorizationHeaderData = "ef4c914c591698b268db3c64163eafda7209a630f236ebf0eebf045460df723a" // received in the response headers
string phonepeS2SCallbackResponseBodyString = @"{
""event"": ""pg.order.completed"",
""payload"": {
""orderId"": ""OMOxx"",
""merchantId"": ""merchantId"",
""merchantOrderId"": ""merchantOrderId"",
""state"": ""EXPIRED"",
""amount"": 10000,
""expireAt"": 1291391291,
""metaInfo"": {
""udf1"": """",
""udf2"": """",
""udf3"": """",
""udf4"": """",
""udf5"": """"
},
""paymentDetails"": [
{
""paymentMode"": ""UPI_COLLECT"",
""timestamp"": 12121212,
""amount"": 10000,
""transactionId"": ""OM12333"",
""state"": ""FAILED"",
""errorCode"": ""AUTHORIZATION_ERROR"",
""detailedErrorCode"": ""ZM"",
""splitInstruments"": [
{
""rail"": {
""type"": ""PPI_EGV""
},
""instrument"": {
""type"": ""CREDIT_CARD"",
""bankTransactionId"": ""bankTransactionId"",
""bankId"": ""bankId"",
""brn"": ""brn"",
""arn"": ""arn""
},
""amount"": 10000
}
]
}
]
}
}"; // callback body as string
var usernameConfigured = "<MERCHANT_USERNAME>"
var passwordConfigured = "<MERCHANT_PASSWORD>"
CallbackResponse callbackResponse = checkoutClient.ValidateCallback(usernameConfigured, passwordConfigured, authorizationHeaderData, phonepeS2SCallbackResponseBodyString);
var orderId = callbackResponse.payload.orderId;
var state = callbackResponse.payload.state;Response
- The function returns a
CallbackResponseobject containing two main parameters:type, which indicates the event type, andpayload, which holds all the event-specific details.
| Parameter Name | Data Type | Description |
event | String | Contains event of callback received at the merchant end. |
payload | CallbackData | Contains all the details related to that event |
- The
CallbackDataare explained below:
| Property | Type | Description |
merchantId | String | The merchant from which request was initiated |
orderId | String | Order id generated by PhonePe (Only present in case of order callbacks) |
merchantOrderId | String | Order id generated by merchant (Only present in case of order callbacks) |
originalMerchantOrderId | String | Order id generated by merchant (Only present in case of refund callback) |
refundId | String | Refund id generated by PhonePe (Only present in case of refund callback) |
merchantRefundId | String | Refund id generated by merchant (Only present in case of refund callback) |
state | String | State of the ORDER/REFUND |
amount | | Amount in Paisa of the order/refund processed |
expireAt | Long | Expiry in epoch |
errorCode | String | Error code. (Only present when state is failed) |
detailedErrorCode | String | Detailed error code. (Only present when state is failed) |
metaInfo | MetaInfo | Additional Information about the order |
paymentDetails | List<PaymentDetail> | Contain list of details of each transaction attempt made corresponding to this particular order |
- The
property contains a list of payment details for each payment attempt made against an order. The details of each payment are explained in the table below.paymentDetails
| Attribute | Data Type | Description |
transactionId | String | Merchant ID from which the request was initiated. |
paymentMode | String | Order ID generated by PhonePe Payment Gateway (only for order callbacks). |
timestamp | Long | Order ID generated by you (only for order callbacks). |
state | String | Attempted transaction state. It can be any one of the following states: • COMPLETED • FAILED • PENDING |
errorCode | String | Error code (only present when the state is failed). |
detailedErrorCode | String | A more specific error code (only present when the state is failed). |
rail | PaymentRail | Contains processing rail details under which transaction attempt is made. |
instrument | PaymentInstrumentV2 | Contains instrument details of that particular transaction ID |
Exception Handling
Exception handling in the PhonePe SDK is managed through the PhonePeException, which captures errors related to PhonePe APIs. It provides detailed information such as HTTP status code, error code, message, and additional error data to help identify and resolve issues effectively.
PhonePeException
Exception raised for errors related to PhonePe APIs.
| Attribute | Type | Description |
code | String | The status code of the http response. |
message | String | The http error message. |
httpStatusCode | Integer | The status code of the http response. |
data | Map<String, String> | The details of the error that happened while calling PhonePe API. |
Sample Request
var merchantOrderID = Guid.NewGuid().ToString();
var payRequest = StandardCheckoutPayRequest.Builder()
.SetMerchantOrderId(merchantOrderID)
.SetAmount(100)
.SetRedirectUrl("https://www.merchant.com/redirect")
.SetExpireAfter(300)
.SetPaymentModeConfig(paymentModeConfig)
.SetMessage("message")
.Build();
try
{
StandardCheckoutPayResponse response = await checkoutClient.Pay(payRequest);
logger.LogInformation("Pay API Response:\n{Response}", JsonSerializer.Serialize(response, JsonOptions.IndentedWithRelaxedEscaping));
}
catch (Exception ex)
{
logger.LogError(ex);
}Response Models for Reference
- PaymentRail
- Represents different types of rail which will be received at the time of
getOrderStatus(). It falls under therailattribute in PaymentDetail Object
- Represents different types of rail which will be received at the time of
UPI RAIL
| Property | Type |
type | PaymentRailType |
utr | String |
upiTransactionId | String |
vpa | String |
PG RAIL
| Property | Type |
type | PaymentRailType |
transactionId | String |
authorizationCode | String |
serviceTransactionId | String |
PPI_WALLET RAIL
| Property | Type |
type | PaymentRailType |
PPI_EGV RAIL
| Property | Type |
type | PaymentRailType |
- PaymentRail
- Defines the type of rail used to initiate payment.
UPI RAIL
| Property | Type |
type | PaymentRailType |
utr | String |
upi_transaction_id | String |
vpa | String |
PG RAIL
| Property | Type |
| PaymentRailType |
| String |
| String |
| String |
- PaymentInstrumentV2
- Represents different types of instruments which will be received at the time of
getOrderStatus(). It falls under theinstrumentattribute in PaymentDetail Object
- Represents different types of instruments which will be received at the time of
ACCOUNT
| Property | Type |
| PaymentInstrumentType |
| String |
| String |
| String |
account_holder_name | String |
CREDIT_CARD
| Property | Type |
| PaymentInstrumentType |
| String |
| String |
| String |
brn | String |
DEBIT_CARD
| Property | Type |
| PaymentInstrumentType |
| String |
| String |
| String |
brn | String |
NET_BANKING
| Property | Type |
| PaymentInstrumentType |
| String |
| String |
| String |
brn | String |
EGV
| Property | Type |
| PaymentInstrumentType |
| String |
| String |
WALLET
| Property | Type |
| PaymentInstrumentType |
| String |
What’s Next?
Now that you have learned how to verify the payment and what happens when the webhook fails, this concludes your website integration. The next step is to complete UAT testing and understand the process to go live.