From 77a1c4a78044d1c22e749c10b7045ce055971b2e Mon Sep 17 00:00:00 2001 From: yaosutu <770858045@qq.com> Date: Mon, 22 Jun 2026 00:26:20 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9E=20order-v3=20?= =?UTF-8?q?=E9=80=80=E6=AC=BE=E5=9F=9F=E7=AE=A1=E7=90=86=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=AF=B4=E6=98=8E=EF=BC=88=E6=94=BF=E7=AD=96?= =?UTF-8?q?/=E5=8E=9F=E5=9B=A0/=E7=94=B3=E8=AF=B7=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E5=85=B1=2021=20=E4=B8=AA=E6=8E=A5=E5=8F=A3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...22_refund-application-接口说明-管理后台.md | 495 ++++++++++++++++++ .../22_refund-policy-接口说明-管理后台.md | 309 +++++++++++ 2 files changed, 804 insertions(+) create mode 100644 changelogs-v2/2026-06/22_refund-application-接口说明-管理后台.md create mode 100644 changelogs-v2/2026-06/22_refund-policy-接口说明-管理后台.md diff --git a/changelogs-v2/2026-06/22_refund-application-接口说明-管理后台.md b/changelogs-v2/2026-06/22_refund-application-接口说明-管理后台.md new file mode 100644 index 0000000..d37b901 --- /dev/null +++ b/changelogs-v2/2026-06/22_refund-application-接口说明-管理后台.md @@ -0,0 +1,495 @@ +# 退款申请管理接口说明(管理后台) + +- **日期**: 2026-06-22 +- **端类型**: 管理后台 +- **接口路径前缀**: /v3/admin/refund +- **服务**: hl-order-service-v3(端口 8086,网关前缀 /v3) +- **说明**: 本文档为现有已上线接口的对接说明,非新版本改动 + +--- + +## 1. 接口背景 + +退款申请管理模块提供客服/管理员全生命周期操作退款申请的能力,包括代客户发起退款、分页查询、审核(支持多级审核,当前配置为单级)、触发实退、手动完成退款(测试/线下场景)、查退款执行记录、查状态流水。 + +存在两套退款通道: + +- 申请单通道(/v3/admin/refund/application/*):标准退款流程,含政策计算、多级审核、自动实退 +- 直接退款通道(/v3/admin/refund/orders/{orderId} 和 /{refundId} 和 /order/{orderId}/list):绕过申请单直接调微信退款 API,需 SUPER_ADMIN/ADMIN/FINANCE 角色,用于紧急场景 + +--- + +## 2. 变更清单 + +| 类型 | 接口 | 说明 | +|------|------|------| +| 接口说明 | POST /v3/admin/refund/application | 客服代下退款申请 | +| 接口说明 | GET /v3/admin/refund/application/page | 退款申请分页查询(14 个筛选维度) | +| 接口说明 | GET /v3/admin/refund/application/{id} | 退款申请详情(含审核/执行记录) | +| 接口说明 | POST /v3/admin/refund/review | 提交审核(APPROVED/REJECTED/PARTIAL) | +| 接口说明 | GET /v3/admin/refund/review/list/{appId} | 查审核历史 | +| 接口说明 | POST /v3/admin/refund/execute/{appId} | 触发实退(APPROVED->REFUNDING) | +| 接口说明 | PUT /v3/admin/refund/application/{applicationId}/complete | 手动完成退款(不调微信) | +| 接口说明 | GET /v3/admin/refund/application/{id}/status-log | 查退款状态流水 | +| 接口说明 | POST /v3/admin/refund/orders/{orderId} | 直接退款(绕申请单,需 FINANCE 角色) | +| 接口说明 | GET /v3/admin/refund/{refundId} | 退款记录详情 | +| 接口说明 | GET /v3/admin/refund/order/{orderId}/list | 按订单查询退款记录列表 | + +--- + +## 3. 接口详情(通用) + +- **认证**: JWT,Header Authorization: Bearer token,需管理员身份 +- **直接退款通道**(POST /orders/{orderId})额外需要角色:SUPER_ADMIN / ADMIN / FINANCE(由 token 中 role 字段判断) +- **幂等性**: 客服代下退款申请使用 DB 唯一索引防重(同一订单仅允许一条活跃申请,状态 PENDING/APPROVED/REFUNDING 为活跃);触发实退支持 CAS 防重复触发;直接退款使用 @Idempotent 基于 orderId 的时间窗去重 +- **Content-Type**: application/json +- **响应格式**: 统一 { "code": 200, "data": ..., "msg": "success" } + +--- + +## 4. 接口入参 + +### 4.1 客服代下退款申请 + +POST /v3/admin/refund/application + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| orderId | Long(String) | 是 | 订单 ID | +| refundType | String | 否 | 退款类型,默认 FULL。可选值见第 6 节 RefundType | +| reasonId | Long | 否 | 退款原因 ID(从退款原因列表选择) | +| reasonText | String | 否 | 退款原因文本(选了 reasonId 时自动填充,也可手填) | +| reasonDetail | String | 否 | 原因详情/备注,自由文本 | +| policyId | Long | 否 | 指定退款政策 ID;不传则按订单绑定政策计算,政策为空时全额退款 | +| departureDate | String | 否 | 出发日期(yyyy-MM-dd),按政策计算时必填,用于计算距出发天数 | +| paidAmount | BigDecimal | 是 | 已付金额快照,用于政策计算基数,需 > 0 | +| requestedAmount | BigDecimal | 否 | 申请退款金额,PARTIAL 退款类型时必填 | +| mediaTraceIds | Array[String] | 否 | 媒体内容 traceId 列表(微信内容安全机审使用) | + +### 4.2 退款申请分页查询 + +GET /v3/admin/refund/application/page(Query 参数) + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| pageNo | Integer | 否 | 页码,默认 1 | +| pageSize | Integer | 否 | 每页条数,默认 10 | +| orderId | Long | 否 | 订单 ID 精确匹配 | +| orderNo | String | 否 | 订单号模糊匹配 | +| applicantName | String | 否 | 申请人姓名模糊匹配 | +| applicantId | Long | 否 | 申请人 ID 精确匹配 | +| status | Array[String] | 否 | 退款状态多选,如 status=PENDING&status=APPROVED | +| auditStatus | String | 否 | 机审状态过滤,如 MANUAL_REVIEW | +| createTimeFrom | String | 否 | 创建时间起,格式 yyyy-MM-ddTHH:mm:ss,如 2026-04-01T00:00:00 | +| createTimeTo | String | 否 | 创建时间止 | +| refundedAtFrom | String | 否 | 退款完成时间起 | +| refundedAtTo | String | 否 | 退款完成时间止 | +| sortField | String | 否 | 排序字段:createTime/refundedAt/actualAmount,默认 createTime | +| sortOrder | String | 否 | 排序方向:ASC/DESC,默认 DESC | + +### 4.3 退款申请详情 + +GET /v3/admin/refund/application/{id} + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| id | Path | Long(String) | 是 | 退款申请 ID | + +### 4.4 提交审核 + +POST /v3/admin/refund/review + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| applicationId | Long(String) | 是 | 退款申请 ID | +| decision | String | 是 | 决议:APPROVED(全额通过)/ REJECTED(拒绝)/ PARTIAL(部分通过) | +| approvedAmount | BigDecimal | PARTIAL 时必填 | 同意退款金额;PARTIAL 时必填,APPROVED 时可选(不填按政策计算金额全退) | +| remark | String | REJECTED 时必填 | 审核备注/拒绝原因,合规要求 | + +### 4.5 查审核历史 + +GET /v3/admin/refund/review/list/{appId} + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| appId | Path | Long(String) | 是 | 退款申请 ID | + +### 4.6 触发实退 + +POST /v3/admin/refund/execute/{appId} + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| appId | Path | Long(String) | 是 | 退款申请 ID,必须为 APPROVED 状态 | + +### 4.7 手动完成退款 + +PUT /v3/admin/refund/application/{applicationId}/complete + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| applicationId | Path | Long(String) | 是 | 退款申请 ID,必须为 REFUNDING 状态 | + +### 4.8 查退款状态流水 + +GET /v3/admin/refund/application/{id}/status-log + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| id | Path | Long(String) | 是 | 退款申请 ID | + +### 4.9 直接退款(绕申请单) + +POST /v3/admin/refund/orders/{orderId},需角色 SUPER_ADMIN / ADMIN / FINANCE。 + +| 参数/字段 | 位置 | 类型 | 必填 | 说明 | +|-----------|------|------|------|------| +| orderId | Path | Long(String) | 是 | 订单 ID | +| refundAmount | Body BigDecimal | 是 | 退款金额(元) | +| reason | Body String | 否 | 退款原因说明 | + +### 4.10 退款记录详情 + +GET /v3/admin/refund/{refundId} + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| refundId | Path | Long(String) | 是 | 退款记录 ID | + +### 4.11 按订单查询退款记录列表 + +GET /v3/admin/refund/order/{orderId}/list + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| orderId | Path | Long(String) | 是 | 订单 ID | + +--- + +## 5. 出参字段 + +### 5.1 RefundApplicationDetailRespVO(申请详情,管理端完整版) + +| 字段 | 类型 | 说明 | +|------|------|------| +| applicationId | String | 退款申请 ID(Long->String) | +| orderId | String | 订单 ID(Long->String) | +| refundType | String | 退款类型:FULL/PARTIAL/DEPOSIT/BALANCE(见第 6 节) | +| reasonId | String | 退款原因 ID | +| reasonText | String | 退款原因文本(快照) | +| reasonDetail | String | 退款原因详情 | +| paidAmount | String | 已付金额(String,前端用 BigNumber.js 处理) | +| calculatedAmount | String | 按政策计算退款金额 | +| actualAmount | String | 实际退款金额(最终决议) | +| policyId | String | 退款政策 ID | +| policyName | String | 退款政策名称(快照) | +| departureDate | String | 出发日期(yyyy-MM-dd) | +| daysBeforeDept | Integer | 距出发天数 | +| refundRatio | Integer | 退款比例(百分比) | +| applicantType | String | 申请人类型:USER/ADMIN/SYSTEM | +| applicantId | String | 申请人 ID | +| applicantName | String | 申请人姓名 | +| status | String | 申请状态枚举值(见第 6 节) | +| statusText | String | 状态中文展示,如「待审核」 | +| refundedAt | String | 退款完成时间 ISO | +| auditStatus | String | 机审状态:PENDING/APPROVED/MANUAL_REVIEW/REJECTED | +| auditStatusText | String | 机审状态中文 | +| mediaTraceIds | Array[String] | 媒体 traceId 列表 | +| createBy | String | 创建人 | +| updateBy | String | 更新人 | +| createTime | String | 创建时间 | +| updateTime | String | 更新时间 | +| orderInfo | Object | 订单概要快照(见下) | +| reviews | Array | 审核记录列表(按 reviewedAt ASC,见下) | +| records | Array | 退款执行记录列表(按 createTime ASC,见下) | + +orderInfo(订单概要快照): + +| 字段 | 类型 | 说明 | +|------|------|------| +| orderNo | String | 订单号 | +| productName | String | 产品名称 | +| departureDate | String | 出发日期 | +| contactName | String | 联系人姓名 | +| contactPhone | String | 联系电话(管理端明文) | + +reviews[i](审核记录项): + +| 字段 | 类型 | 说明 | +|------|------|------| +| reviewId | String | 审核 ID | +| reviewLevel | Integer | 审核级别:1/2/3(当前单级=1) | +| reviewerId | String | 审核人 ID | +| reviewerName | String | 审核人姓名 | +| reviewerRole | String | 审核人角色:CS/SUPERVISOR/EXEC | +| decision | String | 决议:APPROVED/REJECTED/PARTIAL | +| decisionText | String | 决议中文,如「已通过」 | +| approvedAmount | String | 同意退款金额(PARTIAL 时有值) | +| remark | String | 审核备注 | +| reviewedAt | String | 审核时间 | +| createTime | String | 记录创建时间 | + +records[i](退款执行记录项): + +| 字段 | 类型 | 说明 | +|------|------|------| +| refundId | String | 退款记录 ID | +| applicationId | String | 退款申请 ID | +| transactionId | String | 关联支付交易 ID | +| orderNo | String | 订单号 | +| paymentNo | String | 关联支付单号 | +| refundChannel | String | 退款渠道:WECHAT/OFFLINE/BALANCE(见第 6 节) | +| refundChannelText | String | 退款渠道中文,如「微信退款」 | +| mchId | String | 商户号 | +| outRefundNo | String | 商户退款单号 | +| refundIdWx | String | 微信退款单号 | +| refundAmount | String | 本次退款金额(元,String) | +| totalAmount | String | 该交易总金额(元,String) | +| status | String | 退款记录状态:PENDING/SUCCESS/FAILED/ABNORMAL/CLOSED(见第 6 节) | +| statusText | String | 状态中文,如「已成功」 | +| failReason | String | 失败原因(status=FAILED 时有值) | +| refundedAt | String | 退款完成时间 | +| createTime | String | 创建时间 | + +### 5.2 RefundApplicationPageItemRespVO(分页列表项,瘦身版) + +| 字段 | 类型 | 说明 | +|------|------|------| +| applicationId | String | 退款申请 ID | +| orderId | String | 订单 ID | +| orderNo | String | 订单号 | +| refundType | String | 退款类型 | +| reasonText | String | 退款原因文本 | +| paidAmount | String | 已付金额 | +| calculatedAmount | String | 政策计算金额 | +| actualAmount | String | 实际退款金额 | +| applicantType | String | 申请人类型 | +| applicantId | String | 申请人 ID | +| applicantName | String | 申请人姓名 | +| status | String | 申请状态枚举 | +| statusText | String | 状态中文 | +| auditStatus | String | 机审状态 | +| reviewerNameLast | String | 最后审核人姓名(摘要) | +| refundRecordCount | Integer | 退款执行记录数量 | +| refundedAt | String | 退款完成时间 | +| createTime | String | 创建时间 | +| updateTime | String | 更新时间 | + +分页响应外层结构:{ "code": 200, "data": { "list": [...], "total": 100, "pageNo": 1, "pageSize": 10 } } + +### 5.3 RefundStatusLogRespVO(状态流水) + +| 字段 | 类型 | 说明 | +|------|------|------| +| total | Integer | 总记录数 | +| records | Array | 流水列表(按 changedAt ASC) | +| records[i].logId | String | 日志 ID | +| records[i].applicationId | String | 退款申请 ID | +| records[i].fromStatus | String | 变更前状态枚举 | +| records[i].fromStatusText | String | 变更前状态中文 | +| records[i].toStatus | String | 变更后状态枚举 | +| records[i].toStatusText | String | 变更后状态中文 | +| records[i].eventType | String | 事件类型(见第 6 节 RefundLogEventType) | +| records[i].eventTypeText | String | 事件类型中文 | +| records[i].operatorType | String | 操作人类型:USER/ADMIN/SYSTEM/OA | +| records[i].operatorId | String | 操作人 ID | +| records[i].operatorName | String | 操作人姓名 | +| records[i].reason | String | 理由/备注 | +| records[i].extra | Object | 附加快照(按 eventType 路由,见第 6 节 extra 约定) | +| records[i].changedAt | String | 变更时间 | + +### 5.4 RefundRecordVO(直接退款记录) + +| 字段 | 类型 | 说明 | +|------|------|------| +| refundId | Long | 退款 ID(此处为 Long,前端接收需注意精度,建议当 String 处理) | +| transactionId | Long | 关联交易 ID | +| orderId | Long | 订单 ID | +| orderNo | String | 订单号 | +| mchId | String | 商户号 | +| outRefundNo | String | 商户退款单号 | +| refundIdWx | String | 微信退款单号 | +| refundAmount | BigDecimal | 退款金额(元) | +| totalAmount | BigDecimal | 订单总金额(元) | +| reason | String | 退款原因 | +| status | String | 退款状态:PENDING/SUCCESS/FAILED/ABNORMAL | +| successTime | String | 退款成功时间 | +| createTime | String | 创建时间 | + +--- + +## 6. 枚举 / 数据字典 + +### 6.1 RefundApplicationStatus(退款申请状态) + +| 枚举值 | 中文 | 说明 | +|--------|------|------| +| PENDING | 待审核 | 申请已提交,等待审核 | +| APPROVED | 已通过 | 审核通过,可触发实退 | +| REJECTED | 已拒绝 | 审核拒绝,终态 | +| REFUNDING | 退款中 | 实退已触发,等待微信回调 | +| REFUNDED | 已退款 | 退款完成,终态 | +| CANCELLED | 已取消 | 申请被撤回,终态 | +| ABNORMAL | 退款异常 | 实退异常(微信接口失败等),需人工处理 | + +活跃状态:PENDING + APPROVED + REFUNDING。同一订单只允许存在一条活跃申请(DB 唯一索引保证),重复提交返回 530004。 + +### 6.2 RefundType(退款类型) + +| 枚举值 | 中文 | 说明 | +|--------|------|------| +| FULL | 全额退款 | 退全部已付金额 | +| PARTIAL | 部分退款 | 部分退款,需指定金额 | +| DEPOSIT | 订金退款 | 仅退定金部分 | +| BALANCE | 尾款退款 | 仅退尾款部分 | + +### 6.3 RefundApplicantType(申请人类型) + +| 枚举值 | 中文 | 说明 | +|--------|------|------| +| USER | 用户 | C 端用户自主申请 | +| ADMIN | 管理员 | 客服代下 | +| SYSTEM | 系统 | 订单取消时系统自动发起 | + +### 6.4 退款渠道(refundChannel) + +| 值 | 中文 | 说明 | +|----|------|------| +| WECHAT | 微信退款 | 原路退回微信支付 | +| OFFLINE | 线下退款 | 线下转账退款 | +| BALANCE | 余额退款 | 退到用户平台余额 | + +### 6.5 退款记录状态(refund_record.status) + +| 值 | 中文 | 说明 | +|----|------|------| +| PENDING | 处理中 | 退款请求已发送,等待微信回调 | +| SUCCESS | 已成功 | 微信回调确认退款成功 | +| FAILED | 已失败 | 微信退款失败 | +| ABNORMAL | 异常 | 异常状态,等待对账 Job 补偿 | +| CLOSED | 已关闭 | 微信退款单被关闭,资金原路退回,终态 | + +### 6.6 RefundLogEventType(状态流水事件类型)及 extra 约定 + +| 枚举值 | 中文 | extra 字段内容 | +|--------|------|----------------| +| APPLY | 发起申请 | { "reasonId": "xxx", "calculatedAmount": "800.00", "refundRatio": 80, "mediaTraceIds": [] } | +| REVIEW | 审核 | { "reviewId": "xxx", "level": 1, "decision": "APPROVED", "approvedAmount": "800.00", "remark": "" } | +| OA_CALLBACK | OA 回调 | { "approvalNo": "xxx", "spStatus": 2, "approvedAmount": "800.00", "approverName": "张三" } | +| REFUND_EXECUTE | 退款执行 | { "recordIds": ["111", "222"], "totalAmount": "800.00" } | +| AUDIT_UPDATE | 机审状态更新 | { "newAuditStatus": "APPROVED", "traceIds": [] } | + +### 6.7 审核决议(decision) + +| 值 | 中文 | 说明 | +|----|------|------| +| APPROVED | 已通过 | 全额通过(按政策计算金额) | +| REJECTED | 已拒绝 | 拒绝,需填 remark | +| PARTIAL | 部分通过 | 同意部分金额,需填 approvedAmount | + +--- + +## 7. 错误码 + +| 错误码 | 说明 | 触发场景 | +|--------|------|----------| +| 530001 | 无效的退款类型 | refundType 传了非枚举值 | +| 530002 | 该订单暂无可退款金额 | 订单已付金额为 0 | +| 530003 | 无权操作此订单 | 管理员无权限操作该订单 | +| 530004 | 该订单已有退款申请处理中,请勿重复提交 | 同订单存在 PENDING/APPROVED/REFUNDING 状态申请 | +| 530005 | 无权操作此退款申请 | 越权操作 | +| 530101 | 无权查看此退款申请 | 越权查询 | +| 530201 | 当前状态不允许审批,仅待审核状态可审批 | 非 PENDING 状态时尝试审核 | +| 530202 | 实际退款金额不能超过已付金额 | approvedAmount 超出 paidAmount | +| 530203 | 累计退款金额超过已付金额 | 多次退款累计超出已付 | +| 530204 | 仅退款中状态可手动完成退款 | 非 REFUNDING 状态时调 complete 接口 | +| 530401 | 退款申请当前状态不允许审核,仅 PENDING 状态可审核 | 重复审核或状态不符 | +| 530402 | 审核决议必填 | decision 为空 | +| 530403 | PARTIAL 决议必须填写同意退款金额 | PARTIAL 时未填 approvedAmount | +| 530404 | 审核同意金额超出可退额度 | approvedAmount > 可退余额 | +| 530410 | 当前退款申请状态不允许触发实退,仅已通过的申请可触发 | 非 APPROVED 状态触发 execute | +| 530411 | 退款已触发,请勿重复操作 | CAS 防重,execute 接口重复点击 | +| 530412 | 退款状态转换非法 | 状态机约束,非法状态流转 | +| 530417 | 模拟退款通道已禁用 | 生产环境不允许调模拟退款 | + +--- + +## 8. 示例 + +### 8.1 典型成功:客服代下退款申请 + +请求:POST /v3/admin/refund/application,Header Authorization: Bearer admin-token + +请求体: + + + +响应: + + + +### 8.2 边界情况:分页查询,筛选待审核+机审需人工 + +请求:GET /v3/admin/refund/application/page?pageNo=1&pageSize=20&status=PENDING&auditStatus=MANUAL_REVIEW&sortField=createTime&sortOrder=DESC + +响应: + + + +### 8.3 业务失败:重复提交退款申请 + +请求:POST /v3/admin/refund/application,orderId 已有活跃申请 + +响应: + + + +--- + +## 9. 业务边界 + +适用场景: +- 客服在管理后台代客户发起退款,系统自动按政策计算可退金额 +- 管理员在退款列表页审核(单级,当前无需多级流程) +- 金融人员/管理员使用直接退款通道处理紧急退款场景 +- 手动完成退款仅用于测试订单或线下退款,正常流程不应使用 + +不适用场景: +- 小程序 C 端退款走 /v3/mp/refund/application(独立接口,强 IDOR 校验) +- 退款详情接口(/application/{id})禁止直接转发给小程序(含联系电话等管理端明文信息) + +特殊边界: +- 审核通过(APPROVED)后,系统自动异步触发实退(调微信退款 API),通常不需手动点「触发实退」按钮;手动触发作为补充入口 +- PARTIAL 审核通过后实退金额以 approvedAmount 为准,不是 calculatedAmount +- 同一订单仅允许一条活跃申请(PENDING/APPROVED/REFUNDING),已完结(REFUNDED/REJECTED/CANCELLED)的申请不占用,可再次申请 +- 审核通过后发起的退款按支付交易拆分多条 refund_record,records 列表可能有多条 + +--- + +## 10. 修改前后对比 + +本文档为对接说明文档,无改动历史,跳过本节。 + +--- + +## 11. 影响评估 / 回滚 + +本文档为对接说明文档,跳过本节。 + +--- + +## 12. 注意事项 + +1. 金额字段均为 String 类型(申请单通道):paidAmount / calculatedAmount / actualAmount / refundAmount / approvedAmount 在 JSON 中均为 String,请用 BigNumber.js 处理,不要用 JS 原生 Number +2. 直接退款通道(/orders/{orderId})的 RefundRecordVO 中 refundId / transactionId / orderId 为 Long 类型,如值超过 JS 安全整数范围需前端注意 +3. 状态流水 extra 字段:各 eventType 对应不同结构(见第 6.6 节),前端按 eventType 路由渲染对应展示逻辑 +4. 触发实退是异步的:POST /execute/{appId} 返回成功表示已触发,实际退款完成通过微信回调异步通知,状态会从 REFUNDING 变为 REFUNDED;前端列表页需刷新查看最终状态 +5. 测试环境模拟退款:测试服开启了 hulai.refund.simulate-enabled=true,退款不真实调微信;生产环境关闭,调用真实微信退款 API + +--- + +## 13. 关联 / 联系人 + +- **服务**: hl-order-service-v3(端口 8086) +- **后端负责人**: 腰苏图 +- **Gitea 项目**: https://git.1814.love:8443/wx/HL \ No newline at end of file diff --git a/changelogs-v2/2026-06/22_refund-policy-接口说明-管理后台.md b/changelogs-v2/2026-06/22_refund-policy-接口说明-管理后台.md new file mode 100644 index 0000000..33a851f --- /dev/null +++ b/changelogs-v2/2026-06/22_refund-policy-接口说明-管理后台.md @@ -0,0 +1,309 @@ +# 退款政策与退款原因管理接口说明(管理后台) + +- **日期**: 2026-06-22 +- **端类型**: 管理后台 +- **接口路径前缀**: /v3/admin/order/refund-policy +- **服务**: hl-order-service-v3(端口 8086,网关前缀 /v3) +- **说明**: 本文档为现有已上线接口的对接说明,非新版本改动 + +--- + +## 1. 接口背景 + +退款政策模块支持按「距出发天数」设置分阶梯退款比例,产品设计时可绑定指定政策;退款原因模块维护 C 端用户申请退款时可选择的原因选项。两个模块均由管理后台维护,不开放给小程序。 + +--- + +## 2. 变更清单 + +| 类型 | 接口 | 说明 | +|------|------|------| +| 接口说明 | GET /v3/admin/order/refund-policy/list | 退款政策全量列表(含禁用) | +| 接口说明 | GET /v3/admin/order/refund-policy/enabled | 启用政策列表(含 payType 过滤) | +| 接口说明 | GET /v3/admin/order/refund-policy/{policyId} | 退款政策详情(含阶梯规则) | +| 接口说明 | POST /v3/admin/order/refund-policy | 创建退款政策 | +| 接口说明 | PUT /v3/admin/order/refund-policy/{policyId} | 修改退款政策 | +| 接口说明 | DELETE /v3/admin/order/refund-policy/{policyId} | 删除退款政策(软删) | +| 接口说明 | PUT /v3/admin/order/refund-policy/{policyId}/toggle | 启用/禁用退款政策 | +| 接口说明 | POST /v3/admin/order/refund-policy/reason | 创建退款原因 | +| 接口说明 | PUT /v3/admin/order/refund-policy/reason/{reasonId} | 修改退款原因 | +| 接口说明 | DELETE /v3/admin/order/refund-policy/reason/{reasonId} | 删除退款原因(软删) | + +--- + +## 3. 接口详情(通用) + +- **认证**: JWT,Header Authorization: Bearer token,需管理员身份(adminId 从 token 解析) +- **幂等性**: 创建/修改无幂等 header,前端需防止重复点击 +- **Content-Type**: application/json +- **响应格式**: 统一 { "code": 200, "data": ..., "msg": "success" } + +--- + +## 4. 接口入参 + +### 4.1 政策列表 + +#### GET /v3/admin/order/refund-policy/list + +无入参,返回全量政策列表(含禁用),按创建时间倒序。 + +#### GET /v3/admin/order/refund-policy/enabled + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| payType | Query | String | 否 | 按支付类型过滤。传 FULL 返回 FULL+BOTH 的政策;传 DEPOSIT 返回 DEPOSIT+BOTH 的政策;不传返回全部启用政策 | + +#### GET /v3/admin/order/refund-policy/{policyId} + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| policyId | Path | Long(String) | 是 | 退款政策 ID | + +### 4.2 创建/修改退款政策(请求体) + +POST /v3/admin/order/refund-policy 和 PUT /v3/admin/order/refund-policy/{policyId} 共用同一请求体结构: + +| 字段 | 类型 | 必填 | 校验 | 说明 | +|------|------|------|------|------| +| policyName | String | 是 | 最大 100 字 | 政策名称,如「国内游退款政策」 | +| remark | String | 否 | 最大 500 字 | 备注说明 | +| applyPayType | String | 否 | FULL/DEPOSIT/BOTH | 适用支付类型;不传默认 BOTH | +| rules | Array | 是 | 不能为空 | 退款规则阶梯 | +| rules[].minDays | Integer | 是 | >= 0 | 距出发最少天数(含当天)。例如 minDays=7 表示出发前 7 天及以上适用此规则 | +| rules[].refundRatio | Integer | 是 | 0~100 | 退款比例(百分比)。0=不可退;100=全退 | + +PUT 时额外路径参数: + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| policyId | Path | Long(String) | 是 | 退款政策 ID | + +### 4.3 删除退款政策 + +DELETE /v3/admin/order/refund-policy/{policyId} + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| policyId | Path | Long(String) | 是 | 退款政策 ID | + +### 4.4 启用/禁用退款政策 + +PUT /v3/admin/order/refund-policy/{policyId}/toggle + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| policyId | Path | Long(String) | 是 | 退款政策 ID | +| enabled | Query | Boolean | 是 | true=启用;false=禁用 | + +### 4.5 创建/修改退款原因(请求体) + +POST /v3/admin/order/refund-policy/reason 和 PUT /v3/admin/order/refund-policy/reason/{reasonId} 共用: + +| 字段 | 类型 | 必填 | 校验 | 说明 | +|------|------|------|------|------| +| reasonText | String | 是 | 最大 200 字 | 退款原因文本,展示给 C 端用户,如「行程有变」 | +| reasonCode | String | 否 | 最大 64 字 | 机器可读编码,如 TIME_CONFLICT / OTHER | +| category | String | 否 | 最大 50 字 | 分类,走数据字典 refund_reason_category(见第 6 节) | +| sortOrder | Integer | 否 | - | 排序号,数字越小越靠前 | + +### 4.6 删除退款原因 + +DELETE /v3/admin/order/refund-policy/reason/{reasonId} + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| reasonId | Path | Long(String) | 是 | 退款原因 ID | + +--- + +## 5. 出参字段 + +### 5.1 RefundPolicyVO(退款政策) + +| 字段 | 类型 | 说明 | +|------|------|------| +| policyId | String | 政策 ID(Long 序列化为 String,防 JS 精度丢失) | +| policyName | String | 政策名称 | +| enabled | Boolean | 是否启用 | +| applyPayType | String | 适用支付类型:FULL/DEPOSIT/BOTH(见第 6 节) | +| remark | String | 备注 | +| createdBy | String | 创建人 ID | +| createTime | String | 创建时间 ISO 格式,如 2026-06-01T10:00:00 | +| updateTime | String | 更新时间 | +| rules | Array | 退款规则阶梯列表 | +| rules[].ruleId | String | 规则 ID | +| rules[].minDays | Integer | 距出发最少天数 | +| rules[].refundRatio | Integer | 退款比例(百分比) | + +阶梯算法说明:规则按 minDays 降序排列,距出发天数 >= 当前规则 minDays 时命中。calculatedAmount = paidAmount x refundRatio / 100,向下取整保留 2 位小数。 + +### 5.2 RefundReasonVO(退款原因) + +| 字段 | 类型 | 说明 | +|------|------|------| +| reasonId | String | 原因 ID | +| reasonText | String | 原因描述,展示给 C 端 | +| reasonCode | String | 机器可读编码 | +| category | String | 分类(字典 refund_reason_category 的 key) | +| sortOrder | Integer | 排序号 | +| enabled | Boolean | 是否启用 | + +--- + +## 6. 枚举 / 数据字典 + +### 6.1 applyPayType(适用支付类型)—— 字典 payment_type + +| 值 | 中文 | 说明 | +|----|------|------| +| FULL | 全款支付 | 仅适用于全款支付的订单 | +| DEPOSIT | 定金支付 | 仅适用于定金+尾款的订单 | +| BOTH | 两者均可 | 全款和定金订单均适用(不传默认值) | + +### 6.2 退款原因分类 —— 字典 refund_reason_category + +category 字段存储字典 key,前端下拉展示时从数据字典接口获取标签。常见 key 示例(以实际字典表为准): + +| key 示例 | 说明 | +|----------|------| +| USER_REASON | 用户原因(行程变化/临时改变等) | +| SERVICE_REASON | 服务原因(产品质量问题等) | +| OTHER | 其他 | + +字典实际值以管理后台数据字典模块配置为准,前端需从字典接口动态拉取。 + +--- + +## 7. 错误码 + +| 错误码 | 说明 | 触发场景 | +|--------|------|----------| +| 530209 | 退款政策阶梯天数重复或重叠 | 创建/修改政策时 rules 中有 minDays 重叠的规则 | +| 530210 | 退款政策正在被使用,无法删除 | 删除政策时有退款申请正在引用该政策 | +| 400 | 参数校验失败 | policyName 为空、rules 为空、refundRatio 超范围等 | + +--- + +## 8. 示例 + +### 8.1 典型成功:创建退款政策 + +请求:POST /v3/admin/order/refund-policy,请求体: + +```json +{ + "policyName": "国内游标准退款政策", + "applyPayType": "FULL", + "remark": "适用于所有国内游产品", + "rules": [ + { "minDays": 30, "refundRatio": 90 }, + { "minDays": 15, "refundRatio": 70 }, + { "minDays": 7, "refundRatio": 50 }, + { "minDays": 0, "refundRatio": 0 } + ] +} +``` + +响应: + +```json +{ + "code": 200, + "data": { + "policyId": "1234567890123456789", + "policyName": "国内游标准退款政策", + "enabled": true, + "applyPayType": "FULL", + "remark": "适用于所有国内游产品", + "createTime": "2026-06-22T10:00:00", + "rules": [ + { "ruleId": "111", "minDays": 30, "refundRatio": 90 }, + { "ruleId": "112", "minDays": 15, "refundRatio": 70 }, + { "ruleId": "113", "minDays": 7, "refundRatio": 50 }, + { "ruleId": "114", "minDays": 0, "refundRatio": 0 } + ] + }, + "msg": "success" +} +``` + +### 8.2 边界情况:不可退政策(仅一条 minDays=0, refundRatio=0) + +请求体: + +```json +{ + "policyName": "不可退政策", + "applyPayType": "BOTH", + "rules": [ { "minDays": 0, "refundRatio": 0 } ] +} +``` + +响应结构同 8.1,rules 只有一条。 + +### 8.3 业务失败:阶梯天数重叠 + +请求体: + +```json +{ + "policyName": "冲突政策", + "rules": [ + { "minDays": 7, "refundRatio": 80 }, + { "minDays": 7, "refundRatio": 50 } + ] +} +``` + +响应: + +```json +{ "code": 530209, "data": null, "msg": "退款政策阶梯天数重复或重叠:7" } +``` + +--- + +## 9. 业务边界 + +适用场景: +- 管理员在「退款设置」模块维护全局退款政策库 +- 产品编排时从 GET /enabled 拉取可选政策列表绑定到产品;payType 过滤:全款产品传 FULL,定金产品传 DEPOSIT + +不适用场景: +- 接口不开放给小程序 C 端(C 端只能查已绑定政策的规则预览) +- 删除或禁用政策后,已绑定该政策的产品申请退款时降级使用默认政策(全退),前端不需要特殊处理 + +特殊边界: +- 修改政策规则时,替换整个 rules 列表(不做增量合并),需传完整阶梯 +- 历史退款申请已快照政策信息(policyName/refundRatio),修改政策不影响已有退款申请 +- 退款原因删除为软删,C 端不再展示,但已使用该原因的历史申请原因文本仍保留 + +--- + +## 10. 修改前后对比 + +本文档为对接说明文档,无改动历史,跳过本节。 + +--- + +## 11. 影响评估 / 回滚 + +本文档为对接说明文档,跳过本节。 + +--- + +## 12. 注意事项 + +1. ID 字段均为 String 类型:policyId / ruleId / reasonId 在 JSON 中返回 String(Long 转 String 防 JS 精度丢失),前端接收和传参均用 String,不要转 Number +2. rules 阶梯天数语义:minDays 是「距出发最少天数(含)」,无 maxDays 字段,阶梯间隔由两条相邻规则的 minDays 差值隐式决定 +3. enabled 接口 payType 过滤逻辑:传 FULL 返回 FULL+BOTH,传 DEPOSIT 返回 DEPOSIT+BOTH,因为 BOTH 类政策两种支付类型都适用 +4. 修改政策 rules 为全量替换,传入 rules 列表会替换原有所有规则,不支持单条追加 + +--- + +## 13. 关联 / 联系人 + +- **服务**: hl-order-service-v3(端口 8086) +- **后端负责人**: 腰苏图 +- **Gitea 项目**: https://git.1814.love:8443/wx/HL