๐ก What are the webhooks?
Webhooks are a powerful way to receive real-time notifications from our API about specific events. When certain events occur, such as a payment transaction, our system will send an HTTP POST request to a URL you've provided, allowing you to react to the event in your application. Let's dive into the webhook payload structure:
๐จ Request Headers
When setting up your webhook endpoint, make sure to handle incoming HTTP POST
requests and consider including the following headers to handle the payload correctly:
Content-Type: application/json
- Indicates that the request payload is in JSON format.
๐ Request Body Example
{
"RRN": "3524703829728",
"Type": "JustPay",
"Payer": {
"Phone": null,
"FullName": null
},
"Token": "B91LLM0TEST64349UP1B0A670",
"Amount": 51.5,
"Refund": {
"RefundId": 1234,
"Status": "Processed",
"Amount": null,
"Revisions": [],
"RejectReason": null,
"RefundDate": 638123241242235100,
"RefundDateIso": "2023-12-22T06:42:04.223587Z",
"Refundable": true,
"RequestedAmount": null
},
"Source": "Card",
"Splits": [
{
"Iban": "GE65BG0000000000000000",
"PayIn": 0,
"Amount": 35,
"Status": "Draft",
"Description": "Split Funds (ID:99D4DDCC4TEST12BB260418C42A6912A); ",
"CashOutOrder": []
}
],
"Sandbox": false,
"CardMask": "415479xxxxxx4768",
"Currency": "GEL",
"Metadata": {
"Order": {
"OrderId": null,
"AdvanceContactId": null,
"OrderItems": null,
"BillingAddress": {
"City": null,
"Line1": null,
"Line2": null,
"State": null,
"Country": null,
"LastName": null,
"FirstName": null,
"PostalCode": null,
"PhoneNumber": null
},
"ShippingAddress": {
"City": null,
"Line1": null,
"Line2": null,
"State": null,
"Country": null,
"LastName": null,
"FirstName": null,
"PostalCode": null,
"PhoneNumber": null
},
"UzRegulatoryOrderDetails": {
"TaxiTin": null,
"Latitude": null,
"Longitude": null,
"TaxiPinfl": null,
"TaxiVehicleNumber": null
}
},
"Channel": null,
"ExtraAttributes": [
{
"Key": "API_VERSION",
"Value": "V1",
"Description": ""
}
]
},
"BlockDate": 638381923066765000,
"CardBrand": "Visa",
"PaymentId": "2TEST21AF2DTESTDA14L2E05A",
"CardHolder": null,
"Commission": null,
"CreateDate": 638381922898406900,
"CaptureDate": null,
"CardCountry": null,
"FinalAmount": 51.5,
"CanBeCaptured": true,
"PaymentStatus": "Blocked",
"Preauthorized": true,
"ExpirationDate": "2706",
"IdempotencyKey": null,
"CardOrigination": "Off-Us",
"RejectionReason": null,
"CardOwnerEntityType": null
}
๐ Parsing Payment Statuses
You can parse the PaymentStatus field to determine the status of the payment transaction. Here are the possible payment statuses:
Transaction Status | Description |
---|---|
Draft | When the transaction is created and waiting for card details for the next action. |
Blocked | The funds have been successfully blocked on the card. Usually, this means you have used preauthorize: True Transactions with Blocked statuses need to be committed within 30 days, otherwise, they will be refunded automatically. |
Captured | The funds have been captured successfully from the cardholder. |
Refunded | The transaction has been refunded fully. |
PartiallyRefunded | The transaction amount has been refunded partially. |
Rejected | The transaction was rejected, because of different reasons. |
๐ป Example: Parsing Payment Statuses in Python
import json
# Sample JSON response
response_json = '{"data": {"PaymentStatus": "Draft", ...}, "status": {"message": null, "errors": null, "type": null}}'
response_dict = json.loads(response_json)
payment_status = response_dict['data']['PaymentStatus']
if payment_status == 'Draft':
print("Transaction is in draft status, awaiting card details.")
elif payment_status == 'Blocked':
print("Funds have been blocked on the card, ready for capture.")
# ... similar checks for other payment statuses
๐ Webhook Security Enhancements (Optional)
For an additional layer of security, you can validate webhook requests using HMAC signatures.
๐ Note: To enable this security layer for your company, please contact us and request activation.
Follow the steps below:
Step 1: Retrieve the HMAC Signature from the Header
Extract the HMAC signature from the X-HMAC-Signature header of the incoming request.
string suppliedSignature = Request.Headers["X-HMAC-Signature"];
Step 2: Compute the HMAC Signature
Using the shared secret key and the request payload, compute the HMAC signature.
string secretKey = "Your Secret Key"; // Replace with your actual secret key
string payload = JsonConvert.SerializeObject(requestData); // `requestData` is the POST request body
string computedSignature = GenerateHmacSignature(payload, secretKey);
private string GenerateHmacSignature(string data, string secretKey)
{
var secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
var dataBytes = Encoding.UTF8.GetBytes(data);
using var hmac = new HMACSHA256(secretKeyBytes);
var signatureBytes = hmac.ComputeHash(dataBytes);
var signature = BitConverter.ToString(signatureBytes).Replace("-", string.Empty).ToLower();
return signature;
}
Step 3: Compare Both Signatures
Validate the request by comparing the computed HMAC signature with the signature in the header.
if (suppliedSignature == computedSignature)
{
// Request is verified and valid
}
else
{
// Request is not valid
}
By following these guidelines, you can efficiently integrate and secure your webhook endpoints while handling events from our API.