INSTANT NOTIFICATIONS
Webhook Callback Documentation
Webhooks allow your server to receive real-time HTTP POST notifications as soon as an incoming UPI transaction is matched and verified by Qolor Pay.
1. How Webhooks Work
Understand the automated event lifecycle when a customer makes a payment:
- A customer scans the Dynamic QR code and completes payment via any UPI app (GPay, PhonePe, Paytm, etc.).
- Qolor Pay validates the incoming UPI UTR reference number in real-time.
- Our backend triggers an HTTP POST request sending payment data directly to your saved Webhook URL.
- Your endpoint verifies the data, updates the order status in your database, and replies with an HTTP
200 OKresponse.
2. Webhook Payload Structure
Qolor Pay delivers the following 4 parameters in the POST payload body:
| Field Name | Type | Description |
|---|---|---|
| status | String | Payment status confirmation (e.g. SUCCESS, COMPLETED). |
| order_id | String | The unique Order ID passed during your initial order creation request. |
| amount | Numeric | The exact amount paid by the customer in INR. |
| utr | String | The 12-digit Unique Transaction Reference (UTR) generated by the bank/UPI network. |
EXAMPLE POST PAYLOAD (JSON / Form Data)
application/json or application/x-www-form-urlencoded
{
"status": "SUCCESS",
"order_id": "ORD_982348234",
"amount": "399.00",
"utr": "423456789012"
}
3. Demo Receiver Script (PHP)
Use this complete implementation file as a blueprint for your webhook.php receiver:
webhook.php
PHP Implementation
<?php
// Set headers for standard JSON response
header('Content-Type: application/json');
// 1. Capture incoming payload (Supports both JSON and POST form data)
$raw_input = file_get_contents('php://input');
$data = json_decode($raw_input, true);
if (!$data) {
$data = $_POST;
}
// 2. Extract the four key fields
$status = isset($data['status']) ? trim($data['status']) : '';
$order_id = isset($data['order_id']) ? trim($data['order_id']) : '';
$amount = isset($data['amount']) ? trim($data['amount']) : '';
$utr = isset($data['utr']) ? trim($data['utr']) : '';
// 3. Basic validation
if (empty($status) || empty($order_id) || empty($amount) || empty($utr)) {
http_response_code(400);
echo json_encode(["status" => false, "message" => "Missing required webhook parameters."]);
exit();
}
// 4. Verify payment status
if ($status === 'SUCCESS' || $status === 'COMPLETED') {
/*
* DATABASE LOGIC HERE:
* 1. Query your database to find the order by $order_id
* 2. Verify that the order is still in 'PENDING' status (prevents double fulfillment)
* 3. Verify that the received $amount matches the expected order amount
* 4. Update the order status to 'SUCCESS', save the $utr number, and credit the user/service
*
* Example:
* $stmt = $db->prepare("UPDATE orders SET status='PAID', utr=? WHERE order_id=? AND amount=?");
* $stmt->execute([$utr, $order_id, $amount]);
*/
// 5. Always respond with 200 OK to acknowledge receipt
http_response_code(200);
echo json_encode(["status" => true, "message" => "Webhook processed successfully."]);
exit();
} else {
// Handle failed or cancelled transactions
http_response_code(200);
echo json_encode(["status" => false, "message" => "Transaction marked unfulfilled."]);
exit();
}
?>
Security Best Practice: Always check whether an order has already been marked as PAID before granting user credits or shipping items to protect against duplicate webhook events.