# Webhooks

WARNING

Not all REST API endpoints are available to all users. If you need access to functionality like charge creation, please contact us through the dashboard(opens new window)

If you would like to get notified upon charge completion without manually requesting charge info via the REST API, you can set up a webhook in the dashboard or use callbacks. The webhook is an HTTP endpoint that receives notifications.

There are two types of notifications: Webhooks and Callbacks.

Webhooks Callbacks
Trigger Charge completion Charge completion
How to setup Create in the dashboard Pass notifyUrl and notifyPayload parameters during charge creation
Authenticating the request Basic auth is used An RSA signature is sent along with the payload
Requirements Setup webhooks in dashboard Specify required params during charge creation and generate a certificate in the api keys tab in the dashboard

# Webhooks

Webhooks can be created in the merchant dashboard.

Parameters Description
url The endpoint to receive notification
username and password Used to perform request with HTTP Basic Auth(opens new window)

If you wish to pass additional data to webhook request you may use the notifyPayload parameter in checkout url. e.g.


 

https://checkout.xanpay.com/?apiKey=17ea5278c9acbdcc7420bf3be210ca1d&amount=100&currency=SGD
    &notifyPayload=somePayload

Or in the POST /charges request

notifyPayload will be sent to the webhook endpoint along with the other charge data.

# Callbacks

To use callbacks please make sure you have generated a certificate in the dashboard in api keys tab. Private key of this certificate will be used to sign payload in callback request.

To setup callbacks it's necessary to specify notifyUrl and notifyPayload params in checkout url e.g.


 
 

https://checkout.xanpay.com/?apiKey=17ea5278c9acbdcc7420bf3be210ca1d&amount=100&currency=SGD
    &notifyPayload=somePayload
    &notifyUrl=https://webhook.site/7f014519-30dc-4f0f-9fd8-d03798e69ff8

Or in the POST /charges request

# Request format

Webhooks and callbacks both are HTTP POST requests.

Body example:

{
  "merchantId": "605015227b87ad0011c63549",
  "timestamp": 1618226757.504,
  "chargeId": "609c80f6a5b44800116d7c16",
  "message": "CHARGE_COMPLETE",
  "payload": { 
      "chargeId": "609c80f6a5b44800116d7c16",
      "merchantId": "605015227b87ad0011c63549",
      "customerCurrency": "SGD",
      "merchantAmount": 100, 
      "merchantCurrency": "SGD",
      "status":"completed", 
      "paymentMethod": "paynow", 
      "orders": [
          {
            "id":"unique-phone-id",
            "name":"Phone",
            "quantity":1,
            "amount":100,
            "currency":"SGD"
          }
      ]
  },
  // `signature` is provided with Callback requests for authentication
  "signature": "eDHwjHB0TJql2O98E01bUcNZ6aLjH4ugZIw2eeT3a+7xtA0VYTQE6VpnKvkjQG0QlBDGNelfztI0FJ+8hIHsxNW2gK0o+LoHlrBYyIFNbxIbU0DmWkxWyKJuoV9kOHADc+Xkl7DDlBYYgPB0WyJXHp9w9dSyW5LylKJTaf4GoQ83kKFxCYmz769PH1Vfc+d9eujkqGLLy4tAApZyLseGHcveMcKWcONltRXZChqtzCee5JKjI+ZkfBfeCDPRIM+hTLSUSgU13RQbv5oqAReyS9FXiCrNC2Xg6sgRsQ+btpx5HH5Z9e2WSLjTRrn+5inAkPqnteegs/s2xIeltV2jyA"
}

# Testing

You can test the webhooks you set up in the dashboard, to do that press "Send webhooks" button in the Webhooks section.
Another way is to create a charge in sandbox mode and complete it manually on the charge details page. We will notify your webhooks as soon as the charge is completed.

# Authenticating with a signature

The signature parameter sent to callback endpoints is a base64 encoded RSA signature.

Verification examples:

Example of the public key format used in the examples below:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2JNXtYjaKmHY4XuMii6D
PI86/X1r3iBg7ujyG3bdpUuUpKkrYkEvVo1aUTVPWTQ8XipAukldEZhhdJZkCbot
ZGN5G/oZNhTM6kg83q+iHTahYjZhI6sFUIjpqHNLsTkCNsAPkxVcX59rlzSySwPg
Yi3lPMj5l91Lw7eS59Std1P9XuDoWMjo8eh11z0oaWYXwiaYRJtWU+8jYe3M5iwJ
ljgxpLAwxp+YIsRAbNxr5YkJwGb774Ux4gBH6DsQY6HTmdlOLYsjcj4qdvzVTBhy
91gvsn4Qw1lz32L74pVEuwCP0MaMJeqlPkPTD3r51jLsoUMDvKdLx7uVNUHG5lqD
DQIDAQAB
-----END PUBLIC KEY-----

PHP:

private function checkSignature($body, $publicKey) 
{
    $payload = $body['payload'];
    $signature = $body['signature'];
    return (bool)openssl_verify(
        $payload,
        base64_decode($signature),
        $publicKey, 
        OPENSSL_ALGO_SHA256
    );
}

JavaScript:

const crypto = require('crypto')

const verifySignature = (body, publicKey) => {
    const { signature, payload } = body;

    const verifier = crypto.createVerify('RSA-SHA256')
    verifier.update(payload, 'ascii')
    
    const publicKeyBuf = Buffer.from(publicKey, 'ascii')
    const signatureBuf = Buffer.from(signature, 'base64')
    return verifier.verify(publicKeyBuf, signatureBuf)
}