Cách Paddle gửi webhook

Tối đa 60 lần gửi trong khoảng 2 ngày ở live mode, khoảng 10 lần trong giờ đầu tiên. Định dạng chữ ký ts/h1 của Paddle và code xác minh Node.

Hành vi gửi

Lấy từ tài liệu của chính hãng, kiểm tra lần cuối 2026-08-06. Hãng không nêu con số nào thì bảng này cũng không ghi.

Thời hạn phản hồi5 giây

Kiểm tra handler của bạn có phản hồi kịp không

Thử lạiLive: tối đa 60 lần gửi trong khoảng 2 ngày, khoảng 10 lần trong giờ đầu và khoảng 45 lần trong ngày đầu. Sandbox: 3 lần gửi trong khoảng 2 phút
Ngừng gửihãng không công bố
Nguồnhttps://developer.paddle.com/webhooks/about/respond-to-webhooks

Chữ ký

Kiểm chứng bằng một bộ xác minh chạy thật, có bộ test chứng minh, chứ không đọc từ tài liệu. Kiểm chứng lần cuối 2026-08-20.

Thuật toánHMAC-SHA256
Payload được ký{timestamp}:{body}
Encodinghex
Headerpaddle-signature = ts=X;h1=hex
Dung sai5 giây

Xác minh

Dùng raw body của request, đúng từng byte, trước mọi bước parse JSON. Mọi cơ chế trên trang này đều hỏng ngay khi framework serialize lại payload.

const crypto = require("node:crypto");

// paddle-signature: "ts=1700000000;h1=abc..." — HMAC-SHA256 over "{ts}:{body}"
const pairs = Object.fromEntries(
  req.headers["paddle-signature"].split(";").map((p) => p.split("=")),
);
const expected = crypto
  .createHmac("sha256", secretKey) // per destination: pdl_ntfset_...
  .update(`${pairs.ts}:${rawBody}`)
  .digest("hex");
const received = Buffer.from(pairs.h1 ?? "");
const wanted = Buffer.from(expected);
// timingSafeEqual throws on a length mismatch, so check that first.
const valid =
  received.length === wanted.length && crypto.timingSafeEqual(received, wanted);

SDK của Paddle áp dụng dung sai dấu thời gian (timestamp) 5 giây, chặt nhất trong các bên gửi ở đây. Khi đứng sau một dịch vụ trung chuyển hay một hàng đợi, hãy so dấu thời gian với lúc sự kiện tới edge, không phải lúc worker của bạn xử lý tới nó.

Những chỗ dễ vấp

Đường cong thử lại của Paddle dày ở chỗ Stripe thưa: khoảng 10 lần trong giờ đầu, khoảng 45 lần trong ngày đầu, tối đa 60 lần trong khoảng 2 ngày. Một handler chỉ chậm thôi sẽ chạy lại cứ vài phút một lần lúc đầu, và nếu không có idempotency (xử lý nhiều lần vẫn cho cùng một kết quả), mỗi lần chạy lại lặp lại các side effect của nó.

Sandbox không giống live chút nào: chỉ 3 lần gửi trong khoảng 2 phút. Nên phần xử lý thử lại trông ổn khi test thực ra mới chịu 5% áp lực.

Đọc thêm

AnyHook đứng trước các endpoint nhận webhook từ Paddle: trả lời sau khoảng 1 giây, tự thử lại theo lịch riêng khi server của bạn ngừng hoạt động, và giữ mọi sự kiện để bạn phát lại được. Đổi một URL, giữ nguyên code; để nhận được các lần thử lại và phát lại, bạn xác minh AnyHook-Signature, vì chữ ký riêng của Paddle hết hạn sau 5 giây.

Cách hoạt động →