Webhooks & Callbacks
jengo/pesa includes an auto-routed, CSRF-exempt webhook controller accessible at /pesa/webhook/{gateway} to process asynchronous gateway notifications and IPN callbacks.
1. Automatic Webhook Routing
When you install jengo/pesa, the following route is automatically registered via Jengo\Pesa\Config\Routes:
$routes->match(['post', 'get'], 'pesa/webhook/(:segment)', '\Jengo\Pesa\Controllers\PesaWebhookController::handle/$1', [
'as' => 'pesa.webhook',
'csrf' => false, // Exempt from CSRF protection for external API servers
]);You can generate dynamic callback URLs anywhere in your code using CodeIgniter's reverse routing:
$mpesaCallbackUrl = route_to('pesa.webhook', 'mpesa'); // https://myapp.com/pesa/webhook/mpesa
$pesapalCallbackUrl = route_to('pesa.webhook', 'pesapal'); // https://myapp.com/pesa/webhook/pesapal
$stripeWebhookUrl = route_to('pesa.webhook', 'stripe'); // https://myapp.com/pesa/webhook/stripe2. Webhook Security & Verification
Each gateway driver implements a dedicated WebhookHandlerInterface:
- M-Pesa: Parses Safaricom
stkCallback, C2B confirmation, and B2C queue payloads. - Pesapal v3: Verifies IPN notifications and queries the transaction status endpoint using the authenticated bearer token.
- Stripe: Verifies
Stripe-SignatureHMAC signatures using your configuredwebhook_secret. ThrowsWebhookVerificationExceptionon forged requests.
3. Webhook Acknowledgment Responses
PesaWebhookController automatically returns the exact HTTP response format required by each provider:
- M-Pesa:
{"ResultCode": 0, "ResultDesc": "Success"} - Pesapal:
{"status": "200", "message": "OK"} - Stripe:
{"received": true}
4. Dispatched Events
Upon processing a webhook, jengo/pesa updates the transaction ledger and dispatches corresponding events (pesa.payment_succeeded, pesa.payment_failed, pesa.payment_reversed).
See the Events & Listeners guide for full event signatures and examples.
