Webhooks

Implement webhooks to receive real-time notifications about payment events. This guide will help you set up and secure your webhook endpoints.

What Are Webhooks?

Webhooks are HTTP callbacks that notify your server when events occur in the Altafinex system. Instead of polling for payment status, webhooks push updates to you in real-time.

Benefits
  • Real-time notifications without polling
  • Reduced server load and API calls
  • Better user experience with instant updates
  • Automatic retry mechanism for failed deliveries

Available Events

Payment Events
payment.succeeded

Payment completed successfully

payment.failed

Payment was declined or failed

payment.pending

Payment is being processed

Refund Events
refund.completed

Refund has been processed

refund.failed

Refund could not be processed

Webhook Payload

Example Payload
Structure of webhook events
{
  "event": "payment.succeeded",
  "data": {
    "payment_id": "pay_1234567890abcdef",
    "status": "succeeded",
    "amount": 10000,
    "currency": "THB",
    "created_at": "2024-01-15T10:30:00Z"
  },
  "timestamp": "2024-01-15T10:30:15Z"
}

Implementation Examples

Node.js / Express

const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.raw({ type: 'application/json' }));

app.post('/webhooks/payment', (req, res) => {
  const signature = req.headers['x-altafinex-signature'];
  const secret = process.env.WEBHOOK_SECRET;
  
  // Verify signature
  const hmac = crypto.createHmac('sha256', secret);
  const computedSignature = hmac.update(req.body).digest('hex');
  
  if (signature !== computedSignature) {
    return res.status(401).send('Invalid signature');
  }
  
  const event = JSON.parse(req.body);
  
  // Process the event
  switch (event.event) {
    case 'payment.succeeded':
      // Handle successful payment
      break;
    case 'payment.failed':
      // Handle failed payment
      break;
  }
  
  res.status(200).send('OK');
});

Python / Flask

from flask import Flask, request
import hmac
import hashlib

app = Flask(__name__)

@app.route('/webhooks/payment', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Altafinex-Signature')
    secret = os.environ.get('WEBHOOK_SECRET')
    
    # Verify signature
    computed_signature = hmac.new(
        secret.encode(),
        request.data,
        hashlib.sha256
    ).hexdigest()
    
    if signature != computed_signature:
        return 'Invalid signature', 401
    
    event = request.get_json()
    
    # Process the event
    if event['event'] == 'payment.succeeded':
        # Handle successful payment
        pass
    
    return 'OK', 200

Security: Signature Verification

Critical: Always Verify Signatures

Never process webhook events without verifying the signature. This prevents malicious actors from sending fake events to your endpoints.

How Signatures Work

Each webhook request includes an X-Altafinex-Signature header containing an HMAC-SHA256 signature of the raw request body.

To verify:

  1. Get the signature from the X-Altafinex-Signature header
  2. Compute HMAC-SHA256 of the raw request body using your webhook secret
  3. Compare the computed signature with the header value
  4. Only process the event if signatures match

Best Practices

Webhook Implementation Checklist
  • Verify Signatures

    Always verify webhook signatures before processing events

  • Idempotent Processing

    Process events idempotently to handle duplicate deliveries

  • Quick Response

    Return 200 OK quickly, then process the event asynchronously

  • Error Handling

    Log errors but return 200 OK to prevent retries for permanent failures

  • HTTPS Only

    Webhook URLs must use HTTPS and be publicly accessible

Testing Webhooks

Using Webhook Testing Tools

Use tools like ngrok or webhook.site to test webhooks locally during development.

ngrok:

Create a tunnel to your local server: ngrok http 3000

webhook.site:

Get a temporary webhook URL for testing without setting up a server