Browse Source

:art: #2040 【微信支付】增加多商户切换的支持

cloudX 4 years ago
parent
commit
488706b2df

+ 35 - 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfigHolder.java

@@ -0,0 +1,35 @@
+package com.github.binarywang.wxpay.config;
+
+/**
+ * 微信支付配置策略.
+ *
+ * @author zenghao
+ * @date 2021/3/12
+ */
+public class WxPayConfigHolder {
+
+  private static final ThreadLocal<String> THREAD_LOCAL = ThreadLocal.withInitial(() -> "default");
+
+  /**
+   * 获取当前微信支付配置策略.
+   * @return 当前微信支付配置策略
+   */
+  public static String get() {
+    return THREAD_LOCAL.get();
+  }
+
+  /**
+   * 设置当前微信支付配置策略.
+   * @param label 策略名称
+   */
+  public static void set(final String label) {
+    THREAD_LOCAL.set(label);
+  }
+
+  /**
+   * 此方法需要用户根据自己程序代码,在适当位置手动触发调用,本SDK里无法判断调用时机.
+   */
+  public static void remove() {
+    THREAD_LOCAL.remove();
+  }
+}

+ 47 - 0
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java

@@ -36,6 +36,53 @@ public interface WxPayService {
   String getPayBaseUrl();
 
   /**
+   * Map里 加入新的 {@link WxPayConfig},适用于动态添加新的微信公众号配置.
+   *
+   * @param mchId          商户号id
+   * @param wxPayConfig 新的微信配置
+   */
+  void addConfig(String mchId, WxPayConfig wxPayConfig);
+
+  /**
+   * 从 Map中 移除 {@link String mchId} 所对应的 {@link WxPayConfig},适用于动态移除微信公众号配置.
+   *
+   * @param mchId 对应公众号的标识
+   */
+  void removeConfig(String mchId);
+
+  /**
+   * 注入多个 {@link WxPayConfig} 的实现. 并为每个 {@link WxPayConfig} 赋予不同的 {@link String mchId} 值
+   * 随机采用一个{@link String mchId}进行Http初始化操作
+   *
+   * @param wxPayConfigs WxPayConfig map
+   */
+  void setMultiConfig(Map<String, WxPayConfig> wxPayConfigs);
+
+  /**
+   * 注入多个 {@link WxPayConfig} 的实现. 并为每个 {@link WxPayConfig} 赋予不同的 {@link String label} 值
+   *
+   * @param wxPayConfigs WxPayConfig map
+   * @param defaultMchId    设置一个{@link WxPayConfig} 所对应的{@link String mchId}进行Http初始化
+   */
+  void setMultiConfig(Map<String, WxPayConfig> wxPayConfigs, String defaultMchId);
+
+  /**
+   * 进行相应的公众号切换.
+   *
+   * @param mchId 公众号标识
+   * @return 切换是否成功 boolean
+   */
+  boolean switchover(String mchId);
+
+  /**
+   * 进行相应的公众号切换.
+   *
+   * @param mchId 公众号标识
+   * @return 切换成功 ,则返回当前对象,方便链式调用,否则抛出异常
+   */
+  WxPayService switchoverTo(String mchId);
+
+  /**
    * 发送post请求,得到响应字节数组.
    *
    * @param url        请求地址

+ 71 - 3
weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java

@@ -13,6 +13,7 @@ import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
 import com.github.binarywang.wxpay.bean.request.*;
 import com.github.binarywang.wxpay.bean.result.*;
 import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.config.WxPayConfigHolder;
 import com.github.binarywang.wxpay.constant.WxPayConstants;
 import com.github.binarywang.wxpay.constant.WxPayConstants.SignType;
 import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType;
@@ -21,6 +22,7 @@ import com.github.binarywang.wxpay.service.*;
 import com.github.binarywang.wxpay.util.SignUtils;
 import com.github.binarywang.wxpay.util.XmlConfig;
 import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 import jodd.io.ZipUtil;
 import me.chanjar.weixin.common.error.WxRuntimeException;
@@ -65,7 +67,7 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
   private final MarketingMediaService marketingMediaService = new MarketingMediaServiceImpl(this);
   private final MarketingFavorService marketingFavorService = new MarketingFavorServiceImpl(this);
 
-  protected WxPayConfig config;
+  protected Map<String, WxPayConfig> configMap;
 
   @Override
   public EntPayService getEntPayService() {
@@ -119,12 +121,78 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
 
   @Override
   public WxPayConfig getConfig() {
-    return this.config;
+    if (this.configMap.size() == 1) {
+      // 只有一个商户号,直接返回其配置即可
+      return this.configMap.values().iterator().next();
+    }
+    return this.configMap.get(WxPayConfigHolder.get());
   }
 
   @Override
   public void setConfig(WxPayConfig config) {
-    this.config = config;
+    final String defaultMchId = config.getMchId();
+    this.setMultiConfig(ImmutableMap.of(defaultMchId, config), defaultMchId);
+  }
+
+  @Override
+  public void addConfig(String mchId, WxPayConfig wxPayConfig) {
+    synchronized (this) {
+      if (this.configMap == null) {
+        this.setConfig(wxPayConfig);
+      } else {
+        WxPayConfigHolder.set(mchId);
+        this.configMap.put(mchId, wxPayConfig);
+      }
+    }
+  }
+
+  @Override
+  public void removeConfig(String mchId) {
+    synchronized (this) {
+      if (this.configMap.size() == 1) {
+        this.configMap.remove(mchId);
+        log.warn("已删除最后一个商户号配置:{},须立即使用setConfig或setMultiConfig添加配置", mchId);
+        return;
+      }
+      if (WxPayConfigHolder.get().equals(mchId)) {
+        this.configMap.remove(mchId);
+        final String defaultMpId = this.configMap.keySet().iterator().next();
+        WxPayConfigHolder.set(defaultMpId);
+        log.warn("已删除默认商户号配置,商户号【{}】被设为默认配置", defaultMpId);
+        return;
+      }
+      this.configMap.remove(mchId);
+    }
+  }
+
+  @Override
+  public void setMultiConfig(Map<String, WxPayConfig> wxPayConfigs) {
+    this.setMultiConfig(wxPayConfigs, wxPayConfigs.keySet().iterator().next());
+  }
+
+  @Override
+  public void setMultiConfig(Map<String, WxPayConfig> wxPayConfigs, String defaultMchId) {
+    this.configMap = Maps.newHashMap(wxPayConfigs);
+    WxPayConfigHolder.set(defaultMchId);
+  }
+
+  @Override
+  public boolean switchover(String mchId) {
+    if (this.configMap.containsKey(mchId)) {
+      WxPayConfigHolder.set(mchId);
+      return true;
+    }
+    log.error("无法找到对应【{}】的商户号配置信息,请核实!", mchId);
+    return false;
+  }
+
+  @Override
+  public WxPayService switchoverTo(String mchId) {
+    if (this.configMap.containsKey(mchId)) {
+      WxPayConfigHolder.set(mchId);
+      return this;
+    }
+    throw new WxRuntimeException(String.format("无法找到对应【%s】的商户号配置信息,请核实!", mchId));
   }
 
   @Override