Gareth Wilson Gareth Wilson

Guide to Alipay Webhooks: Features and Best Practices

Published


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

FeatureDetails
ConfigurationNotify URL set per API call (paymentNotifyUrl / refundNotifyUrl)
Signature headerSignature: algorithm=RSA256, keyVersion=1, signature=<sig>
Other headersClient-Id, Request-Time
Signature schemeSHA256withRSA over POST <path>\n<client-id>.<request-time>.<body>
Verification keyAlipay's (Antom/Alipay+) public key from the Dashboard
AcknowledgementHTTP 200 with {"result":{"resultCode":"SUCCESS","resultStatus":"S","resultMessage":"Success"}}
Retries~8 times over 24h if not acknowledged
SDKalipay-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:

MethodNotifies you about
notifyPaymentA payment result
notifyRefundA refund result
notifyCaptureA capture result
notifyDisputeA dispute
notifyAuthorizationAn 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.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.