fix(openalipay): 修复支付宝角色ID配置及押金解冻功能
- 将支付宝控制器中用户角色ID硬编码替换为配置读取,默认角色ID为81,配置存在时使用配置值 - 修正用户角色保存时使用动态角色ID,支持多租户配置 - 修改数据源配置,切换本地MySQL连接地址以便开发调试 - 新增押金冻结订单修复与解冻工具类UnfreezeToolTest.java,支持数据库中auth_no为空的冻结订单修复 - 实现基于支付宝Java SDK的证书模式解冻接口调用,避免Python调用时根证书问题 - 设计并完善押金冻结订单解冻的运维手册,指导正确操作及错误处理 - 优化解冻流程,支持自动修复冻结订单状态并更新数据库状态为UNFREEZE - 添加FixFreezeOrderTest.java辅助测试工具类,用于根据订单号或冻结订单号进行押金解冻测试和修复
This commit is contained in:
29
.workbuddy/memory/2026-05-11.md
Normal file
29
.workbuddy/memory/2026-05-11.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# 2026-05-11 工作记录
|
||||||
|
|
||||||
|
## 支付宝押金冻结订单解冻(订单ID=29909)
|
||||||
|
|
||||||
|
### 任务完成
|
||||||
|
- 成功解冻客户押金 200.00 元
|
||||||
|
- 授权号: `2026041610002001650571764471`
|
||||||
|
- 商户冻结订单号: `2044685513146597377`
|
||||||
|
|
||||||
|
### 技术方案
|
||||||
|
- 使用 Java SDK `certificateExecute()` 方法(避免 Python 的根证书问题)
|
||||||
|
- Java 测试类: `src/test/java/com/gxwebsoft/test/UnfreezeToolTest.java`
|
||||||
|
|
||||||
|
### 文件清理
|
||||||
|
- ✅ 删除: `unfreeze_v4.py`(Python 尝试脚本,未成功)
|
||||||
|
- ✅ 保留: `UnfreezeToolTest.java`(成功方案)
|
||||||
|
|
||||||
|
### 创建文档
|
||||||
|
- 创建运维手册: `docs/支付宝押金冻结订单解冻运维手册.md`
|
||||||
|
|
||||||
|
### 执行命令
|
||||||
|
```bash
|
||||||
|
./mvnw test -Dtest=UnfreezeToolTest#fixAndUnfreeze
|
||||||
|
```
|
||||||
|
|
||||||
|
### 注意事项
|
||||||
|
- 需要确保 Redis 已启动: `redis-server --daemonize yes`
|
||||||
|
- 解冻金额 <= 冻结金额
|
||||||
|
- 资金将在1-7个工作日退回客户银行卡
|
||||||
171
docs/支付宝押金冻结订单解冻运维手册.md
Normal file
171
docs/支付宝押金冻结订单解冻运维手册.md
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
# 支付宝押金冻结订单解冻运维手册
|
||||||
|
|
||||||
|
> 用于处理 `shop_freeze_order` 表中客户押金冻结订单的解冻操作
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、背景
|
||||||
|
|
||||||
|
当客户需要退还押金时,需要调用支付宝 `alipay.fund.auth.order.unfreeze` 接口解冻资金。
|
||||||
|
|
||||||
|
### 相关参数(订单ID=29909)
|
||||||
|
| 参数 | 值 |
|
||||||
|
|------|-----|
|
||||||
|
| 授权号 auth_no | `2026041610002001650571764471` |
|
||||||
|
| 商户冻结订单号 out_order_no | `2044685513146597377` |
|
||||||
|
| 冻结金额 | `200.00` 元 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、文件位置
|
||||||
|
|
||||||
|
```
|
||||||
|
src/test/java/com/gxwebsoft/test/UnfreezeToolTest.java
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、修改配置(针对不同订单)
|
||||||
|
|
||||||
|
在 `UnfreezeToolTest.java` 中修改以下常量:
|
||||||
|
|
||||||
|
```java
|
||||||
|
private static final String AUTH_NO = "2026041610002001650571764471"; // 支付宝授权号
|
||||||
|
private static final String OUT_ORDER_NO = "2044685513146597377"; // 商户冻结订单号
|
||||||
|
private static final BigDecimal AMOUNT = new BigDecimal("200.00"); // 解冻金额
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、执行命令
|
||||||
|
|
||||||
|
### 方式一:指定测试方法(推荐)
|
||||||
|
```bash
|
||||||
|
cd /Users/gxwebsoft/JAVA/yunxinwei-java
|
||||||
|
./mvnw test -Dtest=UnfreezeToolTest#fixAndUnfreeze
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方式二:运行整个测试类
|
||||||
|
```bash
|
||||||
|
./mvnw test -Dtest=UnfreezeToolTest
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、执行前检查
|
||||||
|
|
||||||
|
### 1. 确保 Redis 已启动
|
||||||
|
```bash
|
||||||
|
redis-cli ping
|
||||||
|
# 如果返回 PONG,说明已启动
|
||||||
|
# 如果报错,执行:
|
||||||
|
redis-server --daemonize yes
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 确保数据库连接正常
|
||||||
|
检查 `application.yml` 中的数据库配置
|
||||||
|
|
||||||
|
### 3. 验证订单信息
|
||||||
|
执行前先确认:
|
||||||
|
- 订单确实存在且状态为冻结
|
||||||
|
- 授权号 auth_no 正确
|
||||||
|
- 解冻金额与冻结金额一致
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、执行流程
|
||||||
|
|
||||||
|
程序会自动执行以下步骤:
|
||||||
|
|
||||||
|
1. **查找冻结订单** — 根据 `out_order_no` 查询 `shop_freeze_order` 表
|
||||||
|
2. **修复 auth_no** — 如果数据库中 auth_no 为空,补充授权号
|
||||||
|
3. **查找关联订单** — 根据 `freeze_order_no` 查询关联的业务订单
|
||||||
|
4. **修复订单关联** — 修复订单与冻结订单的关联关系
|
||||||
|
5. **调用支付宝解冻接口** — 使用 `alipay.fund.auth.order.unfreeze` API
|
||||||
|
6. **更新数据库状态** — 将 `status` 更新为 `UNFREEZE`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、执行成功示例
|
||||||
|
|
||||||
|
```
|
||||||
|
========================================
|
||||||
|
押金修复 & 解冻工具
|
||||||
|
========================================
|
||||||
|
|
||||||
|
[1] 查找冻结订单...
|
||||||
|
✅ 找到冻结订单: id=29909
|
||||||
|
out_order_no: 2044685513146597377
|
||||||
|
status: FREEZE
|
||||||
|
auth_no: 2026041610002001650571764471
|
||||||
|
|
||||||
|
[2] 修复 auth_no...
|
||||||
|
✅ auth_no 已修复: 2026041610002001650571764471
|
||||||
|
|
||||||
|
[3] 查找关联订单...
|
||||||
|
✅ 找到关联订单: id=29908
|
||||||
|
order_no: 2026041622609876
|
||||||
|
is_freeze: true
|
||||||
|
freeze_order_no: 2044685513146597377
|
||||||
|
|
||||||
|
[5] 调用支付宝解冻接口...
|
||||||
|
----------------------------------------
|
||||||
|
支付宝返回:
|
||||||
|
{
|
||||||
|
"code": "10000",
|
||||||
|
"msg": "Success",
|
||||||
|
"amount": "200.00",
|
||||||
|
"authNo": "2026041610002001650571764471",
|
||||||
|
"outOrderNo": "2044685513146597377",
|
||||||
|
"operationId": "202605111341118651865",
|
||||||
|
"unfreezeTime": "2026-05-11 13:41:11"
|
||||||
|
}
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
🎉 解冻成功!
|
||||||
|
解冻金额: 200.00
|
||||||
|
授权号: 2026041610002001650571764471
|
||||||
|
订单号: 2044685513146597377
|
||||||
|
|
||||||
|
[6] 更新数据库状态...
|
||||||
|
✅ 数据库已更新
|
||||||
|
|
||||||
|
⏰ 资金将在1-7个工作日内退回客户农业银行储蓄卡
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、常见错误处理
|
||||||
|
|
||||||
|
| 错误码 | 含义 | 处理方式 |
|
||||||
|
|--------|------|----------|
|
||||||
|
| `isv.invalid-alipay-root-cert-sn` | 根证书序列号不匹配 | 使用 Java SDK 的 `certificateExecute()` 方法 |
|
||||||
|
| `ACQ.TRADE_NOT_EXIST` | 交易不存在 | 检查 auth_no 是否正确 |
|
||||||
|
| `isv.auth_no_error` | 授权号错误 | 核对 auth_no 值 |
|
||||||
|
| `isv.amount_error` | 金额不匹配 | 确保解冻金额 <= 冻结金额 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、技术要点
|
||||||
|
|
||||||
|
- 使用 **Java SDK** 的证书模式(`DefaultAlipayClient`)
|
||||||
|
- 使用 `certificateExecute()` 方法而非普通 `execute()`
|
||||||
|
- 从数据库 `sys_setting` 表读取商户配置(tenant_id=6)
|
||||||
|
- 使用雪花ID生成 `out_request_no`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、相关文件
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `src/test/java/.../UnfreezeToolTest.java` | 解冻工具类 |
|
||||||
|
| `src/main/resources/cert/` | 支付宝证书目录 |
|
||||||
|
| `shop_freeze_order` | 冻结订单表 |
|
||||||
|
| `order` | 业务订单表 |
|
||||||
|
| `sys_setting` | 系统配置表(支付宝密钥) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*文档创建时间: 2026-05-11*
|
||||||
|
*最后更新: 2026-05-11*
|
||||||
@@ -85,8 +85,14 @@ public class OpenAlipayController extends BaseController {
|
|||||||
// if (setting == null) {
|
// if (setting == null) {
|
||||||
// throw new BusinessException("请先配置注册设置");
|
// throw new BusinessException("请先配置注册设置");
|
||||||
// }
|
// }
|
||||||
JSONObject jsonObject = JSONObject.parseObject(setting);
|
int roleId = 81;
|
||||||
String roleId = jsonObject.getString("roleId");
|
if (StrUtil.isNotBlank(setting)) {
|
||||||
|
JSONObject jsonObject = JSONObject.parseObject(setting);
|
||||||
|
Integer configRoleId = jsonObject == null ? null : jsonObject.getInteger("roleId");
|
||||||
|
if (configRoleId != null) {
|
||||||
|
roleId = configRoleId;
|
||||||
|
}
|
||||||
|
}
|
||||||
// 实例化客户端
|
// 实例化客户端
|
||||||
DefaultAlipayClient alipayClient = alipayConfig.alipayClient(param.getTenantId());
|
DefaultAlipayClient alipayClient = alipayConfig.alipayClient(param.getTenantId());
|
||||||
try {
|
try {
|
||||||
@@ -141,7 +147,7 @@ public class OpenAlipayController extends BaseController {
|
|||||||
UserRole userRole = new UserRole();
|
UserRole userRole = new UserRole();
|
||||||
userRole.setUserId(user.getUserId());
|
userRole.setUserId(user.getUserId());
|
||||||
userRole.setTenantId(param.getTenantId());
|
userRole.setTenantId(param.getTenantId());
|
||||||
userRole.setRoleId(Integer.valueOf(81));
|
userRole.setRoleId(roleId);
|
||||||
userRoleService.save(userRole);
|
userRoleService.save(userRole);
|
||||||
// 添加第三方用户信息
|
// 添加第三方用户信息
|
||||||
UserOauth userOauth2 = new UserOauth();
|
UserOauth userOauth2 = new UserOauth();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# 数据源配置
|
# 数据源配置
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:mysql://47.107.122.174:3318/yunxinwei?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
|
url: jdbc:mysql://127.0.0.1:3308/yunxinwei?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
|
||||||
username: yunxinwei
|
username: yunxinwei
|
||||||
password: A56sK6aW2FA3wBy2
|
password: A56sK6aW2FA3wBy2
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
|||||||
205
src/test/java/com/gxwebsoft/test/FixFreezeOrderTest.java
Normal file
205
src/test/java/com/gxwebsoft/test/FixFreezeOrderTest.java
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
package com.gxwebsoft.test;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alipay.api.DefaultAlipayClient;
|
||||||
|
import com.alipay.api.request.AlipayFundAuthOrderUnfreezeRequest;
|
||||||
|
import com.alipay.api.response.AlipayFundAuthOrderUnfreezeResponse;
|
||||||
|
import com.gxwebsoft.common.core.utils.AlipayConfigUtil;
|
||||||
|
import com.gxwebsoft.shop.entity.FreezeOrder;
|
||||||
|
import com.gxwebsoft.shop.entity.Order;
|
||||||
|
import com.gxwebsoft.shop.service.FreezeOrderService;
|
||||||
|
import com.gxwebsoft.shop.service.OrderService;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 押金冻结订单修复工具
|
||||||
|
* 用于处理客户押金无法解冻的问题
|
||||||
|
*
|
||||||
|
* 使用场景:
|
||||||
|
* 1. 客户反馈押金被冻结无法退款
|
||||||
|
* 2. 数据库中freeze_order记录状态异常
|
||||||
|
* 3. 需要手动触发支付宝解冻接口
|
||||||
|
*/
|
||||||
|
@SpringBootTest
|
||||||
|
public class FixFreezeOrderTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FreezeOrderService freezeOrderService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrderService orderService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AlipayConfigUtil alipayConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据订单号修复并解冻押金
|
||||||
|
*
|
||||||
|
* @param orderNo 订单号,如:20260416262053226505
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void fixAndUnfreezeByOrderNo(String orderNo) {
|
||||||
|
// 1. 查询订单
|
||||||
|
Order order = orderService.lambdaQuery()
|
||||||
|
.eq(Order::getOrderNo, orderNo)
|
||||||
|
.last("limit 1")
|
||||||
|
.one();
|
||||||
|
|
||||||
|
if (order == null) {
|
||||||
|
System.out.println("订单不存在:" + orderNo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("找到订单:" + order);
|
||||||
|
fixAndUnfreeze(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据商户冻结订单号修复并解冻
|
||||||
|
*
|
||||||
|
* @param freezeOrderNo 商户冻结订单号,如:2044685513146597377
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void fixAndUnfreezeByFreezeOrderNo(String freezeOrderNo) {
|
||||||
|
// 1. 查询冻结订单
|
||||||
|
FreezeOrder freezeOrder = freezeOrderService.lambdaQuery()
|
||||||
|
.eq(FreezeOrder::getOutOrderNo, freezeOrderNo)
|
||||||
|
.last("limit 1")
|
||||||
|
.one();
|
||||||
|
|
||||||
|
if (freezeOrder == null) {
|
||||||
|
System.out.println("冻结订单不存在:" + freezeOrderNo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("找到冻结订单:" + freezeOrder);
|
||||||
|
|
||||||
|
// 2. 查询关联的正式订单
|
||||||
|
Order order = orderService.getById(freezeOrder.getRelOrderId());
|
||||||
|
if (order == null) {
|
||||||
|
System.out.println("关联订单不存在,relOrderId:" + freezeOrder.getRelOrderId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("找到关联订单:" + order);
|
||||||
|
fixAndUnfreeze(order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修复并执行解冻
|
||||||
|
*/
|
||||||
|
private void fixAndUnfreeze(Order order) {
|
||||||
|
try {
|
||||||
|
// 1. 检查并修复订单表的freeze_order_no
|
||||||
|
if (order.getFreezeOrderNo() == null || order.getFreezeOrderNo().isEmpty()) {
|
||||||
|
System.out.println("订单缺少freeze_order_no字段,尝试从freeze_order表查找...");
|
||||||
|
|
||||||
|
FreezeOrder freezeOrder = freezeOrderService.lambdaQuery()
|
||||||
|
.eq(FreezeOrder::getRelOrderId, order.getOrderId())
|
||||||
|
.last("limit 1")
|
||||||
|
.one();
|
||||||
|
|
||||||
|
if (freezeOrder != null) {
|
||||||
|
order.setFreezeOrderNo(freezeOrder.getOutOrderNo());
|
||||||
|
order.setOutRequestNo(freezeOrder.getOutRequestNo());
|
||||||
|
order.setIsFreeze(1);
|
||||||
|
orderService.updateById(order);
|
||||||
|
System.out.println("已修复订单freeze_order_no:" + freezeOrder.getOutOrderNo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 检查并修复freeze_order表的状态
|
||||||
|
FreezeOrder freezeOrder = freezeOrderService.lambdaQuery()
|
||||||
|
.eq(FreezeOrder::getOutOrderNo, order.getFreezeOrderNo())
|
||||||
|
.orderByDesc(FreezeOrder::getCreateTime)
|
||||||
|
.last("limit 1")
|
||||||
|
.one();
|
||||||
|
|
||||||
|
if (freezeOrder == null) {
|
||||||
|
System.out.println("没有找到冻结订单记录,需要先创建!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("冻结订单状态:" + freezeOrder.getStatus());
|
||||||
|
System.out.println("冻结金额:" + freezeOrder.getAmount());
|
||||||
|
System.out.println("授权号:" + freezeOrder.getAuthNo());
|
||||||
|
|
||||||
|
// 如果状态不是SUCCESS,修复它
|
||||||
|
if (!"SUCCESS".equals(freezeOrder.getStatus())) {
|
||||||
|
System.out.println("修复冻结订单状态:INIT -> SUCCESS");
|
||||||
|
freezeOrder.setStatus("SUCCESS");
|
||||||
|
freezeOrderService.updateById(freezeOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 执行解冻
|
||||||
|
System.out.println("\n========== 开始执行解冻 ==========");
|
||||||
|
unfreeze(order.getOrderId());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("修复失败:" + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行支付宝解冻接口
|
||||||
|
*/
|
||||||
|
private void unfreeze(Integer orderId) throws Exception {
|
||||||
|
Order order = orderService.getById(orderId);
|
||||||
|
|
||||||
|
FreezeOrder freezeOrder = freezeOrderService.lambdaQuery()
|
||||||
|
.eq(FreezeOrder::getOutOrderNo, order.getFreezeOrderNo())
|
||||||
|
.eq(FreezeOrder::getStatus, "SUCCESS")
|
||||||
|
.orderByDesc(FreezeOrder::getCreateTime)
|
||||||
|
.last("limit 1")
|
||||||
|
.one();
|
||||||
|
|
||||||
|
if (freezeOrder == null) {
|
||||||
|
throw new RuntimeException("没有找到已成功冻结的订单!");
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultAlipayClient alipayClient = alipayConfig.alipayClient(6);
|
||||||
|
AlipayFundAuthOrderUnfreezeRequest request = new AlipayFundAuthOrderUnfreezeRequest();
|
||||||
|
|
||||||
|
JSONObject bizContent = new JSONObject();
|
||||||
|
bizContent.put("auth_no", freezeOrder.getAuthNo());
|
||||||
|
bizContent.put("out_request_no", IdUtil.getSnowflakeNextId());
|
||||||
|
bizContent.put("amount", freezeOrder.getAmount());
|
||||||
|
bizContent.put("remark", "用户申请退款解冻");
|
||||||
|
|
||||||
|
JSONObject extraParam = new JSONObject();
|
||||||
|
JSONObject unfreezeBizInfo = new JSONObject();
|
||||||
|
unfreezeBizInfo.put("bizComplete", true);
|
||||||
|
extraParam.put("unfreezeBizInfo", unfreezeBizInfo);
|
||||||
|
bizContent.put("extra_param", extraParam);
|
||||||
|
|
||||||
|
request.setBizContent(bizContent.toString());
|
||||||
|
|
||||||
|
AlipayFundAuthOrderUnfreezeResponse response = alipayClient.certificateExecute(request);
|
||||||
|
|
||||||
|
if (response.isSuccess()) {
|
||||||
|
System.out.println("✅ 解冻成功!");
|
||||||
|
System.out.println("解冻金额:" + freezeOrder.getAmount());
|
||||||
|
System.out.println("授权号:" + freezeOrder.getAuthNo());
|
||||||
|
} else {
|
||||||
|
System.out.println("❌ 解冻失败:" + response.getSubMsg());
|
||||||
|
System.out.println("错误码:" + response.getSubCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 快捷测试方法 ====================
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFixCustomerFreezeOrder() {
|
||||||
|
// 根据客户订单号修复
|
||||||
|
// fixAndUnfreezeByOrderNo("20260416262053226505");
|
||||||
|
|
||||||
|
// 根据商户冻结订单号修复
|
||||||
|
fixAndUnfreezeByFreezeOrderNo("2044685513146597377");
|
||||||
|
}
|
||||||
|
}
|
||||||
154
src/test/java/com/gxwebsoft/test/UnfreezeToolTest.java
Normal file
154
src/test/java/com/gxwebsoft/test/UnfreezeToolTest.java
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
package com.gxwebsoft.test;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alipay.api.*;
|
||||||
|
import com.alipay.api.request.*;
|
||||||
|
import com.alipay.api.response.*;
|
||||||
|
import com.gxwebsoft.common.core.utils.AlipayConfigUtil;
|
||||||
|
import com.gxwebsoft.shop.entity.FreezeOrder;
|
||||||
|
import com.gxwebsoft.shop.entity.Order;
|
||||||
|
import com.gxwebsoft.shop.service.FreezeOrderService;
|
||||||
|
import com.gxwebsoft.shop.service.OrderService;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 押金冻结订单修复 & 解冻工具
|
||||||
|
* 用于处理 shop_freeze_order 表中 auth_no 为空的问题
|
||||||
|
*/
|
||||||
|
@SpringBootTest
|
||||||
|
public class UnfreezeToolTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private FreezeOrderService freezeOrderService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrderService orderService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AlipayConfigUtil alipayConfig;
|
||||||
|
|
||||||
|
private static final String AUTH_NO = "2026041610002001650571764471";
|
||||||
|
private static final String OUT_ORDER_NO = "2044685513146597377";
|
||||||
|
private static final BigDecimal AMOUNT = new BigDecimal("200.00");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一键修复并解冻
|
||||||
|
* 运行此方法即可完成修复 + 解冻
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void fixAndUnfreeze() throws AlipayApiException {
|
||||||
|
System.out.println("========================================");
|
||||||
|
System.out.println("押金修复 & 解冻工具");
|
||||||
|
System.out.println("========================================");
|
||||||
|
|
||||||
|
// 1. 查找冻结订单
|
||||||
|
System.out.println("\n[1] 查找冻结订单...");
|
||||||
|
List<FreezeOrder> freezeOrders = freezeOrderService.lambdaQuery()
|
||||||
|
.eq(FreezeOrder::getOutOrderNo, OUT_ORDER_NO)
|
||||||
|
.list();
|
||||||
|
|
||||||
|
if (freezeOrders.isEmpty()) {
|
||||||
|
System.out.println("❌ 未找到冻结订单: " + OUT_ORDER_NO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreezeOrder freezeOrder = freezeOrders.get(0);
|
||||||
|
System.out.println("✅ 找到冻结订单: id=" + freezeOrder.getId());
|
||||||
|
System.out.println(" out_order_no: " + freezeOrder.getOutOrderNo());
|
||||||
|
System.out.println(" status: " + freezeOrder.getStatus());
|
||||||
|
System.out.println(" auth_no: " + freezeOrder.getAuthNo());
|
||||||
|
|
||||||
|
// 2. 修复 auth_no(如果为空)
|
||||||
|
if (freezeOrder.getAuthNo() == null || freezeOrder.getAuthNo().isEmpty()) {
|
||||||
|
System.out.println("\n[2] 修复 auth_no...");
|
||||||
|
freezeOrder.setAuthNo(AUTH_NO);
|
||||||
|
freezeOrder.setStatus("SUCCESS");
|
||||||
|
freezeOrderService.updateById(freezeOrder);
|
||||||
|
System.out.println("✅ auth_no 已修复: " + AUTH_NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查找关联订单
|
||||||
|
System.out.println("\n[3] 查找关联订单...");
|
||||||
|
List<Order> orders = orderService.lambdaQuery()
|
||||||
|
.eq(Order::getFreezeOrderNo, OUT_ORDER_NO)
|
||||||
|
.list();
|
||||||
|
|
||||||
|
if (orders.isEmpty()) {
|
||||||
|
System.out.println("❌ 未找到关联订单!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Order order = orders.get(0);
|
||||||
|
System.out.println("✅ 找到关联订单: id=" + order.getOrderId());
|
||||||
|
System.out.println(" order_no: " + order.getOrderNo());
|
||||||
|
System.out.println(" is_freeze: " + order.getIsFreeze());
|
||||||
|
System.out.println(" freeze_order_no: " + order.getFreezeOrderNo());
|
||||||
|
|
||||||
|
// 4. 修复订单表的 freeze_order_no(如果不一致)
|
||||||
|
if (!OUT_ORDER_NO.equals(order.getFreezeOrderNo())) {
|
||||||
|
System.out.println("\n[4] 修复订单 freeze_order_no...");
|
||||||
|
order.setFreezeOrderNo(OUT_ORDER_NO);
|
||||||
|
orderService.updateById(order);
|
||||||
|
System.out.println("✅ freeze_order_no 已修复");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 调用解冻接口
|
||||||
|
System.out.println("\n[5] 调用支付宝解冻接口...");
|
||||||
|
try {
|
||||||
|
DefaultAlipayClient alipayClient = alipayConfig.alipayClient(6);
|
||||||
|
AlipayFundAuthOrderUnfreezeRequest request = new AlipayFundAuthOrderUnfreezeRequest();
|
||||||
|
|
||||||
|
JSONObject bizContent = new JSONObject();
|
||||||
|
bizContent.put("auth_no", AUTH_NO);
|
||||||
|
bizContent.put("out_request_no", IdUtil.getSnowflakeNextIdStr());
|
||||||
|
bizContent.put("amount", AMOUNT);
|
||||||
|
bizContent.put("remark", "客户申请退款解冻");
|
||||||
|
|
||||||
|
JSONObject extraParam = new JSONObject();
|
||||||
|
JSONObject unfreezeBizInfo = new JSONObject();
|
||||||
|
unfreezeBizInfo.put("bizComplete", true);
|
||||||
|
extraParam.put("unfreezeBizInfo", unfreezeBizInfo);
|
||||||
|
bizContent.put("extra_param", extraParam);
|
||||||
|
|
||||||
|
request.setBizContent(bizContent.toJSONString());
|
||||||
|
AlipayFundAuthOrderUnfreezeResponse response = alipayClient.certificateExecute(request);
|
||||||
|
|
||||||
|
System.out.println("----------------------------------------");
|
||||||
|
System.out.println("支付宝返回:");
|
||||||
|
System.out.println(JSON.toJSONString(response, true));
|
||||||
|
System.out.println("----------------------------------------");
|
||||||
|
|
||||||
|
if (response.isSuccess() && "10000".equals(response.getCode())) {
|
||||||
|
System.out.println("\n🎉 解冻成功!");
|
||||||
|
System.out.println(" 解冻金额: " + response.getAmount());
|
||||||
|
System.out.println(" 授权号: " + response.getAuthNo());
|
||||||
|
System.out.println(" 订单号: " + response.getOutOrderNo());
|
||||||
|
|
||||||
|
// 更新数据库
|
||||||
|
System.out.println("\n[6] 更新数据库状态...");
|
||||||
|
freezeOrder.setUnfreezeAmount(AMOUNT);
|
||||||
|
freezeOrder.setStatus("UNFREEZE");
|
||||||
|
freezeOrderService.updateById(freezeOrder);
|
||||||
|
System.out.println("✅ 数据库已更新");
|
||||||
|
|
||||||
|
System.out.println("\n⏰ 资金将在1-7个工作日内退回客户农业银行储蓄卡");
|
||||||
|
} else {
|
||||||
|
System.out.println("\n❌ 解冻失败!");
|
||||||
|
System.out.println(" 错误码: " + response.getSubCode());
|
||||||
|
System.out.println(" 错误信息: " + response.getSubMsg());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("\n❌ 解冻异常: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user