# 如何测试支付集成：沙盒与测试指南

> 开发者支付集成测试指南：沙盒环境、测试卡号、边界情况测试，以及支付流程的 CI/CD 工作流。
- **Author**: Ayush Agarwal
- **Published**: 2026-04-13
- **Category**: Developer Guide
- **URL**: https://dodopayments.com/blogs/zh/test-payment-integration-sandbox

---

未经充分测试就上线支付集成，往往会导致收入损失、客户不满，以及凌晨 3 点被事故告警叫醒。支付流程的失败模式几乎比任何其他功能都多：卡片被拒、令牌过期、Webhook 传送失败、货币转换边界情况、订阅续费时的竞态条件，以及导致账务出错的部分退款。

支付测试尤其具有挑战性，因为你无法在开发环境中使用真实信用卡，需要模拟生产环境中很少发生的失败情况，而且支付服务商是你无法控制的第三方依赖。沙盒环境解决了第一个问题，而系统化的测试规划则能解决其余问题。

本指南将介绍如何从开发到生产环境测试支付集成，包括沙盒配置、测试场景和 CI/CD 策略。

## 沙盒环境与生产环境

每个正规的支付服务商都会提供两个环境：

|          | 沙盒 / 测试环境            | 生产 / 正式环境            |
| -------- | -------------------------- | -------------------------- |
| 真实资金 | 否                         | 是                         |
| 真实卡片 | 仅限测试卡                 | 客户卡片                   |
| Webhook  | 模拟事件                   | 真实事件                   |
| API 密钥 | 测试密钥（前缀为 `test_`） | 正式密钥（前缀为 `live_`） |
| 行为     | 可预测、可控               | 真实世界的波动性           |

```mermaid
flowchart LR
    A[Development] -->|"Test API Keys"| B[Sandbox]
    B -->|"All tests pass"| C[Staging]
    C -->|"Integration tests"| D[Production]
    D -->|"Live API Keys"| E[Real Payments]
    B -->|"Simulate failures"| F[Error Handling Verified]
```

