Skip to main content

Documentation Index

Fetch the complete documentation index at: https://waffo.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

Each Webhook request header includes X-SIGNATURE, which is signed using the Waffo private key. Merchants must use the Waffo public key to verify the signature.

Get the Waffo public key

Log in to Merchant PortalIntegration menu to view and copy the Waffo public key.
Dev or Admin role permissions are required to access this page.
The SDK’s handleWebhook() method automatically performs signature verification, event parsing, routing, and response signing:
app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
  const body = req.body.toString();
  const signature = req.headers['x-signature'] as string;

  const result = await waffo.webhook().handleWebhook(body, signature);

  res.setHeader('X-SIGNATURE', result.responseSignature);
  res.setHeader('Content-Type', 'application/json');
  res.status(200).send(result.responseBody);
});

Manual verification

If you need to handle this manually (without the SDK), the verification steps are:
1

Get the signature

Get X-SIGNATURE from the request header.
2

Get the raw body

Get the raw request body string (do not JSON parse and then stringify).
3

Verify the signature

Use the Waffo public key + SHA256WithRSA to verify the signature.
4

Process the event

Process the event after the signature verification passes.
5

Sign the response

You must set the X-SIGNATURE header in the response (sign the response body with the merchant private key).

Manual examples

import { createVerify, createSign } from 'crypto';

function verifyWaffoSignature(body: string, signature: string): boolean {
  const verify = createVerify('SHA256');
  verify.update(body);
  return verify.verify(process.env.WAFFO_PUBLIC_KEY!, signature, 'base64');
}

function signResponse(responseBody: string): string {
  const sign = createSign('SHA256');
  sign.update(responseBody);
  return sign.sign(process.env.MERCHANT_PRIVATE_KEY!, 'base64');
}

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const body = req.body.toString();
  const signature = req.headers['x-signature'] as string;

  if (!verifyWaffoSignature(body, signature)) {
    const failedBody = JSON.stringify({ message: 'failed' });
    res.setHeader('X-SIGNATURE', signResponse(failedBody));
    return res.status(200).send(failedBody);
  }

  // Process the event...

  const successBody = JSON.stringify({ message: 'success' });
  res.setHeader('X-SIGNATURE', signResponse(successBody));
  res.status(200).send(successBody);
});

Notes

  • You must verify the signature before processing the event. Do not respond first and then verify.
  • The response must include the X-SIGNATURE header, otherwise Waffo will treat the delivery as failed.
  • Verify the signature using the raw request body; do not JSON parse and then stringify.
  • The SDK provides a complete webhook handling pipeline. Using the SDK is recommended over manual handling.