## 获取收钱吧提供的资料
| 资料 | 来源 | 开发时的用途 |
| ----------------- | ---------------------------- | ---------------------------------------------- |
| `vendor_sn` | 收钱吧提供 | 标识接入方开发者,仅在激活终端时作为签名序列号 |
| `vendor_key` | 收钱吧提供 | 生成激活请求签名 |
| `app_id` | 收钱吧提供 | 标识本次激活对应的应用 |
| 测试激活码 `code` | 收钱吧提供 | 在测试门店下生成测试终端 |
| 正式激活码 `code` | 上线前由收钱吧或商户后台提供 | 在正式门店下生成正式终端 |
| API接入域名 | 开放平台 | 拼接标准接口请求地址 |
> `vendor_sn`、`vendor_key`和`app_id`不是支付接口的调用凭证。它们用于激活终端;激活成功后,支付、查询和退款使用返回的`terminal_sn`和`terminal_key`。
收到参数后应保存到服务端安全配置或密钥管理系统,不得放进前端代码、二维码、公开代码仓库或普通业务日志。
## 准备商户系统能力
| 能力 | 准备要求 |
| ------------ | ------------------------------------------------------------ |
| 设备标识 | 为每台商户设备生成稳定且全局唯一的`device_id` |
| 商户订单号 | 每次支付使用能够在商户系统中唯一定位业务订单的编号 |
| 回调地址 | 准备可被收钱吧公网访问的HTTPS地址,支持验签、重复通知和幂等处理 |
| 真实公网IP | 按支付场景取得顾客手机或收银设备的真实公网IP |
| 终端参数存储 | 安全保存`terminal_sn`、`terminal_key`及其所属门店和设备 |
| 订单状态 | 能够保存支付中、成功、失败、结果未知和退款等状态 |
| 主动查询 | 支付请求超时或返回非最终状态时,能够在后台查询原订单 |
`device_id`必须稳定且全局唯一,不得在不同应用、门店或设备之间重复使用。设备更换或终端关系需要重建时,应按照终端恢复流程处理,不要直接复用其他设备的`device_id`或终端参数。
## 建立参数关联关系
系统中至少要保存以下归属关系:
```text
开发者
└── 应用
└── 商户
└── 门店
├── 商户设备A(全局唯一device_id)
│ └── 收钱吧终端A(terminal_sn、terminal_key)
└── 商户设备B(全局唯一device_id)
└── 收钱吧终端B(terminal_sn、terminal_key)
```
建议为每个终端保存:
- 商户和门店的内部编号。
- `app_id`和`device_id`。
- `terminal_sn`和加密后的`terminal_key`。
- 凭证更新时间和当前状态。
不要把一套终端参数作为所有门店共用的全局配置。否则多门店、多设备运行时无法确定交易归属,签到更新密钥时也可能影响其他设备。
## 激活终端
支付、查询和退款使用收钱吧终端参数。在开发具体支付场景前,先为测试门店的实际设备激活终端。
```text
准备app_id、测试激活码和device_id
→ 使用vendor_sn和vendor_key签名
→ 调用激活接口
→ 读取terminal_sn和terminal_key
→ 与应用、门店和device_id绑定保存
```
### 准备激活参数
| 数据 | 从哪里取得 | 用于什么 |
| ------------------------- | -------------------------- | ---------------- |
| `vendor_sn`、`vendor_key` | 收钱吧提供 | 对激活请求签名 |
| `app_id` | 收钱吧提供 | 指定终端所属应用 |
| `code` | 目标测试或正式门店的激活码 | 指定终端所属门店 |
| `device_id` | 商户系统生成 | 标识实际收款设备 |
同一门店增加设备时,可以在激活码仍有效且有剩余次数的情况下使用同一个激活码,但每台设备必须使用不同且全局唯一的`device_id`。
### 调用激活接口
使用`vendor_sn`作为签名序列号、`vendor_key`作为签名密钥,调用**[激活接口](https://open.shouqianba.com/docs/payment/67?category_id=58)**。
先按[交易结果与异常处理](https://open.shouqianba.com/docs/payment/77)判断通信结果和业务结果。只有确认激活成功后,才读取响应中的`terminal_sn`和`terminal_key`。
### 保存终端参数
激活成功后,将`terminal_sn`和`terminal_key`与当前`app_id`、门店、设备和`device_id`一起保存。终端密钥应加密存储;保存成功前,不允许该设备发起支付。
建议在同一事务内保存终端号、终端密钥和启用状态,避免业务节点读取到不完整的终端配置。
### 处理激活异常
- 明确失败:按错误信息修正参数,不保存终端参数。
- 超时或响应无法解析:先确认原设备是否已生成终端,不要更换`device_id`盲目重试。
- 提示设备已激活:恢复原设备与终端的关系,不生成随机`device_id`绕过。
- 激活码过期或次数不足:取得目标门店的新激活码。
- 终端参数遗失:联系收钱吧确认恢复或解绑方案后再激活。
## 签到并更新终端密钥
签到用于取得最新终端密钥。建议每天首次交易前执行。
```text
读取当前terminal_sn和terminal_key
→ 使用当前终端参数签名
→ 调用签到接口
→ 校验响应
→ 原子保存返回的最新终端参数
→ 所有业务节点切换到新密钥
```
### 调用签到接口
使用当前`terminal_sn`和`terminal_key`签名,提交激活时使用的同一个`device_id`,调用**[签到接口](https://open.shouqianba.com/docs/payment/68?category_id=58)**。
不要提前删除旧密钥。收到并校验签到成功响应后,再替换本地终端参数。
### 原子更新密钥
- 在同一事务中保存响应中的最新`terminal_sn`和`terminal_key`。
- 提交成功后,才允许新交易读取新密钥。
- 集群部署时从共享数据库或密钥服务读取,不由各节点单独维护。
- 确认业务节点已切换后,再结束本次签到任务。
### 处理签到结果未知
签到请求超时后,无法直接判断服务端是否已经更新密钥。此时:
- 暂停该终端的后续签到任务,保留当前本地参数。
- 排除网络问题后,使用本地保存的终端参数再次签到。
- 获得成功响应后,原子保存响应中的最新密钥。
- 持续签名错误或仍无法确认时,停止自动重试并进入人工恢复流程。
- 批量签到发生共性异常时,暂停后续批次,避免扩大密钥不同步范围。
## 确认测试环境
- 中国大陆移动支付API使用`https://vsi-api.shouqianba.com`。
- 测试激活码对应收钱吧提供的测试门店;正式上线时使用正式门店激活码重新生成终端。
- 测试和正式业务通常使用相同API域名,不能通过更换域名区分环境。
- 支付测试会产生真实交易,测试完成后应按原交易发起退款。
- 小程序支付还需完成商户与目标小程序的支付关系配置。
- 公众号与H5支付需要能够在目标钱包环境中打开页面并访问回调服务。
## 开发前检查
- [ ] 已确认支付场景。
- [ ] 已取得`vendor_sn`、`vendor_key`、`app_id`和测试激活码。
- [ ] 已定义全局唯一的`device_id`生成规则。
- [ ] 已建立门店、设备和终端参数的存储关系。
- [ ] 已调用激活接口并安全保存测试终端参数。
- [ ] 已验证签到成功后能够原子更新终端密钥。
- [ ] 所有业务节点能够读取同一份最新终端密钥。
- [ ] 服务端能够访问正确的API域名。
- [ ] 已准备唯一商户订单号。
- [ ] 支付回调地址可以从公网访问。
- [ ] 已确定当前场景的真实公网IP来源。
- [ ] 密钥不会进入前端、二维码、公开仓库或普通日志。