@@ -12,7 +12,6 @@ import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; | |||
import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
import me.chanjar.weixin.mp.enums.TicketType; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
@@ -309,12 +308,32 @@ public interface WxMpService { | |||
*/ | |||
void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider); | |||
/** | |||
* {@link Map<String, WxMpConfigStorage>} 加入新的 {@link WxMpConfigStorage},适用于动态添加新的微信应用 | |||
* @param configStorages | |||
*/ | |||
void addWxMpConfigStorage(String label, WxMpConfigStorage configStorages); | |||
/** | |||
* 从{@link Map<String, WxMpConfigStorage>} 移除 {@link String label} 所对应的 {@link WxMpConfigStorage},适用于动态移除的微信应用 | |||
* @param label | |||
*/ | |||
void removeWxMpConfigStorage(String label); | |||
/** | |||
* 注入多个 {@link WxMpConfigStorage} 的实现. 并为每个 {@link WxMpConfigStorage} 赋予不同的 {@link String label} 值 | |||
* @return | |||
* 随机采用一个{@link String lable}进行Http初始化操作 | |||
* @param configStorages | |||
*/ | |||
void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages); | |||
/** | |||
* 注入多个 {@link WxMpConfigStorage} 的实现. 并为每个 {@link WxMpConfigStorage} 赋予不同的 {@link String label} 值 | |||
* @param configStorages | |||
* @param defaultInitLabel 设置一个{@link WxMpConfigStorage} 所对应的{@link String label}进行Http初始化 | |||
*/ | |||
void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages, String defaultInitLabel); | |||
/** | |||
* 进行相应的 WxApp 切换 | |||
* @param label | |||
@@ -1,5 +1,15 @@ | |||
package me.chanjar.weixin.mp.api.impl; | |||
import java.io.IOException; | |||
import java.util.HashMap; | |||
import java.util.concurrent.locks.Lock; | |||
import me.chanjar.weixin.mp.api.*; | |||
import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import com.google.gson.JsonArray; | |||
import com.google.gson.JsonElement; | |||
import com.google.gson.JsonObject; | |||
@@ -13,21 +23,14 @@ import me.chanjar.weixin.common.util.DataUtils; | |||
import me.chanjar.weixin.common.util.RandomUtils; | |||
import me.chanjar.weixin.common.util.crypto.SHA1; | |||
import me.chanjar.weixin.common.util.http.*; | |||
import me.chanjar.weixin.mp.api.*; | |||
import me.chanjar.weixin.mp.bean.WxMpSemanticQuery; | |||
import me.chanjar.weixin.mp.bean.result.WxMpCurrentAutoReplyInfo; | |||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | |||
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; | |||
import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
import me.chanjar.weixin.mp.enums.TicketType; | |||
import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.IOException; | |||
import java.util.Map; | |||
import java.util.concurrent.locks.Lock; | |||
/** | |||
* 基础实现类. | |||
@@ -40,7 +43,6 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH | |||
protected final Logger log = LoggerFactory.getLogger(this.getClass()); | |||
protected WxSessionManager sessionManager = new StandardSessionManager(); | |||
protected WxMpConfigStorage wxMpConfigStorage; | |||
private WxMpKefuService kefuService = new WxMpKefuServiceImpl(this); | |||
private WxMpMaterialService materialService = new WxMpMaterialServiceImpl(this); | |||
private WxMpMenuService menuService = new WxMpMenuServiceImpl(this); | |||
@@ -62,7 +64,6 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH | |||
private WxMpMarketingService marketingService = new WxMpMarketingServiceImpl(this); | |||
private Map<String, WxMpConfigStorage> wxMpConfigStoragePool; | |||
private boolean isMultiWxApp = false; | |||
private int retrySleepMillis = 1000; | |||
private int maxRetryTimes = 5; | |||
@@ -334,26 +335,46 @@ public abstract class BaseWxMpServiceImpl<H, P> implements WxMpService, RequestH | |||
@Override | |||
public WxMpConfigStorage getWxMpConfigStorage() { | |||
if (isMultiWxApp) { | |||
return wxMpConfigStoragePool.get(WxMpConfigStorageHolder.get()); | |||
} | |||
return this.wxMpConfigStorage; | |||
return wxMpConfigStoragePool.get(WxMpConfigStorageHolder.get()); | |||
} | |||
@Override | |||
public void setWxMpConfigStorage(WxMpConfigStorage wxConfigProvider) { | |||
this.wxMpConfigStorage = wxConfigProvider; | |||
this.initHttp(); | |||
Map<String, WxMpConfigStorage> map = new HashMap<>(1); | |||
map.put(WxMpConfigStorageHolder.get(), wxConfigProvider); | |||
setMultiWxMpConfigStorage(map, WxMpConfigStorageHolder.get()); | |||
} | |||
@Override | |||
public void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages) { | |||
String randomKey = configStorages.keySet().iterator().next(); | |||
setMultiWxMpConfigStorage(configStorages, randomKey); | |||
} | |||
@Override | |||
public void setMultiWxMpConfigStorage(Map<String, WxMpConfigStorage> configStorages, String defaultInitLabel) { | |||
wxMpConfigStoragePool = configStorages; | |||
isMultiWxApp = true; | |||
WxMpConfigStorageHolder.set(defaultInitLabel); | |||
this.initHttp(); | |||
} | |||
@Override | |||
public void addWxMpConfigStorage(String label, WxMpConfigStorage configStorages) { | |||
synchronized (this) { | |||
if (wxMpConfigStoragePool.containsKey(label)) { | |||
throw new RuntimeException("该label已存在,请重新设置一个label"); | |||
} | |||
wxMpConfigStoragePool.put(label, configStorages); | |||
} | |||
} | |||
@Override | |||
public void removeWxMpConfigStorage(String label) { | |||
synchronized (this) { | |||
wxMpConfigStoragePool.remove(label); | |||
} | |||
} | |||
@Override | |||
public boolean switchover(String label) { | |||
if (wxMpConfigStoragePool.containsKey(label)) { | |||
@@ -6,6 +6,7 @@ import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.HttpType; | |||
import me.chanjar.weixin.common.util.http.okhttp.OkHttpProxyInfo; | |||
import me.chanjar.weixin.mp.api.WxMpConfigStorage; | |||
import me.chanjar.weixin.mp.api.WxMpService; | |||
import okhttp3.*; | |||
@@ -66,6 +67,7 @@ public class WxMpServiceOkHttpImpl extends BaseWxMpServiceImpl<OkHttpClient, OkH | |||
@Override | |||
public void initHttp() { | |||
WxMpConfigStorage wxMpConfigStorage = getWxMpConfigStorage(); | |||
//设置代理 | |||
if (wxMpConfigStorage.getHttpProxyHost() != null && wxMpConfigStorage.getHttpProxyPort() > 0) { | |||
httpProxy = OkHttpProxyInfo.httpProxy(wxMpConfigStorage.getHttpProxyHost(), | |||
@@ -7,7 +7,12 @@ package me.chanjar.weixin.mp.util; | |||
*/ | |||
public class WxMpConfigStorageHolder { | |||
private final static ThreadLocal<String> WX_MP_CONFIG_STORAGE_CHOSE = new ThreadLocal<>(); | |||
private final static ThreadLocal<String> WX_MP_CONFIG_STORAGE_CHOSE = new ThreadLocal<String>() { | |||
@Override | |||
protected String initialValue() { | |||
return "default"; | |||
} | |||
}; | |||
public static String get() { | |||
return WX_MP_CONFIG_STORAGE_CHOSE.get(); | |||
@@ -85,6 +85,53 @@ public class WxMpMenuServiceImplTest { | |||
"}"; | |||
this.menuId = this.wxService.getMenuService().menuCreate(json); | |||
if (this.wxService.switchover("test-1")) { | |||
this.menuId = this.wxService.getMenuService().menuCreate(json); | |||
} | |||
System.out.println(this.menuId); | |||
} | |||
@Test | |||
public void testMultiCreateConditionalMenu() throws WxErrorException { | |||
String json = "{\n" + | |||
" \"button\":[\n" + | |||
" { \n" + | |||
" \"type\":\"click\",\n" + | |||
" \"name\":\"今日歌曲\",\n" + | |||
" \"key\":\"V1001_TODAY_MUSIC\" \n" + | |||
" },\n" + | |||
" { \n" + | |||
" \"name\":\"菜单\",\n" + | |||
" \"sub_button\":[\n" + | |||
" { \n" + | |||
" \"type\":\"view\",\n" + | |||
" \"name\":\"搜索\",\n" + | |||
" \"url\":\"http://www.soso.com/\"\n" + | |||
" },\n" + | |||
" {\n" + | |||
" \"type\":\"view\",\n" + | |||
" \"name\":\"视频\",\n" + | |||
" \"url\":\"http://v.qq.com/\"\n" + | |||
" },\n" + | |||
" {\n" + | |||
" \"type\":\"click\",\n" + | |||
" \"name\":\"赞一下我们\",\n" + | |||
" \"key\":\"V1001_GOOD\"\n" + | |||
" }]\n" + | |||
" }],\n" + | |||
"\"matchrule\":{\n" + | |||
" \"tag_id\":\"2\",\n" + | |||
" \"sex\":\"1\",\n" + | |||
" \"country\":\"中国\",\n" + | |||
" \"province\":\"广东\",\n" + | |||
" \"city\":\"广州\",\n" + | |||
" \"client_platform_type\":\"2\",\n" + | |||
" \"language\":\"zh_CN\"\n" + | |||
" }\n" + | |||
"}"; | |||
if (this.wxService.switchover("test-1")) { | |||
this.menuId = this.wxService.getMenuService().menuCreate(json); | |||
} | |||
System.out.println(this.menuId); | |||
} | |||
@@ -2,6 +2,8 @@ package me.chanjar.weixin.mp.api.test; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.concurrent.locks.ReentrantLock; | |||
import me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl; | |||
@@ -29,11 +31,14 @@ public class ApiTestModule implements Module { | |||
TestConfigStorage config = this.fromXml(TestConfigStorage.class, inputStream); | |||
config.setAccessTokenLock(new ReentrantLock()); | |||
WxMpService wxService = new WxMpServiceHttpClientImpl(); | |||
wxService.setWxMpConfigStorage(config); | |||
WxMpService wxMpServiceMulti = new WxMpServiceHttpClientImpl(); | |||
// TODO 多WxAppId | |||
wxMpServiceMulti.setWxMpConfigStorage(config); | |||
wxMpServiceMulti.addWxMpConfigStorage("test-1", config); | |||
binder.bind(WxMpService.class).toInstance(wxService); | |||
binder.bind(WxMpConfigStorage.class).toInstance(config); | |||
binder.bind(WxMpService.class).toInstance(wxMpServiceMulti); | |||
} catch (IOException e) { | |||
this.log.error(e.getMessage(), e); | |||
} | |||