Files
jsowell-charger-web/docs/刷新FLAG.md
2026-05-28 13:59:09 +08:00

204 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 需求概述
针对 `adapay_unsplit_record` 表中的未分账/未退款记录通过调用汇付AdapayAPI 查询最新的退款和分账数据,与本地数据库对比更新,并重新计算 `refund_flag``split_flag` 标识,确保数据一致性。
---
## 数据模型
### adapay_unsplit_record 表(核心字段)
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | int | 主键 |
| `payment_id` | varchar | 汇付支付对象ID交易流水号 |
| `order_code` | varchar | 订单编号 |
| `order_no` | varchar | 交易订单号(汇付侧) |
| `merchant_code` | varchar | 商户号 |
| `pay_time` | datetime | 支付时间 |
| `pay_amount` | decimal | 交易订单金额(支付金额) |
| `settle_amount` | decimal | 结算金额(应分账金额,从订单表同步) |
| `confirmed_split_amount` | decimal | 已确认分账金额(汇付实际已分账) |
| `refund_amount` | decimal | 已撤销金额(汇付实际已退款) |
| `due_refund_amount` | decimal | 应退金额(从订单表同步) |
| `payment_revoke_amount` | decimal | 支付确认撤销金额(分账后又撤销) |
| `remaining_split_amount` | decimal | 剩余未分账金额 |
| `pile_type` | varchar | 桩类型EV / eBike |
| **`refund_flag`** | varchar | **退款标识**SUCCESS / PROCESSING / FAILED |
| **`split_flag`** | varchar | **分账标识**SUCCESS / PROCESSING / FAILED |
| `update_time` | datetime | 更新时间 |
> 实体类:`jsowell-pile/.../domain/AdapayUnsplitRecord.java`
> 表只记录通过汇付支付的订单,`refund_flag` 和 `split_flag` 用于标识退款和分账是否已处理完成。
---
## 汇付 API 查询(延时结算模式)
> 所有订单均采用延时结算模式,无需处理实时结算模式。
### 需要调用的 API
| API | 方法 | 用途 |
|-----|------|------|
| 查询支付撤销对象列表 | `queryPaymentReverse(paymentId, wechatAppId)` | 获取已撤销/已退款金额 |
| 查询支付确认对象列表 | `queryPaymentConfirmList(dto)` | 获取已确认分账金额、预留分账金额、剩余未分账金额 |
| 查询支付对象详情 | `queryPaymentDetail(paymentId, wechatAppId)` | 获取支付对象完整信息 |
> 服务类:`jsowell-pile/.../adapay/service/AdapayService.java`
### API 返回的关键数据
**支付撤销 API 返回(延时模式退款用):**
- `reverse_amt`:撤销金额(即退款金额)
- `trans_status`交易状态pending / succeeded / failed
**支付确认列表 API 返回:**
- `confirmed_amt`:已确认分账金额
- `reserved_amt`:预留中金额(已发起但未确认)
- 各分账对象的 `div_members`:分账成员及金额
---
## 处理流程
### 整体流程
```
取得 paymentId
├─ 1. 调用汇付 API 查询最新数据
│ ├─ 查询支付撤销/退款 → 获取实际已退款金额
│ └─ 查询支付确认列表 → 获取实际已分账金额
├─ 2. 与本地数据库对比更新
│ ├─ 对比 due_refund_amount应退 vs refund_amount实退
│ ├─ 对比 settle_amount应分 vs confirmed_split_amount实分
│ └─ 不一致则更新对应字段
└─ 3. 重新计算 refund_flag 和 split_flag
├─ 退款标识:实际退款 >= 应退金额 → SUCCESS
├─ 分账标识:实际分账 >= 应分金额 → SUCCESS
└─ 未达预期则标记 PROCESSING 或 FAILED
```
### 详细步骤
#### 步骤 1查询汇付最新数据
1. **获取退款数据**:调用 `queryPaymentReverse`,查询该 `paymentId` 下所有支付撤销记录,汇总成功状态的撤销金额作为已退款金额
2. **获取分账数据**:调用 `queryPaymentConfirmList`,获取所有分账确认对象的已确认金额和预留金额
3. **获取剩余未分账金额**`pay_amount - due_refund_amount - max(confirmed_amt) - max(reserved_amt)`
#### 步骤 2对比更新本地数据
| 对比项 | 本地字段 | 汇付数据源 | 更新字段 |
|--------|----------|------------|----------|
| 应退金额 | `due_refund_amount` | 订单表 `refund_amount` | `due_refund_amount` |
| 已退款金额 | `refund_amount` | 汇付退款/撤销 API汇总 | `refund_amount` |
| 结算金额 | `settle_amount` | 订单表 `settle_amount` | `settle_amount` |
| 已分账金额 | `confirmed_split_amount` | 汇付分账API汇总 | `confirmed_split_amount` |
| 剩余未分账金额 | `remaining_split_amount` | 计算得出 | `remaining_split_amount` |
> 仅在有差异时才更新,减少不必要的写库操作。
#### 步骤 3计算 flag 标识
**flag 状态值:**
| 值 | 含义 |
|----|------|
| `SUCCESS` | 处理完成(实际金额 >= 预期金额 或 预期金额 <= 0 |
| `PROCESSING` | 处理中(已受理金额 >= 预期金额,但实际成功金额不足) |
| `FAILED` | 处理失败(已受理金额 < 预期金额) |
**退款标识计算:**
```
expected = due_refund_amount应退金额
success = 汇付实际成功退款金额
accepted = 汇付已受理退款金额(成功 + 处理中)
if expected <= 0 或 success >= expected → SUCCESS
else if accepted >= expected → PROCESSING
else → FAILED
```
**分账标识计算:**
```
expected = pay_amount - due_refund_amount预期应分账金额
success = 汇付实际已确认分账金额
accepted = confirmed + reserved已确认 + 预留中)
if expected <= 0 或 success >= expected → SUCCESS
else if accepted >= expected → PROCESSING
else → FAILED
```
---
## 相关代码索引
### 核心实现
| 功能 | 文件路径 |
|------|---------|
| **flag 刷新主逻辑** | `jsowell-quartz/.../service/impl/AdapayUnsplitRecordHandleServiceImpl.java` |
| 方法 `refreshUnsplitRecordHandleFlag()` | 第 532 行 — 核心刷新方法,查询汇付并对比更新 |
| 方法 `calculateHandleFlag()` | 第 686 行 — flag 计算逻辑 |
| 方法 `checkRefundAmount()` | 第 641 行 — 退款金额核对 |
| 方法 `checkSplitAmount()` | 第 653 行 — 分账金额核对 |
| 方法 `getRefundedAmount()` | 第 781 行 — 获取汇总退款金额 |
### 汇付 API 调用
| 功能 | 文件路径 |
|------|---------|
| **AdapayService** | `jsowell-pile/.../adapay/service/AdapayService.java` |
| 查询支付撤销 | `queryPaymentReverse()` 第 1333 行 |
| 查询退款列表 | `queryPaymentRefund()` 第 1417 行 |
| 查询支付确认列表 | `queryPaymentConfirmList()` 第 1435 行 |
| 查询支付详情 | `queryPaymentDetail()` 第 1351 行 |
### 数据层
| 功能 | 文件路径 |
|------|---------|
| **实体类** | `jsowell-pile/.../domain/AdapayUnsplitRecord.java` |
| **Mapper XML** | `jsowell-pile/src/main/resources/mapper/pile/AdapayUnsplitRecordMapper.xml` |
| **Service 接口** | `jsowell-pile/.../service/AdapayUnsplitRecordService.java` |
| **VO 对象** | `jsowell-pile/.../vo/AdapayUnsplitRecordVO.java` |
### 定时任务入口
| 任务 | 文件路径 | 方法 |
|------|---------|------|
| 刷新 flag | `jsowell-quartz/.../task/JsowellTask.java` | — |
| 处理未结算订单 | `AdapayUnsplitRecordHandleServiceImpl.java` | `processUnSettledOrder()` |
| 补齐缺失字段 | `AdapayUnsplitRecordHandleServiceImpl.java` | `completeAdapayUnsplitRecordFields()` |
### 订单退款服务
| 功能 | 文件路径 |
|------|---------|
| 汇付退款 | `jsowell-pile/.../service/impl/OrderBasicInfoServiceImpl.java``refundOrderWithAdapay()` |
| 退款信息查询 | `OrderBasicInfoServiceImpl.java``getOrderRefundInfoList()` |
---
## 注意事项
1. **统一模式**:所有订单均为延时结算模式,退款通过 `queryPaymentReverse`(支付撤销)处理,分账通过 `queryPaymentConfirmList` / `createPaymentConfirmRequest` 处理
2. **触发时机**:该流程通常在定时任务中批量执行,也可针对单个 `paymentId` 手动触发
3. **幂等性**:通过 `insertOrUpdateSelective` 保证更新幂等,重复执行不会产生脏数据
4. **分账前置条件**:有应退金额时,必须先确认退款足额成功才能继续分账
5. **金额精度**:所有金额计算使用 `BigDecimal`,保留 2 位小数,四舍五入
6. **API 限流**:批量处理时注意汇付 API 调用频率限制
---
## 汇付 API 文档
- 查询支付撤销对象列表https://docs.adapay.tech/api/trade.html#id76
- 查询支付确认对象列表https://docs.adapay.tech/api/trade.html#id62
- 汇付开发文档首页https://docs.adapay.tech/api/introduce.html