Webhooks Setup

Implement and handle EcobankPay payment notifications

Overview

EcobankPay uses Instant Payment Notifications (IPNs) - also known as webhooks - to notify your application about payment events. These notifications are sent as HTTP POST requests to a URL you specify during the payment initiation.

Key benefits of implementing webhooks:

  • Real-time updates on payment status changes
  • Automated order processing workflows
  • Reduced need for status polling
  • Improved user experience with faster order confirmations

How EcobankPay Webhooks Work

  1. Setup: You provide an ipn_url parameter when initiating a payment
  2. Payment Event: When a payment status changes (e.g., payment completed, cancelled, or failed), EcobankPay sends a notification
  3. Webhook Delivery: EcobankPay sends an HTTP POST request to your ipn_url with payment details
  4. Response: Your server should respond with HTTP 200 to acknowledge receipt
  5. Verification: You should verify the payment status via the status check API endpoint before fulfilling orders

Important:

While webhooks provide immediate notifications, you should always verify the payment status through the status check endpoint before processing orders. The webhook serves as a prompt to check the status, not as definitive confirmation.

Setting Up Your Webhook Endpoint

1. Create a Webhook URL

Implement an HTTP endpoint in your application that will receive POST requests from EcobankPay:

  • The URL must be publicly accessible over the internet
  • Must accept HTTP POST requests
  • Should be secured with HTTPS
  • Must return a 200 HTTP status code to acknowledge receipt

Example Node.js Webhook Handler:

// Express.js example
const express = require('express');
const app = express();
app.use(express.json());

app.post('/api/ecobankpay-webhook', async (req, res) => {
  try {
    // 1. Log the webhook payload for debugging
    console.log('Received EcobankPay webhook:', req.body);

    // 2. Extract payment details
    const { invoice_id, status, tx_reference } = req.body;

    // 3. Verify payment status using status check API
    // (Important: Always verify before processing)
    const paymentStatus = await verifyPaymentStatus(invoice_id);

    // 4. Update your database and business logic based on status
    if (paymentStatus === 'paid') {
      // Process the order
      await updateOrderStatus(invoice_id, 'paid');
      // Additional business logic
    }

    // 5. Always return 200 to acknowledge receipt
    return res.status(200).send('Webhook received');
  } catch (error) {
    console.error('Error processing webhook:', error);
    // Still return 200 to prevent retries - log the error for investigation
    return res.status(200).send('Webhook received with processing error');
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));

2. Include IPN URL in Payment Requests

When initiating a payment, include your webhook URL in the ipn_url parameter:

{
  "merchant_key": "abcdef1234-f5d6-4931-8544-58dc97a5",
  "invoice_id": "INV12345",
  "total": 10.00,
  "description": "Payment for Order #12345",
  "ipn_url": "https://yourwebsite.com/api/ecobankpay-webhook",
  "success_url": "https://yourwebsite.com/payment/success",
  "cancelled_url": "https://yourwebsite.com/payment/cancelled"
}

3. Handling Payment Notifications

When a customer completes, cancels, or fails a payment, EcobankPay will send a notification to your ipn_url with the following information:

ParameterDescription
invoice_idYour unique transaction ID provided in the initial request
tx_referenceEcobankPay's unique transaction reference
statusPayment status (paid, cancelled, failed, awaiting_payment)
amountTransaction amount
status_reasonAdditional information about the status (mainly for failed payments)

Example Webhook Payload:

{
  "invoice_id": "INV12345",
  "tx_reference": "ECO123456789",
  "status": "paid",
  "amount": 10.00,
  "status_reason": "",
  "payment_method": "mtn_mobile_money",
  "payment_time": "2023-03-28T14:22:30Z"
}

Verifying Webhook Authenticity

To ensure that webhook notifications are genuinely from EcobankPay, you should:

  1. Verify the transaction: Call the status check API to confirm the payment status
    GET https://pgw.paywithonline.com/v1/gateway/json_status_chk?invoice_id=INV12345&merchant_key=YOUR_MERCHANT_KEY
  2. Validate data consistency: Ensure the details in the webhook match your records (invoice ID, amount)
  3. Implement IP whitelisting: Configure your firewall to only accept webhook requests from EcobankPay's IP ranges (contact support for current ranges)

Security Tip:

Never process orders solely based on webhook notifications. Always verify the payment status through the official API endpoint to prevent processing fraudulent orders.

Handling Webhook Failures

EcobankPay employs a retry mechanism for webhook deliveries:

  • If your endpoint returns a non-200 status code, EcobankPay will attempt to redeliver the webhook
  • Retries occur on a diminishing frequency schedule over 24 hours
  • Implement idempotency in your webhook handler to prevent duplicate processing
  • Even if webhooks fail, you can still poll the status check endpoint to get payment updates

Implementing Idempotency

Your webhook handler should be idempotent (able to process the same notification multiple times without side effects):

// Example idempotent webhook handler logic
async function processWebhook(paymentData) {
  const { invoice_id, status } = paymentData;

  // Get current order status from your database
  const order = await getOrderByInvoiceId(invoice_id);

  // Only process if:
  // 1. Order exists
  // 2. Order is in a state that can transition to the new state
  // 3. Payment status is verified via API
  if (order && canTransitionTo(order.status, status)) {
    // Verify payment status via API
    const verifiedStatus = await verifyPaymentStatus(invoice_id);

    if (verifiedStatus === status) {
      // Update order status - use a transaction if possible
      await updateOrderStatus(invoice_id, status);

      // Log the successful processing
      logWebhookProcessed(invoice_id, status);
    }
  }
}

Testing Webhooks

To test your webhook implementation:

  1. Use ngrok or similar tools: For local development, create a temporary public URL that forwards to your local server
  2. Create a test endpoint: Implement a separate endpoint for testing that logs all received payloads
  3. Make test payments: Use the EcobankPay sandbox environment to generate real webhook notifications
  4. Verify handling: Ensure your system correctly processes different payment statuses (paid, cancelled, failed)

Testing with ngrok:

# 1. Install ngrok
npm install -g ngrok

# 2. Start your local server
npm start

# 3. Start ngrok to forward to your local port
ngrok http 3000

# 4. Use the generated ngrok URL as your ipn_url
# Example: https://a1b2c3d4.ngrok.io/api/ecobankpay-webhook

Webhook Best Practices

  • Respond to webhook requests quickly (under 5 seconds) to prevent timeouts
  • Process webhooks asynchronously for complex operations
  • Implement comprehensive logging for all webhook events
  • Set up monitoring and alerts for webhook processing failures
  • Always verify payment status through the API before fulfilling orders
  • Handle all possible payment statuses in your implementation
  • Test your webhook implementation thoroughly in the sandbox environment