diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java index a6fd6317..46dd11f2 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java @@ -164,6 +164,12 @@ public class WxConsts { * 弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息 */ public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo"; + + /** + * 网页应用登录授权作用域 snsapi_login + */ + public static final String QRCONNECT_SCOPE_SNSAPI_LOGIN = "snsapi_login"; + /////////////////////// // 永久素材类型 /////////////////////// diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index 18df437f..503dd55b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -152,6 +152,20 @@ public interface WxMpService { */ WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException; + /** + *
+ * 构造第三方使用网站应用授权登录的url + * 详情请见: 网站应用微信登录开发指南 + * URL格式为:https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect + *+ * + * @param redirectURI 用户授权完成后的重定向链接,无需urlencode, 方法内会进行encode + * @param scope 应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可 + * @param state 非必填,用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 + * @return url + */ + String buildQrConnectUrl(String redirectURI, String scope, String state); + /** *
* 构造oauth2授权的url连接 diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java index cbbd1264..e08432b9 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImpl.java @@ -275,6 +275,23 @@ public class WxMpServiceImpl implements WxMpService { return url.toString(); } + @Override + public String buildQrConnectUrl(String redirectURI, String scope, + String state) { + StringBuilder url = new StringBuilder(); + url.append("https://open.weixin.qq.com/connect/qrconnect?"); + url.append("appid=").append(this.wxMpConfigStorage.getAppId()); + url.append("&redirect_uri=").append(URIUtil.encodeURIComponent(redirectURI)); + url.append("&response_type=code"); + url.append("&scope=").append(scope); + if (state != null) { + url.append("&state=").append(state); + } + + url.append("#wechat_redirect"); + return url.toString(); + } + private WxMpOAuth2AccessToken getOAuth2AccessToken(StringBuilder url) throws WxErrorException { try { RequestExecutorexecutor = new SimpleGetRequestExecutor(); diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java index 4980faca..4557c342 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/ApiTestModule.java @@ -44,6 +44,7 @@ public class ApiTestModule implements Module { private String openId; private String kfAccount; + private String qrconnectRedirectUrl; public String getOpenId() { return this.openId; @@ -66,6 +67,14 @@ public class ApiTestModule implements Module { this.kfAccount = kfAccount; } + public String getQrconnectRedirectUrl() { + return this.qrconnectRedirectUrl; + } + + public void setQrconnectRedirectUrl(String qrconnectRedirectUrl) { + this.qrconnectRedirectUrl = qrconnectRedirectUrl; + } + } } diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImplTest.java new file mode 100644 index 00000000..5791367b --- /dev/null +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpServiceImplTest.java @@ -0,0 +1,162 @@ +package me.chanjar.weixin.mp.api.impl; + +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import com.google.inject.Inject; + +import me.chanjar.weixin.common.api.WxConsts; +import me.chanjar.weixin.mp.api.ApiTestModule; +import me.chanjar.weixin.mp.api.ApiTestModule.WxXmlMpInMemoryConfigStorage; + +import org.testng.Assert; + +@Test +@Guice(modules = ApiTestModule.class) +public class WxMpServiceImplTest { + + @Inject + private WxMpServiceImpl wxService; + + @Test + public void testCheckSignature() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testGetAccessToken() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testGetAccessTokenBoolean() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testGetJsapiTicket() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testGetJsapiTicketBoolean() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testCreateJsapiSignature() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testCustomMessageSend() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testMassNewsUpload() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testMassVideoUpload() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testMassGroupMessageSend() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testMassOpenIdsMessageSend() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testMassMessagePreview() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testShortUrl() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testTemplateSend() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testSetIndustry() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testGetIndustry() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testSemanticQuery() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testOauth2buildAuthorizationUrl() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testBuildQrConnectUrl() { + String qrConnectUrl = this.wxService + .buildQrConnectUrl( + ((WxXmlMpInMemoryConfigStorage) this.wxService + .getWxMpConfigStorage()).getOauth2redirectUri(), + WxConsts.QRCONNECT_SCOPE_SNSAPI_LOGIN, null); + Assert.assertNotNull(qrConnectUrl); + System.out.println(qrConnectUrl); + } + + @Test + public void testOauth2getAccessToken() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testOauth2refreshAccessToken() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testOauth2getUserInfo() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testOauth2validateAccessToken() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testGetCallbackIP() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testGet() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testPost() { + Assert.fail("Not yet implemented"); + } + + @Test + public void testExecute() { + Assert.fail("Not yet implemented"); + } + +} diff --git a/weixin-java-mp/src/test/resources/test-config.sample.xml b/weixin-java-mp/src/test/resources/test-config.sample.xml index 1f79bea2..836b26c4 100644 --- a/weixin-java-mp/src/test/resources/test-config.sample.xml +++ b/weixin-java-mp/src/test/resources/test-config.sample.xml @@ -7,5 +7,6 @@ 可以不填写 某个加你公众号的用户的openId 网页授权获取用户信息回调地址 +网页应用授权登陆回调地址 完整客服账号,格式为:账号前缀@公众号微信号