租借、弹出与归还
协议把选宝、支付、物理弹出、归还检测、服务端确认分成独立步骤,不能压缩成一个成功状态。
通用租借结果字段
设备的选宝/弹出回复包含:
result,slotId,powerBankId,battery,lockState,fastCharge
result | 含义 |
|---|---|
0 | 无符合条件的充电宝 / 选择失败 |
1 | 当前指令阶段选择或弹出成功 |
2 | 锁已打开,等待用户取走 |
100 | 用户超时未取走,锁已关闭 |
110 | 开锁失败;槽位在重启前进入最低租借优先级 |
fastCharge:0 普通,1 22 W,2 未知,3 45 W,4 65 W。
机柜按订单 ID 缓存最近一次结果。使用同一订单 ID 重试同一指令时,必须返回缓存结果,不能再次弹出。
BW: 准备租借
支付前使用 BW,让机柜选择符合条件的充电宝,但暂不弹出。
下行: {BW,messageId,orderId,<rentalProfile>,crc}
不带 rentalProfile 的上行: {BW,sameMessageId,orderId,result,slotId,powerBankId,battery,lockState,fastCharge,crc}
v1.51 原始配置中带 rentalProfile 的上行: {KW,sameMessageId,orderId,result,slotId,powerBankId,battery,lockState,fastCharge,crc}
下行确认: {BR,newMessageId,orderId,crc}
rentalProfile 可以省略;0 请求普通充电宝,1 请求快充充电宝。
v1.51 原始配置规定,带可选租借参数时回复名为 KW,不带时回复名为 BW。对接方应针对同一订单 ID 同时接受两种回复名,并记录设备配置;完成 UAT 前不要擅自改变设备发出的指令名。
准备完成后,服务端必须在 30 秒内使用新的消息 ID 发送 BR。这一步只确认选宝结果,不证明已经物理弹出。窗口超时后,应在支付完成时使用 FB 触发弹出。
KW: 准备快充租借
下行: {KW,messageId,orderId,rentalProfile,crc}
上行选宝结果: {KW,sameMessageId,orderId,result,slotId,powerBankId,battery,lockState,fastCharge,crc}
下行选宝确认: {BR,newMessageId,orderId,crc}
物理弹出后的上行: {FB,sameMessageId,orderId,result,slotId,powerBankId,battery,lockState,fastCharge,crc}
下行弹出确认: {BR,newMessageId,orderId,crc}
rentalProfile=0 请求普通充电宝,1 请求快充。最终物理动作仍使用 FB 上报。
FB: 弹出充电宝
下行: {FB,messageId,orderId,slotId,crc}
上行: {FB,sameMessageId,orderId,result,slotId,powerBankId,battery,lockState,fastCharge,crc}
下行确认: {BR,newMessageId,orderId,crc}
正数 slotId 表示弹出指定槽位。v1.51 对 slotId=0 的原始表述存在歧义,只有在具体机柜配置通过 UAT 后,才能把它作为自动选择使用。生产服务端应优先使用 BW 或 KW 已选出的正数槽位。
库存应在 FB 物理结果后更新,而不是在支付或选宝阶段更新。
BR: 租借确认
{BR,newMessageId,orderId,crc}
BR 根据订单当前阶段,确认选宝结果或最终 FB 结果。要求:
- 使用相同订单 ID。
- 使用新的、单调递增的消息 ID。
- 保存本次确认对应的业务阶段。
- 对设备重复上报进行幂等确认。
- 没有有效的物理弹出结果时,不能把订单标记为租借中。
推荐的支付安全流程
- 创建唯一订单 ID。
- 发送
BW或KW。 - 校验并保存选宝结果。
- 在 30 秒内用新消息 ID 发送
BR。 - 只有存在可用选宝结果后才调起支付。
- 支付成功后,用已选出的正数槽位发送
FB。 - 保存
FB物理结果,再发送一次BR。 - 只有有效弹出成功后才把订单标记为租借中。
- 支付成功但弹出失败时,进入已配置的退款/对账流程。
五秒内没有收到选宝回复时,页面可以让用户使用同一订单 ID重试。用户退出时应取消该订单 ID。禁止盲目重试时生成新订单 ID。
RS: 归还上报
v1.51 的格式行漏写了 deviceId,但示例和字段说明都包含它。可互操作的规范格式为:
上行: {RS,lastMessageId,deviceId,result,slotId,powerBankId,battery,lockState,fastCharge,crc}
下行确认: {RS,newMessageId,slotNumber,confirmCode,crc}
result | 含义 |
|---|---|
0 | 归还失败 |
1 | 成功检测到归还 |
2 | 机柜离线期间发生归还 |
| 确认字段 | 含义 |
|---|---|
slotNumber>0 | 确认单个槽位 |
slotNumber=0 | 批量确认模式 |
confirmCode=1 | 服务端确认归还正常 |
confirmCode=0 | 服务端确认归还异常 |
槽位为 0 且 confirmCode=totalSlots | 批量确认全部槽位 |
收到确认前,AC.returnState 保持 0。只有服务端接受归还并且计费状态一致后,归还才算完成对账。
FR: 异常归还上报
规范格式同样包含设备 ID:
上行: {FR,lastMessageId,deviceId,result,slotId,powerBankId,battery,lockState,cableState,crc}
下行确认: {RS,newMessageId,slotNumber,confirmCode,crc}
result | 含义 |
|---|---|
2 | 锁未完全到位 |
4 | 充电宝 ID 前缀与已配置品牌不匹配 |
FR 使用 RS 确认,而不是 FR。确认后仍需保留异常原因;确认只表示“已接收并分类”,不表示硬件恢复正常。