🆕 #1952 增加腾讯企点子模块,用于对接企点开放平台。

This commit is contained in:
fanxiayang12
2020-12-30 09:17:35 +08:00
committed by GitHub
parent a8232f6c91
commit e7f2bd62f8
54 changed files with 3928 additions and 12 deletions

View File

@@ -0,0 +1,64 @@
package me.chanjar.weixin.qidian.api;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.error.WxRuntimeException;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.qidian.api.impl.WxQidianServiceHttpClientImpl;
import org.testng.annotations.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Test
@Slf4j
public class WxMpBusyRetryTest {
@DataProvider(name = "getService")
public Object[][] getService() {
WxQidianService service = new WxQidianServiceHttpClientImpl() {
@Override
public synchronized <T, E> T executeInternal(
RequestExecutor<T, E> executor, String uri, E data)
throws WxErrorException {
log.info("Executed");
throw new WxErrorException("something");
}
};
service.setMaxRetryTimes(3);
service.setRetrySleepMillis(500);
return new Object[][]{{service}};
}
@Test(dataProvider = "getService", expectedExceptions = RuntimeException.class)
public void testRetry(WxQidianService service) throws WxErrorException {
service.execute(null, (String)null, null);
}
@Test(dataProvider = "getService")
public void testRetryInThreadPool(final WxQidianService service) throws InterruptedException, ExecutionException {
// 当线程池中的线程复用的时候,还是能保证相同的重试次数
ExecutorService executorService = Executors.newFixedThreadPool(1);
Runnable runnable = () -> {
try {
System.out.println("=====================");
System.out.println(Thread.currentThread().getName() + ": testRetry");
service.execute(null, (String)null, null);
} catch (WxErrorException e) {
throw new WxRuntimeException(e);
} catch (RuntimeException e) {
// OK
}
};
Future<?> submit1 = executorService.submit(runnable);
Future<?> submit2 = executorService.submit(runnable);
submit1.get();
submit2.get();
}
}

View File

@@ -0,0 +1,37 @@
package me.chanjar.weixin.qidian.api;
import com.google.inject.Inject;
import me.chanjar.weixin.common.util.crypto.SHA1;
import me.chanjar.weixin.qidian.api.test.ApiTestModule;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
/**
* 测试jsapi ticket接口
*
* @author chanjarster
*/
@Test
@Guice(modules = ApiTestModule.class)
public class WxMpJsAPITest {
@Inject
protected WxQidianService wxService;
public void test() {
long timestamp = 1419835025L;
String url = "http://omstest.vmall.com:23568/thirdparty/wechat/vcode/gotoshare?quantity=1&batchName=MATE7";
String noncestr = "82693e11-b9bc-448e-892f-f5289f46cd0f";
String jsapiTicket = "bxLdikRXVbTPdHSM05e5u4RbEYQn7pNQMPrfzl8lJNb1foLDa3HIwI3BRMkQmSO_5F64VFa75uURcq6Uz7QHgA";
String result = SHA1.genWithAmple(
"jsapi_ticket=" + jsapiTicket,
"noncestr=" + noncestr,
"timestamp=" + timestamp,
"url=" + url
);
Assert.assertEquals(result, "c6f04b64d6351d197b71bd23fb7dd2d44c0db486");
}
}

View File

