Webhooks Integration

Receive real-time payment notifications and updates with ZenPay Webhooks.

Last updated: July 15, 2023
Next: Testing Guide

What are Webhooks?

Webhooks allow ZenPay to send real-time notifications to your application when events occur, such as successful payments, refunds, or subscription updates. This enables your application to take appropriate actions automatically in response to these events.

Setting up Webhooks

Follow these steps to integrate ZenPay webhooks with your application:

1

Create a webhook endpoint

First, create an endpoint on your server that will receive webhook events from ZenPay. This endpoint should be publicly accessible and respond with a 2xx status code.

Express.js Example
// Express.js example
app.post('/webhooks/zenpay', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['zenpay-signature'];
  
  try { 
    const event = zenpay.webhooks.constructEvent(
      req.body,
      signature, 
      process.env.WEBHOOK_SECRET 
    ); 
    
    // Handle the event
    switch (event.type) {
      case 'payment.succeeded':
        // Handle successful payment
        break;
      case 'payment.failed':
        // Handle failed payment
        break;
      // ... handle other event types
      default: 
        console.log(`Unhandled event type ${event.type}`);
    }
    
    res.status(200).send();
  } catch (err) {
    console.log(`Webhook error: ${err.message}`);
    res.status(400).send(`Webhook Error: ${err.message}`);
  }
});
2

Register your endpoint in the dashboard

Go to the ZenPay Dashboard and navigate to Developers → Webhooks. Add your endpoint URL and select the events you wish to receive.

Screenshot of webhook setup in the dashboard
[Webhook dashboard configuration screenshot]
3

Secure your webhook endpoint

ZenPay signs webhook events it sends to your endpoints by including a signature in thezenpay-signature header. Verify this signature to ensure the event was sent by ZenPay and not by a third party.

Python Example
# Python example
@app.route('/webhooks/zenpay', methods=['POST']) 
def handle_webhook():
    payload = request.data
    sig_header = request.headers.get('zenpay-signature')
    
    try:
        event = zenpay.Webhook.construct_event(
            payload, sig_header, webhook_secret
        )
        # Handle the event...
        return '', 200
    except ValueError as e:
        # Invalid payload
        return '', 400
    except zenpay.error.SignatureVerificationError as e:
        # Invalid signature
        return '', 400
4

Test your webhooks

Use the ZenPay Dashboard to send test events to your endpoint. This helps you verify that your integration works correctly before going live with real payments.

Webhook Events

ZenPay sends events for various actions and state changes. Here are the most common events you might want to handle:

payment.succeeded

Sent when a payment is successfully processed and confirmed.

payment.failed

Sent when a payment attempt fails for any reason.

payment.refunded

Sent when a payment is refunded, either partially or fully.

payment.pending

Sent when a payment is created but waiting for confirmation.

checkout.completed

Sent when a customer completes the checkout process.

subscription.created

Sent when a new subscription is created.

Best Practices

Acknowledge receipt quickly

Return a 2xx status code immediately before processing the webhook event. If ZenPay doesn't receive a 2xx response within 10 seconds, it will retry the webhook.

Always verify signatures

Always verify webhook signatures to ensure that events are coming from ZenPay and not from a malicious third party.

Handle idempotency

Design your webhook handler to be idempotent, as the same webhook event might be sent multiple times due to network issues or retry attempts.

Handle concurrency

Webhook events might arrive out of order or in parallel. Make sure your application can handle concurrent webhook requests correctly.

Next Steps

Now that you've set up webhooks, learn how to test your integration thoroughly:

Was this helpful?