Webhooks
Receive real-time notifications for events like payment completions.
What Are Webhooks?
Webhooks are automated messages sent from one server to another when a specific event occurs. In the context of CashPay, our servers will "push" a notification to an endpoint on your server (your `webhookUrl`) when a transaction's status changes.
This is the most reliable way to confirm a payment. While your customer is redirected back to your `redirectUrl` after payment, they might close their browser before this happens. A webhook ensures your backend is always notified, allowing you to reliably fulfill orders or grant access to services.
Server-to-Server Communication
Securing Your Webhooks
To ensure that incoming webhook requests are genuinely from CashPay and not from a malicious third party, you must verify their signature. This is where your **API Secret** is used.
API Secret for Verification
Signature Verification Flow
- CashPay sends a request to your webhook endpoint. The request includes a special header, `X-CashPay-Signature`.
- Your server receives the raw request body (as a string).
- Using your API Secret, you create a HMAC-SHA256 signature of the raw request body.
- You compare your generated signature with the one in the `X-CashPay-Signature` header.
- If they match, you can trust the request and process it. If not, you must discard it.
Pseudo-code for Signature Verification
const crypto = require('crypto');
// The secret you get from your dashboard
const cashpayApiSecret = process.env.CASHPAY_API_SECRET;
// The raw request body from the webhook
const requestBody = JSON.stringify(webhookPayload);
// The signature sent in the request header
const signatureFromHeader = request.headers['X-CashPay-Signature'];
const generatedSignature = crypto
.createHmac('sha256', cashpayApiSecret)
.update(requestBody)
.digest('hex');
if (generatedSignature === signatureFromHeader) {
// The request is authentic, process it
console.log('Webhook verified successfully!');
} else {
// The request is not authentic, ignore it
console.error('Webhook verification failed!');
}Webhook Events & Payloads
Here are examples of the JSON payloads your webhook endpoint will receive for different events.
event: `payment.succeeded`
Sent when a payment initiated via the gateway is successfully completed.
Payload for a Successful Payment
{
"event": "payment.succeeded",
"data": {
"reference": "ORDER-XYZ-123",
"amount": 120.50,
"currency": "USD",
"status": "completed",
"cashpay_transaction_id": "PAY_xxxxxxxxxxxx",
"customer": {
"name": "John Doe",
"email": "john.doe@example.com"
}
}
}event: `payment.failed`
Sent when a payment fails or is declined by the processor.
Payload for a Failed Payment
{
"event": "payment.failed",
"data": {
"reference": "ORDER-XYZ-456",
"amount": 55.00,
"currency": "USD",
"status": "failed",
"failure_reason": "Insufficient funds."
}
}Responding to Webhooks
To acknowledge that you have received the webhook, your endpoint must return a `200 OK` HTTP status code. If our servers do not receive a `200 OK` response, we will retry sending the webhook several times over the next 24 hours.
It is important that your endpoint responds quickly. For long-running processes (like updating an order and sending an email), it's best practice to immediately respond with a `200 OK` and then handle the logic asynchronously in a background job.