📃Webhook Integration

Overview

The PayLater system sends real-time webhook notifications to your backend when key events occur, such as transaction status updates. This ensures your platform stays in sync with the latest PayLater events.

⚠️ Important: To activate webhooks, merchants must share their Webhook Endpoint URL with PayLater and request their unique Webhook Secret from their account manager.

📥 Webhook Request

Webhook events are delivered as an HTTP POST request with a JSON payload.

Endpoint

You must expose a public POST endpoint to receive these requests.

Headers

  • Content-Type: application/json

Request Body

{
  "merchantId": "<merchant_id>",
  "orderId": "<order_id>",
  "paylaterRef": "PL1746499849330726",
  "status": "<status>",
  "timestamp": "<timestamp>",
  "signature": "<signature>",
  "txHash": "<tx_hash>",
  "comments": "<comments>"
}

Parameter Descriptions

Field

Type

Description

merchantId

String

Unique identifier for the merchant

orderId

String

Unique identifier for the order

status

String

Status of the order (e.g., success, failed, pending)

timestamp

Long

Epoch timestamp of the request

signature

String

HMAC SHA-256 signature generated using txHash and the webhook secret

txHash

String

MD5 hash of the concatenated payload (merchantId + orderId + orderstatus + timestamp + comments)

comments

String

Optional comments or metadata

🔐 Security & Validation

To validate the webhook and ensure it's sent by PayLater:

  1. Reconstruct the Data String:

    • Concatenate merchantId + orderId + status + timestamp + comments

    • Convert the whole string to uppercase

    • Generate an MD5 hash of this string and compare it with the provided txHash

  2. Validate Signature:

    • Use HMAC SHA-256 with your merchantWebhookSecret

    • Hash the txHash value

    • Compare the result with the signature field from the request

✅ Sample Node.js Verification

const crypto = require('crypto');

const verifyWebhook = (req) => {
  const { merchantId, orderId, status, timestamp, txHash, signature, comments } = req.body;
  const data = `${merchantId}${orderId}${status}${timestamp}${comments}`.toUpperCase();
  const computedTxHash = crypto.createHash('md5').update(data).digest('hex');
  if (computedTxHash !== txHash) return false;
  const computedSignature = crypto.createHmac('sha256', process.env.WEBHOOK_SECRET)
                                  .update(txHash)
                                  .digest('hex');
  return computedSignature === signature;
};

✅ Sample PHP Verification

$MERCHANT_SECRET = "your_webhook_secret";
$request = json_decode(file_get_contents("php://input"), true);
$dataString = strtoupper($request['merchantId'] . $request['orderId'] . $request['status'] . $request['timestamp'] . $request['comments']);
$computedTxHash = md5($dataString);
$computedSignature = hash_hmac("sha256", $computedTxHash, $MERCHANT_SECRET);
if ($computedSignature === $request['signature']) {
  http_response_code(200);
  echo json_encode(["message" => "Webhook received successfully"]);
} else {
  http_response_code(403);
  echo json_encode(["message" => "Invalid signature"]);
}

Last updated