Skip to content

Commit d52a55f

Browse files
007gzsbinarywang
authored andcommitted
# 368 增加 微信第三方平台 模块
* 增加 微信第三方平台 接口 * WxOpenXmlMessage 消息处理
1 parent 5ec5ae8 commit d52a55f

31 files changed

+2302
-381
lines changed

pom.xml

Lines changed: 387 additions & 381 deletions
Large diffs are not rendered by default.

weixin-java-open/README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
消息机制未实现,下面为通知回调中设置的代码部分
2+
```
3+
@RestController
4+
@RequestMapping("notify")
5+
public class NotifyController extends WechatThridBaseController {
6+
@Autowired
7+
protected WxOpenServiceDemo wxOpenService;
8+
@RequestMapping("receive_ticket")
9+
public Object receiveTicket(@RequestBody(required = false) String requestBody, @RequestParam("timestamp") String timestamp,
10+
@RequestParam("nonce") String nonce, @RequestParam("signature") String signature,
11+
@RequestParam(name = "encrypt_type", required = false) String encType,
12+
@RequestParam(name = "msg_signature", required = false) String msgSignature) {
13+
this.logger.info(
14+
"\n接收微信请求:[signature=[{}], encType=[{}], msgSignature=[{}],"
15+
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
16+
signature, encType, msgSignature, timestamp, nonce, requestBody);
17+
18+
if (!StringUtils.equalsIgnoreCase("aes", encType) || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
19+
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
20+
}
21+
22+
// aes加密的消息
23+
WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(requestBody, wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
24+
this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString());
25+
String out = null;
26+
try {
27+
out = wxOpenService.getWxOpenComponentService().route(inMessage);
28+
} catch (WxErrorException e) {
29+
throw new ResponseException(ErrorCodeEnum.ERROR, e);
30+
}
31+
32+
this.logger.debug("\n组装回复信息:{}", out);
33+
34+
return out;
35+
}
36+
@RequestMapping("{appId}/callback")
37+
public Object callback(@RequestBody(required = false)String requestBody,
38+
@PathVariable ("appId") String appId,
39+
@RequestParam("signature") String signature,
40+
@RequestParam("timestamp") String timestamp,
41+
@RequestParam("nonce") String nonce,
42+
@RequestParam("openid") String openid,
43+
@RequestParam("encrypt_type") String encType,
44+
@RequestParam("msg_signature") String msgSignature) {
45+
this.logger.info(
46+
"\n接收微信请求:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}],"
47+
+ " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
48+
appId, openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
49+
logger.info("query:"+getHttpServletRequest().getQueryString()+"\nbody:"+requestBody);
50+
if (!StringUtils.equalsIgnoreCase("aes", encType) || !wxOpenService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
51+
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
52+
}
53+
54+
String out = "";
55+
// aes加密的消息
56+
WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(requestBody, wxOpenService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
57+
this.logger.debug("\n消息解密后内容为:\n{} ", inMessage.toString());
58+
//wxOpenService.getWxOpenComponentService().getWxMpServiceByAppid(appId);
59+
return out;
60+
}
61+
}
62+
```

