Secure Secret Storage
Treat your API Secret and HMAC Secret as credentials:- Store them in environment variables or a secrets manager (for example, AWS Secrets Manager or HashiCorp Vault).
- Never commit secrets to source control or expose them in client-side code.
- Rotate both secrets immediately if you suspect compromise.
Timestamp Validation
VTPE includesX-Timestamp on every request and webhook. Validate that the timestamp is within plus or minus five minutes of your server’s current time. Reject stale requests to prevent replay attacks.
Idempotent Webhook Processing
VTPE may retry a webhook if the first attempt does not receive an HTTP 200 response. UsepaymentId as an idempotency key:
- Check whether
paymentIdwas already processed before acting on the event. - Return HTTP 200 even if the event is a duplicate, as long as your side has already handled it.
- This protects against duplicate order fulfillment or double crediting.
Logging
Log every incoming webhook for observability and debugging:- Log the event type,
reference,paymentId, andX-Timestampon receipt. - Log the processing outcome (success, duplicate, or failure).
- Never log the values of your API Secret or HMAC Secret.
Retry Handling
Return HTTP 200 immediately after validation, then process the event asynchronously via a job queue:- Synchronous processing that takes too long can cause VTPE to retry unnecessarily.
- An async queue lets you retry failed jobs on your own schedule while still acknowledging the webhook promptly.
- This pattern also helps you recover gracefully from temporary downstream outages.
Error Monitoring
Set up alerts for these signals so you catch problems early:- Unexpected 4xx or 5xx rates from your Product Information API endpoint.
- Webhook processing failures (validation errors, queue backlogs, or handler exceptions).
- Idempotency key collisions that could indicate retry storms or upstream bugs.
Reconciliation with the Payment Status API
Webhook delivery can fail. When it does, you may be holding a locked product with no confirmation of whether the payment went through. Use the Payment Status API as a recovery path in these situations:- Before selling a product on-premise that may have been paid through Mizaniya Pay.
- When reconciling a reference whose webhook never arrived (check
payment.webhookDeliveryin the response). - During periodic reconciliation of open orders past their expected payment window.
stage or locked when you receive the response. Never branch on payment.status. The rate limit is 60 requests per minute; do not poll in a tight loop.
The Payment Status API is a safety net, not a replacement for webhooks. Keep handling
payment.success and payment.fail as your primary signal.Production Deployment Checklist
Before enabling live traffic, verify every item below:- HTTPS only on both the Product Information API and webhook endpoints.
- Signature verification enabled in production and never skipped.
- Timestamp window enforced on all incoming requests.
- Async processing queue set up and monitored.
- Secrets stored securely outside the codebase.
- All three event types handled:
payment.initialized,payment.success, andpayment.fail. - Payment Status API tested as a reconciliation fallback for missed webhooks.