沙盒会完全模拟生产 API，但绝不会处理真实扣款。使用来自 [Dodo Payments 控制台](https://dodopayments.com) 或你的支付服务商的测试 API 密钥来访问沙盒。

### 设置沙盒环境

使用 Dodo Payments 时，设置过程非常简单：

1. 从控制台获取测试 API 密钥
2. 在 [SDK 初始化](https://docs.dodopayments.com/developer-resources/dodo-payments-sdks) 中使用该密钥
3. 现在所有 API 调用都会访问沙盒环境

```javascript
import DodoPayments from "dodopayments";

const client = new DodoPayments({
  bearerToken: process.env.DODO_TEST_API_KEY, // test_ 前缀的密钥
});

// 创建测试支付，不会产生真实扣款
const payment = await client.payments.create({
  payment_link: true,
  billing: {
    city: "SF",
    country: "US",
    state: "CA",
    street: "123 Test St",
    zipcode: 94105,
  },
  customer: { email: "test@example.com", name: "Test Customer" },
  product_cart: [{ product_id: "pdt_test_product", quantity: 1 }],
});
```

如需了解详细的沙盒配置，请参阅[集成指南](https://docs.dodopayments.com/developer-resources/integration-guide)；如需查看可用端点，请参阅 [API 参考](https://docs.dodopayments.com/api-reference/introduction)。

## 测试卡号

支付服务商会提供能够触发可预测结果的特定卡号。常见的测试卡包括：

| 卡号                | 行为           |
| ------------------- | -------------- |
| 4242 4242 4242 4242 | 支付成功       |
| 4000 0000 0000 0002 | 通用拒付       |
| 4000 0000 0000 9995 | 余额不足       |
| 4000 0000 0000 0069 | 卡片过期       |
| 4000 0000 0000 0127 | CVC 错误       |
| 4000 0025 0000 3155 | 需要 3D Secure |
| 4000 0000 0000 3220 | 3DS2 身份验证  |

对于所有测试卡：

- 使用未来的任意到期日期（例如 12/30）
- 使用任意 3 位 CVC（例如 123）
- 使用任意账单邮政编码

> 测试卡是你最重要的调试工具。在编写任何错误处理代码之前，先用每张失败测试卡跑一遍结账流程，看看实际会发生什么。大多数开发者都会对支付失败时 UI 的表现感到意外。
>
> - Ayush Agarwal，Dodo Payments 联合创始人兼 CPTO

## 必测场景

### 成功路径测试

- 一次性支付成功
- 订阅创建成功
- 订阅续费成功
- 从一个套餐升级到另一个套餐
- 按比例计算余额的降级
- 应用优惠券/折扣的支付

### 失败测试

- 卡片被拒（通用拒付、余额不足、卡片过期）
- 需要并完成 3D Secure 身份验证
- 需要 3D Secure 身份验证但用户中途放弃
- 支付过程中网络超时
- 重复提交支付（双击）
- 卡号格式无效的支付

### Webhook 测试

- 接收并处理支付成功 Webhook
- 支付失败 Webhook 触发[催收流程](https://dodopayments.com/blogs/dunning-management)
- 订阅取消 Webhook 撤销访问权限
- 退款 Webhook 更新客户记录
- 拒绝签名无效的 Webhook
- 重复 Webhook（幂等性检查）
- 以错误顺序接收 Webhook

### 边界情况测试

- [国际支付](https://dodopayments.com/blogs/multi-currency-pricing-global-saas)的货币转换
- 零金额授权（卡片验证）
- 金额非常大（测试上限）
- 金额非常小（低于最低阈值）
- 部分退款后再进行全额退款
- 试用期结束的订阅
- 客户在计费周期中途更新支付方式

### 结账界面测试

- [Overlay 结账](https://docs.dodopayments.com/developer-resources/overlay-checkout)能够正确打开和关闭
- [Inline 结账](https://docs.dodopayments.com/developer-resources/inline-checkout)在容器中正确渲染
- 移动设备上的响应式结账体验
- 支付处理过程中的加载状态
- 针对每种拒付类型正确显示错误消息
- 支付成功后正确重定向

## 自动化测试策略

### 支付逻辑的单元测试

独立于支付服务商测试你的业务逻辑：

```javascript
describe("Subscription Activation", () => {
  it("should activate subscription on payment.succeeded", async () => {
    const event = createMockEvent("payment.succeeded", {
      customer_id: "cust_123",
      product_id: "pdt_pro_plan",
    });

    await handleWebhook(event);

    const sub = await db.subscriptions.findOne({ customerId: "cust_123" });
    expect(sub.status).toBe("active");
    expect(sub.planId).toBe("pdt_pro_plan");
  });

  it("should not double-activate on duplicate webhook", async () => {
    const event = createMockEvent("payment.succeeded", {
      customer_id: "cust_123",
      product_id: "pdt_pro_plan",
    });

    await handleWebhook(event);
    await handleWebhook(event); // duplicate

    const subs = await db.subscriptions.find({ customerId: "cust_123" });
    expect(subs.length).toBe(1); // only one subscription created
  });
});
```

### 针对沙盒环境的集成测试

在 CI/CD 流程中针对沙盒 API 运行集成测试：

```yaml
# GitHub Actions 示例

payment-tests:
  runs-on: ubuntu-latest
  env:
    DODO_API_KEY: ${{ secrets.DODO_TEST_API_KEY }}
  steps:
    - uses: actions/checkout@v4
    - run: npm install
    - run: npm run test:payments
```

### 端到端测试

使用 Playwright 或 Cypress 测试完整的结账流程：

1. 进入你的定价页面
2. 选择一个套餐
3. 填写测试卡信息
4. 提交支付
5. 验证是否重定向到成功页面
6. 验证数据库中的订阅是否已激活

## 上线前检查清单

从测试 API 密钥切换到正式 API 密钥之前：

- [ ] 所有成功路径场景均通过
- [ ] 所有失败场景都能优雅处理，并显示用户易懂的错误消息
- [ ] 通过签名验证确认 Webhook 端点有效
- [ ] 已为 Webhook 处理实现幂等性
- [ ] 日志记录支付事件，便于调试
- [ ] 已为支付失败设置错误监控告警
- [ ] 已端到端测试退款流程
- [ ] 已测试[订阅生命周期](https://docs.dodopayments.com/features/subscription)（创建、续费、取消、升级、降级）
- [ ] 已验证[许可证密钥交付](https://docs.dodopayments.com/features/license-keys)（如适用）
- [ ] [国际客户](https://dodopayments.com/blogs/global-billing)看到的货币显示正确
- [ ] [结账组件](https://docs.dodopayments.com/developer-resources/overlay-checkout)在所有目标设备上均能正确渲染
- [ ] 你的数据库与服务商控制台中的收入数字一致

## 生产环境监控

上线后，监控以下指标：

- **支付成功率**：卡片支付应达到 85% 以上，银行转账应更高
- **Webhook 传送率**：应达到 99% 以上
- **平均支付处理时间**：应低于 3 秒
- **退款处理时间**：跟踪 SLA 达成情况
- **按类型划分的错误率**：及早发现系统性问题

为异常情况设置告警。拒付率突然上升，可能意味着处理器中断、结账流程损坏或风控攻击。及早发现这些问题，可以避免严重的[收入流失](https://dodopayments.com/blogs/revenue-leakage-saas)。

如需进一步了解如何构建可靠的支付基础设施，请阅读我们的[支付网关集成](https://dodopayments.com/blogs/payment-gateway-integration-guide)、[支付 API](https://dodopayments.com/blogs/payment-api-guide)以及 [Dodo Payments 的开发者体验](https://dodopayments.com/blogs/developer-experience-dodo-payments)指南。

## 常见问题

### 我可以在沙盒环境中使用真实信用卡吗？

不可以。沙盒环境只接受支付服务商提供的测试卡号。向沙盒提交真实卡号会导致错误，这是为了防止开发和测试期间意外扣款。

### 如果我的服务器无法公开访问，如何在本地测试 Webhook？

使用 ngrok 等隧道服务公开你的本地服务器。运行 `ngrok http 3000` 获取公开 URL，然后在支付服务商的测试控制台中将该 URL 注册为 Webhook 端点。有些服务商还提供 CLI 工具，可以直接将测试事件转发到 localhost。

### 我应该在 CI/CD 流程中运行支付测试吗？

应该。在每次 CI/CD 运行中，针对沙盒 API 运行单元测试和集成测试。这样可以在支付逻辑进入生产环境之前发现回归问题。将测试 API 密钥作为 CI 密钥保存，并将支付测试套件纳入标准测试任务。

### 测试模式和正式模式有什么区别？

测试模式使用沙盒 API 密钥，并通过测试卡号处理模拟交易，不会有真实资金流动。正式模式使用生产 API 密钥，针对真实客户卡片处理真实扣款。两者的 API 接口相同，区别仅在于密钥和卡片验证。

### 如何在测试中模拟 3D Secure 身份验证流程？

大多数支付服务商都会提供能够触发 3D Secure 的特定测试卡号。例如，4000002500003155 通常会触发 3DS 挑战。沙盒会模拟身份验证弹窗，让你可以测试身份验证成功和失败的场景。

## 最后

正确测试支付需要前期投入时间，但可以避免代价高昂的生产事故。充分使用沙盒，尽可能实现自动化，并在正式上线前完成完整的检查清单。

如果你正在寻找配备开发者友好型测试工具和完善 SDK 的支付平台，可以了解 [Dodo Payments](https://dodopayments.com)，并查看[定价](https://dodopayments.com/pricing)。
---
- [More Developer Guide articles](https://dodopayments.com/blogs/category/developer-guide)
- [All articles](https://dodopayments.com/blogs)