Commit 11f1a3ee9ce9513fe56b54d81e0355b95319ecd3

Authored by YunaiV
1 parent 11dd407e

chore: 合并 unibest 2025-12 构建配置修复

部分合并:
- 61cceb5 build: 更新 @uni-helper 相关依赖版本
  - 升级 @uni-helper/vite-plugin-uni-manifest 0.2.11 -> 0.2.12
  - 升级 @uni-helper/vite-plugin-uni-pages 0.3.19 -> 0.3.22

- 4fa7a43 chore: 同步 lock 锁定 61cceb5 的插件版本
  - pnpm-lock.yaml 仅同步 uni-manifest 0.2.12 和 uni-pages 0.3.22
  - 未引入无关依赖漂移

- 36abf49 refactor(vite): 重命名插件导入并调整插件顺序
  - Components -> UniComponents
  - Optimization -> UniOptimization
  - 保留当前项目的 WotResolver 和芋道分包配置

- a75502a refactor(vite配置): 调整 UniPages 和 UniComponents 插件顺序并更新排除规则
  - 将 UniComponents 前置到 UniPages 前
  - UniPages 和 UniKuRoot 均补充 **/sections/**/**.* 排除规则
  - 保留 pages-core、pages-system、pages-infra、pages-bpm 分包

- bfe5c04 fix(scripts): 补充 app/mp 开发命令的基础文件初始化入口
  - 新增 predev:app 和 predev:mp
  - 保留当前项目已有 init-json

- a487ba7 fix(脚本): 修复基础文件创建逻辑,避免空对象文件导致错误
  - src/manifest.json 为空对象时重新生成
  - src/pages.json 为空对象时重新生成

完全合并:
- 无

忽略:
- bffa3bd、8926504 tabbar 重构:当前项目已有芋道定制 tabbar 和登录态保护,暂不合并
- cc8db0d、286f23e、ff5ef61、8a20eec:上游版本号更新,不覆盖当前项目版本
- 1021b55、4ebed7a、b9a3bf2、bd21100、b2a3496、a068049、a09365f:文档/注释更新,不属于本次运行时修复
- 2939eb8:上游合并提交
- 24a6712:VSCode snippets,不合并
- 0f68e06:package script 顺序整理,当前不需要

验证:
- git diff --check 通过
- pnpm build:h5 通过
- pnpm build:mp-weixin 通过
- 浏览器和微信小程序手测通过
yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java
... ... @@ -26,6 +26,14 @@ public interface PayTransferMapper extends BaseMapperX<PayTransferDO> {
26 26 .eq(PayTransferDO::getStatus, whereStatus));
27 27 }
28 28  
  29 + default int updateChannelPackageInfoIfAbsent(Long id, String channelPackageInfo) {
  30 + return update(new PayTransferDO().setChannelPackageInfo(channelPackageInfo),
  31 + new LambdaQueryWrapper<PayTransferDO>()
  32 + .eq(PayTransferDO::getId, id)
  33 + .and(wrapper -> wrapper.isNull(PayTransferDO::getChannelPackageInfo)
  34 + .or().eq(PayTransferDO::getChannelPackageInfo, "")));
  35 + }
  36 +
29 37 default PayTransferDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) {
30 38 return selectOne(PayTransferDO::getAppId, appId,
31 39 PayTransferDO::getMerchantTransferId, merchantOrderId);
... ... @@ -59,7 +67,3 @@ public interface PayTransferMapper extends BaseMapperX&lt;PayTransferDO&gt; {
59 67 }
60 68  
61 69 }
62   -
63   -
64   -
65   -
... ...
yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.transfer;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.util.ObjectUtil;
  5 +import cn.hutool.core.util.StrUtil;
