# 线下收款登记(司机现场代收人 / 对公转账) - **变更日期**: 2026-07-07 - **端类型**: 管理后台 - **变更类型**: 新增接口 - **Issue**: https://git.1814.love:8443/wx/HL/issues/4763 - **PR**: https://git.1814.love:8443/wx/HL/pulls/4766 --- ## 1. 接口背景 核单 epic PR1。核单流程中,定制师需要记录非微信支付渠道的线下收款(司机现场代收人现金、对公转账),并确保订单 `paid_amount` 实时更新。 登记成功后事务层推进 `paid_amount` 累加并重算 `pay_status`(PARTIAL_PAID/FULLY_PAID)。 已撤销的凭据行保留在列表供审计溯源。 --- ## 2. 变更清单 | 序号 | 方法 | 路径 | 说明 | |------|------|------|------| | 1 | POST | `/v3/admin/order/{orderId}/payment/manual-receipt` | 登记线下收款 | | 2 | DELETE | `/v3/admin/order/{orderId}/payment/manual-receipt/{receiptId}` | 撤销线下收款(转删,行保留) | | 3 | GET | `/v3/admin/order/{orderId}/payment/manual-receipt` | 查询订单线下收款列表 | --- ## 3. 接口详情 | 项 | 说明 | |-----|------| | 认证 | JWT Bearer(管理端), Gateway 注入 X-Admin-Id/X-Admin-RealName | | 幂等性 | POST 非幂等; DELETE 幂等守卫(已撤销返 520406) | | 限流 | 网关全局限流 | | 订单状态白名单 | 仅 CANCELLED 拒绝,其余状态(含已结算)均可登记 | --- ## 4. 接口入参 ### 4.1 路径参数(三个接口通用) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | orderId | Long | 是 | 订单 ID | DELETE 额外路径参数: receiptId (Long, 必, 凭据 ID 由 POST 响应获取) ### 4.2 请求体(POST) | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | channel | String | 是 | 收款渠道: DRIVER_CASH/BANK_TRANSFER | | payType | String | 是 | 款项类型: DEPOSIT/BALANCE/FULL | | amount | BigDecimal | 是 | >0 | | receivedAt | LocalDateTime | 否 | 可补录历史,不传默认当前 | | transferRef | String | 条件必填 | `BANK_TRANSFER`时必填 | | collectorStaffId | Long | 条件必填 | `DRIVER_CASH`时必填且属本订单人员 | | voucherUrls | List | 否 | 凭证图片 URL | | remark | String | 否 | 备注, max 500 | **DELETE 请求体**: voidReason (String, 否, 撤销原因) --- ## 5. 出参字段 POST/DELETE 返回单条 `ManualReceiptVO`,GET 返回 `List`。 > `paidAmountAfter`/`payStatusAfter` 仅在 POST/DELETE 响应有値,GET 列表为 null。 | 字段 | 类型 | 说明 | |------|------|------| | id | String(Long) | 凭据 ID(雪花序列化) | | orderId | String(Long) | 订单 ID | | channel | String | DRIVER_CASH/BANK_TRANSFER | | channelLabel | String | 渠道显示标签 | | payType | String | DEPOSIT/BALANCE/FULL | | payTypeLabel | String | 款项显示标签 | | amount | BigDecimal | 收款金额 | | receivedAt | LocalDateTime | 收款时间 | | collectorStaffId | String(Long) | 代收人 assignmentId, 仅 DRIVER_CASH 有値 | | collectorStaffName | String | 代收人姓名, 仅 DRIVER_CASH 有値 | | transferRef | String | 流水号, 仅 BANK_TRANSFER 有値 | | voucherUrls | List | 凭证图片 URL | | remark | String | 备注 | | operatorName | String | 登记人姓名 | | createTime | LocalDateTime | 登记时间 | | voided | Boolean | 是否已撤销 | | voidedByName/voidedAt/voidReason | - | 撤销时有値 | | paidAmountAfter | BigDecimal | 操作后订单累计已付金额, GET 为 null | | payStatusAfter | String | 操作后订单支付状态, GET 为 null | --- ## 6. 枚举/数据字典 **channel:** DRIVER_CASH(司机现场代收人) / BANK_TRANSFER(对公转账) **payType:** DEPOSIT(订金) / BALANCE(尾款) / FULL(全款) **payStatusAfter:** UNPAID(未付款) / PARTIAL_PAID(已付订金) / FULLY_PAID(已付全款) --- ## 7. 错误码 | 错误码 | 含义 | 触发场景 | |--------|------|---------| | 520401 | 收款渠道非法 | channel not DRIVER_CASH/BANK_TRANSFER | | 520402 | 对公转账必填转账流水号 | channel=BANK_TRANSFER & transferRef 为空 | | 520403 | 必须指定代收人 | channel=DRIVER_CASH & collectorStaffId 为空 | | 520404 | 代收人不属本订单人员 | collectorStaffId 不在order_staff_assignment中 | | 520405 | 凭据不存在 | receiptId 非法 | | 520406 | 已撤销,无法重复 | 对已撤销行再 DELETE | | 520407 | 订单已取消,不允许登记 | 订单状态为 CANCELLED | | 520408 | 收款金额必须>0 | amount<=0 | --- ## 8. 示例 ### 8.1 典型成功 -- 登记司机现场代收人尾款 请求: ```http POST /v3/admin/order/1234567890123456/payment/manual-receipt Content-Type: application/json X-Admin-RealName: 扎西师傅 { "channel": "DRIVER_CASH", "payType": "BALANCE", "amount": 8800.00, "collectorStaffId": "9800001001", "remark": "客户现场支付尾款" } ``` 响应: ```json { "code": 200, "data": { "id": "1900000001000001", "channelLabel": "司机现场代收人", "payTypeLabel": "尾款", "amount": 8800.00, "collectorStaffName": "扎西师傅", "voided": false, "paidAmountAfter": 24800.00, "payStatusAfter": "FULLY_PAID" } } ``` ### 8.2 边界 -- 对公转账,补录历史时间 ```json { "channel": "BANK_TRANSFER", "payType": "DEPOSIT", "amount": 5000.00, "receivedAt": "2026-06-20T10:00:00", "transferRef": "GZL20260620001" } ``` 返回: paidAmountAfter 为当前累计已付金额。 ### 8.3 业务失败 -- DRIVER_CASH 未指定代收人 ```json { "channel": "DRIVER_CASH", "amount": 3000.00 } ``` ```json { "code": 520403, "msg": "司机现场必须指定代收人" } ``` --- ## 9. 业务边界 **适用:** 客户现金付款 / 对公转账补录 **不适用:** 微信支付/支付宝 / 订单已取消 **特殊边界:** - 同一订单可登记多条,每条独立计入`paid_amount` - 撤销后`paid_amount`同事务回退,行记录保留 - paidAmountAfter/payStatusAfter 仅在 POST/DELETE 响应, GET 列表为 null --- ## 12. 注意事项 - id/orderId 均为 Long 雪花,序列化为字符串,前端禁 Number - collectorStaffId 属于本订单人员配置(order_staff_assignment)中选取 - 登记后在核单对账页查看`paid_amount`,需重请 GET /v3/admin/order/{orderId}/settlement/recon --- ## 13. 关联/联系人 - Issue: https://git.1814.love:8443/wx/HL/issues/4763 - PR: https://git.1814.love:8443/wx/HL/pulls/4766 - Commit: https://git.1814.love:8443/wx/HL/commit/076bd285a5cc87665fdf431f9fe0a704dcdd7a33 - 后端负责人: 腰苏图