@@ -0,0 +1,407 @@
package me.chanjar.weixin.qidian.api.impl;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.bean.WxNetCheckResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.qidian.api.WxQidianService;
import me.chanjar.weixin.qidian.api.test.ApiTestModule;
import me.chanjar.weixin.qidian.util.WxQidianConfigStorageHolder;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
/**
* <pre>
* Created by BinaryWang on 2019/3/29.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Test
@Guice(modules = ApiTestModule.class)
public class BaseWxQidianServiceImplTest {
@Inject
private WxQidianService wxService;
@Test
public void testSwitchover() {
assertTrue(this.wxService.switchover("another"));
assertThat(WxQidianConfigStorageHolder.get()).isEqualTo("another");
assertFalse(this.wxService.switchover("whatever"));
assertFalse(this.wxService.switchover("default"));
}
@Test
public void testSwitchoverTo() throws WxErrorException {
assertThat(this.wxService.switchoverTo("another").getAccessToken()).isNotEmpty();
assertThat(WxQidianConfigStorageHolder.get()).isEqualTo("another");
}
@Test
public void testNetCheck() throws WxErrorException {
WxNetCheckResult result = this.wxService.netCheck(WxConsts.NetCheckArgs.ACTIONALL, WxConsts.NetCheckArgs.OPERATORDEFAULT);
Assert.assertNotNull(result);
}
@Test
public void testGetCallbackIP() throws WxErrorException {
String[] ipArray = this.wxService.getCallbackIP();
System.out.println(Arrays.toString(ipArray));
Assert.assertNotNull(ipArray);
Assert.assertNotEquals(ipArray.length, 0);
}
public void testShortUrl() throws WxErrorException {
String shortUrl = this.wxService.shortUrl("http://www.baidu.com/test?access_token=123");
assertThat(shortUrl).isNotEmpty();
System.out.println(shortUrl);
}
@Test(expectedExceptions = WxErrorException.class)
public void testShortUrl_with_exceptional_url() throws WxErrorException {
this.wxService.shortUrl("http://www.baidu.com/test?redirect_count=1&access_token=123");
}
@Test
public void refreshAccessTokenDuplicatelyTest() throws InterruptedException {
// 测试多线程刷新accessToken时是否重复刷新
wxService.getWxMpConfigStorage().expireAccessToken();
final Set<String> set = Sets.newConcurrentHashSet();
Runnable r = () -> {
try {
String accessToken = wxService.getAccessToken();
set.add(accessToken);
} catch (WxErrorException e) {
e.printStackTrace();
}
};
final int threadNumber = 10;
ExecutorService executorService = Executors.newFixedThreadPool(threadNumber);
for ( int i = 0; i < threadNumber; i++ ) {
executorService.submit(r);
}
executorService.shutdown();
boolean isTerminated = executorService.awaitTermination(15, TimeUnit.SECONDS);
System.out.println("isTerminated: " + isTerminated);
System.out.println("times of refreshing accessToken: " + set.size());
assertEquals(set.size(), 1);
}
@Test
public void testCheckSignature() {
}
@Test
public void testGetTicket() {
}
@Test
public void testTestGetTicket() {
}
@Test
public void testGetJsapiTicket() {
}
@Test
public void testTestGetJsapiTicket() {
}
@Test
public void testCreateJsapiSignature() throws WxErrorException {
final WxJsapiSignature jsapiSignature = this.wxService.createJsapiSignature("http://www.baidu.com");
assertThat(jsapiSignature).isNotNull();
assertThat(jsapiSignature.getSignature()).isNotNull();
System.out.println(jsapiSignature);
}
@Test
public void testGetAccessToken() {
}
@Test
public void testSemanticQuery() {
}
@Test
public void testOauth2buildAuthorizationUrl() {
}
@Test
public void testBuildQrConnectUrl() {
}
@Test
public void testOauth2getAccessToken() {
}
@Test
public void testOauth2refreshAccessToken() {
}
@Test
public void testOauth2getUserInfo() {
}
@Test
public void testOauth2validateAccessToken() {
}
@Test
public void testGetCurrentAutoReplyInfo() {
}
@Test
public void testClearQuota() {
}
@Test
public void testGet() {
}
@Test
public void testTestGet() {
}
@Test
public void testPost() {
}
@Test
public void testTestPost() {
}
@Test
public void testExecute() {
}
@Test
public void testTestExecute() {
}
@Test
public void testExecuteInternal() {
}
@Test
public void testGetWxMpConfigStorage() {
}
@Test
public void testSetWxMpConfigStorage() {
}
@Test
public void testSetMultiConfigStorages() {
}
@Test
public void testTestSetMultiConfigStorages() {
}
@Test
public void testAddConfigStorage() {
}
@Test
public void testRemoveConfigStorage() {
}
@Test
public void testSetRetrySleepMillis() {
}
@Test
public void testSetMaxRetryTimes() {
}
@Test
public void testGetKefuService() {
}
@Test
public void testGetMaterialService() {
}
@Test
public void testGetMenuService() {
}
@Test
public void testGetUserService() {
}
@Test
public void testGetUserTagService() {
}
@Test
public void testGetQrcodeService() {
}
@Test
public void testGetCardService() {
}
@Test
public void testGetDataCubeService() {
}
@Test
public void testGetBlackListService() {
}
@Test
public void testGetStoreService() {
}
@Test
public void testGetTemplateMsgService() {
}
@Test
public void testGetSubscribeMsgService() {
}
@Test
public void testGetDeviceService() {
}
@Test
public void testGetShakeService() {
}
@Test
public void testGetMemberCardService() {
}
@Test
public void testGetRequestHttp() {
}
@Test
public void testGetMassMessageService() {
}
@Test
public void testSetKefuService() {
}
@Test
public void testSetMaterialService() {
}
@Test
public void testSetMenuService() {
}
@Test
public void testSetUserService() {
}
@Test
public void testSetTagService() {
}
@Test
public void testSetQrCodeService() {
}
@Test
public void testSetCardService() {
}
@Test
public void testSetStoreService() {
}
@Test
public void testSetDataCubeService() {
}
@Test
public void testSetBlackListService() {
}
@Test
public void testSetTemplateMsgService() {
}
@Test
public void testSetDeviceService() {
}
@Test
public void testSetShakeService() {
}
@Test
public void testSetMemberCardService() {
}
@Test
public void testSetMassMessageService() {
}
@Test
public void testGetAiOpenService() {
}
@Test
public void testSetAiOpenService() {
}
@Test
public void testGetWifiService() {
}
@Test
public void testGetOcrService() {
}
@Test
public void testGetMarketingService() {
}
@Test
public void testSetMarketingService() {
}
@Test
public void testSetOcrService() {
}
@Test
public void testGetCommentService() {
}
@Test
public void testSetCommentService() {
}
@Test
public void testGetImgProcService() {
}
@Test
public void testSetImgProcService() {
}
}

View File

@@ -0,0 +1,58 @@
package me.chanjar.weixin.qidian.api.impl;
import java.util.List;
import java.util.Optional;
import com.google.inject.Inject;
import org.testng.Assert;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.qidian.api.WxQidianService;
import me.chanjar.weixin.qidian.api.test.ApiTestModule;
import me.chanjar.weixin.qidian.bean.call.GetSwitchBoardListResponse;
import me.chanjar.weixin.qidian.bean.dial.IVRDialRequest;
import me.chanjar.weixin.qidian.bean.dial.IVRDialResponse;
import me.chanjar.weixin.qidian.bean.dial.IVRListResponse;
import me.chanjar.weixin.qidian.bean.dial.Ivr;
@Test
@Guice(modules = ApiTestModule.class)
@Slf4j
public class WxQidianDialServiceImplTest {
@Inject
private WxQidianService wxService;
@Test
public void dial() throws WxErrorException {
// ivr
IVRListResponse iVRListResponse = this.wxService.getDialService().getIVRList();
Assert.assertEquals(iVRListResponse.getErrcode(), new Integer(0));
log.info("ivr size:" + iVRListResponse.getNode().size());
Optional<Ivr> optional = iVRListResponse.getNode().stream().filter((o) -> o.getIvr_name().equals("自动接听需求测试"))
.findFirst();
Assert.assertTrue(optional.isPresent());
Ivr ivr = optional.get();
String ivr_id = ivr.getIvr_id();
// ivr_id = "433";
// switch
GetSwitchBoardListResponse getSwitchBoardListResponse = this.wxService.getCallDataService().getSwitchBoardList();
Assert.assertEquals(getSwitchBoardListResponse.getErrcode(), new Integer(0));
log.info("switch size:" + getSwitchBoardListResponse.getData().switchBoards().size());
List<String> switchBoards = getSwitchBoardListResponse.getData().switchBoards();
// ivrdial
IVRDialRequest ivrDial = new IVRDialRequest();
ivrDial.setPhone_number("18434399105");
// ivrDial.setPhone_number("13811768266");
ivrDial.setIvr_id(ivr_id);
ivrDial.setCorp_phone_list(switchBoards);
IVRDialResponse ivrDialResponse = this.wxService.getDialService().ivrDial(ivrDial);
Assert.assertEquals(ivrDialResponse.getCode(), new Integer(0));
log.info(ivrDialResponse.getCallid());
}
}

View File

@@ -0,0 +1,51 @@
package me.chanjar.weixin.qidian.api.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.locks.ReentrantLock;
import com.google.inject.Binder;
import com.google.inject.Module;
import com.thoughtworks.xstream.XStream;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxRuntimeException;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.qidian.api.WxQidianService;
import me.chanjar.weixin.qidian.api.impl.WxQidianServiceHttpClientImpl;
import me.chanjar.weixin.qidian.config.WxQidianConfigStorage;
@Slf4j
public class ApiTestModule implements Module {
private static final String TEST_CONFIG_XML = "test-config.xml";
@Override
public void configure(Binder binder) {
try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(TEST_CONFIG_XML)) {
if (inputStream == null) {
throw new WxRuntimeException("测试配置文件【" + TEST_CONFIG_XML + "】未找到请参照test-config-sample.xml文件生成");
}
TestConfigStorage config = this.fromXml(TestConfigStorage.class, inputStream);
config.setAccessTokenLock(new ReentrantLock());
WxQidianService mpService = new WxQidianServiceHttpClientImpl();
mpService.setWxMpConfigStorage(config);
mpService.addConfigStorage("another", config);
binder.bind(WxQidianConfigStorage.class).toInstance(config);
binder.bind(WxQidianService.class).toInstance(mpService);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
@SuppressWarnings("unchecked")
private <T> T fromXml(Class<T> clazz, InputStream is) {
XStream xstream = XStreamInitializer.getInstance();
xstream.alias("xml", clazz);
xstream.processAnnotations(clazz);
return (T) xstream.fromXML(is);
}
}

View File

@@ -0,0 +1,69 @@
package me.chanjar.weixin.qidian.api.test;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.qidian.config.impl.WxQidianDefaultConfigImpl;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.util.concurrent.locks.Lock;
@XStreamAlias("xml")
public class TestConfigStorage extends WxQidianDefaultConfigImpl {
private String openid;
private String kfAccount;
private String qrconnectRedirectUrl;
private String templateId;
private String keyPath;
public String getKeyPath() {
return keyPath;
}
public void setKeyPath(String keyPath) {
this.keyPath = keyPath;
}
public String getOpenid() {
return this.openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
public String getKfAccount() {
return this.kfAccount;
}
public void setKfAccount(String kfAccount) {
this.kfAccount = kfAccount;
}
public String getQrconnectRedirectUrl() {
return this.qrconnectRedirectUrl;
}
public void setQrconnectRedirectUrl(String qrconnectRedirectUrl) {
this.qrconnectRedirectUrl = qrconnectRedirectUrl;
}
@Override
public String getTemplateId() {
return this.templateId;
}
@Override
public void setTemplateId(String templateId) {
this.templateId = templateId;
}
public void setAccessTokenLock(Lock lock) {
super.accessTokenLock = lock;
}
}

View File

@@ -0,0 +1,13 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %replace(%caller{1}){'Caller', ''} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

View File

@@ -0,0 +1,16 @@
<xml>
<appId>公众号appID</appId>
<secret>公众号appsecret</secret>
<token>公众号Token</token>
<aesKey>公众号EncodingAESKey</aesKey>
<accessToken>可以不填写</accessToken>
<expiresTime>可以不填写</expiresTime>
<openid>某个加你公众号的用户的openId</openid>
<partnerId>微信商户平台ID</partnerId>
<partnerKey>商户平台设置的API密钥</partnerKey>
<keyPath>商户平台的证书文件地址</keyPath>
<templateId>模版消息的模版ID</templateId>
<oauth2redirectUri>网页授权获取用户信息回调地址</oauth2redirectUri>
<qrconnectRedirectUrl>网页应用授权登陆回调地址</qrconnectRedirectUrl>
<kfAccount>完整客服账号,格式为:账号前缀@公众号微信号</kfAccount>
</xml>

View File

@@ -0,0 +1,30 @@
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Weixin-java-tool-suite" verbose="1">
<test name="API_Test">
<classes>
<class name="me.chanjar.weixin.qidian.api.WxMpBusyRetryTest"/>
<class name="me.chanjar.weixin.qidian.api.WxMpBaseAPITest"/>
<class name="me.chanjar.weixin.qidian.api.impl.WxMpMassMessageServiceImplTest"/>
<class name="me.chanjar.weixin.qidian.api.impl.WxMpUserServiceImplTest"/>
<class name="me.chanjar.weixin.qidian.api.impl.WxMpQrcodeServiceImplTest"/>
<class name="me.chanjar.weixin.qidian.api.WxMpShortUrlAPITest"/>
<class name="me.chanjar.weixin.qidian.api.WxMpMessageRouterTest"/>
<class name="me.chanjar.weixin.qidian.api.WxMpJsAPITest"/>
<class name="me.chanjar.weixin.qidian.api.WxMpMiscAPITest"/>
</classes>
</test>
<test name="Bean_Test">
<classes>
<class name="me.chanjar.weixin.qidian.bean.kefu.WxMpKefuMessageTest"/>
<class name="me.chanjar.weixin.qidian.bean.message.WxMpXmlMessageTest"/>
<class name="me.chanjar.weixin.qidian.bean.message.WxMpXmlOutImageMessageTest"/>
<class name="me.chanjar.weixin.qidian.bean.message.WxMpXmlOutMusicMessageTest"/>
<class name="me.chanjar.weixin.qidian.bean.message.WxMpXmlOutNewsMessageTest"/>
<class name="me.chanjar.weixin.qidian.bean.message.WxMpXmlOutVideoMessageTest"/>
<class name="me.chanjar.weixin.qidian.bean.message.WxMpXmlOutVoiceMessageTest"/>
<class name="me.chanjar.weixin.qidian.bean.message.WxMpXmlOutTextMessageTest"/>
</classes>
</test>
</suite>