披露:本文包含联盟链接。如您通過链接购買,我们可能獲得佣金,且您無需承担额外费用。
測試結账流程,意味着要模拟用户點擊“支付”到后端确認“资金到账”之间發生的一切——拒付、风控检查、退款、乱序触發的 Webhook——而全程不能真正扣款。支付處理商發佈沙盒环境和公開的測試卡号,正是為此而生。本指南介绍 Stripe、PayPal、Braintree、Adyen 和 Square 提供的測試卡與沙盒工具,以及如何将它们與虚拟账单資料結合使用的工作流程。
“測試卡”到底是什么
測試卡是支付處理商在沙盒中保留的一個 16 位 PAN(主账号)。这個卡号能通過 Luhn 校驗,看起来像真實的 Visa 或 Mastercard,并会触發特定的處理商回應——成功、拒付、余额不足、過期等——而永远不会路由到真實發卡行。多数處理商会在文档中發佈一組公開的測試卡;请使用这些卡号而不是自己编造,因為末四位通常被编碼為特定的拒付原因碼。
Stripe——最完整的沙盒
Stripe 是測試基础設施的黄金標准。其沙盒(“測試模式”)接受以 pk_test_ 和 sk_test_ 開头的可發佈密钥和秘密測試密钥,因此每個 API 呼叫都有測試對应版本,每個 Webhook 都可以通過 Stripe CLI 镜像到本地。
必備 Stripe 測試卡
| 卡号 | 品牌 | 結果 |
|---|---|---|
| 4242 4242 4242 4242 | Visa | 支付成功 |
| 4000 0027 6000 3184 | Visa | 拒付——附带欺诈拦截標记 |
| 4000 0000 0000 0002 | Visa | 通用拒付 |
| 4000 0000 0000 9995 | Visa | 余额不足 |
| 4000 0000 0000 0069 | Visa | 卡片過期 |
| 4000 0082 6000 3178 | Visa | 需要 3DS 驗證 |
| 5555 5555 5555 4444 | Mastercard | 支付成功 |
| 3782 822463 10005 | Amex | 支付成功(Amex 測試卡,15 位) |
Stripe CLI:在本地重放 Webhook
杀手级功能是 Stripe CLI,它能把測試模式的實时事件轉發到你本地的 Webhook 端點:
stripe login
stripe listen --forward-to http://localhost:8080/webhooks/stripe
这一條命令,就是“我測試了顺利路径”和“我測試了完整的顺利路径——包括那條更新我資料函式庫的 Webhook”之间的区别。還可以手动触發特定事件:
stripe trigger payment_intent.succeeded
stripe trigger invoice.payment_failed
stripe trigger charge.refunded
PayPal——沙盒帳戶與虚拟卡
PayPal 提供了一個“沙盒”环境,你可以在開發者控制台建立独立的沙盒買家帳戶和商户帳戶。至少建立一個沙盒企業帳戶(商户)和一個個人帳戶(買家)。
沙盒測試卡——在 PayPal 沙盒内用于游客結账——包括以下公開卡号:
- Visa:4032035728984848(有效期填任意未来日期,CVV 123)
- Mastercard:5425233430109242
- Amex:374245455400126
这些卡仅在 PayPal 沙盒内有效;在其他任何地方使用都会得到通用拒付。PayPal 沙盒不像 Stripe 那样支援丰富的拒付場景——要測試 PayPal 拒付,请使用開發者控制台中的 reviewer 工具,给你的沙盒帳戶附加一個“负面測試”標记,强制下一笔交易失败。
Braintree——沙盒卡
Braintree(PayPal 旗下公司)在初始化时区分沙盒密钥與生產密钥,并發佈了一套按特定回應碼劃分的測試卡:
| 卡号 | 結果 |
|---|---|
| 4111 1111 1111 1111 | 批准 |
| 5105 1051 0510 5100 | 批准(Mastercard) |
| 4000 1111 1111 1115 | 處理商拒付——卡类型未啟用 |
| 5000 1111 1111 1114 | 處理商拒付——被發卡行拒付 |
| 4000 1111 1111 1112 | 處理商拒付——已拦截 |
Braintree 還允许你通過設置特定的街道地址或 CVV 值来控制 AVS 和 CVV 回應——这在測試高级风控和卡片驗證路径时非常有用。
Adyen 和 Square
Adyen 提供測試帳戶,每個卡号都有可预测的結果,拒付原因碼也非常出色。常用測試卡包括 4111 1111 1111 1111(Visa,已授权)和 5101 1800 0000 0007(Mastercard)。Adyen 回應對象上的“test”前綴让审计工作变得簡单。
Square 發佈了沙盒卡,如 4111 1111 1111 1111(Visa 扣款成功)和 5105 1051 0510 5100(Mastercard 拒付)。Square 沙盒允许你建立沙盒客户并将卡片存档。
最佳實践:測試每一條拒付路径
下面这份清单覆蓋了大多数团隊容易遗忘的失败面:
- 使用有效卡片成功扣款
- 通用處理商拒付
- 余额不足
- 卡片過期
- 需要 3DS 的場景(驗證挑战弹窗出現且挑战完成成功;驗證與取消——每條路径都重要)
- 卡片存档后,通過已保存的令牌稍后扣款
- 全额退款與部分退款
- 對已被拒付(争议)的扣款發起退款(追回路径)
- Webhook 到達两次——驗證你的處理器是幂等的
- Webhook 在資料函式庫写入之前到達(Stripe 称之為“事件 ID 领先于状态”的罕见乱序情况)
幂等的 Webhook 處理器是底線,不容妥协。使用事件 ID 作為你的幂等键。如果你發現自己在處理器里写出
if (!exists) { insert } else { skip }——恭喜你,你已经写出了幂等性。下次重构时千万别把它弄丢了。
将測試卡與虚拟账单資料配對使用
一次成功的沙盒扣款還依赖于 AVS(地址驗證系统)——發卡行会核對郵遞區號和街道号是否與卡片档案一致。大多数沙盒卡的測試环境会忽略 AVS 結果,但要測試你表单的錯誤路径(例如郵遞區號錯誤触發錯誤提示),你需要稳定但明显虚构的账单資料。
这正是 USA Data Tools 地址產生器的用武之地:
curl "https://vic999.com/us-address/api/v1/address?count=20" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o fixtures/billing-addresses.JSON
- 真實的地址让你能断言表单接受每一种郵遞區號到州的組合。
- 按州產生的資料對測試扣款前的銷售稅明细行無价。
- 免稅州產生器让你能驗證德拉瓦、蒙大拿、新罕布什爾和奧勒岡的零税結账。
把產生的账单地址、Stripe 的需要 3DS 測試卡和一個產生的购買金额組合起来,你就得到了一個完全可复現的結账測試場景,一次性覆蓋 AVS、税费和 3DS。
幂等性——悄無声息的結账杀手
真實世界的支付事故往往长这样:用户點擊支付,要求在第 28 秒超时,用户再次點擊支付——然后被扣了两次款。每個支付 API 都支援幂等键;请务必使用:
// Stripe 示例:傳入幂等键
const paymentIntent = await stripe.paymentIntents.create({
amount: 1999,
currency: "usd",
customer: customerId,
}, {
idempotencyKey: `order_${orderId}_pay`,
});
同一客户端的重复呼叫(或恐慌用户連點 50 次)只会產生一次扣款。建構一個端到端測試:重复發送支付要求,断言只存在一笔扣款;这一個測試就能预防约 30% 的真實生產支付事故。
Webhook 重放:抓住罕见但致命的 Bug
Stripe 允许你在控制台重放任意 Webhook。保存 payment_intent.id,12 小时后點擊“Resend”,驗證你的處理器是否處理得当——很多真實 Bug 只在这种場景下才会浮現。結合產生的订单 ID 和地址,你就拥有了一個完全可复現的夹具,能精确触發你想要的路径。
CI 集成
使用独立的沙盒密钥,把你的拒付矩阵接入每晚運行的 CI:
- name: Checkout decline matrix
run: npx playwright test checkout-declines
env:
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_TEST_SECRET_KEY }}
STRIPE_PUBLISHABLE_KEY: ${{ secrets.STRIPE_TEST_PUBLISHABLE_KEY }}
BILLING_FIXTURES_URL: https://vic999.com/us-address/api/v1/address?count=50
矩阵全绿的那個夜晚,就是可以發佈的夜晚。
在支付場景中使用測試資料產生器
总結
測試支付流程并不复雜——但需要全面。處理商的沙盒覆蓋了扣款侧;產生的虚拟資料覆蓋了表单與 AVS 侧;幂等键模式加上重放驱动的 Webhook 測試,则覆蓋了那些最终会演变成 3 万美元退款的隱性失败。先写出上面的拒付矩阵,用 Stripe CLI 接入本地 Webhook,再用地址產生器產生虚拟账单記錄。矩阵全绿的第一晚,你的結账流程就不再是黑盒。