@@ -69,9 +69,9 @@ public interface WxMpConfigStorage { | |||||
public String getSecret(); | public String getSecret(); | ||||
public String getPartnerId(); | |||||
public String getPartnerKey(); | |||||
public String getPartnerId(); | |||||
public String getPartnerKey(); | |||||
public String getToken(); | public String getToken(); | ||||
@@ -1,232 +1,232 @@ | |||||
package me.chanjar.weixin.mp.api; | |||||
import me.chanjar.weixin.common.session.InternalSession; | |||||
import me.chanjar.weixin.common.session.InternalSessionManager; | |||||
import me.chanjar.weixin.common.session.StandardSessionManager; | |||||
import me.chanjar.weixin.common.session.WxSessionManager; | |||||
import me.chanjar.weixin.common.util.LogExceptionHandler; | |||||
import me.chanjar.weixin.common.api.WxErrorExceptionHandler; | |||||
import me.chanjar.weixin.common.api.WxMessageDuplicateChecker; | |||||
import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker; | |||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | |||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.concurrent.ExecutionException; | |||||
import java.util.concurrent.ExecutorService; | |||||
import java.util.concurrent.Executors; | |||||
import java.util.concurrent.Future; | |||||
/** | |||||
* <pre> | |||||
* 微信消息路由器,通过代码化的配置,把来自微信的消息交给handler处理 | |||||
* | |||||
* 说明: | |||||
* 1. 配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理 | |||||
* 2. 默认情况下消息只会被处理一次,除非使用 {@link WxMpMessageRouterRule#next()} | |||||
* 3. 规则的结束必须用{@link WxMpMessageRouterRule#end()}或者{@link WxMpMessageRouterRule#next()},否则不会生效 | |||||
* | |||||
* 使用方法: | |||||
* WxMpMessageRouter router = new WxMpMessageRouter(); | |||||
* router | |||||
* .rule() | |||||
* .msgType("MSG_TYPE").event("EVENT").eventKey("EVENT_KEY").content("CONTENT") | |||||
* .interceptor(interceptor, ...).handler(handler, ...) | |||||
* .end() | |||||
* .rule() | |||||
* // 另外一个匹配规则 | |||||
* .end() | |||||
* ; | |||||
* | |||||
* // 将WxXmlMessage交给消息路由器 | |||||
* router.route(message); | |||||
* | |||||
* </pre> | |||||
* @author Daniel Qian | |||||
* | |||||
*/ | |||||
public class WxMpMessageRouter { | |||||
protected final Logger log = LoggerFactory.getLogger(WxMpMessageRouter.class); | |||||
private static final int DEFAULT_THREAD_POOL_SIZE = 100; | |||||
private final List<WxMpMessageRouterRule> rules = new ArrayList<WxMpMessageRouterRule>(); | |||||
private final WxMpService wxMpService; | |||||
private ExecutorService executorService; | |||||
private WxMessageDuplicateChecker messageDuplicateChecker; | |||||
private WxSessionManager sessionManager; | |||||
private WxErrorExceptionHandler exceptionHandler; | |||||
public WxMpMessageRouter(WxMpService wxMpService) { | |||||
this.wxMpService = wxMpService; | |||||
this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE); | |||||
this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); | |||||
this.sessionManager = new StandardSessionManager(); | |||||
this.exceptionHandler = new LogExceptionHandler(); | |||||
} | |||||
/** | |||||
* <pre> | |||||
* 设置自定义的 {@link ExecutorService} | |||||
* 如果不调用该方法,默认使用 Executors.newFixedThreadPool(100) | |||||
* </pre> | |||||
* @param executorService | |||||
*/ | |||||
public void setExecutorService(ExecutorService executorService) { | |||||
this.executorService = executorService; | |||||
} | |||||
/** | |||||
* <pre> | |||||
* 设置自定义的 {@link me.chanjar.weixin.common.api.WxMessageDuplicateChecker} | |||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker} | |||||
* </pre> | |||||
* @param messageDuplicateChecker | |||||
*/ | |||||
public void setMessageDuplicateChecker(WxMessageDuplicateChecker messageDuplicateChecker) { | |||||
this.messageDuplicateChecker = messageDuplicateChecker; | |||||
} | |||||
/** | |||||
* <pre> | |||||
* 设置自定义的{@link me.chanjar.weixin.common.session.WxSessionManager} | |||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.session.StandardSessionManager} | |||||
* </pre> | |||||
* @param sessionManager | |||||
*/ | |||||
public void setSessionManager(WxSessionManager sessionManager) { | |||||
this.sessionManager = sessionManager; | |||||
} | |||||
/** | |||||
* <pre> | |||||
* 设置自定义的{@link me.chanjar.weixin.common.api.WxErrorExceptionHandler} | |||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.util.LogExceptionHandler} | |||||
* </pre> | |||||
* @param exceptionHandler | |||||
*/ | |||||
public void setExceptionHandler(WxErrorExceptionHandler exceptionHandler) { | |||||
this.exceptionHandler = exceptionHandler; | |||||
} | |||||
List<WxMpMessageRouterRule> getRules() { | |||||
return this.rules; | |||||
} | |||||
/** | |||||
* 开始一个新的Route规则 | |||||
* @return | |||||
*/ | |||||
public WxMpMessageRouterRule rule() { | |||||
return new WxMpMessageRouterRule(this); | |||||
} | |||||
/** | |||||
* 处理微信消息 | |||||
* @param wxMessage | |||||
*/ | |||||
public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage) { | |||||
if (isDuplicateMessage(wxMessage)) { | |||||
// 如果是重复消息,那么就不做处理 | |||||
return null; | |||||
} | |||||
final List<WxMpMessageRouterRule> matchRules = new ArrayList<WxMpMessageRouterRule>(); | |||||
// 收集匹配的规则 | |||||
for (final WxMpMessageRouterRule rule : rules) { | |||||
if (rule.test(wxMessage)) { | |||||
matchRules.add(rule); | |||||
if(!rule.isReEnter()) { | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if (matchRules.size() == 0) { | |||||
return null; | |||||
} | |||||
WxMpXmlOutMessage res = null; | |||||
final List<Future> futures = new ArrayList<Future>(); | |||||
for (final WxMpMessageRouterRule rule : matchRules) { | |||||
// 返回最后一个非异步的rule的执行结果 | |||||
if(rule.isAsync()) { | |||||
futures.add( | |||||
executorService.submit(new Runnable() { | |||||
public void run() { | |||||
rule.service(wxMessage, wxMpService, sessionManager, exceptionHandler); | |||||
} | |||||
}) | |||||
); | |||||
} else { | |||||
res = rule.service(wxMessage, wxMpService, sessionManager, exceptionHandler); | |||||
// 在同步操作结束,session访问结束 | |||||
log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName()); | |||||
sessionEndAccess(wxMessage); | |||||
} | |||||
} | |||||
if (futures.size() > 0) { | |||||
executorService.submit(new Runnable() { | |||||
@Override | |||||
public void run() { | |||||
for (Future future : futures) { | |||||
try { | |||||
future.get(); | |||||
log.debug("End session access: async=true, sessionId={}", wxMessage.getFromUserName()); | |||||
// 异步操作结束,session访问结束 | |||||
sessionEndAccess(wxMessage); | |||||
} catch (InterruptedException e) { | |||||
log.error("Error happened when wait task finish", e); | |||||
} catch (ExecutionException e) { | |||||
log.error("Error happened when wait task finish", e); | |||||
} | |||||
} | |||||
} | |||||
}); | |||||
} | |||||
return res; | |||||
} | |||||
protected boolean isDuplicateMessage(WxMpXmlMessage wxMessage) { | |||||
String messageId = ""; | |||||
if (wxMessage.getMsgId() == null) { | |||||
messageId = String.valueOf(wxMessage.getCreateTime()) | |||||
+ "-" + wxMessage.getFromUserName() | |||||
+ "-" + String.valueOf(wxMessage.getEventKey() == null ? "" : wxMessage.getEventKey()) | |||||
+ "-" + String.valueOf(wxMessage.getEvent() == null ? "" : wxMessage.getEvent()) | |||||
; | |||||
} else { | |||||
messageId = String.valueOf(wxMessage.getMsgId()); | |||||
} | |||||
if (messageDuplicateChecker.isDuplicate(messageId)) { | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
/** | |||||
* 对session的访问结束 | |||||
* @param wxMessage | |||||
*/ | |||||
protected void sessionEndAccess(WxMpXmlMessage wxMessage) { | |||||
InternalSession session = ((InternalSessionManager)sessionManager).findSession(wxMessage.getFromUserName()); | |||||
if (session != null) { | |||||
session.endAccess(); | |||||
} | |||||
} | |||||
} | |||||
package me.chanjar.weixin.mp.api; | |||||
import me.chanjar.weixin.common.session.InternalSession; | |||||
import me.chanjar.weixin.common.session.InternalSessionManager; | |||||
import me.chanjar.weixin.common.session.StandardSessionManager; | |||||
import me.chanjar.weixin.common.session.WxSessionManager; | |||||
import me.chanjar.weixin.common.util.LogExceptionHandler; | |||||
import me.chanjar.weixin.common.api.WxErrorExceptionHandler; | |||||
import me.chanjar.weixin.common.api.WxMessageDuplicateChecker; | |||||
import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker; | |||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | |||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.concurrent.ExecutionException; | |||||
import java.util.concurrent.ExecutorService; | |||||
import java.util.concurrent.Executors; | |||||
import java.util.concurrent.Future; | |||||
/** | |||||
* <pre> | |||||
* 微信消息路由器,通过代码化的配置,把来自微信的消息交给handler处理 | |||||
* | |||||
* 说明: | |||||
* 1. 配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理 | |||||
* 2. 默认情况下消息只会被处理一次,除非使用 {@link WxMpMessageRouterRule#next()} | |||||
* 3. 规则的结束必须用{@link WxMpMessageRouterRule#end()}或者{@link WxMpMessageRouterRule#next()},否则不会生效 | |||||
* | |||||
* 使用方法: | |||||
* WxMpMessageRouter router = new WxMpMessageRouter(); | |||||
* router | |||||
* .rule() | |||||
* .msgType("MSG_TYPE").event("EVENT").eventKey("EVENT_KEY").content("CONTENT") | |||||
* .interceptor(interceptor, ...).handler(handler, ...) | |||||
* .end() | |||||
* .rule() | |||||
* // 另外一个匹配规则 | |||||
* .end() | |||||
* ; | |||||
* | |||||
* // 将WxXmlMessage交给消息路由器 | |||||
* router.route(message); | |||||
* | |||||
* </pre> | |||||
* @author Daniel Qian | |||||
* | |||||
*/ | |||||
public class WxMpMessageRouter { | |||||
protected final Logger log = LoggerFactory.getLogger(WxMpMessageRouter.class); | |||||
private static final int DEFAULT_THREAD_POOL_SIZE = 100; | |||||
private final List<WxMpMessageRouterRule> rules = new ArrayList<WxMpMessageRouterRule>(); | |||||
private final WxMpService wxMpService; | |||||
private ExecutorService executorService; | |||||
private WxMessageDuplicateChecker messageDuplicateChecker; | |||||
private WxSessionManager sessionManager; | |||||
private WxErrorExceptionHandler exceptionHandler; | |||||
public WxMpMessageRouter(WxMpService wxMpService) { | |||||
this.wxMpService = wxMpService; | |||||
this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE); | |||||
this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); | |||||
this.sessionManager = new StandardSessionManager(); | |||||
this.exceptionHandler = new LogExceptionHandler(); | |||||
} | |||||
/** | |||||
* <pre> | |||||
* 设置自定义的 {@link ExecutorService} | |||||
* 如果不调用该方法,默认使用 Executors.newFixedThreadPool(100) | |||||
* </pre> | |||||
* @param executorService | |||||
*/ | |||||
public void setExecutorService(ExecutorService executorService) { | |||||
this.executorService = executorService; | |||||
} | |||||
/** | |||||
* <pre> | |||||
* 设置自定义的 {@link me.chanjar.weixin.common.api.WxMessageDuplicateChecker} | |||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker} | |||||
* </pre> | |||||
* @param messageDuplicateChecker | |||||
*/ | |||||
public void setMessageDuplicateChecker(WxMessageDuplicateChecker messageDuplicateChecker) { | |||||
this.messageDuplicateChecker = messageDuplicateChecker; | |||||
} | |||||
/** | |||||
* <pre> | |||||
* 设置自定义的{@link me.chanjar.weixin.common.session.WxSessionManager} | |||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.session.StandardSessionManager} | |||||
* </pre> | |||||
* @param sessionManager | |||||
*/ | |||||
public void setSessionManager(WxSessionManager sessionManager) { | |||||
this.sessionManager = sessionManager; | |||||
} | |||||
/** | |||||
* <pre> | |||||
* 设置自定义的{@link me.chanjar.weixin.common.api.WxErrorExceptionHandler} | |||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.util.LogExceptionHandler} | |||||
* </pre> | |||||
* @param exceptionHandler | |||||
*/ | |||||
public void setExceptionHandler(WxErrorExceptionHandler exceptionHandler) { | |||||
this.exceptionHandler = exceptionHandler; | |||||
} | |||||
List<WxMpMessageRouterRule> getRules() { | |||||
return this.rules; | |||||
} | |||||
/** | |||||
* 开始一个新的Route规则 | |||||
* @return | |||||
*/ | |||||
public WxMpMessageRouterRule rule() { | |||||
return new WxMpMessageRouterRule(this); | |||||
} | |||||
/** | |||||
* 处理微信消息 | |||||
* @param wxMessage | |||||
*/ | |||||
public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage) { | |||||
if (isDuplicateMessage(wxMessage)) { | |||||
// 如果是重复消息,那么就不做处理 | |||||
return null; | |||||
} | |||||
final List<WxMpMessageRouterRule> matchRules = new ArrayList<WxMpMessageRouterRule>(); | |||||
// 收集匹配的规则 | |||||
for (final WxMpMessageRouterRule rule : rules) { | |||||
if (rule.test(wxMessage)) { | |||||
matchRules.add(rule); | |||||
if(!rule.isReEnter()) { | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if (matchRules.size() == 0) { | |||||
return null; | |||||
} | |||||
WxMpXmlOutMessage res = null; | |||||
final List<Future> futures = new ArrayList<Future>(); | |||||
for (final WxMpMessageRouterRule rule : matchRules) { | |||||
// 返回最后一个非异步的rule的执行结果 | |||||
if(rule.isAsync()) { | |||||
futures.add( | |||||
executorService.submit(new Runnable() { | |||||
public void run() { | |||||
rule.service(wxMessage, wxMpService, sessionManager, exceptionHandler); | |||||
} | |||||
}) | |||||
); | |||||
} else { | |||||
res = rule.service(wxMessage, wxMpService, sessionManager, exceptionHandler); | |||||
// 在同步操作结束,session访问结束 | |||||
log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName()); | |||||
sessionEndAccess(wxMessage); | |||||
} | |||||
} | |||||
if (futures.size() > 0) { | |||||
executorService.submit(new Runnable() { | |||||
@Override | |||||
public void run() { | |||||
for (Future future : futures) { | |||||
try { | |||||
future.get(); | |||||
log.debug("End session access: async=true, sessionId={}", wxMessage.getFromUserName()); | |||||
// 异步操作结束,session访问结束 | |||||
sessionEndAccess(wxMessage); | |||||
} catch (InterruptedException e) { | |||||
log.error("Error happened when wait task finish", e); | |||||
} catch (ExecutionException e) { | |||||
log.error("Error happened when wait task finish", e); | |||||
} | |||||
} | |||||
} | |||||
}); | |||||
} | |||||
return res; | |||||
} | |||||
protected boolean isDuplicateMessage(WxMpXmlMessage wxMessage) { | |||||
StringBuffer messageId = new StringBuffer(); | |||||
if (wxMessage.getMsgId() == null) { | |||||
messageId.append(wxMessage.getCreateTime()) | |||||
.append("-").append(wxMessage.getFromUserName()) | |||||
.append("-").append(wxMessage.getEventKey() == null ? "" : wxMessage.getEventKey()) | |||||
.append("-").append(wxMessage.getEvent() == null ? "" : wxMessage.getEvent()) | |||||
; | |||||
} else { | |||||
messageId.append(wxMessage.getMsgId()); | |||||
} | |||||
if (messageDuplicateChecker.isDuplicate(messageId.toString())) { | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
/** | |||||
* 对session的访问结束 | |||||
* @param wxMessage | |||||
*/ | |||||
protected void sessionEndAccess(WxMpXmlMessage wxMessage) { | |||||
InternalSession session = ((InternalSessionManager)sessionManager).findSession(wxMessage.getFromUserName()); | |||||
if (session != null) { | |||||
session.endAccess(); | |||||
} | |||||
} | |||||
} |
@@ -728,8 +728,8 @@ public interface WxMpService { | |||||
* @return | * @return | ||||
* @throws WxErrorException | * @throws WxErrorException | ||||
*/ | */ | ||||
Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) throws WxErrorException; | |||||
Map<String, String> getJSSDKPayInfo(Map<String, String> parameters) throws WxErrorException; | |||||
/** | /** | ||||
* 该接口调用“统一下单”接口,并拼装JSSDK发起支付请求需要的参数 | * 该接口调用“统一下单”接口,并拼装JSSDK发起支付请求需要的参数 | ||||
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 | * 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82 | ||||
@@ -100,9 +100,10 @@ public class WxMpServiceImpl implements WxMpService { | |||||
if (wxMpConfigStorage.isAccessTokenExpired()) { | if (wxMpConfigStorage.isAccessTokenExpired()) { | ||||
synchronized (globalAccessTokenRefreshLock) { | synchronized (globalAccessTokenRefreshLock) { | ||||
if (wxMpConfigStorage.isAccessTokenExpired()) { | if (wxMpConfigStorage.isAccessTokenExpired()) { | ||||
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" | |||||
+ "&appid=" + wxMpConfigStorage.getAppId() | |||||
+ "&secret=" + wxMpConfigStorage.getSecret(); | |||||
String url = new StringBuffer() | |||||
.append("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential") | |||||
.append("&appid=").append(wxMpConfigStorage.getAppId()) | |||||
.append("&secret=").append(wxMpConfigStorage.getSecret()).toString(); | |||||
try { | try { | ||||
HttpGet httpGet = new HttpGet(url); | HttpGet httpGet = new HttpGet(url); | ||||
if (httpProxy != null) { | if (httpProxy != null) { | ||||
@@ -505,29 +506,31 @@ public class WxMpServiceImpl implements WxMpService { | |||||
@Override | @Override | ||||
public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { | public String oauth2buildAuthorizationUrl(String redirectURI, String scope, String state) { | ||||
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?"; | |||||
url += "appid=" + wxMpConfigStorage.getAppId(); | |||||
url += "&redirect_uri=" + URIUtil.encodeURIComponent(redirectURI); | |||||
url += "&response_type=code"; | |||||
url += "&scope=" + scope; | |||||
StringBuffer url = new StringBuffer(); | |||||
url.append("https://open.weixin.qq.com/connect/oauth2/authorize?"); | |||||
url.append("appid=").append(wxMpConfigStorage.getAppId()); | |||||
url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); | |||||
url.append("&response_type=code"); | |||||
url.append("&scope=").append(scope); | |||||
if (state != null) { | if (state != null) { | ||||
url += "&state=" + state; | |||||
url.append("&state=").append(state); | |||||
} | } | ||||
url += "#wechat_redirect"; | |||||
return url; | |||||
url.append("#wechat_redirect"); | |||||
return url.toString(); | |||||
} | } | ||||
@Override | @Override | ||||
public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { | public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException { | ||||
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?"; | |||||
url += "appid=" + wxMpConfigStorage.getAppId(); | |||||
url += "&secret=" + wxMpConfigStorage.getSecret(); | |||||
url += "&code=" + code; | |||||
url += "&grant_type=authorization_code"; | |||||
StringBuffer url = new StringBuffer(); | |||||
url.append("https://api.weixin.qq.com/sns/oauth2/access_token?"); | |||||
url.append("appid=").append(wxMpConfigStorage.getAppId()); | |||||
url.append("&secret=").append(wxMpConfigStorage.getSecret()); | |||||
url.append("&code=").append(code); | |||||
url.append("&grant_type=authorization_code"); | |||||
try { | try { | ||||
RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | ||||
String responseText = executor.execute(getHttpclient(), httpProxy, url, null); | |||||
String responseText = executor.execute(getHttpclient(), httpProxy, url.toString(), null); | |||||
return WxMpOAuth2AccessToken.fromJson(responseText); | return WxMpOAuth2AccessToken.fromJson(responseText); | ||||
} catch (ClientProtocolException e) { | } catch (ClientProtocolException e) { | ||||
throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
@@ -538,14 +541,15 @@ public class WxMpServiceImpl implements WxMpService { | |||||
@Override | @Override | ||||
public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { | public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException { | ||||
String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?"; | |||||
url += "appid=" + wxMpConfigStorage.getAppId(); | |||||
url += "&grant_type=refresh_token"; | |||||
url += "&refresh_token=" + refreshToken; | |||||
StringBuffer url = new StringBuffer(); | |||||
url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?"); | |||||
url.append("appid=").append(wxMpConfigStorage.getAppId()); | |||||
url.append("&grant_type=refresh_token"); | |||||
url.append("&refresh_token=").append(refreshToken); | |||||
try { | try { | ||||
RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | ||||
String responseText = executor.execute(getHttpclient(), httpProxy, url, null); | |||||
String responseText = executor.execute(getHttpclient(), httpProxy, url.toString(), null); | |||||
return WxMpOAuth2AccessToken.fromJson(responseText); | return WxMpOAuth2AccessToken.fromJson(responseText); | ||||
} catch (ClientProtocolException e) { | } catch (ClientProtocolException e) { | ||||
throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
@@ -556,18 +560,19 @@ public class WxMpServiceImpl implements WxMpService { | |||||
@Override | @Override | ||||
public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException { | public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException { | ||||
String url = "https://api.weixin.qq.com/sns/userinfo?"; | |||||
url += "access_token=" + oAuth2AccessToken.getAccessToken(); | |||||
url += "&openid=" + oAuth2AccessToken.getOpenId(); | |||||
StringBuffer url = new StringBuffer(); | |||||
url.append("https://api.weixin.qq.com/sns/userinfo?"); | |||||
url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); | |||||
url.append("&openid=").append(oAuth2AccessToken.getOpenId()); | |||||
if (lang == null) { | if (lang == null) { | ||||
url += "&lang=zh_CN"; | |||||
url.append("&lang=zh_CN"); | |||||
} else { | } else { | ||||
url += "&lang=" + lang; | |||||
url.append("&lang=").append(lang); | |||||
} | } | ||||
try { | try { | ||||
RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | ||||
String responseText = executor.execute(getHttpclient(), httpProxy, url, null); | |||||
String responseText = executor.execute(getHttpclient(), httpProxy, url.toString(), null); | |||||
return WxMpUser.fromJson(responseText); | return WxMpUser.fromJson(responseText); | ||||
} catch (ClientProtocolException e) { | } catch (ClientProtocolException e) { | ||||
throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
@@ -578,13 +583,14 @@ public class WxMpServiceImpl implements WxMpService { | |||||
@Override | @Override | ||||
public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken) { | public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken) { | ||||
String url = "https://api.weixin.qq.com/sns/auth?"; | |||||
url += "access_token=" + oAuth2AccessToken.getAccessToken(); | |||||
url += "&openid=" + oAuth2AccessToken.getOpenId(); | |||||
StringBuffer url = new StringBuffer(); | |||||
url.append("https://api.weixin.qq.com/sns/auth?"); | |||||
url.append("access_token=").append(oAuth2AccessToken.getAccessToken()); | |||||
url.append("&openid=").append(oAuth2AccessToken.getOpenId()); | |||||
try { | try { | ||||
RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | RequestExecutor<String, String> executor = new SimpleGetRequestExecutor(); | ||||
executor.execute(getHttpclient(), httpProxy, url, null); | |||||
executor.execute(getHttpclient(), httpProxy, url.toString(), null); | |||||
} catch (ClientProtocolException e) { | } catch (ClientProtocolException e) { | ||||
throw new RuntimeException(e); | throw new RuntimeException(e); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
@@ -984,7 +990,7 @@ public class WxMpServiceImpl implements WxMpService { | |||||
@Override | @Override | ||||
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature) { | public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature) { | ||||
return signature.equals(WxCryptUtil.createSign(kvm, wxMpConfigStorage.getPartnerKey())); | |||||
return signature.equals(WxCryptUtil.createSign(kvm, wxMpConfigStorage.getPartnerKey())); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -30,15 +30,15 @@ import java.util.UUID; | |||||
public class QrCodeRequestExecutor implements RequestExecutor<File, WxMpQrCodeTicket> { | public class QrCodeRequestExecutor implements RequestExecutor<File, WxMpQrCodeTicket> { | ||||
@Override | @Override | ||||
public File execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, WxMpQrCodeTicket ticket) throws WxErrorException, ClientProtocolException, IOException { | |||||
public File execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, | |||||
WxMpQrCodeTicket ticket) throws WxErrorException, ClientProtocolException, IOException { | |||||
if (ticket != null) { | if (ticket != null) { | ||||
if (uri.indexOf('?') == -1) { | if (uri.indexOf('?') == -1) { | ||||
uri += '?'; | uri += '?'; | ||||
} | } | ||||
uri += uri.endsWith("?") ? | |||||
"ticket=" + URLEncoder.encode(ticket.getTicket(), "UTF-8") | |||||
: | |||||
"&ticket=" + URLEncoder.encode(ticket.getTicket(), "UTF-8"); | |||||
uri += uri.endsWith("?") | |||||
? "ticket=" + URLEncoder.encode(ticket.getTicket(), "UTF-8") | |||||
: "&ticket=" + URLEncoder.encode(ticket.getTicket(), "UTF-8"); | |||||
} | } | ||||
HttpGet httpGet = new HttpGet(uri); | HttpGet httpGet = new HttpGet(uri); | ||||
@@ -59,7 +59,7 @@ public class QrCodeRequestExecutor implements RequestExecutor<File, WxMpQrCodeTi | |||||
InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response); | InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response); | ||||
return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); | return FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), "jpg"); | ||||
}finally { | |||||
} finally { | |||||
httpGet.releaseConnection(); | httpGet.releaseConnection(); | ||||
} | } | ||||
@@ -1,18 +1,15 @@ | |||||
package me.chanjar.weixin.mp.util.json; | package me.chanjar.weixin.mp.util.json; | ||||
import java.lang.reflect.Type; | |||||
import com.google.gson.JsonDeserializationContext; | import com.google.gson.JsonDeserializationContext; | ||||
import com.google.gson.JsonDeserializer; | import com.google.gson.JsonDeserializer; | ||||
import com.google.gson.JsonElement; | import com.google.gson.JsonElement; | ||||
import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||
import com.google.gson.JsonParseException; | import com.google.gson.JsonParseException; | ||||
import com.google.gson.reflect.TypeToken; | |||||
import me.chanjar.weixin.common.util.json.GsonHelper; | import me.chanjar.weixin.common.util.json.GsonHelper; | ||||
import me.chanjar.weixin.mp.bean.WxMpCard; | import me.chanjar.weixin.mp.bean.WxMpCard; | ||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import java.lang.reflect.Type; | |||||
import java.util.List; | |||||
/** | /** | ||||
* Created by YuJian on 15/11/11. | * Created by YuJian on 15/11/11. | ||||
@@ -1,20 +1,17 @@ | |||||
package me.chanjar.weixin.mp.util.json; | package me.chanjar.weixin.mp.util.json; | ||||
import java.lang.reflect.Type; | |||||
import com.google.gson.JsonDeserializationContext; | import com.google.gson.JsonDeserializationContext; | ||||
import com.google.gson.JsonDeserializer; | import com.google.gson.JsonDeserializer; | ||||
import com.google.gson.JsonElement; | import com.google.gson.JsonElement; | ||||
import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||
import com.google.gson.JsonParseException; | import com.google.gson.JsonParseException; | ||||
import com.google.gson.reflect.TypeToken; | import com.google.gson.reflect.TypeToken; | ||||
import me.chanjar.weixin.common.util.json.GsonHelper; | import me.chanjar.weixin.common.util.json.GsonHelper; | ||||
import me.chanjar.weixin.mp.bean.WxMpCard; | import me.chanjar.weixin.mp.bean.WxMpCard; | ||||
import me.chanjar.weixin.mp.bean.result.WxMpCardResult; | import me.chanjar.weixin.mp.bean.result.WxMpCardResult; | ||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import java.lang.reflect.Type; | |||||
import java.text.ParseException; | |||||
import java.util.List; | |||||
/** | /** | ||||
* Created by YuJian on 15/11/11. | * Created by YuJian on 15/11/11. | ||||