Commit 11f1a3ee9ce9513fe56b54d81e0355b95319ecd3
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 通过 - 浏览器和微信小程序手测通过
Showing
4 changed files
with
123 additions
and
4 deletions
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<PayTransferDO> { |
| 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 '', | ... | ... |