Guide to Alipay Webhooks: Features and Best Practices
Alipay notifications tell your systems about payment activity: a payment completes, a refund is processed, a dispute is raised. If you're integrating Alipay's global products, these async notifications are how you react to money movement without polling.
This guide covers how Alipay notifications work, how to verify the RSA signature (this is asymmetric crypto, verified with Alipay's public key), how the legacy scheme differs, and the best practices for production.
What are Alipay webhooks?
Alipay's modern global products (Antom / Alipay+, the AMS API) send async notifications signed with asymmetric RSA (algorithm=RSA256, i.e. SHA256withRSA). Each request carries a Signature header plus Client-Id and Request-Time headers, and you verify with Alipay's public key from the dashboard.
There's an important caveat up front: Alipay has more than one signing scheme. This guide covers the Antom / Alipay+ header-RSA scheme (what the modern products and the Hookdeck source use). The legacy openapi/MAPI gateway uses a completely different form-param scheme, covered at the end. Confirm which your integration uses before verifying.
Alipay webhook features
| Feature | Details |
|---|---|
| Configuration | Notify URL set per API call (paymentNotifyUrl / refundNotifyUrl) |
| Signature header | Signature: algorithm=RSA256, keyVersion=1, signature=<sig> |
| Other headers | Client-Id, Request-Time |
| Signature scheme | SHA256withRSA over POST <path>\n<client-id>.<request-time>.<body> |
| Verification key | Alipay's (Antom/Alipay+) public key from the Dashboard |
| Acknowledgement | HTTP 200 with {"result":{"resultCode":"SUCCESS","resultStatus":"S","resultMessage":"Success"}} |
| Retries | ~8 times over 24h if not acknowledged |
| SDK | alipay-sdk (targets the legacy gateway signing) |
Common notifications
Alipay notification "names" are API method names, not a payload type field, the payload distinguishes via notifyType + result.resultStatus:
| Method | Notifies you about |
|---|---|
notifyPayment | A payment result |
notifyRefund | A refund result |
notifyCapture | A capture result |
notifyDispute | A dispute |
notifyAuthorization | An authorization result |
Branch on notifyType and result.resultStatus (for example S for success) rather than a single event string.
Setting up Alipay webhooks
The notify URL is set per API call (paymentNotifyUrl, refundNotifyUrl), not in a global dashboard. Download Alipay's (Antom/Alipay+) public key from the Dashboard to verify signatures. Acknowledge each notification with HTTP 200 and the success result body; if you don't, Antom retries roughly 8 times over 24 hours.
Securing Alipay webhooks
The modern Antom / Alipay+ header-RSA scheme
Each notification carries a Signature header (algorithm=RSA256, keyVersion=1, signature=<sig>), a Client-Id, and a Request-Time. To verify, reconstruct the signed content as POST <path>\n<client-id>.<request-time>.<body> (the HTTP method and path on line one, then client id, request time, and the raw body joined by dots), URL-decode and base64-decode the signature value, and verify with SHA256withRSA against Alipay's public key. Use the raw body directly, do not parse and reconstruct the JSON, or verification fails.
const crypto = require("crypto");
const ALIPAY_PUBLIC_KEY = process.env.ALIPAY_PUBLIC_KEY; // PEM from the Dashboard
function parseSignature(header) {
// "algorithm=RSA256, keyVersion=1, signature=<sig>"
const m = /signature=([^,]+)/.exec(header || "");
return m ? decodeURIComponent(m[1]) : "";
}
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const clientId = req.headers["client-id"];
const requestTime = req.headers["request-time"];
const signature = parseSignature(req.headers["signature"]);
const content = `POST ${req.path}\n${clientId}.${requestTime}.${req.body.toString()}`;
const verifier = crypto.createVerify("RSA-SHA256");
verifier.update(content);
if (!verifier.verify(ALIPAY_PUBLIC_KEY, Buffer.from(signature, "base64"))) {
return res.sendStatus(401);
}
res.status(200).json({
result: { resultCode: "SUCCESS", resultStatus: "S", resultMessage: "Success" },
});
processQueue.add(JSON.parse(req.body)); // process asynchronously
});
The same verification in Python (using cryptography):
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
def verify(method, path, client_id, request_time, raw_body, signature_b64, public_key):
content = f"{method} {path}\n{client_id}.{request_time}.{raw_body.decode()}".encode()
try:
public_key.verify(signature_b64, content, padding.PKCS1v15(), hashes.SHA256())
return True
except Exception:
return False
The legacy openapi / MAPI scheme
The older gateway (global.alipay.com, openapi.alipay.com) is completely different: form-encoded parameters with sign and sign_type=RSA2, verified by removing sign/sign_type, sorting the remaining params A-Z, joining with &, and RSA2-verifying against Alipay's public key, then replying with the plain text success. If your integration is on this gateway, use that scheme instead.
Alipay webhook limitations and pain points
Three schemes under one brand
The Problem: Antom AMS, Alipay+ Acquirer, and the legacy openapi/MAPI gateway sign differently. Verifying with the wrong scheme fails, and it's not always obvious which one a merchant is on.
Why It Happens: Alipay's products evolved separately, each with its own signing.
Workarounds:
- Confirm your integration vintage and use the matching scheme (this guide's header-RSA for modern products, form-param RSA2 for legacy).
How Hookdeck Can Help: Hookdeck verifies the signature at the edge, so your application receives pre-verified notifications without untangling which Alipay scheme applies.
The signed content is a request representation, not just the body
The Problem: The modern scheme signs POST <path>\n<client-id>.<request-time>.<body>, so you need the method, path, and headers, not just the body, and the raw body must be used verbatim.
Why It Happens: Antom signs a canonical request representation.
Workarounds:
- Reconstruct the exact string and use the raw body; don't reparse the JSON.
How Hookdeck Can Help: Hookdeck handles the canonical-string RSA verification at the edge, so your app doesn't reproduce it.
Ack format and retries
The Problem: Alipay expects a specific success result body, not just a 200. An incorrect ack leads to ~8 retries over 24 hours, so the same notification arrives repeatedly.
Why It Happens: Antom keys retry behavior on the structured result acknowledgement.
Workarounds:
- Return the exact
{"result":{"resultCode":"SUCCESS",...}}body, and dedupe/idempotently process retries.
How Hookdeck Can Help: Hookdeck acknowledges Alipay correctly and deduplicates, so retries don't double-process. See our guide to webhook idempotency.
Method-name, not event-type, payloads
The Problem: There's no single event type string; you branch on the method (notifyPayment, ...) plus notifyType and result.resultStatus. Handlers expecting a flat event name mis-route.
Why It Happens: Alipay models notifications as API methods with result codes.
Workarounds:
- Branch on
notifyType+result.resultStatus.
How Hookdeck Can Help: Hookdeck's transformations can normalize notifications into a consistent event shape for downstream handlers.
Best practices
Verify the header-RSA scheme with the raw body
Reconstruct POST <path>\n<client-id>.<request-time>.<body>, URL-decode and base64-decode the signature, and verify SHA256withRSA with Alipay's public key. Use the raw body.
Return the exact success ack
Reply 200 with {"result":{"resultCode":"SUCCESS","resultStatus":"S","resultMessage":"Success"}} to stop retries.
Confirm your scheme
Use the modern header-RSA scheme for Antom/Alipay+, or the legacy form-param RSA2 scheme for the openapi/MAPI gateway.
Dedupe and confirm before fulfilling
Dedupe across the ~8 retries, and re-verify the order amount via the API before releasing value.
Make Alipay webhooks production-ready
Hookdeck verifies the RSA signature, deduplicates, and durably queues every payment notification
Conclusion
Alipay's modern notifications are signed with SHA256withRSA over POST <path>\n<client-id>.<request-time>.<body>, verified with Alipay's public key, and acknowledged with a structured success result. Confirm which of Alipay's schemes you're on (modern header-RSA vs legacy form-param RSA2), verify against the raw body, return the exact ack, and dedupe across retries.
Hookdeck verifies the RSA signature, deduplicates, and durably queues every notification at the edge, so your app only ever processes verified, unique payment events.
Get started with Hookdeck for free and handle Alipay webhooks reliably in minutes.