weixin-java-open/pom.xml

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
5+
xmlns="http://maven.apache.org/POM/4.0.0">
6+
7+
<modelVersion>4.0.0</modelVersion>
8+
<parent>
9+
<groupId>com.github.binarywang</groupId>
10+
<artifactId>weixin-java-parent</artifactId>
11+
<version>2.8.6.BETA</version>
12+
</parent>
13+
<artifactId>weixin-java-open</artifactId>
14+
<name>WeiXin Java Tools - Open</name>
15+
<description>微信开放平台Java SDK</description>
16+
<developers>
17+
<developer>
18+
<name>007</name>
19+
<email>[email protected]</email>
20+
<url>https://github.com/007gzs</url>
21+
</developer>
22+
</developers>
23+
<dependencies>
24+
<dependency>
25+
<groupId>com.github.binarywang</groupId>
26+
<artifactId>weixin-java-common</artifactId>
27+
<version>${project.version}</version>
28+
</dependency>
29+
<dependency>
30+
<groupId>com.github.binarywang</groupId>
31+
<artifactId>weixin-java-mp</artifactId>
32+
<version>${project.version}</version>
33+
</dependency>
34+
35+
<dependency>
36+
<groupId>org.jodd</groupId>
37+
<artifactId>jodd-http</artifactId>
38+
<scope>provided</scope>
39+
</dependency>
40+
<dependency>
41+
<groupId>com.squareup.okhttp3</groupId>
42+
<artifactId>okhttp</artifactId>
43+
<scope>provided</scope>
44+
</dependency>
45+
46+
<dependency>
47+
<groupId>org.testng</groupId>
48+
<artifactId>testng</artifactId>
49+
<scope>test</scope>
50+
</dependency>
51+
<dependency>
52+
<groupId>com.google.inject</groupId>
53+
<artifactId>guice</artifactId>
54+
<scope>test</scope>
55+
</dependency>
56+
<dependency>
57+
<groupId>org.eclipse.jetty</groupId>
58+
<artifactId>jetty-server</artifactId>
59+
<scope>test</scope>
60+
</dependency>
61+
<dependency>
62+
<groupId>org.eclipse.jetty</groupId>
63+
<artifactId>jetty-servlet</artifactId>
64+
<scope>test</scope>
65+
</dependency>
66+
<dependency>
67+
<groupId>joda-time</groupId>
68+
<artifactId>joda-time</artifactId>
69+
<scope>test</scope>
70+
</dependency>
71+
<dependency>
72+
<groupId>redis.clients</groupId>
73+
<artifactId>jedis</artifactId>
74+
</dependency>
75+
<dependency>
76+
<groupId>ch.qos.logback</groupId>
77+
<artifactId>logback-classic</artifactId>
78+
<scope>test</scope>
79+
</dependency>
80+
</dependencies>
81+
82+
<build>
83+
<plugins>
84+
<plugin>
85+
<groupId>org.apache.maven.plugins</groupId>
86+
<artifactId>maven-surefire-plugin</artifactId>
87+
<configuration>
88+
<suiteXmlFiles>
89+
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
90+
</suiteXmlFiles>
91+
</configuration>
92+
</plugin>
93+
</plugins>
94+
</build>
95+
96+
97+
</project>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package me.chanjar.weixin.open.api;
2+
3+
import me.chanjar.weixin.common.bean.result.WxError;
4+
import me.chanjar.weixin.common.exception.WxErrorException;
5+
import me.chanjar.weixin.mp.api.WxMpService;
6+
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
7+
import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
8+
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerInfoResult;
9+
import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerOptionResult;
10+
import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult;
11+
12+
/**
13+
* @author <a href="https://github.com/007gzs">007</a>
14+
*/
15+
public interface WxOpenComponentService {
16+
17+
String API_COMPONENT_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
18+
String API_CREATE_PREAUTHCODE_URL = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode";
19+
String API_QUERY_AUTH_URL = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth";
20+
String API_AUTHORIZER_TOKEN_URL = "https://api.weixin.qq.com /cgi-bin/component/api_authorizer_token";
21+
String API_GET_AUTHORIZER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info";
22+
String API_GET_AUTHORIZER_OPTION_URL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option";
23+
String API_SET_AUTHORIZER_OPTION_URL = "https://api.weixin.qq.com/cgi-bin/component/ api_set_authorizer_option";
24+
25+
26+
String COMPONENT_LOGIN_PAGE_URL = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=%s&pre_auth_code=%s&redirect_uri=%s";
27+
String CONNECT_OAUTH2_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s&component_appid=%s#wechat_redirect";
28+
29+
/**
30+
* 用code换取oauth2的access token
31+
*/
32+
String OAUTH2_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&code=%s&grant_type=authorization_code&component_appid=%s";
33+
/**
34+
* 刷新oauth2的access token
35+
*/
36+
String OAUTH2_REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s&component_appid==%s";
37+
WxMpService getWxMpServiceByAppid(String appid);
38+
39+
WxOpenConfigStorage getWxOpenConfigStorage();
40+
41+
boolean checkSignature(String timestamp, String nonce, String signature);
42+
43+
String getComponentAccessToken(boolean forceRefresh) throws WxErrorException;
44+
45+
/**
46+
* 获取用户授权页URL(来路URL和成功跳转URL 的域名都需要为三方平台设置的 登录授权的发起页域名)
47+
*/
48+
String getPreAuthUrl(String redirectURI) throws WxErrorException;
49+
50+
String route(WxOpenXmlMessage wxMessage) throws WxErrorException;
51+
52+
/**
53+
* 使用授权码换取公众号或小程序的接口调用凭据和授权信息
54+
*/
55+
WxOpenQueryAuthResult getQueryAuth(String authorizationCode) throws WxErrorException;
56+
57+
/**
58+
* 获取授权方的帐号基本信息
59+
*/
60+
WxOpenAuthorizerInfoResult getAuthorizerInfo(String authorizerAppid) throws WxErrorException;
61+
62+
/**
63+
* 获取授权方的选项设置信息
64+
*/
65+
WxOpenAuthorizerOptionResult getAuthorizerOption(String authorizerAppid, String optionName) throws WxErrorException;
66+
67+
/**
68+
* 设置授权方的选项信息
69+
*/
70+
WxError setAuthorizerOption(String authorizerAppid, String optionName, String optionValue) throws WxErrorException;
71+
72+
String getAuthorizerAccessToken(String appid, boolean forceRefresh) throws WxErrorException;
73+
74+
WxMpOAuth2AccessToken oauth2getAccessToken(String appid, String code) throws WxErrorException;
75+
76+
boolean checkSignature(String appId, String timestamp, String nonce, String signature);
77+
78+
WxMpOAuth2AccessToken oauth2refreshAccessToken(String appid, String refreshToken) throws WxErrorException;
79+
80+
String oauth2buildAuthorizationUrl(String appid, String redirectURI, String scope, String state);
81+
82+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package me.chanjar.weixin.open.api;
2+
3+
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
4+
import me.chanjar.weixin.open.bean.WxOpenAuthorizerAccessToken;
5+
import me.chanjar.weixin.open.bean.WxOpenComponentAccessToken;
6+
7+
/**
8+
* @author <a href="https://github.com/007gzs">007</a>
9+
*/
10+
public interface WxOpenConfigStorage {
11+
12+
void setComponentAppId(String componentAppId);
13+
14+
void setComponentAppSecret(String componentAppSecret);
15+
16+
void setComponentToken(String componentToken);
17+
18+
void setComponentAesKey(String componentAesKey);
19+
20+
String getComponentAppId();
21+
String getComponentAppSecret();
22+
String getComponentToken();
23+
String getComponentAesKey();
24+
String getComponentVerifyTicket();
25+
void setComponentVerifyTicket(String componentVerifyTicket);
26+
String getComponentAccessToken();
27+
boolean isComponentAccessTokenExpired();
28+
void updateComponentAccessTokent(WxOpenComponentAccessToken componentAccessToken);
29+
WxMpConfigStorage getWxMpConfigStorage(String appId);
30+
/**
31+
* 应该是线程安全的
32+
*
33+
* @param componentAccessToken 新的accessToken值
34+
* @param expiresInSeconds 过期时间,以秒为单位
35+
*/
36+
void updateComponentAccessTokent(String componentAccessToken, int expiresInSeconds);
37+
38+
/**
39+
* 是否自动刷新token
40+
*/
41+
boolean autoRefreshToken();
42+
43+
44+
String getAuthorizerRefreshToken(String appId);
45+
void setAuthorizerRefreshToken(String appId, String authorizerRefreshToken);
46+
String getAuthorizerAccessToken(String appId);
47+
48+
49+
boolean isAuthorizerAccessTokenExpired(String appId);
50+
51+
/**
52+
* 强制将access token过期掉
53+
*/
54+
void expireAuthorizerAccessToken(String appId);
55+
56+
/**
57+
* 应该是线程安全的
58+
*
59+
* @param authorizerAccessToken 要更新的WxAccessToken对象
60+
*/
61+
void updateAuthorizerAccessToken(String appId, WxOpenAuthorizerAccessToken authorizerAccessToken);
62+
63+
/**
64+
* 应该是线程安全的
65+
*
66+
* @param authorizerAccessToken 新的accessToken值
67+
* @param expiresInSeconds 过期时间,以秒为单位
68+
*/
69+
void updateAuthorizerAccessToken(String appId, String authorizerAccessToken, int expiresInSeconds);
70+
71+
String getJsapiTicket(String appId);
72+
73+
boolean isJsapiTicketExpired(String appId);
74+
75+
/**
76+
* 强制将jsapi ticket过期掉
77+
*/
78+
void expireJsapiTicket(String appId);
79+
80+
/**
81+
* 应该是线程安全的
82+
*
83+
* @param jsapiTicket 新的jsapi ticket值
84+
* @param expiresInSeconds 过期时间,以秒为单位
85+
*/
86+
void updateJsapiTicket(String appId, String jsapiTicket, int expiresInSeconds);
87+
88+
String getCardApiTicket(String appId);
89+
90+
91+
boolean isCardApiTicketExpired(String appId);
92+
93+
/**
94+
* 强制将卡券api ticket过期掉
95+
*/
96+
void expireCardApiTicket(String appId);
97+
98+
/**
99+
* 应该是线程安全的
100+
*
101+
* @param cardApiTicket 新的cardApi ticket值
102+
* @param expiresInSeconds 过期时间,以秒为单位
103+
*/
104+
void updateCardApiTicket(String appId, String cardApiTicket, int expiresInSeconds);
105+
106+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package me.chanjar.weixin.open.api;
2+
3+
import me.chanjar.weixin.common.exception.WxErrorException;
4+
5+
/**
6+
* @author <a href="https://github.com/007gzs">007</a>
7+
*/
8+
public interface WxOpenService {
9+
WxOpenComponentService getWxOpenComponentService();
10+
WxOpenConfigStorage getWxOpenConfigStorage();
11+
void setWxOpenConfigStorage(WxOpenConfigStorage wxOpenConfigStorage);
12+
/**
13+
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求
14+
*/
15+
String get(String url, String queryParam) throws WxErrorException;
16+
17+
/**
18+
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的POST请求
19+
*/
20+
String post(String url, String postData) throws WxErrorException;
21+
22+
}

0 commit comments

Comments
 (0)