From ff349fd3709eba8977a62d8a247ad5777476f6d9 Mon Sep 17 00:00:00 2001 From: jinyu Date: Tue, 5 Jul 2016 23:34:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=AC=AC=E4=B8=89=E6=96=B9?= =?UTF-8?q?=E7=BB=84=E4=BB=B6ComponentApi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGE.md | 4 +- .../foxinmy/weixin4j/token/TicketManager.java | 45 ++-- weixin4j-mp/CHANGE.md | 4 +- .../com/foxinmy/weixin4j/mp/WeixinProxy.java | 21 ++ .../foxinmy/weixin4j/mp/api/ComponentApi.java | 173 ++++++++++++- .../com/foxinmy/weixin4j/mp/api/OauthApi.java | 36 ++- .../foxinmy/weixin4j/mp/api/weixin.properties | 13 +- .../WeixinComponentPreCodeCreator.java | 2 +- .../WeixinComponentTokenCreator.java | 12 +- .../WeixinTokenComponentCreator.java | 57 +++++ .../weixin4j/mp/model/AuthorizerOption.java | 128 ++++++++++ .../weixin4j/mp/model/ComponentAuthInfo.java | 235 ++++++++++++++++++ .../foxinmy/weixin4j/mp/type/URLConsts.java | 18 +- .../com/foxinmy/weixin4j/qy/WeixinProxy.java | 18 +- .../foxinmy/weixin4j/qy/WeixinSuiteProxy.java | 53 +++- .../com/foxinmy/weixin4j/qy/api/SuiteApi.java | 61 ++--- .../qy/suite/SuitePerCodeManager.java | 73 ------ .../qy/suite/WeixinSuiteTokenCreator.java | 8 +- .../qy/suite/WeixinTokenSuiteCreator.java | 23 +- 19 files changed, 804 insertions(+), 180 deletions(-) create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinTokenComponentCreator.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/AuthorizerOption.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/ComponentAuthInfo.java delete mode 100644 weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/SuitePerCodeManager.java diff --git a/CHANGE.md b/CHANGE.md index b9c11ed2..13ab2194 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -721,4 +721,6 @@ * 2016-07-05 - + weixin4j-mp:初始化开放平台第三方组件TokenCreator \ No newline at end of file + + weixin4j-mp:初始化开放平台第三方组件TokenCreator + + + weixin4j-mp:新增第三方组件ComponentApi \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/token/TicketManager.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/token/TicketManager.java index 82ee829d..b891b3b1 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/token/TicketManager.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/token/TicketManager.java @@ -18,11 +18,11 @@ public class TicketManager { /** * 第三方ID */ - private final String id; + private final String thirdId; /** * 第三方secret */ - private final String secret; + private final String thirdSecret; /** * ticket存储策略 */ @@ -30,27 +30,38 @@ public class TicketManager { /** * - * @param id - * 第三方ID - * @param secret + * @param thirdId + * 第三方ID suiteId/componentId + * @param thirdSecret * 第三方secret * @param cacheStorager * ticket存储策略 */ - public TicketManager(String id, String secret, CacheStorager cacheStorager) { - this.id = id; - this.secret = secret; + public TicketManager(String thirdId, String thirdSecret, + CacheStorager cacheStorager) { + this.thirdId = thirdId; + this.thirdSecret = thirdSecret; this.cacheStorager = cacheStorager; } + /** + * 获取ticket对象 + * + * @return token对象 + * @throws WeixinException + */ + public Token getTicket() throws WeixinException { + return cacheStorager.lookup(getCacheKey()); + } + /** * 获取ticket * - * @return + * @return ticket * @throws WeixinException */ - public String getTicket() throws WeixinException { - return cacheStorager.lookup(getCacheKey()).getAccessToken(); + public String getAccessTicket() throws WeixinException { + return getTicket().getAccessToken(); } /** @@ -59,13 +70,15 @@ public class TicketManager { * @return */ public String getCacheKey() { - return String.format("%sthird_party_ticket_%s", TokenCreator.CACHEKEY_PREFIX, id); + return String.format("%sthird_party_ticket_%s", + TokenCreator.CACHEKEY_PREFIX, thirdId); } /** * 缓存ticket * * @param ticket + * 票据凭证 * @throws WeixinException */ public void cachingTicket(String ticket) throws WeixinException { @@ -73,12 +86,12 @@ public class TicketManager { cacheStorager.caching(getCacheKey(), token); } - public String getId() { - return id; + public String getThirdId() { + return thirdId; } - public String getSecret() { - return secret; + public String getThirdSecret() { + return thirdSecret; } public CacheStorager getCacheStorager() { diff --git a/weixin4j-mp/CHANGE.md b/weixin4j-mp/CHANGE.md index 2f202616..ae5b128b 100644 --- a/weixin4j-mp/CHANGE.md +++ b/weixin4j-mp/CHANGE.md @@ -232,4 +232,6 @@ * 2016-07-05 - + 初始化开放平台第三方组件TokenCreator \ No newline at end of file + + 初始化开放平台第三方组件TokenCreator + + + 新增第三方组件ComponentApi \ No newline at end of file diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java index 5fce6f28..1876b3c2 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinProxy.java @@ -26,6 +26,7 @@ import com.foxinmy.weixin4j.mp.api.QrApi; import com.foxinmy.weixin4j.mp.api.TagApi; import com.foxinmy.weixin4j.mp.api.TmplApi; import com.foxinmy.weixin4j.mp.api.UserApi; +import com.foxinmy.weixin4j.mp.component.WeixinTokenComponentCreator; import com.foxinmy.weixin4j.mp.message.NotifyMessage; import com.foxinmy.weixin4j.mp.message.TemplateMessage; import com.foxinmy.weixin4j.mp.model.AutoReplySetting; @@ -51,6 +52,7 @@ import com.foxinmy.weixin4j.mp.type.DatacubeType; import com.foxinmy.weixin4j.mp.type.IndustryType; import com.foxinmy.weixin4j.mp.type.Lang; import com.foxinmy.weixin4j.setting.Weixin4jSettings; +import com.foxinmy.weixin4j.token.PerTicketManager; import com.foxinmy.weixin4j.token.TokenManager; import com.foxinmy.weixin4j.tuple.MassTuple; import com.foxinmy.weixin4j.tuple.MpArticle; @@ -149,6 +151,25 @@ public class WeixinProxy { this.settings = settings; } + /** + * 第三方组件(永久刷新令牌机制) + * + * @param perTicketManager + * 第三方组件永久刷新令牌 + * {@link com.foxinmy.weixin4j.mp.api.ComponentApi#getPerCodeManager(String)} + * @param componentTokenManager + * 第三方组件凭证token + * {@link com.foxinmy.weixin4j.mp.api.ComponentApi#getTokenManager} + * @see com.foxinmy.weixin4j.mp.api.ComponentApi + */ + public WeixinProxy(PerTicketManager perTicketManager, + TokenManager componentTokenManager) { + this(new TokenManager(new WeixinTokenComponentCreator(perTicketManager, + componentTokenManager), perTicketManager.getCacheStorager())); + this.settings = new Weixin4jSettings(new WeixinAccount( + perTicketManager.getAuthAppId(), null)); + } + /** * 注意:TokenCreator 需为 WeixinTokenCreator * diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/ComponentApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/ComponentApi.java index f3001549..be9d3219 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/ComponentApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/ComponentApi.java @@ -1,8 +1,24 @@ package com.foxinmy.weixin4j.mp.api; +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.weixin.JsonResult; +import com.foxinmy.weixin4j.http.weixin.WeixinResponse; +import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.mp.component.WeixinComponentPreCodeCreator; import com.foxinmy.weixin4j.mp.component.WeixinComponentTokenCreator; +import com.foxinmy.weixin4j.mp.component.WeixinTokenComponentCreator; +import com.foxinmy.weixin4j.mp.model.AuthorizerOption; +import com.foxinmy.weixin4j.mp.model.AuthorizerOption.AuthorizerOptionName; +import com.foxinmy.weixin4j.mp.model.ComponentAuthInfo; +import com.foxinmy.weixin4j.token.PerTicketManager; import com.foxinmy.weixin4j.token.TicketManager; +import com.foxinmy.weixin4j.token.TokenCreator; import com.foxinmy.weixin4j.token.TokenManager; /** @@ -36,9 +52,11 @@ public class ComponentApi extends MpApi { */ public ComponentApi(TicketManager ticketManager) { this.ticketManager = ticketManager; - this.tokenManager = new TokenManager(new WeixinComponentTokenCreator(ticketManager), - ticketManager.getCacheStorager()); - this.preCodeManager = new TokenManager(new WeixinComponentPreCodeCreator(tokenManager, ticketManager.getId()), + this.tokenManager = new TokenManager(new WeixinComponentTokenCreator( + ticketManager), ticketManager.getCacheStorager()); + this.preCodeManager = new TokenManager( + new WeixinComponentPreCodeCreator(tokenManager, + ticketManager.getThirdId()), ticketManager.getCacheStorager()); } @@ -68,4 +86,153 @@ public class ComponentApi extends MpApi { public TokenManager getPreCodeManager() { return this.preCodeManager; } + + /** + * 应用套组件永久刷新令牌:刷新令牌主要用于公众号第三方平台获取和刷新已授权用户的access_token,只会在授权时刻提供,请妥善保存。 + * 一旦丢失,只能让用户重新授权,才能再次拿到新的刷新令牌 + * + * @param authAppId + * 授权方appid + * @return + */ + public PerTicketManager getRefreshTokenManager(String authAppId) { + return new PerTicketManager(authAppId, ticketManager.getThirdId(), + ticketManager.getThirdSecret(), + ticketManager.getCacheStorager()); + } + + /** + * 使用授权码换取公众号的接口调用凭据和授权信息:用于使用授权码换取授权公众号的授权信息, + * 并换取authorizer_access_token和authorizer_refresh_token。 + * 授权码的获取,需要在用户在第三方平台授权页中完成授权流程后 + * ,在回调URI中通过URL参数提供给第三方平台方。请注意,由于现在公众号可以自定义选择部分权限授权给第三方平台 + * ,因此第三方平台开发者需要通过该接口来获取公众号具体授权了哪些权限,而不是简单地认为自己声明的权限就是公众号授权的权限。 + * + * @param authCode + * 授权code + * @return 第三方组件授权信息 + * @see com.foxinmy.weixin4j.mp.model.ComponentAuthInfo + * @throws WeixinException + */ + public ComponentAuthInfo exchangeComponentAuthInfo(String authCode) + throws WeixinException { + String component_exchange_authorizer_uri = getRequestUri("component_exchange_authorizer_uri"); + JSONObject obj = new JSONObject(); + obj.put("component_appid", ticketManager.getThirdId()); + obj.put("authorization_code", authCode); + WeixinResponse response = weixinExecutor.post( + String.format(component_exchange_authorizer_uri, + tokenManager.getAccessToken()), obj.toJSONString()); + obj = response.getAsJson(); + JSONObject authObj = obj.getJSONObject("authorization_info"); + JSONArray privilegesObj = authObj.getJSONArray("func_info"); + List privileges = new ArrayList(privilegesObj.size()); + for (int i = 0; i < privilegesObj.size(); i++) { + privileges.add(privilegesObj.getJSONObject(i) + .getJSONObject("funcscope_category").getInteger("id")); + } + ComponentAuthInfo info = new ComponentAuthInfo(); + info.setPrivileges(privileges); + info.setAppId(authObj.getString("authorizer_appid")); + // 微信授权公众号的永久刷新令牌 + PerTicketManager perTicketManager = getRefreshTokenManager(info + .getAppId()); + // 缓存微信公众号的access_token + TokenCreator tokenCreator = new WeixinTokenComponentCreator( + perTicketManager, tokenManager); + Token token = new Token(authObj.getString("authorizer_access_token"), + authObj.getLongValue("expires_in") * 1000l); + ticketManager.getCacheStorager().caching(tokenCreator.key(), token); + // 缓存微信企业号的永久授权码 + perTicketManager.cachingTicket(authObj + .getString("authorizer_refresh_token")); + return info; + } + + /** + * 获取授权方的公众号帐号基本信息:获取授权方的公众号基本信息,包括头像、昵称、帐号类型、认证类型、微信号、原始ID和二维码图片URL。 + * 需要特别记录授权方的帐号类型,在消息及事件推送时,对于不具备客服接口的公众号,需要在5秒内立即响应;而若有客服接口,则可以选择暂时不响应, + * 而选择后续通过客服接口来发送消息触达粉丝 + * + * @param authAppId + * 授权方appid + * @return 第三方组件授权信息 + * @see com.foxinmy.weixin4j.mp.model.ComponentAuthInfo + * @throws WeixinException + */ + public ComponentAuthInfo getComponentAuthInfo(String authAppId) + throws WeixinException { + String component_get_authorizer_uri = getRequestUri("component_get_authorizer_uri"); + JSONObject obj = new JSONObject(); + obj.put("component_appid", ticketManager.getThirdId()); + obj.put("authorizer_appid", authAppId); + WeixinResponse response = weixinExecutor.post( + String.format(component_get_authorizer_uri, + tokenManager.getAccessToken()), obj.toJSONString()); + obj = response.getAsJson().getJSONObject("authorizer_info"); + ComponentAuthInfo info = JSON + .toJavaObject(obj, ComponentAuthInfo.class); + info.setServiceType(obj.getJSONObject("service_type_info").getIntValue( + "id")); + info.setVerifyType(obj.getJSONObject("verify_type_info").getIntValue( + "id")); + JSONArray privilegesObj = obj.getJSONObject("authorization_info") + .getJSONArray("func_info"); + List privileges = new ArrayList(privilegesObj.size()); + for (int i = 0; i < privilegesObj.size(); i++) { + privileges.add(privilegesObj.getJSONObject(i) + .getJSONObject("funcscope_category").getInteger("id")); + } + info.setPrivileges(privileges); + info.setAppId(authAppId); + return info; + } + + /** + * 获取授权方的公众号的选项设置信息,如:地理位置上报,语音识别开关,多客服开关。注意,获取各项选项设置信息 + * + * @param authAppId + * 授权方appid + * @param option + * 选项名称 + * @return 选项信息 + * @see com.foxinmy.weixin4j.mp.model.AuthorizerOption + * @throws WeixinException + */ + public AuthorizerOption getAuthorizerOption(String authAppId, + AuthorizerOptionName optionName) throws WeixinException { + String component_get_authorizer_option_uri = getRequestUri("component_get_authorizer_option_uri"); + JSONObject obj = new JSONObject(); + obj.put("component_appid", ticketManager.getThirdId()); + obj.put("authorizer_appid", authAppId); + obj.put("option_name", optionName.name()); + WeixinResponse response = weixinExecutor.post( + String.format(component_get_authorizer_option_uri, + tokenManager.getAccessToken()), obj.toJSONString()); + int optionValue = response.getAsJson().getIntValue("option_value"); + return AuthorizerOption.parse(optionName, optionValue); + } + + /** + * 设置授权方的公众号的选项信息,如:地理位置上报,语音识别开关,多客服开关。注意,获取各项选项设置信息 + * + * @param option + * 选项信息 + * @return 设置标识 + * @see com.foxinmy.weixin4j.mp.model.AuthorizerOption + * @throws WeixinException + */ + public JsonResult getAuthorizerOption(String authAppId, + AuthorizerOption option) throws WeixinException { + String component_set_authorizer_option_uri = getRequestUri("component_set_authorizer_option_uri"); + JSONObject obj = new JSONObject(); + obj.put("component_appid", ticketManager.getThirdId()); + obj.put("authorizer_appid", authAppId); + obj.put("option_name", option.getName()); + obj.put("option_value", option.getValue()); + WeixinResponse response = weixinExecutor.post( + String.format(component_set_authorizer_option_uri, + tokenManager.getAccessToken()), obj.toJSONString()); + return response.getAsJsonResult(); + } } diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java index ef1eed3d..ece1040e 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java @@ -45,7 +45,7 @@ public class OauthApi extends MpApi { } /** - * base静默授权:重定向URL使用weixin4j.properties#user.oauth.redirect.uri + * 公众号base静默oauth授权:重定向URL使用weixin4j.properties#user.oauth.redirect.uri * * @see {@link #getAuthorizeURL(String, String,String)} * @@ -205,4 +205,38 @@ public class OauthApi extends MpApi { return response.getAsObject(new TypeReference() { }); } + + /** + * 微信开放平台oauth授权:重定向URL使用weixin4j.properties#user.oauth.redirect.uri + * + * @see {@link #getOpenAuthorizeURL(String, String)} + * + * @return 请求授权的URL + */ + public String getOpenAuthorizeURL() { + String redirectUri = Weixin4jConfigUtil + .getValue("user.oauth.redirect.uri"); + return getOpenAuthorizeURL(redirectUri, "state"); + } + + /** + * 请求CODE + * + * @param redirectUri + * 重定向地址 域名与审核时填写的授权域名一致 + * @param state + * 用于保持请求和回调的状态,授权请求后原样带回给第三方 + * @return 请求授权的URL + */ + public String getOpenAuthorizeURL(String redirectUri, String state) { + String open_user_auth_uri = getRequestUri("open_user_auth_uri"); + try { + return String.format(open_user_auth_uri, account.getId(), + URLEncoder.encode(redirectUri, Consts.UTF_8.name()), + "snsapi_login", state); + } catch (UnsupportedEncodingException e) { + ; + } + return ""; + } } diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties index e972784d..2dd6d764 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/weixin.properties @@ -11,11 +11,11 @@ tenpay_gw_base_url=https://gw.tenpay.com # \u7f51\u9875\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f sns_user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect -#open_user_auth_uri=https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect sns_user_token_uri=https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code sns_token_refresh_uri=https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s sns_auth_token_uri=https://api.weixin.qq.com/sns/auth?access_token=%s&openid=%s sns_user_info_uri=https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s +open_user_auth_uri=https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect # \u76f4\u63a5\u83b7\u53d6\u7528\u6237\u4fe1\u606f api_user_info_uri={api_cgi_url}/user/info?access_token=%s&openid=%s&lang=%s @@ -178,4 +178,13 @@ tag_untagging_uri={api_cgi_url}/tags/members/batchuntagging?access_token=%s # \u83b7\u53d6\u7528\u6237\u8eab\u4e0a\u7684\u6807\u7b7e\u5217\u8868 tag_userids_uri={api_cgi_url}/tags/getidlist?access_token=%s # \u83b7\u53d6\u6807\u7b7e\u4e0b\u7c89\u4e1d\u5217\u8868 -tag_user_uri={api_cgi_url}/user/tag/get?access_token=%s \ No newline at end of file +tag_user_uri={api_cgi_url}/user/tag/get?access_token=%s + +# \u4f7f\u7528\u6388\u6743\u7801\u6362\u53d6\u516c\u4f17\u53f7\u7684\u63a5\u53e3\u8c03\u7528\u51ed\u636e\u548c\u6388\u6743\u4fe1\u606f +component_exchange_authorizer_uri={api_cgi_url}/component/api_query_auth?component_access_token=%s +# \u83b7\u53d6\u6388\u6743\u65b9\u7684\u516c\u4f17\u53f7\u5e10\u53f7\u57fa\u672c\u4fe1\u606f +component_get_authorizer_uri={api_cgi_url}/component/api_get_authorizer_info?component_access_token=%s +# \u83b7\u53d6\u6388\u6743\u65b9\u7684\u9009\u9879\u8bbe\u7f6e\u4fe1\u606f +component_get_authorizer_option_uri={api_cgi_url}/component/api_get_authorizer_option?component_access_token=%s +# \u8bbe\u7f6e\u6388\u6743\u65b9\u7684\u9009\u9879\u4fe1\u606f +component_set_authorizer_option_uri={api_cgi_url}component/api_set_authorizer_option?component_access_token=%s \ No newline at end of file diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinComponentPreCodeCreator.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinComponentPreCodeCreator.java index 1d742923..743ea182 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinComponentPreCodeCreator.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinComponentPreCodeCreator.java @@ -9,7 +9,7 @@ import com.foxinmy.weixin4j.token.TokenCreator; import com.foxinmy.weixin4j.token.TokenManager; /** - * 微信企业号应用套件预授权码创建 + * 微信开发平台应用组件预授权码创建 * * @className WeixinComponentPreCodeCreator * @author jinyu(foxinmy@gmail.com) diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinComponentTokenCreator.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinComponentTokenCreator.java index de3cadce..97aced14 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinComponentTokenCreator.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinComponentTokenCreator.java @@ -9,7 +9,7 @@ import com.foxinmy.weixin4j.token.TicketManager; import com.foxinmy.weixin4j.token.TokenCreator; /** - * 微信公众号应用组件凭证创建 + * 微信开发平台应用组件凭证创建 * * @className WeixinComponentTokenCreator * @author jinyu(foxinmy@gmail.com) @@ -30,19 +30,19 @@ public class WeixinComponentTokenCreator extends TokenCreator { @Override public String key0() { - return String.format("mp_component_token_%s", ticketManager.getId()); + return String.format("mp_component_token_%s", ticketManager.getThirdId()); } @Override public Token create() throws WeixinException { JSONObject obj = new JSONObject(); - obj.put("component_appid", ticketManager.getId()); - obj.put("component_appsecret", ticketManager.getSecret()); - obj.put("component_verify_ticket", ticketManager.getTicket()); + obj.put("component_appid", ticketManager.getThirdId()); + obj.put("component_appsecret", ticketManager.getThirdSecret()); + obj.put("component_verify_ticket", ticketManager.getAccessTicket()); WeixinResponse response = weixinExecutor.post( URLConsts.COMPONENT_TOKEN_URL, obj.toJSONString()); obj = response.getAsJson(); - return new Token(obj.getString("suite_access_token"), + return new Token(obj.getString("component_access_token"), obj.getLongValue("expires_in") * 1000l); } } diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinTokenComponentCreator.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinTokenComponentCreator.java new file mode 100644 index 00000000..5417ad0b --- /dev/null +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/component/WeixinTokenComponentCreator.java @@ -0,0 +1,57 @@ +package com.foxinmy.weixin4j.mp.component; + +import com.alibaba.fastjson.JSONObject; +import com.foxinmy.weixin4j.exception.WeixinException; +import com.foxinmy.weixin4j.http.weixin.WeixinResponse; +import com.foxinmy.weixin4j.model.Token; +import com.foxinmy.weixin4j.mp.type.URLConsts; +import com.foxinmy.weixin4j.token.PerTicketManager; +import com.foxinmy.weixin4j.token.TokenCreator; +import com.foxinmy.weixin4j.token.TokenManager; + +/** + * 微信公众号token创建(永久刷新令牌) + * + * @className WeixinTokenComponentCreator + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月5日 + * @since JDK 1.6 + */ +public class WeixinTokenComponentCreator extends TokenCreator { + + private final PerTicketManager perTicketManager; + private final TokenManager componentTokenManager; + + /** + * + * @param perTicketManager + * 第三方套件永久授权码 + * @param componentTokenManager + * 第三方套件凭证token + */ + public WeixinTokenComponentCreator(PerTicketManager perTicketManager, + TokenManager componentTokenManager) { + this.perTicketManager = perTicketManager; + this.componentTokenManager = componentTokenManager; + } + + @Override + public String key0() { + return String.format("mp_token_suite_%s_%s", + perTicketManager.getThirdId(), perTicketManager.getAuthAppId()); + } + + @Override + public Token create() throws WeixinException { + JSONObject obj = new JSONObject(); + obj.put("component_appid", perTicketManager.getThirdId()); + obj.put("authorizer_appid", perTicketManager.getAuthAppId()); + obj.put("authorizer_refresh_token", perTicketManager.getAccessTicket()); + WeixinResponse response = weixinExecutor.post( + String.format(URLConsts.TOKEN_COMPONENT_URL, + componentTokenManager.getAccessToken()), obj.toJSONString()); + obj = response.getAsJson(); + return new Token(obj.getString("access_token"), + obj.getLongValue("expires_in") * 1000l); + } +} diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/AuthorizerOption.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/AuthorizerOption.java new file mode 100644 index 00000000..4120eddf --- /dev/null +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/AuthorizerOption.java @@ -0,0 +1,128 @@ +package com.foxinmy.weixin4j.mp.model; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; + +/** + * 授权方的选项信息 + * + * @className AuthorizerOption + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月5日 + * @since JDK 1.6 + */ +public final class AuthorizerOption implements Serializable { + + private static final long serialVersionUID = -3124882411789627403L; + + /** + * 选项名称 + * + * @className AuthorizerOptionName + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月5日 + * @since JDK 1.6 + */ + public enum AuthorizerOptionName { + /** + * 地理位置上报选项 + */ + location_report, + /** + * 语音识别开关选项 + */ + voice_recognize, + /** + * 多客服开关选项 + */ + customer_service; + } + + private AuthorizerOptionName name; + private int value; + private List options; + + private AuthorizerOption(AuthorizerOptionName name, int value, + Integer... options) { + this.name = name; + this.value = value; + this.options = Arrays.asList(options); + } + + /** + * 地理位置上报选项 + * + * @param value + * 选项值 + * @return 选项对象 + */ + public static AuthorizerOption createLocationReportOption(int value) { + return new AuthorizerOption(AuthorizerOptionName.location_report, + value, 0, 1, 2); + } + + /** + * 语音识别开关选项 + * + * @param value + * 选项值 + * @return 选项对象 + */ + public static AuthorizerOption createVoiceRecognizeOption(int value) { + return new AuthorizerOption(AuthorizerOptionName.voice_recognize, + value, 0, 1); + } + + /** + * 多客服开关选项 + * + * @param value + * 选项值 + * @return 选项对象 + */ + public static AuthorizerOption createCustomerServiceOption(int value) { + return new AuthorizerOption(AuthorizerOptionName.customer_service, + value, 0, 1); + } + + /** + * 返回选项对象 + * + * @param optionName + * 选项名 + * @param optionValue + * 选项值 + * @return 选项对象 + */ + public static AuthorizerOption parse(AuthorizerOptionName optionName, + int optionValue) { + if (optionName == AuthorizerOptionName.customer_service) { + return createCustomerServiceOption(optionValue); + } else if (optionName == AuthorizerOptionName.location_report) { + return createLocationReportOption(optionValue); + } else if (optionName == AuthorizerOptionName.voice_recognize) { + return createVoiceRecognizeOption(optionValue); + } else { + throw new IllegalArgumentException("unkown option:" + optionName); + } + } + + public AuthorizerOptionName getName() { + return name; + } + + public int getValue() { + return value; + } + + public List getOptions() { + return options; + } + + @Override + public String toString() { + return "AuthorizerOption [name=" + name + ", value=" + value + + ", options=" + options + "]"; + } +} diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/ComponentAuthInfo.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/ComponentAuthInfo.java new file mode 100644 index 00000000..daaca736 --- /dev/null +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/ComponentAuthInfo.java @@ -0,0 +1,235 @@ +package com.foxinmy.weixin4j.mp.model; + +import java.io.Serializable; +import java.util.List; + +import com.alibaba.fastjson.annotation.JSONField; + +/** + * 第三方组件授权信息 + * + * @className ComponentAuthInfo + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月5日 + * @since JDK 1.6 + */ +public class ComponentAuthInfo implements Serializable { + private static final long serialVersionUID = -3610172415045923599L; + /** + * 授权方appId + */ + @JSONField(name = "appid") + private String appId; + /** + * 授权方昵称 + */ + @JSONField(name = "nick_name") + private String nickName; + /** + * 授权方头像 + */ + @JSONField(name = "head_img") + private String headImg; + /** + * 授权方公众号类型,0代表订阅号,1代表由历史老帐号升级后的订阅号,2代表服务号 + */ + @JSONField(deserialize = false) + private int serviceType; + /** + * 授权方认证类型,-1代表未认证,0代表微信认证,1代表新浪微博认证,2代表腾讯微博认证,3代表已资质认证通过但还未通过名称认证,4 + * 代表已资质认证通过、还未通过名称认证,但通过了新浪微博认证,5代表已资质认证通过、还未通过名称认证,但通过了腾讯微博认证 + */ + @JSONField(deserialize = false) + private int verifyType; + /** + * 授权方公众号的原始ID + */ + @JSONField(name = "user_name") + private String userName; + /** + * 授权方公众号所设置的微信号,可能为空 + */ + @JSONField(name = "alias") + private String alias; + /** + * 二维码图片的URL,开发者最好自行也进行保存 + */ + @JSONField(name = "qrcode_url") + private String qrcodeUrl; + /** + * 公众号功能的开通状况 + */ + @JSONField(name = "business_info") + private BusinessInfo businessInfo; + /** + * 公众号授权给开发者的权限集列表,ID为1到15时分别代表: 消息管理权限 用户管理权限 帐号服务权限 网页服务权限 微信小店权限 微信多客服权限 + * 群发与通知权限 微信卡券权限 微信扫一扫权限 微信连WIFI权限 素材管理权限 微信摇周边权限 微信门店权限 微信支付权限 自定义菜单权限 + */ + @JSONField(deserialize = false) + private List privileges; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getHeadImg() { + return headImg; + } + + public void setHeadImg(String headImg) { + this.headImg = headImg; + } + + public int getServiceType() { + return serviceType; + } + + public void setServiceType(int serviceType) { + this.serviceType = serviceType; + } + + public int getVerifyType() { + return verifyType; + } + + public void setVerifyType(int verifyType) { + this.verifyType = verifyType; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public String getQrcodeUrl() { + return qrcodeUrl; + } + + public void setQrcodeUrl(String qrcodeUrl) { + this.qrcodeUrl = qrcodeUrl; + } + + public BusinessInfo getBusinessInfo() { + return businessInfo; + } + + public void setBusinessInfo(BusinessInfo businessInfo) { + this.businessInfo = businessInfo; + } + + public List getPrivileges() { + return privileges; + } + + public void setPrivileges(List privileges) { + this.privileges = privileges; + } + + @Override + public String toString() { + return "ComponentAuthInfo [nickName=" + nickName + ", headImg=" + + headImg + ", serviceType=" + serviceType + ", verifyType=" + + verifyType + ", userName=" + userName + ", alias=" + alias + + ", qrcodeUrl=" + qrcodeUrl + ", businessInfo=" + businessInfo + + ", privileges=" + privileges + "]"; + } + + public static class BusinessInfo implements Serializable { + private static final long serialVersionUID = 3106626182191149662L; + /** + * 是否开通微信门店功能 + */ + @JSONField(name = "open_store") + private boolean openStore; + /** + * 是否开通微信扫商品功能 + */ + @JSONField(name = "open_scan") + private boolean openScan; + /** + * 是否开通微信支付功能 + */ + @JSONField(name = "open_pay") + private boolean openPay; + /** + * 是否开通微信卡券功能 + */ + @JSONField(name = "open_card") + private boolean openCard; + /** + * 是否开通微信摇一摇功能 + */ + @JSONField(name = "open_shake") + private boolean openShake; + + public boolean isOpenStore() { + return openStore; + } + + public void setOpenStore(boolean openStore) { + this.openStore = openStore; + } + + public boolean isOpenScan() { + return openScan; + } + + public void setOpenScan(boolean openScan) { + this.openScan = openScan; + } + + public boolean isOpenPay() { + return openPay; + } + + public void setOpenPay(boolean openPay) { + this.openPay = openPay; + } + + public boolean isOpenCard() { + return openCard; + } + + public void setOpenCard(boolean openCard) { + this.openCard = openCard; + } + + public boolean isOpenShake() { + return openShake; + } + + public void setOpenShake(boolean openShake) { + this.openShake = openShake; + } + + @Override + public String toString() { + return "BusinessInfo [openStore=" + openStore + ", openScan=" + + openScan + ", openPay=" + openPay + ", openCard=" + + openCard + ", openShake=" + openShake + "]"; + } + } +} diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/URLConsts.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/URLConsts.java index b5f57e5d..8588659b 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/URLConsts.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/type/URLConsts.java @@ -14,18 +14,26 @@ public final class URLConsts { /** * 公众平台获取token的url */ - public static final String ASSESS_TOKEN_URL = BASE_URL + "/token?grant_type=client_credential&appid=%s&secret=%s"; + public static final String ASSESS_TOKEN_URL = BASE_URL + + "/token?grant_type=client_credential&appid=%s&secret=%s"; /** * 公众平台jssdk获取token的url */ - public static final String JS_TICKET_URL = BASE_URL + "/ticket/getticket?access_token=%s&type=%s"; + public static final String JS_TICKET_URL = BASE_URL + + "/ticket/getticket?access_token=%s&type=%s"; /** - * 开发平台获取token的url + * 开放平台获取token的url */ - public static final String COMPONENT_TOKEN_URL = BASE_URL + "/component/api_component_token"; + public static final String COMPONENT_TOKEN_URL = BASE_URL + + "/component/api_component_token"; /** - * 开发平台获取预授权码的url + * 开放平台获取预授权码的url */ public static final String COMPONENET_PRE_CODE_URL = BASE_URL + "/component/api_create_preauthcode?component_access_token=%s"; + /** + * 开放平台获取公众号access_token的url + */ + public static final String TOKEN_COMPONENT_URL = BASE_URL + + "/component/api_authorizer_token?component_access_token=%s"; } diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java index a025f591..82c29995 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinProxy.java @@ -38,7 +38,6 @@ import com.foxinmy.weixin4j.qy.model.IdParameter; import com.foxinmy.weixin4j.qy.model.Party; import com.foxinmy.weixin4j.qy.model.Tag; import com.foxinmy.weixin4j.qy.model.User; -import com.foxinmy.weixin4j.qy.suite.SuitePerCodeManager; import com.foxinmy.weixin4j.qy.suite.WeixinTokenSuiteCreator; import com.foxinmy.weixin4j.qy.token.WeixinTicketCreator; import com.foxinmy.weixin4j.qy.token.WeixinTokenCreator; @@ -47,6 +46,7 @@ import com.foxinmy.weixin4j.qy.type.InviteType; import com.foxinmy.weixin4j.qy.type.KfType; import com.foxinmy.weixin4j.qy.type.UserStatus; import com.foxinmy.weixin4j.setting.Weixin4jSettings; +import com.foxinmy.weixin4j.token.PerTicketManager; import com.foxinmy.weixin4j.token.TokenManager; import com.foxinmy.weixin4j.tuple.MpArticle; import com.foxinmy.weixin4j.type.MediaType; @@ -137,21 +137,21 @@ public class WeixinProxy { /** * 第三方套件(永久授权码机制) * - * @param perCodeManager + * @param perTicketManager * 第三方套件永久授权码 * {@link com.foxinmy.weixin4j.qy.api.SuiteApi#getPerCodeManager(String)} - * @param perTokenManager + * @param suiteTokenManager * 第三方套件凭证token - * {@link com.foxinmy.weixin4j.qy.api.SuiteApi#getPerTokenManager(String)} + * {@link com.foxinmy.weixin4j.qy.api.SuiteApi#getTokenManager} * @see com.foxinmy.weixin4j.qy.api.SuiteApi * @see WeixinSuiteProxy#getWeixinProxy(String, String) */ - public WeixinProxy(SuitePerCodeManager perCodeManager, - TokenManager perTokenManager) { - this(new TokenManager(new WeixinTokenSuiteCreator(perCodeManager, - perTokenManager), perCodeManager.getCacheStorager())); + public WeixinProxy(PerTicketManager perTicketManager, + TokenManager suiteTokenManager) { + this(new TokenManager(new WeixinTokenSuiteCreator(perTicketManager, + suiteTokenManager), perTicketManager.getCacheStorager())); this.settings = new Weixin4jSettings(new WeixinAccount( - perCodeManager.getAuthCorpId(), null)); + perTicketManager.getAuthAppId(), null)); } /** diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinSuiteProxy.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinSuiteProxy.java index d1627cde..e25849d9 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinSuiteProxy.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/WeixinSuiteProxy.java @@ -9,6 +9,7 @@ import java.util.Map; import com.alibaba.fastjson.JSON; import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.model.Consts; +import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.model.WeixinAccount; import com.foxinmy.weixin4j.qy.api.ProviderApi; import com.foxinmy.weixin4j.qy.api.SuiteApi; @@ -54,8 +55,8 @@ public class WeixinSuiteProxy { * 默认使用文件方式保存token、使用weixin4j.properties配置的账号信息 */ public WeixinSuiteProxy() { - this(new Weixin4jSettings( - JSON.parseObject(Weixin4jConfigUtil.getValue("account"), WeixinQyAccount.class))); + this(new Weixin4jSettings(JSON.parseObject( + Weixin4jConfigUtil.getValue("account"), WeixinQyAccount.class))); } /** @@ -70,15 +71,18 @@ public class WeixinSuiteProxy { this.suiteMap = new HashMap(suites.size()); for (WeixinAccount suite : suites) { this.suiteMap.put(suite.getId(), new SuiteApi( - new TicketManager(suite.getId(), suite.getSecret(), settings.getCacheStorager0()))); + new TicketManager(suite.getId(), suite.getSecret(), + settings.getCacheStorager0()))); } this.suiteMap.put(null, suiteMap.get(suites.get(0).getId())); } if (StringUtil.isNotBlank(settings.getAccount().getId()) - && StringUtil.isNotBlank(settings.getAccount().getProviderSecret())) { + && StringUtil.isNotBlank(settings.getAccount() + .getProviderSecret())) { this.providerApi = new ProviderApi( - new TokenManager(new WeixinProviderTokenCreator(settings.getAccount().getId(), - settings.getAccount().getProviderSecret()), settings.getCacheStorager0()), + new TokenManager(new WeixinProviderTokenCreator(settings + .getAccount().getId(), settings.getAccount() + .getProviderSecret()), settings.getCacheStorager0()), settings.getCacheStorager0()); } } @@ -114,6 +118,24 @@ public class WeixinSuiteProxy { return this.suiteMap.get(suiteId); } + /** + * 获取套件的预授权码 + * + * @param suiteId + * 套件ID + * @return 预授权码 + * @see com.foxinmy.weixin4j.qy.api.SuiteApi + * @see com.foxinmy.weixin4j.qy.api.SuiteApi#getPreCodeManager() + * @throws WeixinException + */ + public String preSuiteTicket(String suiteId) throws WeixinException { + Token token = suite(suiteId).getTicketManager().getTicket(); + if (token == null || StringUtil.isBlank(token.getAccessToken())) { + throw new WeixinException("maybe oauth first?"); + } + return token.getAccessToken(); + } + /** * 缓存套件ticket(多个套件 * @@ -126,7 +148,8 @@ public class WeixinSuiteProxy { * 推送suite_ticket协议 * @throws WeixinException */ - public void cacheTicket(String suiteId, String suiteTicket) throws WeixinException { + public void cacheTicket(String suiteId, String suiteTicket) + throws WeixinException { suite(suiteId).getTicketManager().cachingTicket(suiteTicket); } @@ -141,7 +164,8 @@ public class WeixinSuiteProxy { * @throws WeixinException */ public String getSuiteAuthorizeURL(String suiteId) throws WeixinException { - String redirectUri = Weixin4jConfigUtil.getValue("suite.oauth.redirect.uri"); + String redirectUri = Weixin4jConfigUtil + .getValue("suite.oauth.redirect.uri"); return getSuiteAuthorizeURL(suiteId, redirectUri, "state"); } @@ -161,9 +185,11 @@ public class WeixinSuiteProxy { * @return 请求授权的URL * @throws WeixinException */ - public String getSuiteAuthorizeURL(String suiteId, String redirectUri, String state) throws WeixinException { + public String getSuiteAuthorizeURL(String suiteId, String redirectUri, + String state) throws WeixinException { try { - return String.format(URLConsts.SUITE_OAUTH_URL, suiteId, suite(suiteId).getTicketManager().getTicket(), + return String.format(URLConsts.SUITE_OAUTH_URL, suiteId, + suite(suiteId).getTicketManager().getTicket(), URLEncoder.encode(redirectUri, Consts.UTF_8.name()), state); } catch (UnsupportedEncodingException e) { ; @@ -205,7 +231,8 @@ public class WeixinSuiteProxy { * 获取登录企业号官网的url * @throws WeixinException */ - public String getLoginUrl(String corpId, LoginTargetType targetType, int agentId) throws WeixinException { + public String getLoginUrl(String corpId, LoginTargetType targetType, + int agentId) throws WeixinException { return providerApi.getLoginUrl(corpId, targetType, agentId); } @@ -220,8 +247,8 @@ public class WeixinSuiteProxy { * @return */ public WeixinProxy getWeixinProxy(String suiteId, String authCorpId) { - return new WeixinProxy(suite(suiteId).getPerCodeManager(authCorpId), - suite(suiteId).getPerTokenManager(authCorpId)); + return new WeixinProxy(suite(suiteId).getPerTicketManager(authCorpId), + suite(suiteId).getTokenManager()); } public final static String VERSION = "1.7.0"; diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/SuiteApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/SuiteApi.java index 8f6ff973..4bc80fd6 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/SuiteApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/SuiteApi.java @@ -10,10 +10,10 @@ import com.foxinmy.weixin4j.qy.model.AgentInfo; import com.foxinmy.weixin4j.qy.model.AgentSetter; import com.foxinmy.weixin4j.qy.model.OUserInfo; import com.foxinmy.weixin4j.qy.model.User; -import com.foxinmy.weixin4j.qy.suite.SuitePerCodeManager; import com.foxinmy.weixin4j.qy.suite.WeixinSuitePreCodeCreator; import com.foxinmy.weixin4j.qy.suite.WeixinSuiteTokenCreator; import com.foxinmy.weixin4j.qy.suite.WeixinTokenSuiteCreator; +import com.foxinmy.weixin4j.token.PerTicketManager; import com.foxinmy.weixin4j.token.TicketManager; import com.foxinmy.weixin4j.token.TokenCreator; import com.foxinmy.weixin4j.token.TokenManager; @@ -51,9 +51,8 @@ public class SuiteApi extends QyApi { this.ticketManager = ticketManager; this.tokenManager = new TokenManager(new WeixinSuiteTokenCreator( ticketManager), ticketManager.getCacheStorager()); - this.preCodeManager = new TokenManager( - new WeixinSuitePreCodeCreator(tokenManager, - ticketManager.getId()), + this.preCodeManager = new TokenManager(new WeixinSuitePreCodeCreator( + tokenManager, ticketManager.getThirdId()), ticketManager.getCacheStorager()); } @@ -91,9 +90,9 @@ public class SuiteApi extends QyApi { * 授权方corpid * @return */ - public SuitePerCodeManager getPerCodeManager(String authCorpId) { - return new SuitePerCodeManager(authCorpId, - ticketManager.getId(), + public PerTicketManager getPerTicketManager(String authCorpId) { + return new PerTicketManager(authCorpId, ticketManager.getThirdId(), + ticketManager.getThirdSecret(), ticketManager.getCacheStorager()); } @@ -106,7 +105,7 @@ public class SuiteApi extends QyApi { */ public TokenManager getPerTokenManager(String authCorpId) { return new TokenManager(new WeixinTokenSuiteCreator( - getPerCodeManager(authCorpId), tokenManager), + getPerTicketManager(authCorpId), tokenManager), ticketManager.getCacheStorager()); } @@ -130,8 +129,7 @@ public class SuiteApi extends QyApi { para.put("session_info", appid); WeixinResponse response = weixinExecutor.post( String.format(suite_set_session_uri, - tokenManager.getAccessToken()), - para.toJSONString()); + tokenManager.getAccessToken()), para.toJSONString()); return response.getAsJsonResult(); } @@ -151,28 +149,26 @@ public class SuiteApi extends QyApi { throws WeixinException { String suite_get_permanent_uri = getRequestUri("suite_get_permanent_uri"); JSONObject obj = new JSONObject(); - obj.put("suite_id", ticketManager.getId()); + obj.put("suite_id", ticketManager.getThirdId()); obj.put("auth_code", authCode); - WeixinResponse response = weixinExecutor - .post(String.format(suite_get_permanent_uri, + WeixinResponse response = weixinExecutor.post( + String.format(suite_get_permanent_uri, tokenManager.getAccessToken()), obj.toJSONString()); obj = response.getAsJson(); obj.put("corp_info", obj.remove("auth_corp_info")); obj.put("user_info", obj.remove("auth_user_info")); OUserInfo oInfo = JSON.toJavaObject(obj, OUserInfo.class); // 微信授权企业号的永久授权码 - SuitePerCodeManager suitePerCodeManager = getPerCodeManager(oInfo + PerTicketManager perTicketManager = getPerTicketManager(oInfo .getCorpInfo().getCorpId()); - // 缓存微信企业号access_token + // 缓存微信企业号的access_token TokenCreator tokenCreator = new WeixinTokenSuiteCreator( - suitePerCodeManager, tokenManager); + perTicketManager, tokenManager); Token token = new Token(obj.getString("access_token"), obj.getLongValue("expires_in") * 1000l); - ticketManager.getCacheStorager() - .caching(tokenCreator.key(), token); - // 缓存微信企业号永久授权码 - suitePerCodeManager.cachingPermanentCode(obj - .getString("permanent_code")); + ticketManager.getCacheStorager().caching(tokenCreator.key(), token); + // 缓存微信企业号的永久授权码 + perTicketManager.cachingTicket(obj.getString("permanent_code")); return oInfo; } @@ -190,12 +186,11 @@ public class SuiteApi extends QyApi { public OUserInfo getOAuthInfo(String authCorpId) throws WeixinException { String suite_get_authinfo_uri = getRequestUri("suite_get_authinfo_uri"); JSONObject obj = new JSONObject(); - obj.put("suite_id", ticketManager.getId()); + obj.put("suite_id", ticketManager.getThirdId()); obj.put("auth_corpid", authCorpId); - obj.put("permanent_code", getPerCodeManager(authCorpId) - .getPermanentCode()); - WeixinResponse response = weixinExecutor - .post(String.format(suite_get_authinfo_uri, + obj.put("permanent_code", getPerTicketManager(authCorpId).getAccessTicket()); + WeixinResponse response = weixinExecutor.post( + String.format(suite_get_authinfo_uri, tokenManager.getAccessToken()), obj.toJSONString()); obj = response.getAsJson(); obj.put("corp_info", obj.remove("auth_corp_info")); @@ -220,13 +215,12 @@ public class SuiteApi extends QyApi { throws WeixinException { String suite_get_agent_uri = getRequestUri("suite_get_agent_uri"); JSONObject obj = new JSONObject(); - obj.put("suite_id", ticketManager.getId()); + obj.put("suite_id", ticketManager.getThirdId()); obj.put("auth_corpid", authCorpId); - obj.put("permanent_code", getPerCodeManager(authCorpId) - .getPermanentCode()); + obj.put("permanent_code", getPerTicketManager(authCorpId).getAccessTicket()); obj.put("agentid", agentid); - WeixinResponse response = weixinExecutor - .post(String.format(suite_get_agent_uri, + WeixinResponse response = weixinExecutor.post( + String.format(suite_get_agent_uri, tokenManager.getAccessToken()), obj.toJSONString()); JSONObject jsonObj = response.getAsJson(); AgentInfo agent = JSON.toJavaObject(jsonObj, AgentInfo.class); @@ -258,10 +252,9 @@ public class SuiteApi extends QyApi { throws WeixinException { String suite_set_agent_uri = getRequestUri("suite_set_agent_uri"); JSONObject obj = new JSONObject(); - obj.put("suite_id", ticketManager.getId()); + obj.put("suite_id", ticketManager.getThirdId()); obj.put("auth_corpid", authCorpId); - obj.put("permanent_code", getPerCodeManager(authCorpId) - .getPermanentCode()); + obj.put("permanent_code", getPerTicketManager(authCorpId).getAccessTicket()); obj.put("agent", agentSet); WeixinResponse response = weixinExecutor.post( String.format(suite_set_agent_uri, diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/SuitePerCodeManager.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/SuitePerCodeManager.java deleted file mode 100644 index 847ef422..00000000 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/SuitePerCodeManager.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.foxinmy.weixin4j.qy.suite; - -import com.foxinmy.weixin4j.cache.CacheStorager; -import com.foxinmy.weixin4j.exception.WeixinException; -import com.foxinmy.weixin4j.model.Token; -import com.foxinmy.weixin4j.token.TokenCreator; - -/** - * 应用套件永久授权码的存取 - * - * @className SuitePerCodeManager - * @author jinyu(foxinmy@gmail.com) - * @date 2015年6月22日 - * @since JDK 1.6 - * @see - */ -public class SuitePerCodeManager { - - private final String authCorpId; - private final String suiteId; - private final CacheStorager cacheStorager; - - public SuitePerCodeManager(String authCorpId, String suiteId, - CacheStorager cacheStorager) { - this.authCorpId = authCorpId; - this.suiteId = suiteId; - this.cacheStorager = cacheStorager; - } - - /** - * 缓存永久授权码 - * - * @param permanentCode - * @throws WeixinException - */ - public void cachingPermanentCode(String permanentCode) - throws WeixinException { - Token token = new Token(permanentCode); - cacheStorager.caching(getCacheKey(), token); - } - - /** - * 获取永久授权码的key - * - * @return - */ - public String getCacheKey() { - return String.format("%sqy_suite_percode_%s_%s", - TokenCreator.CACHEKEY_PREFIX, suiteId, authCorpId); - } - - /** - * 查找永久授权码 - * - * @return - * @throws WeixinException - */ - public String getPermanentCode() throws WeixinException { - return cacheStorager.lookup(getCacheKey()).getAccessToken(); - } - - public String getSuiteId() { - return this.suiteId; - } - - public String getAuthCorpId() { - return this.authCorpId; - } - - public CacheStorager getCacheStorager() { - return this.cacheStorager; - } -} diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinSuiteTokenCreator.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinSuiteTokenCreator.java index 54c638d9..d88e4a90 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinSuiteTokenCreator.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinSuiteTokenCreator.java @@ -34,15 +34,15 @@ public class WeixinSuiteTokenCreator extends TokenCreator { @Override public String key0() { - return String.format("qy_suite_token_%s", ticketManager.getId()); + return String.format("qy_suite_token_%s", ticketManager.getThirdId()); } @Override public Token create() throws WeixinException { JSONObject obj = new JSONObject(); - obj.put("suite_id", ticketManager.getId()); - obj.put("suite_secret", ticketManager.getSecret()); - obj.put("suite_ticket", ticketManager.getTicket()); + obj.put("suite_id", ticketManager.getThirdId()); + obj.put("suite_secret", ticketManager.getThirdSecret()); + obj.put("suite_ticket", ticketManager.getAccessTicket()); WeixinResponse response = weixinExecutor.post( URLConsts.SUITE_TOKEN_URL, obj.toJSONString()); obj = response.getAsJson(); diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinTokenSuiteCreator.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinTokenSuiteCreator.java index 4d6934d4..1cfa7f2a 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinTokenSuiteCreator.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinTokenSuiteCreator.java @@ -5,6 +5,7 @@ import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.http.weixin.WeixinResponse; import com.foxinmy.weixin4j.model.Token; import com.foxinmy.weixin4j.qy.type.URLConsts; +import com.foxinmy.weixin4j.token.PerTicketManager; import com.foxinmy.weixin4j.token.TokenCreator; import com.foxinmy.weixin4j.token.TokenManager; @@ -22,36 +23,36 @@ import com.foxinmy.weixin4j.token.TokenManager; */ public class WeixinTokenSuiteCreator extends TokenCreator { - private final SuitePerCodeManager perCodeManager; + private final PerTicketManager perTicketManager; private final TokenManager suiteTokenManager; /** * - * @param perCodeManager + * @param perTicketManager * 第三方套件永久授权码 - * @param suitetokenManager + * @param suiteTokenManager * 第三方套件凭证token */ - public WeixinTokenSuiteCreator(SuitePerCodeManager perCodeManager, + public WeixinTokenSuiteCreator(PerTicketManager perTicketManager, TokenManager suiteTokenManager) { - this.perCodeManager = perCodeManager; + this.perTicketManager = perTicketManager; this.suiteTokenManager = suiteTokenManager; } @Override public String key0() { return String.format("qy_token_suite_%s_%s", - perCodeManager.getSuiteId(), perCodeManager.getAuthCorpId()); + perTicketManager.getThirdId(), perTicketManager.getAuthAppId()); } @Override public Token create() throws WeixinException { JSONObject obj = new JSONObject(); - obj.put("suite_id", perCodeManager.getSuiteId()); - obj.put("auth_corpid", perCodeManager.getAuthCorpId()); - obj.put("permanent_code", perCodeManager.getPermanentCode()); - WeixinResponse response = weixinExecutor - .post(String.format(URLConsts.TOKEN_SUITE_URL, + obj.put("suite_id", perTicketManager.getThirdId()); + obj.put("auth_corpid", perTicketManager.getAuthAppId()); + obj.put("permanent_code", perTicketManager.getAccessTicket()); + WeixinResponse response = weixinExecutor.post( + String.format(URLConsts.TOKEN_SUITE_URL, suiteTokenManager.getAccessToken()), obj.toJSONString()); obj = response.getAsJson(); return new Token(obj.getString("access_token"),