From 3cdd53d7657f5f0a4ac583aa2b46d8674a7b7a7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 08:44:58 +0000 Subject: [PATCH] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E4=BB=A3=E7=A0=81=E5=AE=A1?= =?UTF-8?q?=E6=9F=A5=E6=84=8F=E8=A7=81=E6=94=B9=E8=BF=9B=EF=BC=9A=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=8F=82=E6=95=B0=E6=A0=A1=E9=AA=8C=E3=80=81=E6=94=B9?= =?UTF-8?q?=E8=BF=9B=E6=96=87=E6=A1=A3=E6=B3=A8=E9=87=8A=E3=80=81=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=BE=B9=E7=95=8C=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- .../wxpay/service/WxPayService.java | 11 ++- .../service/impl/BaseWxPayServiceImpl.java | 11 +++ .../impl/MultiAppIdSwitchoverTest.java | 87 +++++++++++++++++++ 3 files changed, 105 insertions(+), 4 deletions(-) diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index f7bdb5606..ebe4de02e 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -80,10 +80,11 @@ public interface WxPayService { /** * 仅根据商户号进行切换. - * 适用于一个商户号对应多个appId的场景,切换时会匹配第一个符合该商户号的配置. + * 适用于一个商户号对应多个appId的场景,切换时会匹配符合该商户号的配置. + * 注意:由于HashMap迭代顺序不确定,当存在多个匹配项时返回的配置是不可预测的,建议使用精确匹配方式. * * @param mchId 商户标识 - * @return 切换是否成功 boolean + * @return 切换是否成功,如果找不到匹配的配置则返回false */ boolean switchover(String mchId); @@ -98,10 +99,12 @@ public interface WxPayService { /** * 仅根据商户号进行切换. - * 适用于一个商户号对应多个appId的场景,切换时会匹配第一个符合该商户号的配置. + * 适用于一个商户号对应多个appId的场景,切换时会匹配符合该商户号的配置. + * 注意:由于HashMap迭代顺序不确定,当存在多个匹配项时返回的配置是不可预测的,建议使用精确匹配方式. * * @param mchId 商户标识 - * @return 切换成功 ,则返回当前对象,方便链式调用,否则抛出异常 + * @return 切换成功,则返回当前对象,方便链式调用 + * @throws WxRuntimeException 如果找不到匹配的配置 */ WxPayService switchoverTo(String mchId); diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java index dc880e0f9..4b51c498d 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java @@ -214,6 +214,12 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { @Override public boolean switchover(String mchId) { + // 参数校验 + if (StringUtils.isBlank(mchId)) { + log.error("商户号mchId不能为空"); + return false; + } + // 先尝试精确匹配(针对只有mchId没有appId的配置) if (this.configMap.containsKey(mchId)) { WxPayConfigHolder.set(mchId); @@ -246,6 +252,11 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { @Override public WxPayService switchoverTo(String mchId) { + // 参数校验 + if (StringUtils.isBlank(mchId)) { + throw new WxRuntimeException("商户号mchId不能为空"); + } + // 先尝试精确匹配(针对只有mchId没有appId的配置) if (this.configMap.containsKey(mchId)) { WxPayConfigHolder.set(mchId); diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MultiAppIdSwitchoverTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MultiAppIdSwitchoverTest.java index c88766bfa..c1c1460fe 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MultiAppIdSwitchoverTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/MultiAppIdSwitchoverTest.java @@ -220,4 +220,91 @@ public class MultiAppIdSwitchoverTest { success = singlePayService.switchover("single_mch_id"); assertTrue(success); } + + /** + * 测试空参数或null参数的处理 + */ + @Test + public void testSwitchoverWithNullOrEmptyMchId() { + // 测试 null 参数 + boolean success = payService.switchover(null); + assertFalse(success, "使用null作为mchId应该返回false"); + + // 测试空字符串 + success = payService.switchover(""); + assertFalse(success, "使用空字符串作为mchId应该返回false"); + + // 测试空白字符串 + success = payService.switchover(" "); + assertFalse(success, "使用空白字符串作为mchId应该返回false"); + } + + /** + * 测试 switchoverTo 方法对空参数或null参数的处理 + */ + @Test(expectedExceptions = WxRuntimeException.class) + public void testSwitchoverToWithNullMchId() { + payService.switchoverTo((String) null); + } + + @Test(expectedExceptions = WxRuntimeException.class) + public void testSwitchoverToWithEmptyMchId() { + payService.switchoverTo(""); + } + + @Test(expectedExceptions = WxRuntimeException.class) + public void testSwitchoverToWithBlankMchId() { + payService.switchoverTo(" "); + } + + /** + * 测试商户号存在包含关系的场景 + * 例如同时配置 "123" 和 "1234",验证前缀匹配不会错误匹配 + */ + @Test + public void testSwitchoverWithOverlappingMchIds() { + WxPayService testService = new WxPayServiceImpl(); + + // 配置两个有包含关系的商户号 + String mchId1 = "123"; + String mchId2 = "1234"; + String appId1 = "wx_app_123"; + String appId2 = "wx_app_1234"; + + WxPayConfig config1 = new WxPayConfig(); + config1.setMchId(mchId1); + config1.setAppId(appId1); + config1.setMchKey("key_123"); + + WxPayConfig config2 = new WxPayConfig(); + config2.setMchId(mchId2); + config2.setAppId(appId2); + config2.setMchKey("key_1234"); + + Map configMap = new HashMap<>(); + configMap.put(mchId1 + "_" + appId1, config1); + configMap.put(mchId2 + "_" + appId2, config2); + testService.setMultiConfig(configMap); + + // 切换到 "123",应该只匹配 "123_wx_app_123" + boolean success = testService.switchover(mchId1); + assertTrue(success); + assertEquals(testService.getConfig().getMchId(), mchId1); + assertEquals(testService.getConfig().getAppId(), appId1); + + // 切换到 "1234",应该只匹配 "1234_wx_app_1234" + success = testService.switchover(mchId2); + assertTrue(success); + assertEquals(testService.getConfig().getMchId(), mchId2); + assertEquals(testService.getConfig().getAppId(), appId2); + + // 精确切换验证 + success = testService.switchover(mchId1, appId1); + assertTrue(success); + assertEquals(testService.getConfig().getAppId(), appId1); + + success = testService.switchover(mchId2, appId2); + assertTrue(success); + assertEquals(testService.getConfig().getAppId(), appId2); + } }