@alipay/alipay-aipay 0.1.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/bin/alipay-aipay.js +6 -0
- package/dist/commands/install.d.ts +10 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +92 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/uninstall.d.ts +10 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +82 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.d.ts +10 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +125 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/alipay-cli.d.ts +15 -0
- package/dist/utils/alipay-cli.d.ts.map +1 -0
- package/dist/utils/alipay-cli.js +228 -0
- package/dist/utils/alipay-cli.js.map +1 -0
- package/dist/utils/config.d.ts +48 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +207 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/file.d.ts +55 -0
- package/dist/utils/file.d.ts.map +1 -0
- package/dist/utils/file.js +154 -0
- package/dist/utils/file.js.map +1 -0
- package/dist/utils/gpg.d.ts +14 -0
- package/dist/utils/gpg.d.ts.map +1 -0
- package/dist/utils/gpg.js +247 -0
- package/dist/utils/gpg.js.map +1 -0
- package/dist/utils/jq.d.ts +14 -0
- package/dist/utils/jq.d.ts.map +1 -0
- package/dist/utils/jq.js +221 -0
- package/dist/utils/jq.js.map +1 -0
- package/dist/utils/npm.d.ts +17 -0
- package/dist/utils/npm.d.ts.map +1 -0
- package/dist/utils/npm.js +42 -0
- package/dist/utils/npm.js.map +1 -0
- package/dist/utils/shell.d.ts +11 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +54 -0
- package/dist/utils/shell.js.map +1 -0
- package/package.json +53 -0
- package/skill/SKILL.md +118 -0
- package/skill/references/integration/flow.md +487 -0
- package/skill/references/integration/modules/alipay-sdk-reminder.md +256 -0
- package/skill/references/integration/modules/checklist.md +122 -0
- package/skill/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +68 -0
- package/skill/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +77 -0
- package/skill/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +74 -0
- package/skill/references/integration/modules/code-examples/csharp/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +73 -0
- package/skill/references/integration/modules/code-examples/csharp/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +58 -0
- package/skill/references/integration/modules/code-examples/csharp/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +128 -0
- package/skill/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.cs +500 -0
- package/skill/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +72 -0
- package/skill/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +80 -0
- package/skill/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +78 -0
- package/skill/references/integration/modules/code-examples/java/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +77 -0
- package/skill/references/integration/modules/code-examples/java/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +66 -0
- package/skill/references/integration/modules/code-examples/java/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +135 -0
- package/skill/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.java +610 -0
- package/skill/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +51 -0
- package/skill/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +57 -0
- package/skill/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +55 -0
- package/skill/references/integration/modules/code-examples/nodejs/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +54 -0
- package/skill/references/integration/modules/code-examples/nodejs/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +77 -0
- package/skill/references/integration/modules/code-examples/nodejs/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +65 -0
- package/skill/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.js +461 -0
- package/skill/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +59 -0
- package/skill/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +67 -0
- package/skill/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +66 -0
- package/skill/references/integration/modules/code-examples/php/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +65 -0
- package/skill/references/integration/modules/code-examples/php/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +56 -0
- package/skill/references/integration/modules/code-examples/php/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +107 -0
- package/skill/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.php +444 -0
- package/skill/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/345/205/263/351/227/255/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +57 -0
- package/skill/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +65 -0
- package/skill/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +63 -0
- package/skill/references/integration/modules/code-examples/python/1-/351/200/232/347/224/250/346/216/245/345/217/243//347/273/237/344/270/200/346/224/266/345/215/225/344/272/244/346/230/223/351/200/200/346/254/276/346/237/245/350/257/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +62 -0
- package/skill/references/integration/modules/code-examples/python/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +48 -0
- package/skill/references/integration/modules/code-examples/python/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +43 -0
- package/skill/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.py +465 -0
- package/skill/references/integration/modules/interface-guide.md +90 -0
- package/skill/references/integration/modules/product-decision.md +90 -0
- package/skill/references/integration/modules/sandbox/a2m-sandbox-test.md +270 -0
- package/skill/references/integration/modules/sandbox/alipay-sandbox-tool.md +133 -0
- package/skill/references/integration/modules/sandbox/sandbox-setup-guide.md +218 -0
- package/skill/references/integration/modules/scripts/local_402_sandbox_pay.py +659 -0
- package/skill/references/normal/alipay-cli-env.md +211 -0
- package/skill/references/normal/rejection-guide.md +37 -0
- package/skill/references/normal/scripts/common.sh +32 -0
- package/skill/references/normal/scripts/detect_dev_tool.sh +46 -0
- package/skill/references/onboarding/flow.md +571 -0
- package/skill/references/onboarding/modules/app-release.md +411 -0
- package/skill/references/onboarding/modules/authorization.md +269 -0
- package/skill/references/onboarding/modules/error-handling.md +247 -0
- package/skill/references/onboarding/modules/mcc-reference.md +209 -0
- package/skill/references/onboarding/modules/product-sign.md +304 -0
- package/skill/references/onboarding/modules/scripts/app.sh +705 -0
- package/skill/references/onboarding/modules/scripts/ar_sign_apply.sh +248 -0
- package/skill/references/onboarding/modules/scripts/auth.sh +505 -0
- package/skill/references/onboarding/modules/scripts/error_handler.sh +312 -0
- package/skill/references/onboarding/modules/scripts/query_sign_status.sh +146 -0
- package/skill/references/onboarding/modules/scripts/service.sh +267 -0
- package/skill/references/onboarding/modules/scripts/upload_screenshots.sh +152 -0
- package/skill/references/onboarding/modules/service-registration.md +294 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# 按量付费沙箱测试
|
|
2
|
+
|
|
3
|
+
> ⚠️ **仅当产品为「按量付费」时执行此步骤**。网站支付和APP支付无需此步骤,跳过直接进入步骤 6。
|
|
4
|
+
|
|
5
|
+
本文档定义按量付费 402 协议的沙箱端到端支付测试流程。测试脚本位于 `../scripts/local_402_sandbox_pay.py`。
|
|
6
|
+
|
|
7
|
+
> 本文档位于 `references/integration/modules/sandbox/`,文中的 `../scripts/...` 路径相对本目录;从技能包根目录执行时对应 `references/integration/modules/scripts/...`。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 前提条件
|
|
12
|
+
|
|
13
|
+
在执行此步骤前,必须满足:
|
|
14
|
+
|
|
15
|
+
1. **已完成步骤 4 代码生成**:按量付费集成代码已生成并整合进用户项目
|
|
16
|
+
2. **用户本地服务已启动**:服务端已运行在可访问的地址上(如 `http://localhost:5000/demo/a2m/resource`)
|
|
17
|
+
3. **已知沙箱买家 2088 账号**:从步骤 2 沙箱信息输出的买家账号中获取 `userId`(如 `2088722100508485`)
|
|
18
|
+
4. **Python 3 可用**:测试脚本依赖 Python 3 运行
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 测试前预检
|
|
23
|
+
|
|
24
|
+
执行沙箱测试脚本前,先解码服务返回的 `Payment-Needed`,确认关键字段存在。`SERVICE_URL` 使用用户实际服务地址。
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
curl -s -D - -o /dev/null "$SERVICE_URL" \
|
|
28
|
+
| python3 -c 'import sys, base64, json
|
|
29
|
+
headers = sys.stdin.read().splitlines()
|
|
30
|
+
statuses = [line.split() for line in headers if line.startswith("HTTP/")]
|
|
31
|
+
status = statuses[-1][1] if statuses and len(statuses[-1]) > 1 else ""
|
|
32
|
+
if status != "402":
|
|
33
|
+
raise SystemExit(f"HTTP 状态不是 402: {status or '未知'}")
|
|
34
|
+
value = next((line.split(":", 1)[1].strip().strip("\"") for line in headers if line.lower().startswith("payment-needed:")), "")
|
|
35
|
+
if not value:
|
|
36
|
+
raise SystemExit("未找到 Payment-Needed 响应头")
|
|
37
|
+
value += "=" * ((4 - len(value) % 4) % 4)
|
|
38
|
+
data = json.loads(base64.urlsafe_b64decode(value).decode())
|
|
39
|
+
required = [
|
|
40
|
+
("protocol", "out_trade_no"), ("protocol", "amount"), ("protocol", "currency"),
|
|
41
|
+
("protocol", "resource_id"), ("protocol", "pay_before"), ("protocol", "seller_signature"),
|
|
42
|
+
("protocol", "seller_sign_type"), ("protocol", "seller_unique_id"),
|
|
43
|
+
("method", "seller_name"), ("method", "seller_id"), ("method", "seller_app_id"),
|
|
44
|
+
("method", "goods_name"), ("method", "seller_unique_id_key"), ("method", "service_id"),
|
|
45
|
+
]
|
|
46
|
+
missing = [f"{path[0]}.{path[1]}" for path in required if not data.get(path[0], {}).get(path[1])]
|
|
47
|
+
if missing:
|
|
48
|
+
raise SystemExit("缺少字段: " + ", ".join(missing))
|
|
49
|
+
print("Payment-Needed 预检通过,已确认 HTTP 402 和关键字段存在。")
|
|
50
|
+
print("已校验字段: " + ", ".join(f"{path[0]}.{path[1]}" for path in required))'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
POST 服务将首行 curl 替换为 `curl -s -D - -o /dev/null -X POST -H "Content-Type: ${CONTENT_TYPE:-application/json}" -d "$BODY" "$SERVICE_URL"`。`seller_signature` 由代码示例中的 `generateSellerSignature` / `generate_seller_signature` 生成,禁止使用空值或占位符。预检输出只打印校验结论和字段名,不打印字段值。
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 测试脚本路径
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python3 ../scripts/local_402_sandbox_pay.py
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
脚本提供两个子命令:
|
|
64
|
+
- `run`:获取 Payment-Needed 并生成沙箱付款链接
|
|
65
|
+
- `complete`:携带 Payment-Proof 重试原始服务
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 完成条件
|
|
70
|
+
|
|
71
|
+
- [M-05] 已确认用户本地按量付费服务已启动可访问
|
|
72
|
+
- [M-05] 已完成 Payment-Needed 预检,确认 HTTP 402 和关键字段存在
|
|
73
|
+
- [M-05] 已执行沙箱支付测试脚本 `run`,成功获取 Payment-Needed 并生成付款链接
|
|
74
|
+
- [M-05] 用户已在浏览器使用沙箱买家账号完成付款
|
|
75
|
+
- [M-05] 已携带 Payment-Proof 重试原服务并验证响应成功
|
|
76
|
+
- [M-05] 已确认全链路 402 支付流程通过
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 测试流程
|
|
81
|
+
|
|
82
|
+
### 第一步:确认服务就绪
|
|
83
|
+
|
|
84
|
+
向用户确认:
|
|
85
|
+
1. 按量付费集成代码已部署到本地服务
|
|
86
|
+
2. 服务已启动并可通过 URL 访问
|
|
87
|
+
3. 服务实现了 402 协议(无 Payment-Proof 时返回 HTTP 402 + Payment-Needed 头)
|
|
88
|
+
|
|
89
|
+
**收集测试参数**:
|
|
90
|
+
- `SERVICE_URL`:本地服务请求地址(含 GET 参数,如 `http://localhost:5000/demo/a2m/resource?gift=demo`)
|
|
91
|
+
- `HTTP_METHOD`:`GET` 或 `POST`
|
|
92
|
+
- `BUYER_2088`:沙箱买家 2088 账号(`userId`,如 `2088722100508485`)
|
|
93
|
+
|
|
94
|
+
> ⚠️ 如果缺少任一值,先询问用户。不要编造买家账号。
|
|
95
|
+
|
|
96
|
+
### 第二步:执行沙箱支付测试脚本
|
|
97
|
+
|
|
98
|
+
**⚠️ 脚本的收银接口地址和付款链接前缀已硬编码在脚本中(`PAY_ENDPOINT`、`PAY_URL_PREFIX`),执行时无需额外指定。**
|
|
99
|
+
|
|
100
|
+
GET 请求:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
python3 ../scripts/local_402_sandbox_pay.py run \
|
|
104
|
+
--url "$SERVICE_URL" \
|
|
105
|
+
--method GET \
|
|
106
|
+
--buyer-id "$BUYER_2088"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
POST 请求:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
python3 ../scripts/local_402_sandbox_pay.py run \
|
|
113
|
+
--url "$SERVICE_URL" \
|
|
114
|
+
--method POST \
|
|
115
|
+
--body "$BODY" \
|
|
116
|
+
--buyer-id "$BUYER_2088"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**脚本执行步骤**:
|
|
120
|
+
1. 请求 `$SERVICE_URL`,提取 `Payment-Needed` 响应头
|
|
121
|
+
2. Base64 解码账单 JSON
|
|
122
|
+
3. 将下划线字段转换为驼峰字段(适配沙箱收银接口)
|
|
123
|
+
4. 补充 `method.buyerUniqueIdKey = "buyerExternalId"`
|
|
124
|
+
5. 补充 `protocol.buyerUniqueId = <买家 2088>`
|
|
125
|
+
6. 补充 `signature` 字段
|
|
126
|
+
7. POST 到沙箱收银接口 `http://aicashier.dl.alipaydev.com/openclawpay/agent/v1/pay`
|
|
127
|
+
8. 生成浏览器付款链接
|
|
128
|
+
|
|
129
|
+
**脚本输出**:
|
|
130
|
+
- Payment-Needed 获取结果和本地过程产物路径(终端不输出原始值)
|
|
131
|
+
- 脱敏后的账单 JSON
|
|
132
|
+
- 脱敏后的收银接口请求体
|
|
133
|
+
- 收银接口返回
|
|
134
|
+
- **浏览器付款链接**(格式:`https://render.alipay.com/p/yuyan/180020010001290755/pay.html?schema=...`)
|
|
135
|
+
- 过程产物目录路径(`$ARTIFACT_DIR`)
|
|
136
|
+
|
|
137
|
+
**错误处理**:
|
|
138
|
+
- 沙箱化 Agent 环境执行本脚本时,首次执行即申请可联网权限;如果已因网络受限失败,复用同一条命令申请可联网权限重试
|
|
139
|
+
- 如果未找到 `Payment-Needed` 响应头,确认服务端是否实现了 402 协议
|
|
140
|
+
- 如果收银接口返回 `PARAM_INVALID: protocol.sellerSignature不能为空`,回到预检步骤检查 `protocol.seller_signature` 是否为空、缺失或仍是占位符
|
|
141
|
+
- 如果 `pay_before` 相关参数报错,检查是否使用 ISO 8601 带时区格式
|
|
142
|
+
- 如果收银接口返回 `PAY_SUBMIT_FAILED`、`系统繁忙` 或缺少 `payScheme`,不要重新请求用户服务生成新订单。脚本默认会自动重试;仍失败时,复用过程产物重试收银接口:
|
|
143
|
+
```bash
|
|
144
|
+
python3 ../scripts/local_402_sandbox_pay.py run \
|
|
145
|
+
--reuse-artifact "$ARTIFACT_DIR"
|
|
146
|
+
```
|
|
147
|
+
`--reuse-artifact` 会复用上一轮产物中的 `Payment-Needed`、服务 URL、HTTP 方法、POST 请求体和 Content-Type。脚本不会重新请求用户服务生成新订单。这样可以避免本地内存订单堆积,导致后续 `ORDER_NOT_FOUND` 或多订单兜底匹配失败。
|
|
148
|
+
- `run` 命令支持 `--pay-retries` 和 `--pay-retry-delay`,用于调大沙箱收银接口临时失败时的重试次数与间隔。
|
|
149
|
+
|
|
150
|
+
### 第三步:用户完成付款
|
|
151
|
+
|
|
152
|
+
**必须将脚本输出的付款链接发给用户**,并提示:
|
|
153
|
+
|
|
154
|
+
> 请在浏览器打开以下链接,使用沙箱买家账号完成付款:
|
|
155
|
+
> - 买家账号:`{email}`(如 `xxxxx@sandbox.com`)
|
|
156
|
+
> - 登录密码:`{logonPassword}`(如 `111111`)
|
|
157
|
+
> - 支付密码:`{payPassword}`(如 `111111`)
|
|
158
|
+
>
|
|
159
|
+
> {付款链接}
|
|
160
|
+
|
|
161
|
+
同时提醒用户:
|
|
162
|
+
|
|
163
|
+
> 沙箱支付宝当前仅支持安卓系统。如果尚未安装沙箱版支付宝,请复制以下链接到网页浏览器打开,并使用支付宝客户端扫码下载沙箱版支付宝安装包:
|
|
164
|
+
>
|
|
165
|
+
> https://mdn.alipayobjects.com/sandboxsys/afts/img/_itHRrdOD9oAAAAAAAAAAAAADgSLAQBr/original
|
|
166
|
+
|
|
167
|
+
等待用户确认付款成功后,记录过程产物目录 `$ARTIFACT_DIR`,进入第四步。
|
|
168
|
+
|
|
169
|
+
### 第四步:验证 Payment-Proof 重试
|
|
170
|
+
|
|
171
|
+
用户确认付款成功后,运行 `complete` 命令:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
python3 ../scripts/local_402_sandbox_pay.py complete \
|
|
175
|
+
--artifact-dir "$ARTIFACT_DIR"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**脚本执行步骤**:
|
|
179
|
+
1. 读取过程产物目录中的 `state.json`
|
|
180
|
+
2. 使用前面沙箱收银接口下单返回的 `trade_no` 构建 `Payment-Proof` 请求头(含 `payment_proof`、`trade_no`、`client_session`)
|
|
181
|
+
3. 携带 `Payment-Proof` 请求头重试原始服务地址
|
|
182
|
+
4. 打印最终服务响应
|
|
183
|
+
|
|
184
|
+
**沙箱 Payment-Proof 构建规则**:
|
|
185
|
+
- `trade_no` 必须使用前面沙箱收银接口下单返回的交易号,即脚本从 `payResponse.protocol.tradeNo` 提取并写入 `state.json` 的值;不要使用商户侧 `out_trade_no`,也不要重新生成。
|
|
186
|
+
- `protocol.payment_proof` 在沙箱环境不做强校验,脚本默认用 `trade_no`、买家 2088 和当前毫秒时间戳生成一个非空 SHA-256 值。
|
|
187
|
+
- `method.client_session` 是 `{"externalId":"<BUYER_2088>","signature":"-","timestamp":"<毫秒时间戳>"}` 紧凑 JSON 的 Base64 编码。
|
|
188
|
+
- 最终 `Payment-Proof` 请求头值是下面整体 JSON 紧凑序列化后的 Base64 编码。
|
|
189
|
+
|
|
190
|
+
参考结构:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"protocol": {
|
|
195
|
+
"payment_proof": "bc0535fc673722fee9d37306239859fb30bddae8fdc971df2069e37401380452",
|
|
196
|
+
"trade_no": "20260702008281225779190000002293"
|
|
197
|
+
},
|
|
198
|
+
"method": {
|
|
199
|
+
"client_session": "eyJleHRlcm5hbElkIjoiMjA4ODcyMjEwMjczMjcwNyIsInNpZ25hdHVyZSI6Ii0iLCJ0aW1lc3RhbXAiOiIxNzgyODg0OTkyODc5In0="
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**验证要点**:
|
|
205
|
+
- 服务返回 HTTP 200(而非 402)
|
|
206
|
+
- 响应体包含服务资源内容(如 `resource_id`、`content` 等)
|
|
207
|
+
- 如果服务实现了 `Payment-Validation` 响应头,检查其内容
|
|
208
|
+
|
|
209
|
+
**常见失败与排查**:
|
|
210
|
+
- `ORDER_NOT_FOUND`:`alipay.aipay.agent.payment.verify` 成功只代表支付宝凭证有效,不代表商户本地订单已匹配成功。检查服务端是否在返回 `Payment-Needed` 前持久化了 `out_trade_no`、`resource_id`、金额和订单状态;验证成功后应优先用验付返回的 `outTradeNo` 查询订单。沙箱响应字段可能为空字符串,排查时先判断字段是否非空;如果本地服务重启导致内存订单丢失,已付款旧链接不能继续用于重启后的服务。
|
|
211
|
+
- `RESOURCE_ID_MISMATCH`:检查验付返回的 `resourceId` 是否非空且与本地订单保存的资源一致。沙箱字段为空时不要把空字符串当作有效资源字段参与强校验;生产环境必须把资源字段缺失作为异常处理。
|
|
212
|
+
- `FULFILLMENT_CONFIRM_FAILED` 或 HTTP 5xx:资源生成后调用 `alipay.aipay.agent.fulfillment.confirm` 失败时,不要返回成功交付;应保留服务结果并允许同一笔 `Payment-Proof` 重试履约确认。
|
|
213
|
+
|
|
214
|
+
### 第五步:测试结论
|
|
215
|
+
|
|
216
|
+
测试通过后输出:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
✅ 按量付费沙箱全链路测试通过
|
|
220
|
+
|
|
221
|
+
| 测试项 | 状态 |
|
|
222
|
+
|--------|------|
|
|
223
|
+
| 402 Payment-Needed 返回 | ✅ |
|
|
224
|
+
| 沙箱收银台付款 | ✅ |
|
|
225
|
+
| Payment-Proof 重试 | ✅ |
|
|
226
|
+
| 资源交付 | ✅ |
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## 已有 Payment-Needed 值(可选)
|
|
232
|
+
|
|
233
|
+
如果用户已经提供了 `Payment-Needed` 响应头值(如之前已从其他渠道获取),可以通过 `--payment-needed` 参数直接传入,跳过对用户服务的首次请求:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
python3 ../scripts/local_402_sandbox_pay.py run --url "$SERVICE_URL" --method GET --buyer-id "$BUYER_2088" --payment-needed "$PAYMENT_NEEDED_VALUE"
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
脚本将直接解码该值并继续后续流程,不再发起 curl 请求。
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## 注意事项
|
|
244
|
+
|
|
245
|
+
1. **沙箱收银接口**:脚本默认使用 `http://aicashier.dl.alipaydev.com/openclawpay/agent/v1/pay`,此地址已硬编码在脚本中
|
|
246
|
+
2. **付款链接**:前缀为 `https://render.alipay.com/p/yuyan/180020010001290755/pay.html?schema=`,通过 URL 编码的 `payScheme` 拼接
|
|
247
|
+
3. **过程产物**:默认写入 `/tmp/alipay_local_402_sandbox_pay_<timestamp>`,可通过 `--artifact-dir` 指定
|
|
248
|
+
4. **买家签名**:默认占位值 `-`,无需修改
|
|
249
|
+
5. **沙箱化 Agent 网络权限**:脚本内 `fetch_payment_needed` 使用 curl,且收银测试会访问沙箱接口;沙箱化 Agent 环境首次执行即申请可联网权限
|
|
250
|
+
6. **沙箱支付宝安装包**:沙箱支付宝当前仅支持安卓系统;如无法完成付款,引导用户复制 `https://mdn.alipayobjects.com/sandboxsys/afts/img/_itHRrdOD9oAAAAAAAAAAAAADgSLAQBr/original` 到网页浏览器打开,并使用支付宝客户端扫码下载沙箱版支付宝安装包
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 脚本内部流程概要
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
用户服务 (无 Payment-Proof)
|
|
258
|
+
↓ HTTP 402 + Payment-Needed (base64 JSON)
|
|
259
|
+
脚本提取并解码
|
|
260
|
+
↓ snake_case → camelCase + 补充买家ID
|
|
261
|
+
沙箱收银接口
|
|
262
|
+
↓ payScheme
|
|
263
|
+
浏览器付款链接
|
|
264
|
+
↓ 用户扫码/登录付款
|
|
265
|
+
脚本构建 Payment-Proof
|
|
266
|
+
↓ base64(protocol + method)
|
|
267
|
+
重试用户服务
|
|
268
|
+
↓ HTTP 200 + 资源内容
|
|
269
|
+
验证通过 ✅
|
|
270
|
+
```
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Alipay Sandbox Tool
|
|
2
|
+
|
|
3
|
+
提供沙箱能力:**创建快速沙箱**。
|
|
4
|
+
|
|
5
|
+
## 1. 环境检测
|
|
6
|
+
|
|
7
|
+
> ⚠️ **前置要求**:在调用沙箱工具前,必须先按 `../../../normal/alipay-cli-env.md` 完成 alipay-cli 检测与安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
which alipay-cli 2>/dev/null && alipay-cli version
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> 📎 详细检测、安装、验证流程及环境检测结果不透出规范见 `../../../normal/alipay-cli-env.md`
|
|
14
|
+
|
|
15
|
+
## 2. 创建快速沙箱
|
|
16
|
+
|
|
17
|
+
**重要:输出时必须完整展示所有字段,不允许省略 privateKey、publicKey 等长字段。如果输出被截断,需按 `sandbox-setup-guide.md` 的表格格式重新输出完整字段。**
|
|
18
|
+
|
|
19
|
+
`createAnonymousSandbox` 的 MCP 请求体只有业务入参 `request.appType`。`PLATFORM`、`PRODUCT` 是 alipay-cli 上下文环境变量,禁止写入 `--data` 的 JSON。
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
PLATFORM="<PLATFORM>" \
|
|
23
|
+
PRODUCT="<PRODUCT>" \
|
|
24
|
+
alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox \
|
|
25
|
+
--data '{"request":{"appType":"<APP_TYPE>"}}' \
|
|
26
|
+
--json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**参数推断:**
|
|
30
|
+
|
|
31
|
+
| 用户关键词 | appType |
|
|
32
|
+
|------|------|
|
|
33
|
+
| 网页应用、移动应用、按量付费 | PUBLICAPP |
|
|
34
|
+
|
|
35
|
+
**上下文变量:**
|
|
36
|
+
|
|
37
|
+
| 变量 | 来源 | 取值规则 |
|
|
38
|
+
|------|------|----------|
|
|
39
|
+
| `PLATFORM` | AI 编程工具识别结果 | 参考通用脚本 `../../../normal/scripts/detect_dev_tool.sh` 识别当前工具后使用其输出值;缺失时使用 `unknown`。例如 Codex 环境检测结果为 `codex` |
|
|
40
|
+
| `PRODUCT` | 当前 Skill 产品名称 | `按量付费` / `网站支付` / `APP支付`。用户说“手机网站支付”“H5支付”“PC网页支付”时,按本 Skill 术语归一为 `网站支付` |
|
|
41
|
+
|
|
42
|
+
> `PRODUCT` 不是 `createAnonymousSandbox` 的 MCP 请求体字段,仅作为 alipay-cli 上下文变量传入。Skill 内按产品决策结果归一为上表中的产品名。
|
|
43
|
+
|
|
44
|
+
**Codex 环境示例:**
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
PLATFORM=codex \
|
|
48
|
+
PRODUCT="网站支付" \
|
|
49
|
+
alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox \
|
|
50
|
+
--data '{"request":{"appType":"PUBLICAPP"}}' \
|
|
51
|
+
--json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**结果解析:**
|
|
55
|
+
|
|
56
|
+
1. 取 `result.content[0].text`,去转义还原 JSON
|
|
57
|
+
2. `success === true` → 输出简短成功提示,将 `data` 字段**完整原样**按 [沙箱环境初始化](sandbox-setup-guide.md) 中的沙箱信息输出格式以表格展示,保持原始字段值不变,不做任何脱敏、省略或重排
|
|
58
|
+
3. `success !== true` → 按错误处理流程
|
|
59
|
+
|
|
60
|
+
## 3. 错误处理
|
|
61
|
+
|
|
62
|
+
CLI 输出不暴露 HTTP 状态码,统一按响应体中的 `success` 字段判断:
|
|
63
|
+
|
|
64
|
+
| 条件 | 策略 |
|
|
65
|
+
|------|------|
|
|
66
|
+
| `success === false` 且 `msg` 含"证书密钥"等临时错误 | 静默等待 2 秒后自动重试 1 次,仍失败则展示 `errorCode`、`msg`/`resultMsg`、`traceId` |
|
|
67
|
+
| `success === false` 且 `msg` 含"版本过旧"或 CLI 退出码非 0 | 不重试,友好提示"服务不可用,可能是 CLI 版本过旧",询问用户是否升级 CLI |
|
|
68
|
+
| CLI 执行超时或网络错误 | 最多重试 2 次 |
|
|
69
|
+
|
|
70
|
+
所有失败均提取 traceId 展示给用户。
|
|
71
|
+
|
|
72
|
+
## 4. 注意事项
|
|
73
|
+
|
|
74
|
+
- 执行前向用户展示即将运行的命令
|
|
75
|
+
- 参数不确定时先向用户确认
|
|
76
|
+
|
|
77
|
+
## 返回示例
|
|
78
|
+
|
|
79
|
+
### 成功示例
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"appIds": [
|
|
84
|
+
{
|
|
85
|
+
"alipayPublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...",
|
|
86
|
+
"appId": "9021000162691374",
|
|
87
|
+
"appPrivateKey": "MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...",
|
|
88
|
+
"appPrivatePkcsKey": "MIIEpAIBAAKCAQEA...",
|
|
89
|
+
"appPublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...",
|
|
90
|
+
"pid": "2088721100529696",
|
|
91
|
+
"type": null,
|
|
92
|
+
"uid": null
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
"isClaimed": false,
|
|
96
|
+
"sandboxAccounts": {
|
|
97
|
+
"partner": {
|
|
98
|
+
"accountDesc": "商家账号",
|
|
99
|
+
"acctrans": "1000000.00",
|
|
100
|
+
"email": "xxxxx@sandbox.com",
|
|
101
|
+
"merchantId": "221187076",
|
|
102
|
+
"userId": "2088721100529696"
|
|
103
|
+
},
|
|
104
|
+
"user": {
|
|
105
|
+
"accountDesc": "买家账号",
|
|
106
|
+
"acctrans": "1000000.00",
|
|
107
|
+
"email": "xxxxx@sandbox.com",
|
|
108
|
+
"userName": "xxxxx",
|
|
109
|
+
"userId": "2088722100508485",
|
|
110
|
+
"logonPassword": "111111",
|
|
111
|
+
"payPassword": "111111",
|
|
112
|
+
"certNo": "195109197300184083",
|
|
113
|
+
"certType": "IDENTITY_CARD"
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"sandboxId": "al1458801837b7495b",
|
|
117
|
+
"sandboxName": "匿名沙箱-al1458801837b7495b"
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 错误示例
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"data": null,
|
|
126
|
+
"errorCode": null,
|
|
127
|
+
"msg": "查询沙箱证书密钥信息失败",
|
|
128
|
+
"resultCode": null,
|
|
129
|
+
"resultMsg": null,
|
|
130
|
+
"success": false,
|
|
131
|
+
"traceId": "218f563417783158778985995e4b5d"
|
|
132
|
+
}
|
|
133
|
+
```
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# 沙箱环境初始化指南
|
|
2
|
+
|
|
3
|
+
本文档是沙箱环境配置的**单一可信来源**。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. 环境说明
|
|
8
|
+
|
|
9
|
+
### 1.1 快速沙箱优势
|
|
10
|
+
- ✅ **零配置启动**:无需登录支付宝开放平台,自动获取测试账号与密钥
|
|
11
|
+
- ✅ **即开即用**:全自动配置网关及应用信息
|
|
12
|
+
- ✅ **安全隔离**:测试环境不涉及真实资金,可放心调试
|
|
13
|
+
|
|
14
|
+
### 1.2 Windows 用户注意事项
|
|
15
|
+
**快速沙箱 CLI 工具暂不支持 Windows 系统**。
|
|
16
|
+
|
|
17
|
+
Windows 用户请前往支付宝开放平台(https://open.alipay.com)- 控制台 - 沙箱应用 自行获取沙箱信息。
|
|
18
|
+
|
|
19
|
+
### 1.3 其他说明
|
|
20
|
+
沙箱环境暂不支持用户主动通过看板查看测试账号的交易信息(如:卖家余额、交易状态等)。**严禁**引导用户访问所谓的“支付宝沙箱网页版”查看测试账户的余额变动等。
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. 密钥格式说明
|
|
25
|
+
|
|
26
|
+
| 语言 | 私钥格式 | 使用字段 |
|
|
27
|
+
|------|----------|----------|
|
|
28
|
+
| Java | PKCS#8 | `appPrivateKey` |
|
|
29
|
+
| 非 Java(Python、Node.js、PHP、.NET 等) | PKCS#1 | `appPrivatePkcsKey` |
|
|
30
|
+
|
|
31
|
+
**⚠️ 防误判提醒**:
|
|
32
|
+
- 沙箱配置直接使用沙箱返回的对应私钥字段;生产配置必须确认应用私钥格式与项目语言匹配
|
|
33
|
+
- 写入 SDK 配置的私钥值都使用不带 PEM 头尾或其他前后缀的原始密钥字符串,禁止手动添加 PEM 头尾、其他前后缀、包装行或说明文字
|
|
34
|
+
- 生产应用私钥格式与当前语言 SDK 要求不一致时,使用支付宝开放平台密钥工具做私钥格式转换后再配置
|
|
35
|
+
- 禁止因 `ERR_OSSL_UNSUPPORTED` 推断私钥格式有问题(通常是 SDK 配置参数错误)
|
|
36
|
+
- 详见 [SDK 说明文档 - 私钥格式](../alipay-sdk-reminder.md)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 3. 配置流程
|
|
41
|
+
|
|
42
|
+
### 3.1 调用工具创建环境
|
|
43
|
+
|
|
44
|
+
参考 [alipay-sandbox-tool](alipay-sandbox-tool.md) 创建快速沙箱环境。
|
|
45
|
+
|
|
46
|
+
**异常处理**:创建失败时提示 "❌ 快速沙箱创建失败,请稍后重试"。
|
|
47
|
+
|
|
48
|
+
### 3.2 沙箱信息输出格式
|
|
49
|
+
|
|
50
|
+
**必须按以下表格格式**输出,**严禁**使用 JSON 代码块。所有字段完整原样展示,不得脱敏、省略或截断。
|
|
51
|
+
|
|
52
|
+
**应用配置**
|
|
53
|
+
|
|
54
|
+
| 字段 | 说明 | 值 |
|
|
55
|
+
|------|------|-----|
|
|
56
|
+
| `appId` | 沙箱应用 ID | {实际返回值} |
|
|
57
|
+
| `appPrivateKey` | 应用私钥(PKCS#8,Java 语言使用) | {实际返回值} |
|
|
58
|
+
| `appPrivatePkcsKey` | 应用私钥(PKCS#1,非 Java 语言使用) | {实际返回值} |
|
|
59
|
+
| `alipayPublicKey` | 支付宝公钥 | {实际返回值} |
|
|
60
|
+
| `appPublicKey` | 应用公钥 | {实际返回值} |
|
|
61
|
+
| `pid` | 商户 PID | {实际返回值} |
|
|
62
|
+
|
|
63
|
+
**商家账号**
|
|
64
|
+
|
|
65
|
+
| 字段 | 值 |
|
|
66
|
+
|------|-----|
|
|
67
|
+
| `accountDesc` | {实际返回值} |
|
|
68
|
+
| `email` | {实际返回值} |
|
|
69
|
+
| `merchantId` | {实际返回值} |
|
|
70
|
+
| `userId` | {实际返回值} |
|
|
71
|
+
| `acctrans` | {实际返回值} |
|
|
72
|
+
|
|
73
|
+
**买家账号**
|
|
74
|
+
|
|
75
|
+
| 字段 | 值 |
|
|
76
|
+
|------|-----|
|
|
77
|
+
| `accountDesc` | {实际返回值} |
|
|
78
|
+
| `email` | {实际返回值} |
|
|
79
|
+
| `userName` | {实际返回值} |
|
|
80
|
+
| `userId` | {实际返回值} |
|
|
81
|
+
| `logonPassword` | {实际返回值} |
|
|
82
|
+
| `payPassword` | {实际返回值} |
|
|
83
|
+
| `certNo` | {实际返回值} |
|
|
84
|
+
| `certType` | {实际返回值} |
|
|
85
|
+
| `acctrans` | {实际返回值} |
|
|
86
|
+
|
|
87
|
+
**沙箱信息**
|
|
88
|
+
|
|
89
|
+
| 字段 | 值 |
|
|
90
|
+
|------|-----|
|
|
91
|
+
| `sandboxId` | {实际返回值} |
|
|
92
|
+
| `sandboxName` | {实际返回值} |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 4. 强校验规则(卡点)
|
|
97
|
+
|
|
98
|
+
工具返回环境信息后,**必须执行逐项强校验**,校验通过方可进入后续步骤。未通过则**阻断流程**,要求重新创建。
|
|
99
|
+
|
|
100
|
+
### 4.1 必含字段清单
|
|
101
|
+
|
|
102
|
+
以下字段必须全部存在且非空:
|
|
103
|
+
|
|
104
|
+
| 字段 | 说明 |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `appId` | 沙箱应用 ID |
|
|
107
|
+
| `appPrivateKey` / `appPrivatePkcsKey` | 应用私钥(Java 使用 `appPrivateKey`,非 Java 使用 `appPrivatePkcsKey`) |
|
|
108
|
+
| `alipayPublicKey` | 支付宝公钥 |
|
|
109
|
+
| `appPublicKey` | 应用公钥 |
|
|
110
|
+
| 商家账号 | 沙箱商家登录账号 |
|
|
111
|
+
| 买家账号 | 沙箱买家测试账号 |
|
|
112
|
+
|
|
113
|
+
### 4.2 绝对禁止(红线)
|
|
114
|
+
|
|
115
|
+
**以下行为严格禁止:**
|
|
116
|
+
|
|
117
|
+
1. **禁止编造字段** —— 不得生成、拼接、模拟、猜测缺失的字段值
|
|
118
|
+
2. **禁止用占位符冒充真实数据** —— 当沙箱成功返回完整配置时,禁止用占位符代替真实返回值
|
|
119
|
+
3. **禁止假数据** —— 不得自行生成示例私钥、示例账号等任何假数据
|
|
120
|
+
4. **禁止假设存在** —— 不得假设"工具返回的应该都有"而不逐项检查
|
|
121
|
+
5. **禁止部分通过** —— 不得因"只有 1 个字段缺失"而继续执行
|
|
122
|
+
6. **禁止跳过校验** —— 不得在未完成逐项校验的情况下直接使用返回结果
|
|
123
|
+
|
|
124
|
+
### 4.3 校验执行清单
|
|
125
|
+
|
|
126
|
+
**规则:** 任一字段缺失 → **立即停止** → 输出错误提示 → **禁止继续**
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
□ 检查 appId
|
|
130
|
+
IF 缺失:输出 "❌ 沙箱环境校验失败:appId 为空,无法继续集成,请重新创建沙箱环境。" → STOP
|
|
131
|
+
|
|
132
|
+
□ 检查应用私钥(根据语言选择)
|
|
133
|
+
- Java:检查 `appPrivateKey`(PKCS#8)
|
|
134
|
+
- 非 Java:检查 `appPrivatePkcsKey`(PKCS#1)
|
|
135
|
+
IF 缺失:输出 "❌ 沙箱环境校验失败:应用私钥字段为空,无法继续集成,请重新创建沙箱环境。" → STOP
|
|
136
|
+
|
|
137
|
+
□ 检查 alipayPublicKey / appPublicKey / 商家账号 / 买家账号
|
|
138
|
+
IF 任一缺失:输出对应字段缺失错误 → STOP
|
|
139
|
+
|
|
140
|
+
□ 全部通过 → 输出 "✅ 沙箱环境校验通过"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 4.3.1 配置写入后的后置校验
|
|
144
|
+
|
|
145
|
+
后续步骤将沙箱配置写入用户项目后,必须立即做配置准确性后置校验;校验失败时停止联调,先重新复制沙箱字段或修正 SDK 配置。必须确认以下目标:
|
|
146
|
+
|
|
147
|
+
- 确认写入项目的 `appId`、应用私钥、支付宝公钥来自同一份沙箱返回配置,且与沙箱返回配置一致。
|
|
148
|
+
- 确认应用私钥不是占位符、示例值或其他来源的密钥,未出现复制截断或粘贴污染。
|
|
149
|
+
- 检查 SDK 配置与私钥字段匹配:`appPrivatePkcsKey` 对应 PKCS#1,`appPrivateKey` 对应 PKCS#8。
|
|
150
|
+
- 检查写入 SDK 配置的私钥值不包含 PEM 头尾、其他前后缀、包装行或说明文字。
|
|
151
|
+
- 校验输出不得包含私钥、公钥、签名串或完整支付表单。
|
|
152
|
+
|
|
153
|
+
**常见失败处理:**
|
|
154
|
+
- 私钥不完整、配置不一致或 SDK 初始化/解析失败:重新复制完整私钥字段,禁止补字符、猜测或格式转换。
|
|
155
|
+
- `DECODER routines::unsupported`:优先检查私钥是否复制完整、是否错误添加 PEM 头尾或其他前后缀、`keyType` 是否错误,不要切换成 PKCS#8 试错。
|
|
156
|
+
|
|
157
|
+
### 4.4 重试与失败处理
|
|
158
|
+
|
|
159
|
+
| 失败场景 | 处理策略 |
|
|
160
|
+
|---------|---------|
|
|
161
|
+
| 首次失败 | 提示 "❌ 快速沙箱创建失败,请稍后重试",等待用户指示后重试 |
|
|
162
|
+
| 字段缺失 | 明确告知**具体缺失字段名称**,禁止只说"部分字段缺失" |
|
|
163
|
+
| 反复失败(≥2次) | 输出强提醒,提供两个选项:①重新输入指令 ②自行申领沙箱应用,禁止继续自动重试 |
|
|
164
|
+
| 用户提供手动配置 | 仍需按「校验执行清单」逐项校验,通过后方可继续 |
|
|
165
|
+
|
|
166
|
+
**反复失败提示模板**:
|
|
167
|
+
```
|
|
168
|
+
🚨 快速沙箱环境多次创建失败/字段不完整
|
|
169
|
+
|
|
170
|
+
缺失字段:[列出具体缺失的字段名称]
|
|
171
|
+
|
|
172
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
173
|
+
请您选择以下方式之一解决:
|
|
174
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
175
|
+
|
|
176
|
+
【选项一】重新输入创建快速沙箱指令
|
|
177
|
+
操作方式:在对话中重新输入"创建快速沙箱"或类似指令
|
|
178
|
+
适用场景:可能因服务波动导致创建失败,稍后重试可能成功
|
|
179
|
+
|
|
180
|
+
【选项二】自行申领沙箱应用
|
|
181
|
+
操作方式:前往支付宝开放平台(https://open.alipay.com)手动申领沙箱应用
|
|
182
|
+
适用场景:需要使用自己的沙箱账号,获取 appId、应用私钥、支付宝公钥等信息后手动配置
|
|
183
|
+
|
|
184
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
185
|
+
⚠️ 在配置完整之前,无法继续集成流程。
|
|
186
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 5. 成功创建后提示(卡点)
|
|
192
|
+
|
|
193
|
+
**⛔ 强制要求:校验通过后,必须在回复中完整输出以下内容。**
|
|
194
|
+
|
|
195
|
+
- **禁止省略**:不得跳过、缩减
|
|
196
|
+
- **禁止改写**:必须按原文输出
|
|
197
|
+
- **未输出此提示即继续 = 违规**
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
⚠️ 快速沙箱环境已创建完成
|
|
201
|
+
|
|
202
|
+
📌 环境说明
|
|
203
|
+
- 当前快速沙箱环境仅供测试,不涉及真实资金
|
|
204
|
+
- 完整展示沙箱信息,无需对内容脱敏
|
|
205
|
+
- 切勿在项目日志中打印私钥信息
|
|
206
|
+
- 切勿提交正式环境、沙箱环境信息至公共代码仓库(GitHub、GitLab 等)
|
|
207
|
+
|
|
208
|
+
🔔 必做操作
|
|
209
|
+
- 请自行妥善保管密钥及测试账号等信息
|
|
210
|
+
|
|
211
|
+
🔒 安全提醒
|
|
212
|
+
- 正式上线前请确保您已拥有正式的应用 appId、经过审核的应用私钥及支付宝公钥,并切换至正式环境重新配置密钥
|
|
213
|
+
- 替换生产配置或启动生产支付测试前,确认 `appId`、应用公钥、应用私钥属于同一套生产应用密钥,并根据项目语言确认私钥格式正确;格式不匹配时使用支付宝开放平台密钥工具转换
|
|
214
|
+
- 正式环境网关地址:https://openapi.alipay.com/gateway.do
|
|
215
|
+
- 正式环境涉及真实资金交易,强烈建议在正式上线之前在沙箱环境中完成全链路测试
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**输出检查:** 确认包含 ⚠️📌🔔🔒 四个标记及全部内容后,方可继续后续集成步骤。
|