5 6 import cn.hutool.extra.spring.SpringUtil;
6 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 8 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
... ... @@ -162,6 +163,7 @@ public class PayTransferServiceImpl implements PayTransferService {
162 163 throw exception(PAY_TRANSFER_NOT_FOUND);
163 164 }
164 165 if (PayTransferStatusEnum.isProcessing(transfer.getStatus())) { // 如果已经是转账中,直接返回,不用重复更新
  166 + updateChannelPackageInfoIfAbsent(transfer, notify);
165 167 log.info("[notifyTransferProgressing][transfer({}) 已经是转账中状态,无需更新]", transfer.getId());
166 168 return;
167 169 }
... ... @@ -175,11 +177,35 @@ public class PayTransferServiceImpl implements PayTransferService {
175 177 new PayTransferDO().setStatus(PayTransferStatusEnum.PROCESSING.getStatus())
176 178 .setChannelPackageInfo(notify.getChannelPackageInfo()));
177 179 if (updateCounts == 0) {
  180 + PayTransferDO latestTransfer = transferMapper.selectById(transfer.getId());
  181 + if (latestTransfer != null && PayTransferStatusEnum.isProcessing(latestTransfer.getStatus())) {
  182 + updateChannelPackageInfoIfAbsent(latestTransfer, notify);
  183 + log.info("[notifyTransferProgressing][transfer({}) 已被并发更新为转账中状态,无需重复更新]",
  184 + transfer.getId());
  185 + return;
  186 + }
178 187 throw exception(PAY_TRANSFER_NOTIFY_FAIL_STATUS_IS_NOT_WAITING);
179 188 }
180 189 log.info("[notifyTransferProgressing][transfer({}) 更新为转账进行中状态]", transfer.getId());
181 190 }
182 191  
  192 + /**
  193 + * 补充渠道 package 信息:处理同步任务先更新为转账中,发起转账接口后返回 channelPackageInfo 的场景
  194 + *
  195 + * @see <a href="https://github.com/YunaiV/ruoyi-vue-pro/issues/1144">Issue #1144</a>
  196 + */
  197 + private void updateChannelPackageInfoIfAbsent(PayTransferDO transfer, PayTransferRespDTO notify) {
  198 + if (StrUtil.isBlank(notify.getChannelPackageInfo())
  199 + || StrUtil.isNotBlank(transfer.getChannelPackageInfo())) {
  200 + return;
  201 + }
  202 + int updateCount = transferMapper.updateChannelPackageInfoIfAbsent(transfer.getId(),
  203 + notify.getChannelPackageInfo());
  204 + if (updateCount > 0) {
  205 + log.info("[updateChannelPackageInfoIfAbsent][transfer({}) 补充渠道 package 信息]", transfer.getId());
  206 + }
  207 + }
  208 +
