From ed5703c36f654a4050d93ced0ca2e030b40e64f0 Mon Sep 17 00:00:00 2001 From: jinyu Date: Wed, 6 Jul 2016 11:02:31 +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=B6WeixinComponentProxy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGE.md | 6 +- weixin4j-mp/CHANGE.md | 6 +- weixin4j-mp/README.md | 2 + .../weixin4j/mp/WeixinComponentProxy.java | 189 ++++++++++++++++++ .../foxinmy/weixin4j/mp/api/ComponentApi.java | 8 +- .../weixin4j/mp/model/WeixinMpAccount.java | 54 +++++ .../foxinmy/weixin4j/mp/type/URLConsts.java | 14 +- .../src/main/resources/weixin4j.properties | 6 +- .../foxinmy/weixin4j/qy/WeixinSuiteProxy.java | 40 ++-- .../com/foxinmy/weixin4j/qy/api/SuiteApi.java | 8 +- .../weixin4j/qy/model/WeixinQyAccount.java | 2 +- .../src/main/resources/weixin4j.properties | 2 +- 12 files changed, 294 insertions(+), 43 deletions(-) create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinComponentProxy.java create mode 100644 weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/WeixinMpAccount.java diff --git a/CHANGE.md b/CHANGE.md index 13ab2194..b35ac2b1 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -723,4 +723,8 @@ + weixin4j-mp:初始化开放平台第三方组件TokenCreator - + weixin4j-mp:新增第三方组件ComponentApi \ No newline at end of file + + weixin4j-mp:新增第三方组件ComponentApi + +* 2016-07-06 + + + weixin4j-mp:新增第三方组件WeixinComponentProxy \ No newline at end of file diff --git a/weixin4j-mp/CHANGE.md b/weixin4j-mp/CHANGE.md index ae5b128b..afa53064 100644 --- a/weixin4j-mp/CHANGE.md +++ b/weixin4j-mp/CHANGE.md @@ -234,4 +234,8 @@ + 初始化开放平台第三方组件TokenCreator - + 新增第三方组件ComponentApi \ No newline at end of file + + 新增第三方组件ComponentApi + +* 2016-07-06 + + + 新增第三方组件WeixinComponentProxy \ No newline at end of file diff --git a/weixin4j-mp/README.md b/weixin4j-mp/README.md index 3250387d..d5ba2a33 100644 --- a/weixin4j-mp/README.md +++ b/weixin4j-mp/README.md @@ -32,6 +32,8 @@ weixin4j-mp * TmplApi `模板消息API` * UserApi `用户管理API` + + * ComponentApi `第三方组件API` [如何使用](https://github.com/foxinmy/weixin4j/wiki) --------- diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinComponentProxy.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinComponentProxy.java new file mode 100644 index 00000000..9868f16b --- /dev/null +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/WeixinComponentProxy.java @@ -0,0 +1,189 @@ +package com.foxinmy.weixin4j.mp; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.List; +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.mp.api.ComponentApi; +import com.foxinmy.weixin4j.mp.model.WeixinMpAccount; +import com.foxinmy.weixin4j.mp.type.URLConsts; +import com.foxinmy.weixin4j.setting.Weixin4jSettings; +import com.foxinmy.weixin4j.token.TicketManager; +import com.foxinmy.weixin4j.util.StringUtil; +import com.foxinmy.weixin4j.util.Weixin4jConfigUtil; + +/** + * 微信第三方应用接口实现 + * + * @className WeixinComponentProxy + * @author jinyu(foxinmy@gmail.com) + * @date 2016年7月5日 + * @since JDK 1.6 + * @see com.foxinmy.weixin4j.mp.api.ComponentApi + * @see + * 公众号第三方应用 + */ +public class WeixinComponentProxy { + + /** + * 每个组件授权不一样 componentId - componentApi + */ + private Map componentMap; + /** + * 配置相关 + */ + private final Weixin4jSettings settings; + + /** + * 默认使用文件方式保存token、使用weixin4j.properties配置的账号信息 + */ + public WeixinComponentProxy() { + this(new Weixin4jSettings( + JSON.parseObject(Weixin4jConfigUtil.getValue("account"), WeixinMpAccount.class))); + } + + /** + * + * @param settings + * 配置信息 + */ + public WeixinComponentProxy(Weixin4jSettings settings) { + this.settings = settings; + List components = settings.getAccount().getComponents(); + this.componentMap = new HashMap(components.size()); + for (WeixinAccount component : components) { + this.componentMap.put(component.getId(), new ComponentApi( + new TicketManager(component.getId(), component.getSecret(), settings.getCacheStorager0()))); + } + this.componentMap.put(null, componentMap.get(components.get(0).getId())); + } + + /** + * 公众号信息 + * + * @return + */ + public WeixinMpAccount getWeixinAccount() { + return this.settings.getAccount(); + } + + /** + * 获取组接口对象(只关注第一个套件 + * + * @see com.foxinmy.weixin4j.mp.api.ComponentApi + * @return API实例 + */ + public ComponentApi component() { + return this.componentMap.get(null); + } + + /** + * 获取套件接口对象(多个套件 + * + * @see com.foxinmy.weixin4j.mp.api.ComponentApi + * @param componentId + * 组件ID + * @return API实例 + */ + public ComponentApi component(String componentId) { + return this.componentMap.get(componentId); + } + + /** + * 获取组件的预授权码 需先缓存ticket + * + * @param componentId + * 组件ID + * @return 预授权码 + * @see com.foxinmy.weixin4j.mp.api.ComponentApi + * @see com.foxinmy.weixin4j.mp.api.ComponentApi#getTicketManager() + * @see com.foxinmy.weixin4j.mp.api.ComponentApi#getPreCodeManager() + * @throws WeixinException + */ + public String getPreComponentTicket(String componentId) throws WeixinException { + Token token = component(componentId).getTicketManager().getTicket(); + if (token == null || StringUtil.isBlank(token.getAccessToken())) { + throw new WeixinException("maybe oauth first?"); + } + return token.getAccessToken(); + } + + /** + * 缓存组件ticket + * + * @param componentId + * 组件ID + * @param componentTicket + * 组件ticket内容 + * @throws WeixinException + */ + public void cacheTicket(String componentId, String componentTicket) throws WeixinException { + component(componentId).getTicketManager().cachingTicket(componentTicket); + } + + /** + * 应用组件授权 需先缓存ticket + * + * @see {@link #getComponentAuthorizeURL(String, String,String)} + * @param componentId + * 组件ID + * @see {@link #cacheTicket(String, String)} + * @return 请求授权的URL + * @throws WeixinException + */ + public String getComponentAuthorizeURL(String componentId) throws WeixinException { + String redirectUri = Weixin4jConfigUtil.getValue("component.oauth.redirect.uri"); + return getComponentAuthorizeURL(componentId, redirectUri, "state"); + } + + /** + * 应用组件授权 需先缓存ticket + * + * @param componentId + * 组件ID + * @param redirectUri + * 授权后重定向url + * @param state + * 回调后原样返回 + * @see com.foxinmy.weixin4j.mp.api.ComponentApi + * @see com.foxinmy.weixin4j.mp.api.ComponentApi#getTicketManager() + * @see com.foxinmy.weixin4j.mp.api.ComponentApi#getPreCodeManager() + * @return 请求授权的URL + * @throws WeixinException + */ + public String getComponentAuthorizeURL(String componentId, String redirectUri, String state) + throws WeixinException { + try { + return String.format(URLConsts.COMPONENT_OAUTH_URL, componentId, getPreComponentTicket(componentId), + URLEncoder.encode(redirectUri, Consts.UTF_8.name()), state); + } catch (UnsupportedEncodingException e) { + ; + } + return ""; + } + + /** + * 创建WeixinProxy对象 + * + * @param componentId + * 组件ID + * @param authAppId + * 已授权的appid + * @see com.foxinmy.weixin4j.mp.WeixinProxy + * @return + */ + public WeixinProxy getWeixinProxy(String componentId, String authAppId) { + return new WeixinProxy(component(componentId).getRefreshTokenManager(authAppId), + component(componentId).getTokenManager()); + } + + public final static String VERSION = "1.7.0"; +} 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 be9d3219..d285875c 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 @@ -63,7 +63,7 @@ public class ComponentApi extends MpApi { /** * 应用组件token * - * @return + * @return 应用组件的token管理 */ public TokenManager getTokenManager() { return this.tokenManager; @@ -72,7 +72,7 @@ public class ComponentApi extends MpApi { /** * 应用组件ticket * - * @return + * @return 应用组件的ticket管理 */ public TicketManager getTicketManager() { return this.ticketManager; @@ -81,7 +81,7 @@ public class ComponentApi extends MpApi { /** * 应用组件预授权码 * - * @return + * @return 应用组件的precode管理 */ public TokenManager getPreCodeManager() { return this.preCodeManager; @@ -93,7 +93,7 @@ public class ComponentApi extends MpApi { * * @param authAppId * 授权方appid - * @return + * @return 应用组件的perticket管理 */ public PerTicketManager getRefreshTokenManager(String authAppId) { return new PerTicketManager(authAppId, ticketManager.getThirdId(), diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/WeixinMpAccount.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/WeixinMpAccount.java new file mode 100644 index 00000000..8c6a94e7 --- /dev/null +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/WeixinMpAccount.java @@ -0,0 +1,54 @@ +package com.foxinmy.weixin4j.mp.model; + +import java.util.List; + +import com.alibaba.fastjson.annotation.JSONCreator; +import com.alibaba.fastjson.annotation.JSONField; +import com.foxinmy.weixin4j.model.WeixinAccount; + +/** + * 微信公众号信息 + * + * @className WeixinMpAccount + * @author jinyu + * @date Jul 6, 2016 + * @since JDK 1.8 + * @see + */ +public class WeixinMpAccount extends WeixinAccount { + + private static final long serialVersionUID = 3689999353867189585L; + /** + * 多个应用组件信息 + */ + private List components; + + /** + * + * @param appId + * 应用组件ID 必填 + * @param appSecret + * 应用组件密钥 使用普通接口(WeixinProxy对象)必须填写 + * @param components + * 应用组件集合 使用套件接口(WeixinSuiteProxy#SuiteApi)必须填写 + */ + @JSONCreator + public WeixinMpAccount(@JSONField(name = "id") String appId, @JSONField(name = "secret") String appSecret, + @JSONField(name = "components") List components) { + super(appId, appSecret); + this.components = components; + } + + public List getComponents() { + return components; + } + + public WeixinAccount[] componentsToArray() { + return components != null ? components.toArray(new WeixinAccount[components.size()]) : null; + } + + @Override + public String toString() { + return "WeixinMpAccount [" + super.toString() + ", components=" + components + "]"; + } +} 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 8588659b..8d371d04 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,15 @@ 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 */ - 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 */ @@ -36,4 +33,9 @@ public final class URLConsts { */ public static final String TOKEN_COMPONENT_URL = BASE_URL + "/component/api_authorizer_token?component_access_token=%s"; + /** + * 开放平台oauth授权的url + */ + public static final String COMPONENT_OAUTH_URL = BASE_URL + + "/componentloginpage?component_appid=%s&pre_auth_code=%s&redirect_uri=%s"; } diff --git a/weixin4j-mp/src/main/resources/weixin4j.properties b/weixin4j-mp/src/main/resources/weixin4j.properties index 09a197d4..6aae84f2 100644 --- a/weixin4j-mp/src/main/resources/weixin4j.properties +++ b/weixin4j-mp/src/main/resources/weixin4j.properties @@ -2,6 +2,7 @@ # \u516c\u4f17\u53f7\u4fe1\u606f \u8bf7\u6309\u9700\u586b\u5199 weixin4j.account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\ +"components":[{"id":"\u5e94\u7528\u7ec4\u4ef6\u7684id","secret":"\u5e94\u7528\u7ec4\u4ef6\u7684secret"}],\ "mchId":"\u5fae\u4fe1\u5546\u6237\u53f7 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\ "certificateKey":"\u52a0\u8f7d\u652f\u4ed8\u8bc1\u4e66\u6587\u4ef6\u7684\u5bc6\u7801 \u5982\u679c\u4e0d\u586b\u5199\u5219\u9ed8\u8ba4\u83b7\u53d6mchId\u4f5c\u4e3a\u5bc6\u7801",\ "paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"} @@ -17,4 +18,7 @@ weixin4j.tmpdir= weixin4j.certificate.file=/tmp/weixin4j/xxxxx.p12 # \u7528\u6237oauth\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199) -weixin4j.user.oauth.redirect.uri= \ No newline at end of file +weixin4j.user.oauth.redirect.uri= + +# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528ComponentApi\u65f6\u586b\u5199) +weixin4j.component.oauth.redirect.uri= \ No newline at end of file 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 e25849d9..07b57a02 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 @@ -55,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))); } /** @@ -71,18 +71,15 @@ 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()); } } @@ -119,16 +116,17 @@ public class WeixinSuiteProxy { } /** - * 获取套件的预授权码 + * 获取套件的预授权码 需先缓存ticket * * @param suiteId * 套件ID * @return 预授权码 * @see com.foxinmy.weixin4j.qy.api.SuiteApi + * @see com.foxinmy.weixin4j.qy.api.SuiteApi#getTicketManager() * @see com.foxinmy.weixin4j.qy.api.SuiteApi#getPreCodeManager() * @throws WeixinException */ - public String preSuiteTicket(String suiteId) throws WeixinException { + public String getPreSuiteTicket(String suiteId) throws WeixinException { Token token = suite(suiteId).getTicketManager().getTicket(); if (token == null || StringUtil.isBlank(token.getAccessToken())) { throw new WeixinException("maybe oauth first?"); @@ -137,7 +135,7 @@ public class WeixinSuiteProxy { } /** - * 缓存套件ticket(多个套件 + * 缓存套件ticket * * @param suiteId * 套件ID @@ -148,8 +146,7 @@ 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); } @@ -164,8 +161,7 @@ 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"); } @@ -185,11 +181,9 @@ 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, getPreSuiteTicket(suiteId), URLEncoder.encode(redirectUri, Consts.UTF_8.name()), state); } catch (UnsupportedEncodingException e) { ; @@ -231,8 +225,7 @@ 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); } @@ -247,8 +240,7 @@ public class WeixinSuiteProxy { * @return */ public WeixinProxy getWeixinProxy(String suiteId, String authCorpId) { - return new WeixinProxy(suite(suiteId).getPerTicketManager(authCorpId), - suite(suiteId).getTokenManager()); + 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 4bc80fd6..cfb6db60 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 @@ -59,7 +59,7 @@ public class SuiteApi extends QyApi { /** * 应用套件token * - * @return + * @return 应用套件的token管理 */ public TokenManager getTokenManager() { return this.tokenManager; @@ -68,7 +68,7 @@ public class SuiteApi extends QyApi { /** * 应用套件ticket * - * @return + * @return 应用套件的ticket管理 */ public TicketManager getTicketManager() { return this.ticketManager; @@ -77,7 +77,7 @@ public class SuiteApi extends QyApi { /** * 应用套件预授权码 * - * @return + * @return 应用套件的precode管理 */ public TokenManager getPreCodeManager() { return this.preCodeManager; @@ -88,7 +88,7 @@ public class SuiteApi extends QyApi { * * @param authCorpid * 授权方corpid - * @return + * @return 应用套件的preticket管理 */ public PerTicketManager getPerTicketManager(String authCorpId) { return new PerTicketManager(authCorpId, ticketManager.getThirdId(), diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/WeixinQyAccount.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/WeixinQyAccount.java index 9794eb4b..6f4c23cf 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/WeixinQyAccount.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/model/WeixinQyAccount.java @@ -77,7 +77,7 @@ public class WeixinQyAccount extends WeixinAccount { @Override public String toString() { - return "WeixinQyAccount [" + super.toString() + ", suiteAccounts=" + return "WeixinQyAccount [" + super.toString() + ", suites=" + suites + ", providerSecret=" + providerSecret + ", chatSecret=" + chatSecret + "]"; } diff --git a/weixin4j-qy/src/main/resources/weixin4j.properties b/weixin4j-qy/src/main/resources/weixin4j.properties index fb47608e..e4a403fd 100644 --- a/weixin4j-qy/src/main/resources/weixin4j.properties +++ b/weixin4j-qy/src/main/resources/weixin4j.properties @@ -25,5 +25,5 @@ weixin4j.user.oauth.redirect.uri= # \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u63d0\u4f9b\u5546\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199) weixin4j.third.oauth.redirect.uri= -# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u5e94\u7528\u5957\u4ef6\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199) +# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u5e94\u7528\u5957\u4ef6\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528SuiteApi\u65f6\u586b\u5199) weixin4j.suite.oauth.redirect.uri= \ No newline at end of file