143 lines
3.9 KiB
Markdown
143 lines
3.9 KiB
Markdown
# 支付+轮询+交付详细流程
|
||
|
||
## 3.1 获取 Payment-Needed
|
||
|
||
在创建订单后,调用获取支付参数接口:
|
||
|
||
```bash
|
||
curl -s -X POST "{STORE_BASE_URL}/api/orders/{orderNo}/payment-needed" \
|
||
-H "Accept: application/json" \
|
||
| grep -i "^Payment-Needed:" \
|
||
| sed "s/^[Pp]ayment-[Nn]eeded: //" \
|
||
| tr -d "\r\n" \
|
||
> 402_needed_file.txt
|
||
```
|
||
|
||
失败处理:
|
||
- 返回非 402 状态码或不包含 Payment-Needed 头 → 提示"获取支付参数失败" → 终止流程
|
||
|
||
## 3.2 提交支付
|
||
|
||
```bash
|
||
alipay-bot 402-buyer-pay \
|
||
--session-id "<session-uuid>" \
|
||
-f "402_needed_file.txt" \
|
||
-r "{STORE_BASE_URL}/api/orders/{orderNo}/payment-needed" \
|
||
--intent-summary "原始请求:用户购买软件订单:{orderNo}" \
|
||
-m POST
|
||
```
|
||
|
||
输出判断:
|
||
|
||
| CLI 输出 | 动作 |
|
||
|---------|------|
|
||
| 含 `✓ 支付待确认` + 二维码 | 展示给用户 → 进入 3.3 轮询 |
|
||
| 含 `✓ 支付成功并获取资源` | 跳过轮询 → 直接进入 Step 4 |
|
||
| 含 `✗ 支付失败` | 原样输出 → 终止 |
|
||
| 其他错误 JSON | 原样输出 errorMsg → 终止 |
|
||
|
||
可重试错误(最多3次):
|
||
- SERVER_TIMEOUT / CLIENT_TIMEOUT / SYSTEM_ERROR / SYSTEM_ERR
|
||
- POLL_INTERRUPTED / PAY_SUBMIT_FAILED / PAY_STATUS_UNKNOWN
|
||
|
||
不可重试错误(直接终止):
|
||
- SERVICE_SELLER_ID_MISMATCH(卖家ID不匹配)
|
||
- BUYER_SELLER_SAME(买家和卖家相同)
|
||
- REQUEST_EXPIRED(请求过期)
|
||
- 其他未识别错误码
|
||
|
||
## 3.3 自动轮询
|
||
|
||
支付发起后自动轮询,**不需要用户手动通知"已支付"**:
|
||
|
||
```python
|
||
import time, subprocess, json
|
||
|
||
def poll_payment_status(trade_no, resource_url, max_wait=180, interval=5):
|
||
"""自动轮询支付状态"""
|
||
elapsed = 0
|
||
|
||
while elapsed < max_wait:
|
||
time.sleep(interval)
|
||
elapsed += interval
|
||
|
||
# 执行查询命令
|
||
result = subprocess.run([
|
||
"alipay-bot", "402-query-payment-status",
|
||
"-t", trade_no,
|
||
"-r", resource_url,
|
||
"-m", "POST"
|
||
], capture_output=True, text=True)
|
||
|
||
try:
|
||
data = json.loads(result.stdout)
|
||
if data.get("success") == True:
|
||
return {"status": "success", "data": data}
|
||
except (json.JSONDecodeError, KeyError):
|
||
pass
|
||
|
||
# 每30秒输出进度
|
||
if elapsed % 30 == 0:
|
||
print(f"⏳ 正在等待支付确认...(已等待{elapsed}秒)")
|
||
|
||
return {"status": "timeout"}
|
||
```
|
||
|
||
轮询结果处理:
|
||
- success=true → 进入 Step 4 交付
|
||
- 超时 → 提示"支付等待超时,请稍后重试"
|
||
- 命令失败 → 重试1次,仍失败则终止
|
||
|
||
## Step 4:交付文件
|
||
|
||
### 4.1 获取交付链接(网盘链接)
|
||
|
||
```bash
|
||
# 构造 Payment-Proof
|
||
PROOF=$(python -c "
|
||
import json, base64
|
||
proof = {
|
||
'protocol': {'payment_proof': 'verified', 'trade_no': '<trade_no>'},
|
||
'method': {'client_session': base64.b64encode(b'agent-session').decode()},
|
||
}
|
||
print(base64.urlsafe_b64encode(json.dumps(proof).encode()).decode())
|
||
")
|
||
|
||
# 调用验证接口获取网盘链接
|
||
curl -s -X POST "{STORE_BASE_URL}/api/orders/{orderNo}/verify" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Payment-Proof: $PROOF" \
|
||
-d "{\"paymentProof\": \"$PROOF\"}"
|
||
```
|
||
|
||
### 4.2 履约回执
|
||
|
||
```bash
|
||
alipay-bot 402-buyer-fulfillment-ack -t '<trade_no>'
|
||
```
|
||
|
||
可重试错误(最多3次同 trade_no 重试):
|
||
- TR_FULFILLMENT_FAILED / FULFILLMENT_FAILED / SYSTEM_ERROR / SYSTEM_ERR
|
||
|
||
不可重试错误:
|
||
- 原样输出 errorMsg + trade_no → 终止
|
||
|
||
### 4.3 通知用户
|
||
|
||
```
|
||
✅ 支付成功!
|
||
订单号:{orderNo}
|
||
交易号:{trade_no}
|
||
|
||
🎉 您的软件提取信息如下:
|
||
🔗 网盘地址:{返回的 downloadUrl}
|
||
🔑 提取码:{若有提取码则展示}
|
||
|
||
⚠️ 注意:请在有效期内尽快保存或下载,不要分享给他人。
|
||
```
|
||
|
||
## 交易号校验
|
||
|
||
- 必须恰好 32 位纯数字
|
||
- 校验不通过 → 输出"交易号格式异常" → 立即终止
|
||
- 禁止对非32位 trade_no 执行任何后续命令 |