Webhook Processing¶
Overview¶
Midtrans sends HTTP POST notifications to your webhook endpoint when payment statuses change. The subscriptions package handles the entire webhook lifecycle:
Receive — Log the raw payload in
WebhookLogVerify — Validate the SHA-512 signature
Deduplicate — Skip already-processed notifications
Process — Update payment and subscription status
Notify — Create
NotificationLogentries
Setup¶
1. Configure the Webhook URL¶
Set the notification URL in your .env:
MIDTRANS_NOTIFICATION_URL=https://yourdomain.com/api/subscriptions/webhook/notification/
2. Include the URL¶
# urls.py
urlpatterns = [
path("api/subscriptions/", include("subscriptions.urls")),
]
The webhook endpoint is at POST /api/subscriptions/webhook/notification/.
3. Register in Midtrans Dashboard¶
Go to Midtrans Dashboard → Settings → Configuration → Payment Notification URL.
Set your public URL (e.g., https://yourdomain.com/api/subscriptions/webhook/notification/).
For local development, use a tunnel like ngrok:
ngrok http 8000
# Set MIDTRANS_NOTIFICATION_URL=https://xxxx.ngrok.io/api/subscriptions/webhook/notification/
Signature Verification¶
Every Midtrans notification includes a signature_key field. The package verifies it using:
SHA512(order_id + status_code + gross_amount + server_key)
If the signature is invalid, the webhook log is marked as invalid and processing stops.
from subscriptions.client import MidtransClient
is_valid = MidtransClient.verify_signature(
order_id="SUB-A1B2C3D4E5F6",
status_code="200",
gross_amount="49000.00",
signature_key="sha512hash...",
)
Processing Flow¶
Payment Notifications (order_id starts with SUB-)¶
Transaction Status |
Action |
|---|---|
|
Activate subscription, mark invoice paid |
|
Activate subscription, mark invoice paid |
|
Create pending notification |
|
Mark subscription past due |
|
Update refund amount, create notification |
Top-Up Notifications (order_id starts with TOPUP-)¶
Transaction Status |
Action |
|---|---|
|
Mark top-up as success, credit wallet |
|
Mark top-up as failed |
|
Mark top-up as expired |
WebhookLog Statuses¶
Status |
Description |
|---|---|
|
Payload received, not yet processed |
|
Successfully processed |
|
Processing error occurred |
|
Invalid signature |
|
Same order_id + transaction_status already processed |
Security¶
The webhook endpoint has no authentication (
AllowAny) — Midtrans needs to call itSignature verification prevents spoofed notifications
The sender IP is logged in
WebhookLog.ip_addressCSRF is exempt on the webhook view
Testing Webhooks Locally¶
The example app includes a webhook simulator at /example/webhook-simulator/ that sends test notifications to your local webhook endpoint.
You can also test via curl:
curl -X POST http://localhost:8000/api/subscriptions/webhook/notification/ \
-H "Content-Type: application/json" \
-d '{
"order_id": "SUB-TEST123",
"transaction_status": "settlement",
"status_code": "200",
"gross_amount": "49000.00",
"signature_key": "computed-sha512-hash",
"payment_type": "bank_transfer",
"transaction_id": "test-txn-id"
}'