---
id: 028
title: 支付宝沙箱接入（E2E 测试 L2 的买信封闭环）
status: closed
labels: [testing, payment, infra, P1]
assignee: team-lead
closed_at: 2026-04-23
created_at: 2026-04-23
---

# #028 支付宝沙箱接入（E2E L2）

## 背景

`#026` 阶段 2。支付真付已接入生产（v0.5.1 FEAT-013），但 E2E 测试一直用 `buy_envelopes(mock=True)` 绕过真协议 —— 跑不到 RSA 签名 / webhook 签名 / precreate 响应格式等细节。

vault 里早有 `alipay-sandbox-app` 凭证（沙箱 gateway `openapi-sandbox.dl.alipaydev.com`），不用重新申请。

## 做什么

### 阶段 A（本 issue 核心，最小可交付）

1. `src/xiangqin/alipay.py`：
   - `_is_sandbox()` 读 env `XIANGQIN_ALIPAY_SANDBOX`
   - `_get_gateway()` 根据 sandbox 切 endpoint
   - `_get_conf()` 切 vault credential key：`alipay` vs `alipay_sandbox`
2. `vault.json`：声明 `alipay_sandbox` credential 引用 `alipay-sandbox-app`
3. `test/test_alipay.py`：新增切换逻辑单测（mock vault）
4. 全套测试跑过

### 阶段 B（staging 真跑通，独立 issue）

- `deploy-staging.yml` 注入 `XIANGQIN_ALIPAY_SANDBOX=1` 到 alpha .env
- vault install 在 alpha 塞入 sandbox credential
- `xq envelope buy` 在 alpha 真调 sandbox precreate 拿 qr_code

### 阶段 C（CI 真集成测试，后续）

- GHA runner 里 `vault install` 后调 sandbox API
- assert qr_code 是合法 URL + sandbox webhook 签名验通

## Acceptance（阶段 A）

- [ ] `alipay.py` sandbox 分支
- [ ] `vault.json` 加 alipay_sandbox
- [ ] `test_alipay.py` 单测通过
- [ ] CI 全绿，覆盖率不降

## 相关

- 父：[#026 E2E 测试闭环](026-e2e-testing.md)
- 父 blueprint：[testing-strategy.md](../blueprints/testing-strategy.md)
- 生产 alipay：`FEAT-013` / `alipay-kongxuanpin`（不动）

## 讨论

### 2026-04-23 @team-lead

**阶段 A 完成**：`alipay.py` sandbox 分支 + 单测全绿（v0.5.4 release）。

**阶段 B 部分完成**：`vault deploy` 子命令（vault 仓 issue #001）端到端通；alpha `/opt/xiangqin/.vault/secrets.json` 已含 `alipay_sandbox` 字段；alpha .env 已注入 `XIANGQIN_ALIPAY_SANDBOX=1`；systemd 重启成功，`/health` → 0.5.4 active。

**E2E 真跑信封购买遇到 sandbox key 格式问题**，不属本 issue 范围，见新开 [issue #029](029-alipay-sandbox-key-format.md)。

**阶段 B 还剩**：#029 修好后真跑一次 `curl /envelope/buy` 拿到真 sandbox qr_code URL。
