@@ -53,7 +53,64 @@ configMap.put(mchId + "_" + config3.getAppId(), config3);
5353payService. setMultiConfig(configMap);
5454```
5555
56- ### 2. 切换配置的方式
56+ ### 2. 获取配置的方式
57+
58+ #### 方式一:直接获取配置(推荐,新功能)
59+
60+ 直接通过商户号和 appId 获取配置,** 不依赖 ThreadLocal** ,适用于多商户管理场景:
61+
62+ ``` java
63+ // 精确获取指定商户号和 appId 的配置
64+ WxPayConfig config1 = payService. getConfig(" 1234567890" , " wx1111111111111111" );
65+
66+ // 仅使用商户号获取配置(会返回该商户号的任意一个配置)
67+ // 注意:当存在多个 appId 时,返回结果基于内部存储顺序,不应依赖其稳定性
68+ WxPayConfig config = payService. getConfig(" 1234567890" );
69+
70+ // 使用获取的配置读取信息(仅用于读取配置,不用于执行支付操作)
71+ if (config != null ) {
72+ String appId = config. getAppId();
73+ String mchKey = config. getMchKey();
74+ String apiV3Key = config. getApiV3Key();
75+ // ... 使用配置信息进行业务逻辑判断或记录
76+ }
77+ ```
78+
79+ ** 优势** :
80+ - 不依赖 ThreadLocal,可以在任何上下文中使用
81+ - 适合在异步场景、线程池等环境中使用
82+ - 线程安全,不会因为线程切换导致配置丢失
83+ - 可以同时获取多个不同的配置
84+
85+ ** 使用场景** :
86+ - 仅需读取配置信息(如获取 mchKey、appId 等)
87+ - 不需要执行 WxPayService 的支付相关方法
88+ - 如需执行支付操作,请使用方式二的 switchover 方法
89+
90+ #### 方式二:切换配置后使用(原有方式)
91+
92+ 通过切换配置,然后调用 ` getConfig() ` 获取当前配置或直接执行支付操作:
93+
94+ ``` java
95+ // 精确切换到指定的配置
96+ payService. switchover(" 1234567890" , " wx1111111111111111" );
97+ WxPayConfig config = payService. getConfig(); // 获取当前切换的配置
98+
99+ // 仅使用商户号切换
100+ payService. switchover(" 1234567890" );
101+ config = payService. getConfig(); // 获取切换后的配置
102+
103+ // 切换后可直接执行支付操作
104+ WxPayUnifiedOrderResult result = payService. unifiedOrder(request);
105+ ```
106+
107+ ** 注意** :此方式依赖 ThreadLocal,需要注意线程上下文的问题。
108+
109+ ** 使用场景** :
110+ - 需要执行 WxPayService 的支付相关方法(如 unifiedOrder、refund 等)
111+ - 在同一线程中连续执行多个支付操作
112+
113+ ### 3. 切换配置的方式
57114
58115#### 方式一:精确切换(原有方式,向后兼容)
59116
@@ -92,7 +149,7 @@ WxPayUnifiedOrderResult result = payService
92149 .unifiedOrder(request);
93150```
94151
95- ### 3 . 动态添加配置
152+ ### 4 . 动态添加配置
96153
97154``` java
98155// 运行时动态添加新的 appId 配置
@@ -107,7 +164,7 @@ payService.addConfig("1234567890", "wx4444444444444444", newConfig);
107164payService. switchover(" 1234567890" , " wx4444444444444444" );
108165```
109166
110- ### 4 . 移除配置
167+ ### 5 . 移除配置
111168
112169``` java
113170// 移除特定的 appId 配置
@@ -174,24 +231,78 @@ WxPayRefundRequest refundRequest = new WxPayRefundRequest();
174231WxPayRefundResult refundResult = payService. refund(refundRequest);
175232```
176233
234+ ### 场景4:多商户管理(推荐使用直接获取配置)
235+
236+ ``` java
237+ // 在多商户管理系统中,可以直接获取指定商户的配置
238+ // 这种方式不依赖 ThreadLocal,适合异步场景和线程池环境
239+
240+ public void processMerchantOrder(String mchId, String appId, Order order) {
241+ // 直接获取配置,无需切换
242+ WxPayConfig config = payService. getConfig(mchId, appId);
243+
244+ if (config == null ) {
245+ log. error(" 找不到商户配置:mchId={}, appId={}" , mchId, appId);
246+ return ;
247+ }
248+
249+ // 使用配置信息
250+ String merchantKey = config. getMchKey();
251+ String apiV3Key = config. getApiV3Key();
252+
253+ // ... 处理订单逻辑
254+ }
255+
256+ // 或者在不确定 appId 的情况下,仅通过商户号发起退款
257+ public void processRefund(String mchId, String outTradeNo) {
258+ // 直接根据商户号切换(内部会选择该商户号下的一个配置)
259+ if (! payService. switchover(mchId)) {
260+ log. error(" 商户配置切换失败:mchId={}" , mchId);
261+ return ;
262+ }
263+
264+ // 在完成上下文切换后,执行退款操作
265+ WxPayRefundRequest request = new WxPayRefundRequest ();
266+ request. setOutTradeNo(outTradeNo);
267+ // ... 设置其他退款参数
268+ WxPayRefundResult refundResult = payService. refund(request);
269+ }
270+ ```
271+
272+ ## 新增方法对比
273+
274+ | 方法 | 说明 | 是否依赖 ThreadLocal | 适用场景 |
275+ | -----| ------| ---------------------| ---------|
276+ | ` getConfig() ` | 获取当前配置 | 是 | 单线程同步场景 |
277+ | ` getConfig(String mchId, String appId) ` | 直接获取指定配置 | ** 否** | 多商户管理、异步场景、线程池 |
278+ | ` getConfig(String mchId) ` | 根据商户号获取配置 | ** 否** | 不确定 appId 的场景 |
279+ | ` switchover(String mchId, String appId) ` | 精确切换配置 | 是 | 需要切换上下文的场景 |
280+ | ` switchover(String mchId) ` | 根据商户号切换 | 是 | 不关心 appId 的切换场景 |
281+
177282## 注意事项
178283
1792841 . ** 向后兼容** :所有原有的使用方式继续有效,不需要修改现有代码。
180285
1812862 . ** 配置隔离** :每个 ` mchId + appId ` 组合都是独立的配置,修改一个配置不会影响其他配置。
182287
183- 3 . ** 线程安全** :配置切换使用 ` WxPayConfigHolder ` (基于 ` ThreadLocal ` ),是线程安全的。
288+ 3 . ** 线程安全** :
289+ - 配置切换使用 ` WxPayConfigHolder ` (基于 ` ThreadLocal ` ),是线程安全的
290+ - 直接获取配置方法(` getConfig(mchId, appId) ` )不依赖 ThreadLocal,可以在任何上下文中安全使用
184291
1852924 . ** 自动切换** :在处理支付回调时,SDK 会自动根据回调中的 ` mchId ` 和 ` appId ` 切换到正确的配置。
186293
1872945 . ** 推荐实践** :
188- - 如果知道具体的 appId,建议使用精确切换方式,避免歧义
189- - 如果使用仅商户号切换,确保该商户号下至少有一个可用的配置
295+ - 如果知道具体的 appId,建议使用精确切换或获取方式,避免歧义
296+ - 在多商户管理、异步场景、线程池等环境中,建议使用 ` getConfig(mchId, appId) ` 直接获取配置
297+ - 如果使用仅商户号切换或获取,确保该商户号下至少有一个可用的配置
190298
191299## 相关 API
192300
193301| 方法 | 参数 | 返回值 | 说明 |
194302| -----| ------| --------| ------|
303+ | ` getConfig() ` | 无 | WxPayConfig | 获取当前配置(依赖 ThreadLocal) |
304+ | ` getConfig(String mchId, String appId) ` | 商户号, appId | WxPayConfig | 直接获取指定配置(不依赖 ThreadLocal) |
305+ | ` getConfig(String mchId) ` | 商户号 | WxPayConfig | 根据商户号获取配置(不依赖 ThreadLocal) |
195306| ` switchover(String mchId, String appId) ` | 商户号, appId | boolean | 精确切换到指定配置 |
196307| ` switchover(String mchId) ` | 商户号 | boolean | 仅使用商户号切换 |
197308| ` switchoverTo(String mchId, String appId) ` | 商户号, appId | WxPayService | 精确切换,支持链式调用 |
0 commit comments