183 209 private void notifyTransferSuccess(PayChannelDO channel, PayTransferRespDTO notify) {
184 210 // 1. 校验状态
185 211 PayTransferDO transfer = transferMapper.selectByAppIdAndNo(channel.getAppId(), notify.getOutTransferNo());
... ...
yudao-module-pay/src/test/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.service.transfer;
  2 +
  3 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
  4 +import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
  5 +import cn.iocoder.yudao.module.pay.dal.dataobject.transfer.PayTransferDO;
  6 +import cn.iocoder.yudao.module.pay.dal.mysql.transfer.PayTransferMapper;
  7 +import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO;
  8 +import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
  9 +import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
  10 +import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
  11 +import cn.iocoder.yudao.module.pay.service.app.PayAppService;
  12 +import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
  13 +import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
  14 +import jakarta.annotation.Resource;
  15 +import org.junit.jupiter.api.Test;
  16 +import org.springframework.context.annotation.Import;
  17 +import org.springframework.test.context.bean.override.mockito.MockitoBean;
  18 +
  19 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  20 +import static org.junit.jupiter.api.Assertions.assertEquals;
  21 +import static org.junit.jupiter.api.Assertions.assertNull;
  22 +
  23 +/**
  24 + * {@link PayTransferServiceImpl} 的单元测试类
  25 + *
  26 + * @author 芋道源码
  27 + */
  28 +@Import({PayTransferServiceImpl.class, PayNoRedisDAO.class})
  29 +public class PayTransferServiceTest extends BaseDbAndRedisUnitTest {
  30 +
  31 + @Resource
  32 + private PayTransferServiceImpl transferService;
  33 +
  34 + @Resource
  35 + private PayTransferMapper transferMapper;
  36 +
  37 + @MockitoBean
  38 + private PayProperties payProperties;
  39 + @MockitoBean
  40 + private PayAppService appService;
  41 + @MockitoBean
  42 + private PayChannelService channelService;
  43 + @MockitoBean
  44 + private PayNotifyService notifyService;
  45 +
  46 + @Test
  47 + public void testNotifyTransferProgressing_fillChannelPackageInfoIfAbsent() {
  48 + // mock 数据(PayTransferDO):初始为等待转账
  49 + PayTransferDO transfer = randomPojo(PayTransferDO.class,
  50 + o -> o.setAppId(10L)
  51 + .setNo("T110")
  52 + .setStatus(PayTransferStatusEnum.WAITING.getStatus())
  53 + .setChannelPackageInfo(null));
  54 + transferMapper.insert(transfer);
  55 + // 准备参数
  56 + PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setAppId(10L));
  57 + PayTransferRespDTO syncNotify = PayTransferRespDTO.processingOf("WX_TRANSFER_110",
  58 + "T110", "sync");
  59 +
  60 + // 调用:模拟同步任务先把 WAITING 更新为 PROCESSING,但是不返回 package 信息
  61 + transferService.notifyTransfer(channel, syncNotify);
  62 +
  63 + // 断言:状态已转账中,package 信息为空
  64 + PayTransferDO dbTransfer = transferMapper.selectById(transfer.getId());
  65 + assertEquals(PayTransferStatusEnum.PROCESSING.getStatus(), dbTransfer.getStatus());
  66 + assertNull(dbTransfer.getChannelPackageInfo());
  67 +
  68 + // 调用:模拟发起转账接口随后返回 PROCESSING,并携带微信确认收款 package 信息
  69 + PayTransferRespDTO createNotify = PayTransferRespDTO.processingOf("WX_TRANSFER_110",
  70 + "T110", "create");
  71 + createNotify.setChannelPackageInfo("package-info-110");
  72 + transferService.notifyTransfer(channel, createNotify);
  73 +
  74 + // 断言:已是 PROCESSING 时仍会补写 package 信息
  75 + dbTransfer = transferMapper.selectById(transfer.getId());
  76 + assertEquals(PayTransferStatusEnum.PROCESSING.getStatus(), dbTransfer.getStatus());
  77 + assertEquals("package-info-110", dbTransfer.getChannelPackageInfo());
  78 +
  79 + // 调用:后续同步任务仍不返回 package 信息,不应覆盖已有值
  80 + transferService.notifyTransfer(channel, syncNotify);
  81 +
  82 + // 断言:已有 package 信息不被空值覆盖
  83 + dbTransfer = transferMapper.selectById(transfer.getId());
  84 + assertEquals("package-info-110", dbTransfer.getChannelPackageInfo());
  85 + }
  86 +
  87 +}
... ...
yudao-module-pay/src/test/resources/sql/create_tables.sql
... ... @@ -165,12 +165,14 @@ CREATE TABLE IF NOT EXISTS `pay_transfer` (
165 165 `user_name` varchar(64) NULL DEFAULT NULL,
166 166 `status` tinyint(4) NOT NULL,
167 167 `notify_url` varchar(1024) NULL DEFAULT NULL,
  168 + `user_ip` varchar(50) NULL DEFAULT NULL,
168 169 `channel_transfer_no` varchar(64) NULL DEFAULT NULL,
169 170 `success_time` datetime(0) NULL DEFAULT NULL,
170 171 `channel_error_code` varchar(128) NULL DEFAULT NULL,
171 172 `channel_error_msg` varchar(256) NULL DEFAULT NULL,
172 173 `channel_notify_data` varchar(1024) NULL DEFAULT NULL,
173 174 `channel_extras` varchar(1024) NULL DEFAULT NULL,
  175 + `channel_package_info` varchar(1024) NULL DEFAULT NULL,
174 176 `creator` varchar(64) NULL DEFAULT '',
175 177 `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
176 178 `updater` varchar(64) NULL DEFAULT '',
... ...