# [新增接口·管理后台] admin H5 客服代用户发起退款 (#2930) > **PR**: #2932 | **服务**: hl-order-service-v2 | **更新时间**: 2026-05-23 10:30 ## 1. 接口背景 管理后台 H5 客服操作台需要支持定制师/客服代用户发起退款申请。现有小程序端退款接口由用户自助发起,不适用客服代操作场景。 本接口允许客服在 H5 操作台手动填写退款金额并代用户提交,后端校验金额不超过订单订金金额,申请人留痕为 ADMIN 类型,创建后仍走主管审批流程。 ## 2. 变更清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 代用户发起退款申请 | POST | /admin/order/refund/apply | 新增 | 客服 H5 代用户提交退款,金额客服手填,不超订金 | ## 3. 接口详情 ### 3.1 代用户发起退款申请 - **使用场景**:客服在 H5 操作台查看订单后,代用户发起退款申请 - **认证**:需要管理后台 JWT(Bearer Token),adminId 由后端从 Token 中提取 - **幂等性**:是,Header 携带 `Idempotent-Key`(UUID),5 秒内重复提交视为同一请求 - **限流**:无 调用前置步骤:先调 `GET /admin/order/refund/reason/list` 获取退款原因字典,拿到 reasonValue(字典 key)和 reasonText(字典显示文本)后再调本接口。 ## 4. 接口入参 ### 4.1 路径参数 / Query 参数 无。 ### 4.2 请求体字段 | 字段 | 类型 | 必填 | 说明 | 校验规则 | |------|------|------|------|----------| | orderId | Long | 是 | 订单 ID | 不能为空 | | amount | BigDecimal | 是 | 退款金额 | 最小 0.01,且不能超过订单订金金额 | | reasonValue | String | 是 | 退款原因字典值 | 从 /admin/order/refund/reason/list 获取;最长 100 字符 | | reasonText | String | 是 | 退款原因文本 | 字典对应的显示文本;最长 500 字符 | | reasonDetail | String | 否 | 补充说明 | 最长 2000 字符 | 注意:refundType 无需前端传入,后端固定设置为 DEPOSIT(订金退款)。 ## 5. 出参(响应) ### 5.1 响应结构 `Result` ### 5.2 响应字段 | 字段 | 类型 | 说明 | |------|------|------| | applicationId | Long | 退款申请 ID | | orderId | Long | 订单 ID | | orderNo | String | 订单号 | | productName | String | 产品名称 | | refundType | String | 退款类型,本接口固定返回 DEPOSIT | | refundTypeLabel | String | 退款类型标签,固定返回 订金退款 | | reasonText | String | 退款原因文本 | | reasonDetail | String | 补充说明(可为 null) | | paidAmount | BigDecimal | 订单已付金额 | | calculatedAmount | BigDecimal | 本次退款金额(即客服填写的 amount) | | actualAmount | BigDecimal | 实际退款金额(审批后确认,初始为 null) | | status | String | 退款申请状态,创建后固定返回 PENDING | | statusLabel | String | 退款状态标签,创建后固定返回 待审核 | | applicantType | String | 申请人类型,固定返回 ADMIN | | applicantId | Long | 申请人管理员 ID | | applicantName | String | 申请人姓名 | | createTime | String (ISO 8601) | 申请创建时间 | | updateTime | String (ISO 8601) | 最后更新时间 | | reviewAdminId | Long | 审批人 ID(创建时为 null,审批后填充) | | reviewAdminName | String | 审批人姓名(创建时为 null) | | reviewRemark | String | 审批备注(创建时为 null) | | reviewedAt | String (ISO 8601) | 审批时间(创建时为 null) | | approvalNo | String | 审批单号(创建时为 null) | | departureDate | String (yyyy-MM-dd) | 出发日期 | | daysBeforeDept | Integer | 距出发天数 | | refundRatio | Integer | 退款比例(百分比,本接口为 null,不调退款政策) | | policyId | Long | 退款政策 ID(本接口为 null) | | policyName | String | 退款政策名称(本接口为 null) | | appealStatus | Integer | 申诉状态(创建时为 null) | | appealStatusLabel | String | 申诉状态标签(创建时为 null) | | appealReason | String | 申诉原因(创建时为 null) | | appealAmount | BigDecimal | 申诉退款金额(创建时为 null) | | appealedAt | String (ISO 8601) | 申诉时间(创建时为 null) | | refundedAt | String (ISO 8601) | 退款完成时间(创建时为 null) | 本接口创建的申请:policyId / policyName / refundRatio 均为 null(客服手填金额,不走退款政策计算)。 ## 6. 枚举 / 数据字典 ### 6.1 refundType(退款类型,出参字段) **所属字段**:refundType | **类型**:String | 本接口固定为 DEPOSIT | 值 | 中文 | 说明 | |----|------|------| | FULL | 全额退款 | 全额退还已付金额 | | PARTIAL | 部分退款 | 部分退款 | | DEPOSIT | 订金退款 | 仅退还订金部分,本接口固定此类型 | | BALANCE | 尾款退款 | 仅退还尾款部分 | ### 6.2 status(退款申请状态,出参字段) **所属字段**:status | **类型**:String | 创建后固定为 PENDING | 值 | 中文 | 说明 | |----|------|------| | PENDING | 待审核 | 申请已提交,等待主管审批 | | APPROVED | 已通过 | 主管审批通过,进入退款流程 | | REJECTED | 已拒绝 | 主管审批拒绝 | | APPEALING | 申诉中 | 用户对拒绝结果申诉 | | APPEAL_APPROVED | 申诉通过 | 申诉被通过 | | APPEAL_REJECTED | 申诉拒绝 | 申诉被拒绝 | | REFUNDING | 退款中 | 正在处理退款 | | REFUNDED | 已退款 | 退款已完成 | | CANCELLED | 已取消 | 申请已撤回取消 | 活跃状态(同订单已有此类状态时拒绝重复提交):PENDING / APPROVED / REFUNDING / APPEALING / APPEAL_APPROVED ### 6.3 applicantType(申请人类型,出参字段) **所属字段**:applicantType | **类型**:String | 本接口固定为 ADMIN | 值 | 中文 | 说明 | |----|------|------| | USER | 用户 | 小程序用户自助发起(mp 接口) | | ADMIN | 管理员 | 客服/定制师代发起(本接口) | ### 6.4 reasonValue(退款原因字典值,入参字段) **所属字段**:reasonValue | **类型**:String | **必填**:是 字典值通过 `GET /admin/order/refund/reason/list` 接口获取,下面为示例(以实际字典接口返回为准): | 值(示例) | 中文 | |-----------|------| | schedule_conflict | 行程冲突/时间变动 | | personal_reason | 个人原因 | | product_issue | 产品问题 | | service_complaint | 服务投诉 | 实际可用值以 `GET /admin/order/refund/reason/list` 返回为准。 ## 7. 错误码 | code | 含义 | 触发场景 | |------|------|----------| | 200 | 成功 | 退款申请创建成功 | | 401 | 未授权 | 未携带或 Token 无效/过期 | | 404 | 订单不存在 | orderId 对应的订单不存在 | | 530007 | 退款金额超过订金金额 | amount 大于订单 depositAmount,message 含具体金额:退款金额不能超过订金金额: amount={x}, deposit={y} | | 530004 | 重复退款申请 | 同一订单已存在 ACTIVE 状态的退款申请 | ## 8. 示例 ### 8.1 典型成功 场景说明:客服代用户发起订金退款,退 500 元,选择行程冲突原因。 请求: ``` POST /admin/order/refund/apply Authorization: Bearer Idempotent-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890 Content-Type: application/json ``` ```json { "orderId": 1234567890123, "amount": 500.00, "reasonValue": "schedule_conflict", "reasonText": "行程冲突/时间变动", "reasonDetail": "客户因工作变动无法出行,需要退款" } ``` 响应: ```json { "code": 200, "data": { "applicationId": 9876543210001, "orderId": 1234567890123, "orderNo": "HL2026052300001", "productName": "云南大理双廊古镇 5 日深度游", "refundType": "DEPOSIT", "refundTypeLabel": "订金退款", "reasonText": "行程冲突/时间变动", "reasonDetail": "客户因工作变动无法出行,需要退款", "paidAmount": 2000.00, "calculatedAmount": 500.00, "actualAmount": null, "policyId": null, "policyName": null, "refundRatio": null, "status": "PENDING", "statusLabel": "待审核", "applicantType": "ADMIN", "applicantId": 10086, "applicantName": "李小明", "departureDate": "2026-06-15", "daysBeforeDept": 23, "reviewAdminId": null, "reviewAdminName": null, "reviewRemark": null, "reviewedAt": null, "approvalNo": null, "appealStatus": null, "appealStatusLabel": null, "appealReason": null, "appealAmount": null, "appealedAt": null, "refundedAt": null, "createTime": "2026-05-23T10:30:00", "updateTime": "2026-05-23T10:30:00" }, "message": "ok", "success": true } ``` ### 8.2 边界情况 场景说明:退款金额等于订单订金金额上限(全额退订金),不填补充说明(reasonDetail 为 null)。 请求: ``` POST /admin/order/refund/apply Authorization: Bearer Idempotent-Key: b2c3d4e5-f6a7-8901-bcde-f12345678901 Content-Type: application/json ``` ```json { "orderId": 1234567890124, "amount": 2000.00, "reasonValue": "personal_reason", "reasonText": "个人原因", "reasonDetail": null } ``` 响应: ```json { "code": 200, "data": { "applicationId": 9876543210002, "orderId": 1234567890124, "orderNo": "HL2026052300002", "productName": "西藏拉萨布达拉宫 7 日游", "refundType": "DEPOSIT", "refundTypeLabel": "订金退款", "reasonText": "个人原因", "reasonDetail": null, "paidAmount": 5000.00, "calculatedAmount": 2000.00, "actualAmount": null, "policyId": null, "policyName": null, "refundRatio": null, "status": "PENDING", "statusLabel": "待审核", "applicantType": "ADMIN", "applicantId": 10086, "applicantName": "李小明", "departureDate": "2026-06-10", "daysBeforeDept": 18, "reviewAdminId": null, "reviewAdminName": null, "reviewRemark": null, "reviewedAt": null, "approvalNo": null, "createTime": "2026-05-23T10:35:00", "updateTime": "2026-05-23T10:35:00" }, "message": "ok", "success": true } ``` ### 8.3 业务失败(异常) 场景说明:退款金额超过订金金额,触发 530007 错误。 请求: ``` POST /admin/order/refund/apply Authorization: Bearer Idempotent-Key: c3d4e5f6-a7b8-9012-cdef-123456789012 Content-Type: application/json ``` ```json { "orderId": 1234567890123, "amount": 9999.00, "reasonValue": "personal_reason", "reasonText": "个人原因" } ``` 响应: ```json { "code": 530007, "message": "退款金额不能超过订金金额: amount=9999.00, deposit=2000.00", "success": false } ``` ## 9. 业务边界 - 适用场景:订单已支付(存在成功支付记录)时可发起退款申请 - 不适用场景: - 订单不存在 -> 返回 404 - 订单未支付 -> 后端校验失败,返回业务错误 - 同订单已有 ACTIVE 状态退款申请(PENDING/APPROVED/REFUNDING/APPEALING/APPEAL_APPROVED)-> 返回 530004 拒绝重复提交 - amount 超过订单订金金额 -> 返回 530007 - amount <= 0 -> 返回 400 参数校验失败 - 特殊边界: - 本接口不调退款政策计算,policyId/policyName/refundRatio 均为 null - 退款类型固定为 DEPOSIT,不允许客服指定其他类型 - 申请创建后状态固定为 PENDING,需走 `PUT /admin/order/refund/{applicationId}/review` 主管审批流程 - 5 秒内携带相同 Idempotent-Key 重复提交视为同一请求,返回第一次的结果(不重复创建) ## 10. 修改前后对比 全新接口,无修改前后对比。管理后台之前没有代用户发起退款的入口,本次为纯新增。 ## 11. 影响评估 / 回滚 - 是否破坏向后兼容:否(全新接口,旧代码无感知) - 前端是否必须同步上线:否(后端先上,前端可独立部署) ## 12. 注意事项 - Header 必须携带 `Idempotent-Key`(UUID 格式),防止客服误操作重复提交。前端在进入发起退款页时生成一个 UUID,整个提交流程复用同一个 key - 退款原因字典值需提前获取:调本接口前先调 `GET /admin/order/refund/reason/list` 拿到可用的 reasonValue 列表,不可自行填写字典 key - 金额校验上限为订单订金金额,超过返回 530007,message 含具体金额数值 - 提交成功后申请状态为 PENDING,可通过 applicationId 跳转至退款进度页,或按订单维度查询退款列表 ## 13. 关联 / 联系人 ### 13.1 链接 - **Issue**: [#2930](https://git.1814.love:8443/wx/HL/issues/2930) - **PR**: [#2932](https://git.1814.love:8443/wx/HL/pulls/2932) - **Merge commit**: [17e7fce90](https://git.1814.love:8443/wx/HL/commit/17e7fce90e5e4eb21e4e9c6bb4fb1d86e9c1fa21) - **实现 commit**: [ca5e1a366](https://git.1814.love:8443/wx/HL/commit/ca5e1a36647edb01ba6c7b1337c07149c41665cb) ### 13.2 联系人 - **后端负责人**: @yaosutu