Tất cả bài viết
StripeStripe Connectmarketplacewebhook debugging

Webhook Stripe Connect: hướng dẫn kiểm thử cục bộ

Stripe Connect là một hệ sinh thái webhook khác với Stripe thông thường. Toán chữ ký giống nhau. Mọi thứ khác đều khác. Nếu bạn đang truy tìm vì sao handler Connect của mình âm thầm bỏ qua account.application.deauthorized, bài này dành cho bạn.

Connect thay đổi sự kiện bạn nhận

Webhook Stripe thông thường đến từ tài khoản nền tảng của bạn: charges, customers, subscriptions. Webhook Connect đến từ các tài khoản kết nối và từ các sự kiện vòng đời đặc thù Connect trên nền tảng của bạn. Danh sách trùng lặp nhiều nhưng gồm các sự kiện bạn chỉ thấy khi bật Connect:

  • account.updated — trạng thái xác minh, capabilities, yêu cầu
  • account.application.deauthorized — tài khoản kết nối thu hồi quyền truy cập của bạn
  • capability.updated — trạng thái kích hoạt payouts/transfers
  • person.created, person.updated — cho tài khoản Custom và Express
  • payout.failed, payout.paid — trên tài khoản kết nối, không phải nền tảng của bạn

Hầu hết đội phát hiện điều này sau khi deploy. Kiểm thử cục bộ thì phơi bày vấn đề trong vài phút.

Header Stripe-Account thay đổi mọi thứ

Khi một sự kiện xảy ra trên tài khoản kết nối, Stripe đính kèm header Stripe-Account với ID của tài khoản kết nối (acct_xxx). Handler của bạn cần định tuyến theo header đó, không theo những gì bên trong payload.

const connectedAccountId = req.headers['stripe-account'];
const event = stripe.webhooks.constructEvent(
  rawBody,
  req.headers['stripe-signature'],
  endpointSecret,
);

// Now process the event in the context of connectedAccountId
await handleConnectEvent(event, connectedAccountId);

Nếu bạn quên đọc header, handler coi mọi sự kiện Connect như thể nó xảy ra trên nền tảng của bạn. Bug từ mẫu này thường hiện ra dưới dạng "payout hiển thị cho sai merchant".

Kiểm thử Connect cục bộ với PortPreview

Thiết lập giống kiểm thử Stripe thông thường cục bộ, cộng một bước thêm:

  1. Chạy app nền tảng cục bộ.
  2. Khởi động một tunnel: npx portpreview 3000.
  3. Trong dashboard Stripe, thêm URL tunnel làm endpoint webhook tick tùy chọn Events on Connected accounts. Đó là công tắc thay đổi toàn bộ luồng sự kiện.
  4. Dùng một tài khoản kết nối thử Express hoặc Custom. Chế độ test của Stripe có một trình tạo tài khoản giả "Jenny Rosen" bắn ra sự kiện thực tế.
  5. Kích hoạt sự kiện từ giao diện test Connect: hoàn tất onboarding, yêu cầu payout, hủy ủy quyền một tài khoản.

Luồng hủy ủy quyền là cái khó

Khi một tài khoản kết nối thu hồi quyền truy cập của app bạn, Stripe bắn account.application.deauthorized đúng một lần. Nếu handler của bạn crash, trả về 5xx, hoặc không xác nhận sự kiện kịp thời, Stripe thử lại — nhưng tài khoản kết nối đã đi rồi. Các lời gọi API sau đó cho tài khoản đó trả về 401.

Kiểm thử luồng deauth cẩn thận. Dùng chế độ test Connect để hủy ủy quyền tài khoản thử, bắt webhook, và chạy logic dọn dẹp của bạn với payload đã bắt. Replay cho tới khi đường đi chống đạn.

Express vs Standard vs Custom

Loại tài khoản thay đổi sự kiện person/capability bạn nhận. Tài khoản Express và Custom phát sự kiện person.* vì nền tảng của bạn giúp hoàn tất onboarding. Tài khoản Standard tự xử lý onboarding qua màn hình do Stripe host, nên bạn thấy ít sự kiện hơn. Nếu bạn đổi loại tài khoản giữa dự án — và người ta có làm — handler webhook của bạn cần điều chỉnh.

Điều chúng tôi thực sự sẽ làm

Cho một marketplace thật với analytics cấp nền tảng và báo cáo theo từng merchant, hãy dựng hai đường handler riêng biệt từ ngày đầu: một cho sự kiện nền tảng (không có header Stripe-Account), một cho sự kiện tài khoản kết nối. Định tuyến ở đầu hàm. Điều này tránh 90% bug "cái này cho ta hay cho merchant" về sau.

Webhook Connect dùng chung scheme chữ ký của Stripe, nên cơ chế xác minh giống hệt kiểm thử webhook Stripe thông thường. Về nền tảng toán chữ ký qua các nhà cung cấp, xem hướng dẫn xác minh chữ ký. Tham gia danh sách chờ PortPreview để kiểm thử Connect với bắt và replay tích hợp sẵn.

Câu hỏi thường gặp

Webhook Stripe Connect khác webhook Stripe thông thường thế nào?
Sự kiện Connect đến từ các tài khoản kết nối và mang header Stripe-Account xác định tài khoản nào bắn sự kiện. Cơ chế chữ ký giống Stripe thông thường, nhưng bạn phải bật Events on Connected accounts trong dashboard và định tuyến theo header trong handler.
Header Stripe-Account dùng để làm gì?
Nó xác định tài khoản kết nối đã kích hoạt sự kiện. Handler nên đọc nó trước khi xử lý vì cùng một loại sự kiện có thể bắn trên nền tảng của bạn hoặc trên một tài khoản kết nối, và logic nghiệp vụ khác nhau.
Làm sao kiểm thử webhook hủy ủy quyền cục bộ?
Thiết lập một endpoint Connect với tunnel, kết nối một tài khoản thử Express hoặc Custom, rồi hủy ủy quyền nó từ giao diện test Connect. Sự kiện account.application.deauthorized đến handler cục bộ của bạn — replay khi cần trong lúc bạn tinh chỉnh logic dọn dẹp.