From 6358d2e932187484889d9cc46d143069b8229663 Mon Sep 17 00:00:00 2001 From: acezuo Date: Sun, 4 Feb 2018 01:33:25 +0800 Subject: [PATCH 1/4] support wechat oauth --- README.md | 1 + .../com/github/scribejava/apis/WechatApi.java | 105 ++++++++++++++++++ .../apis/service/WechatService.java | 66 +++++++++++ .../apis/wechat/WechatOAuth2AccessToken.java | 42 +++++++ .../WechatOAuth2AccessTokenErrorResponse.java | 64 +++++++++++ .../WechatOAuth2AccessTokenJsonExtractor.java | 60 ++++++++++ .../apis/wechat/WechatOAuth2Constants.java | 20 ++++ .../apis/examples/WechatExample.java | 82 ++++++++++++++ 8 files changed, 440 insertions(+) create mode 100644 scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java create mode 100644 scribejava-apis/src/main/java/com/github/scribejava/apis/service/WechatService.java create mode 100644 scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessToken.java create mode 100644 scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenErrorResponse.java create mode 100644 scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenJsonExtractor.java create mode 100644 scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2Constants.java create mode 100644 scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java diff --git a/README.md b/README.md index 7359b47da..3690cb49d 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ ScribeJava support out-of-box several HTTP clients: * XING (https://www.xing.com/) * Yahoo (https://www.yahoo.com/) * Misfit (http://misfit.com/) +* WeChat (http://www.wechat.com/) * check the [examples folder](https://github.com/scribejava/scribejava/tree/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples) ### Small and modular diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java new file mode 100644 index 000000000..3872a4dcb --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java @@ -0,0 +1,105 @@ +package com.github.scribejava.apis; + +import com.github.scribejava.apis.service.WechatService; +import com.github.scribejava.apis.wechat.WechatOAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.builder.api.OAuth2SignatureType; +import com.github.scribejava.core.model.OAuthConfig; +import com.github.scribejava.core.model.ParameterList; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.util.Arrays; +import java.util.Map; + +import static com.github.scribejava.apis.wechat.WechatOAuth2Constants.*; + +/** + * http://www.wechat.com/ https://mp.weixin.qq.com/ + */ +public class WechatApi extends DefaultApi20 { + + protected WechatApi() { + } + + private static class InstanceHolder { + private static final WechatApi INSTANCE = new WechatApi(); + } + + public static WechatApi instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public String getAccessTokenEndpoint() { + return ACCESS_TOKEN_ENDPOINT_URL; + } + + @Override + public String getRefreshTokenEndpoint() { + return REFRESH_TOKEN_ENDPOINT_URL; + } + + @Override + public WechatOAuth2AccessTokenJsonExtractor getAccessTokenExtractor() { + return WechatOAuth2AccessTokenJsonExtractor.instance(); + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.GET; + } + + /** + * Reference https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 + * The authorization provided by WeChat does not fully reference the oauth2.0. + * For example, the parameter name is not the same, and the parameter order requirements. + * so I have to override this method to meet the requirements of it. + */ + @Override + public String getAuthorizationUrl(OAuthConfig config, Map additionalParams) { + final ParameterList parameters = new ParameterList(additionalParams); + + parameters.add(CLIENT_ID, config.getApiKey()); + + final String callback = config.getCallback(); + if (callback == null) { + throw new IllegalArgumentException("Missing required parameter 'redirect_uri'."); + } + parameters.add(REDIRECT_URI, callback); + + final String responseType = config.getResponseType(); + if (!CODE_RESPONSE_TYPE.equals(responseType)) { + throw new IllegalArgumentException("Parameter response_type must be 'code'."); + } + parameters.add(RESPONSE_TYPE, config.getResponseType()); + + final String scope = config.getScope(); + if (scope == null || Arrays.binarySearch(SCOPE_VALUES, scope) < 0) { + throw new IllegalArgumentException("Parameter scope can only be 'snsapi_base' or 'snsapi_userinfo'."); + } + parameters.add(SCOPE, scope); + + final String state = config.getState(); + if (state != null) { + parameters.add(STATE, state); + } + + return parameters.appendTo(getAuthorizationBaseUrl()).concat("#wechat_redirect"); + } + + @Override + public OAuth20Service createService(OAuthConfig config) { + return new WechatService(this, config); + } + + @Override + public OAuth2SignatureType getSignatureType() { + return OAuth2SignatureType.BEARER_URI_QUERY_PARAMETER; + } + + @Override + protected String getAuthorizationBaseUrl() { + return AUTHORIZE_URL; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/service/WechatService.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/service/WechatService.java new file mode 100644 index 000000000..e58b9e620 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/service/WechatService.java @@ -0,0 +1,66 @@ +package com.github.scribejava.apis.service; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.model.OAuthConfig; +import com.github.scribejava.core.model.OAuthConstants; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.util.Map; + +import static com.github.scribejava.apis.wechat.WechatOAuth2Constants.*; + + +public class WechatService extends OAuth20Service { + + public WechatService(DefaultApi20 api, OAuthConfig config) { + super(api, config); + } + + /** + * The reason to override this method is the same as + * {@link com.github.scribejava.apis.WechatApi#getAuthorizationUrl(OAuthConfig, Map)} + */ + @Override + protected OAuthRequest createAccessTokenRequest(String code) { + final OAuthRequest request = new OAuthRequest(getApi().getAccessTokenVerb(), getApi().getAccessTokenEndpoint()); + final OAuthConfig config = getConfig(); + + request.addParameter(CLIENT_ID, config.getApiKey()); + request.addParameter(CLIENT_SECRET, config.getApiSecret()); + + request.addParameter(CODE, code); + request.addParameter(GRANT_TYPE, AUTHORIZATION_CODE); + + return request; + } + + /** + * The reason to override this method is the same as + * {@link com.github.scribejava.apis.WechatApi#getAuthorizationUrl(OAuthConfig, Map)} + */ + @Override + protected OAuthRequest createRefreshTokenRequest(String refreshToken) { + if (refreshToken == null || refreshToken.isEmpty()) { + throw new IllegalArgumentException("The refreshToken cannot be null or empty"); + } + final OAuthRequest request = new OAuthRequest(getApi().getAccessTokenVerb(), getApi().getRefreshTokenEndpoint()); + + request.addParameter(CLIENT_ID, getConfig().getApiKey()); + + request.addParameter(OAuthConstants.GRANT_TYPE, REFRESH_TOKEN); + request.addParameter(REFRESH_TOKEN, refreshToken); + + return request; + } + + @Override + protected OAuthRequest createAccessTokenPasswordGrantRequest(String username, String password) { + throw new UnsupportedOperationException("WeChat doesn't support Resource Owner Password Credentials Grant"); + } + + @Override + protected OAuthRequest createAccessTokenClientCredentialsGrantRequest() { + throw new UnsupportedOperationException("WeChat doesn't support Client Credentials Grant"); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessToken.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessToken.java new file mode 100644 index 000000000..2b5ffa587 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessToken.java @@ -0,0 +1,42 @@ +package com.github.scribejava.apis.wechat; + +import com.github.scribejava.core.model.OAuth2AccessToken; + +public class WechatOAuth2AccessToken extends OAuth2AccessToken { + + private final String openid; + + public WechatOAuth2AccessToken(String accessToken, Integer expiresIn, String refreshToken, String scope, String openid, String response) { + super(accessToken, null, expiresIn, refreshToken, scope, response); + this.openid = openid; + } + + public String getOpenid() { + return openid; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof WechatOAuth2AccessToken)) { + return false; + } + if (!super.equals(o)) { + return false; + } + + WechatOAuth2AccessToken that = (WechatOAuth2AccessToken) o; + + return openid.equals(that.openid); + + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + openid.hashCode(); + return result; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenErrorResponse.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenErrorResponse.java new file mode 100644 index 000000000..ec000ddbb --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenErrorResponse.java @@ -0,0 +1,64 @@ +package com.github.scribejava.apis.wechat; + +import com.github.scribejava.core.exceptions.OAuthException; + +public class WechatOAuth2AccessTokenErrorResponse extends OAuthException { + + private String errcode; + + private String errmsg; + + private String rawResponse; + + public WechatOAuth2AccessTokenErrorResponse(String message) { + super(message); + } + + public WechatOAuth2AccessTokenErrorResponse(String message, String errcode, String errmsg, String rawResponse) { + super(message); + this.errcode = errcode; + this.errmsg = errmsg; + this.rawResponse = rawResponse; + } + + public String getErrcode() { + return errcode; + } + + public String getErrmsg() { + return errmsg; + } + + public String getRawResponse() { + return rawResponse; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + WechatOAuth2AccessTokenErrorResponse that = (WechatOAuth2AccessTokenErrorResponse) o; + + if (errcode != null ? !errcode.equals(that.errcode) : that.errcode != null) { + return false; + } + if (errmsg != null ? !errmsg.equals(that.errmsg) : that.errmsg != null) { + return false; + } + return rawResponse != null ? rawResponse.equals(that.rawResponse) : that.rawResponse == null; + + } + + @Override + public int hashCode() { + int result = errcode != null ? errcode.hashCode() : 0; + result = 31 * result + (errmsg != null ? errmsg.hashCode() : 0); + result = 31 * result + (rawResponse != null ? rawResponse.hashCode() : 0); + return result; + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenJsonExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenJsonExtractor.java new file mode 100644 index 000000000..a96730898 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenJsonExtractor.java @@ -0,0 +1,60 @@ +package com.github.scribejava.apis.wechat; + +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.utils.Preconditions; + +import java.io.IOException; +import java.util.regex.Pattern; + +public class WechatOAuth2AccessTokenJsonExtractor extends OAuth2AccessTokenJsonExtractor { + + private static final Pattern ERRCODE_REGEX_PATTERN = Pattern.compile("\"errcode\"\\s*:\\s*([0-9]+)"); + private static final Pattern ERRMSG_REGEX_PATTERN = Pattern.compile("\"errmsg\"\\s*:\\s*\"([\\S\\s]*?)\""); + private static final Pattern OPENID_REGEX_PATTERN = Pattern.compile("\"openid\"\\s*:\\s*\"(\\S*?)\""); + + protected WechatOAuth2AccessTokenJsonExtractor() { + } + + private static class InstanceHolder { + private static final WechatOAuth2AccessTokenJsonExtractor INSTANCE = new WechatOAuth2AccessTokenJsonExtractor(); + } + + public static WechatOAuth2AccessTokenJsonExtractor instance() { + return InstanceHolder.INSTANCE; + } + + @Override + public OAuth2AccessToken extract(Response response) throws IOException { + checkError(response.getBody()); + return super.extract(response); + } + + /** + * Try to extract the error information in response. If 'errcode' or 'errmsg' is found, + * {@link WechatOAuth2AccessTokenErrorResponse} will be thrown, otherwise execute super method. + */ + private void checkError(final String response) { + if (!Preconditions.hasText(response)) { + return; + } + final String errcode = extractParameter(response, ERRCODE_REGEX_PATTERN, false); + final String errmsg = extractParameter(response, ERRMSG_REGEX_PATTERN, false); + + if (errcode != null || errmsg != null) { + throw new WechatOAuth2AccessTokenErrorResponse("Obtaining WeChat OAuth2 access_token failed.", errcode, errmsg, response); + } + } + + @Override + public void generateError(String response) { + throw new WechatOAuth2AccessTokenErrorResponse("An unknown failure occurred while obtaining the WeChat OAuth2 access_token."); + } + + @Override + protected WechatOAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, String scope, String response) { + final String openid = extractParameter(response, OPENID_REGEX_PATTERN, true); + return new WechatOAuth2AccessToken(accessToken, expiresIn, refreshToken, scope, openid, response); + } +} diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2Constants.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2Constants.java new file mode 100644 index 000000000..b843d47c1 --- /dev/null +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2Constants.java @@ -0,0 +1,20 @@ +package com.github.scribejava.apis.wechat; + +import com.github.scribejava.core.model.OAuthConstants; + +public interface WechatOAuth2Constants extends OAuthConstants { + + String ACCESS_TOKEN_ENDPOINT_URL = "https://api.weixin.qq.com/sns/oauth2/access_token"; + + String REFRESH_TOKEN_ENDPOINT_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token"; + + String AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize"; + + String CODE_RESPONSE_TYPE = "code"; + + String[] SCOPE_VALUES = new String[]{"snsapi_base", "snsapi_userinfo "}; + + String CLIENT_ID = "appid"; + + String CLIENT_SECRET = "secret"; +} diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java new file mode 100644 index 000000000..bbbcd369a --- /dev/null +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java @@ -0,0 +1,82 @@ +package com.github.scribejava.apis.examples; + +import com.github.scribejava.apis.WechatApi; +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuthRequest; +import com.github.scribejava.core.model.Response; +import com.github.scribejava.core.model.Verb; +import com.github.scribejava.core.oauth.OAuth20Service; + +import java.io.IOException; +import java.util.Random; +import java.util.Scanner; +import java.util.concurrent.ExecutionException; + +public class WechatExample { + + private static final String NETWORK_NAME = "WeChat"; + private static final String PROTECTED_RESOURCE_URL = "https://graph.facebook.com/v2.11/me"; + + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { + // Replace these with your client id and secret + final String clientId = "your client id"; + final String clientSecret = "your client secret"; + final String secretState = "secret" + new Random().nextInt(999_999); + final OAuth20Service service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .scope("snsapi_base") + .state(secretState) + .callback("http://www.example.com/oauth_callback/") + .build(WechatApi.instance()); + + final Scanner in = new Scanner(System.in, "UTF-8"); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth2 Workflow ==="); + System.out.println(); + + // Obtain the Authorization URL + System.out.println("Fetching the Authorization URL..."); + final String authorizationUrl = service.getAuthorizationUrl(); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize ScribeJava here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + final String code = in.nextLine(); + System.out.println(); + + System.out.println("And paste the state from server here. We have set 'secretState'='" + secretState + "'."); + System.out.print(">>"); + final String value = in.nextLine(); + if (secretState.equals(value)) { + System.out.println("State value does match!"); + } else { + System.out.println("Ooops, state value does not match!"); + System.out.println("Expected = " + secretState); + System.out.println("Got = " + value); + System.out.println(); + } + + // Trade the Request Token and Verfier for the Access Token + System.out.println("Trading the Request Token for an Access Token..."); + final OAuth2AccessToken accessToken = service.getAccessToken(code); + System.out.println("Got the Access Token!"); + System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + service.signRequest(accessToken, request); + final Response response = service.execute(request); + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with ScribeJava! :)"); + + } +} From 4b685f651b8916b0b503d766ca79e2965e0c3826 Mon Sep 17 00:00:00 2001 From: acezuo Date: Sun, 4 Feb 2018 01:36:31 +0800 Subject: [PATCH 2/4] testing --- .../com/github/scribejava/apis/examples/WechatExample.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java index bbbcd369a..e8adb1f97 100644 --- a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java @@ -1,6 +1,7 @@ package com.github.scribejava.apis.examples; import com.github.scribejava.apis.WechatApi; +import com.github.scribejava.apis.wechat.WechatOAuth2AccessToken; import com.github.scribejava.core.builder.ServiceBuilder; import com.github.scribejava.core.model.OAuth2AccessToken; import com.github.scribejava.core.model.OAuthRequest; @@ -16,7 +17,7 @@ public class WechatExample { private static final String NETWORK_NAME = "WeChat"; - private static final String PROTECTED_RESOURCE_URL = "https://graph.facebook.com/v2.11/me"; + private static final String PROTECTED_RESOURCE_URL = "https://api.weixin.qq.com/sns/userinfo"; public static void main(String... args) throws IOException, InterruptedException, ExecutionException { // Replace these with your client id and secret @@ -60,7 +61,7 @@ public static void main(String... args) throws IOException, InterruptedException // Trade the Request Token and Verfier for the Access Token System.out.println("Trading the Request Token for an Access Token..."); - final OAuth2AccessToken accessToken = service.getAccessToken(code); + final WechatOAuth2AccessToken accessToken = (WechatOAuth2AccessToken) service.getAccessToken(code); System.out.println("Got the Access Token!"); System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')"); System.out.println(); @@ -68,6 +69,7 @@ public static void main(String... args) throws IOException, InterruptedException // Now let's go and ask for a protected resource! System.out.println("Now we're going to access a protected resource..."); final OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + request.addParameter("openid", accessToken.getOpenid()); service.signRequest(accessToken, request); final Response response = service.execute(request); System.out.println("Got it! Lets see what we found..."); From ced781acc0ef27cd1acb43fd563200b675326c94 Mon Sep 17 00:00:00 2001 From: acezuo Date: Sun, 4 Feb 2018 01:41:00 +0800 Subject: [PATCH 3/4] update comments --- .../src/main/java/com/github/scribejava/apis/WechatApi.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java index 3872a4dcb..f20d1ca0c 100644 --- a/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java @@ -14,9 +14,6 @@ import static com.github.scribejava.apis.wechat.WechatOAuth2Constants.*; -/** - * http://www.wechat.com/ https://mp.weixin.qq.com/ - */ public class WechatApi extends DefaultApi20 { protected WechatApi() { From 6d57c1299d83e1e2134a3c3021e0396f4bd11aa9 Mon Sep 17 00:00:00 2001 From: acezuo Date: Sun, 4 Feb 2018 15:22:20 +0800 Subject: [PATCH 4/4] checkstyle & javadoc --- .../com/github/scribejava/apis/WechatApi.java | 25 +++++++++---------- .../apis/service/WechatService.java | 20 +++++++-------- .../apis/wechat/WechatOAuth2AccessToken.java | 5 ++-- .../WechatOAuth2AccessTokenErrorResponse.java | 2 +- .../WechatOAuth2AccessTokenJsonExtractor.java | 9 ++++--- .../apis/examples/WechatExample.java | 6 +++-- 6 files changed, 36 insertions(+), 31 deletions(-) diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java index f20d1ca0c..551d59f77 100644 --- a/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/WechatApi.java @@ -2,6 +2,7 @@ import com.github.scribejava.apis.service.WechatService; import com.github.scribejava.apis.wechat.WechatOAuth2AccessTokenJsonExtractor; +import com.github.scribejava.apis.wechat.WechatOAuth2Constants; import com.github.scribejava.core.builder.api.DefaultApi20; import com.github.scribejava.core.builder.api.OAuth2SignatureType; import com.github.scribejava.core.model.OAuthConfig; @@ -12,8 +13,6 @@ import java.util.Arrays; import java.util.Map; -import static com.github.scribejava.apis.wechat.WechatOAuth2Constants.*; - public class WechatApi extends DefaultApi20 { protected WechatApi() { @@ -29,12 +28,12 @@ public static WechatApi instance() { @Override public String getAccessTokenEndpoint() { - return ACCESS_TOKEN_ENDPOINT_URL; + return WechatOAuth2Constants.ACCESS_TOKEN_ENDPOINT_URL; } @Override public String getRefreshTokenEndpoint() { - return REFRESH_TOKEN_ENDPOINT_URL; + return WechatOAuth2Constants.REFRESH_TOKEN_ENDPOINT_URL; } @Override @@ -48,7 +47,7 @@ public Verb getAccessTokenVerb() { } /** - * Reference https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 + * @see WeChat * The authorization provided by WeChat does not fully reference the oauth2.0. * For example, the parameter name is not the same, and the parameter order requirements. * so I have to override this method to meet the requirements of it. @@ -57,29 +56,29 @@ public Verb getAccessTokenVerb() { public String getAuthorizationUrl(OAuthConfig config, Map additionalParams) { final ParameterList parameters = new ParameterList(additionalParams); - parameters.add(CLIENT_ID, config.getApiKey()); + parameters.add(WechatOAuth2Constants.CLIENT_ID, config.getApiKey()); final String callback = config.getCallback(); if (callback == null) { throw new IllegalArgumentException("Missing required parameter 'redirect_uri'."); } - parameters.add(REDIRECT_URI, callback); + parameters.add(WechatOAuth2Constants.REDIRECT_URI, callback); final String responseType = config.getResponseType(); - if (!CODE_RESPONSE_TYPE.equals(responseType)) { + if (!WechatOAuth2Constants.CODE_RESPONSE_TYPE.equals(responseType)) { throw new IllegalArgumentException("Parameter response_type must be 'code'."); } - parameters.add(RESPONSE_TYPE, config.getResponseType()); + parameters.add(WechatOAuth2Constants.RESPONSE_TYPE, config.getResponseType()); final String scope = config.getScope(); - if (scope == null || Arrays.binarySearch(SCOPE_VALUES, scope) < 0) { + if (scope == null || Arrays.binarySearch(WechatOAuth2Constants.SCOPE_VALUES, scope) < 0) { throw new IllegalArgumentException("Parameter scope can only be 'snsapi_base' or 'snsapi_userinfo'."); } - parameters.add(SCOPE, scope); + parameters.add(WechatOAuth2Constants.SCOPE, scope); final String state = config.getState(); if (state != null) { - parameters.add(STATE, state); + parameters.add(WechatOAuth2Constants.STATE, state); } return parameters.appendTo(getAuthorizationBaseUrl()).concat("#wechat_redirect"); @@ -97,6 +96,6 @@ public OAuth2SignatureType getSignatureType() { @Override protected String getAuthorizationBaseUrl() { - return AUTHORIZE_URL; + return WechatOAuth2Constants.AUTHORIZE_URL; } } diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/service/WechatService.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/service/WechatService.java index e58b9e620..ac9389180 100644 --- a/scribejava-apis/src/main/java/com/github/scribejava/apis/service/WechatService.java +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/service/WechatService.java @@ -1,5 +1,6 @@ package com.github.scribejava.apis.service; +import com.github.scribejava.apis.wechat.WechatOAuth2Constants; import com.github.scribejava.core.builder.api.DefaultApi20; import com.github.scribejava.core.model.OAuthConfig; import com.github.scribejava.core.model.OAuthConstants; @@ -8,8 +9,6 @@ import java.util.Map; -import static com.github.scribejava.apis.wechat.WechatOAuth2Constants.*; - public class WechatService extends OAuth20Service { @@ -26,11 +25,11 @@ protected OAuthRequest createAccessTokenRequest(String code) { final OAuthRequest request = new OAuthRequest(getApi().getAccessTokenVerb(), getApi().getAccessTokenEndpoint()); final OAuthConfig config = getConfig(); - request.addParameter(CLIENT_ID, config.getApiKey()); - request.addParameter(CLIENT_SECRET, config.getApiSecret()); + request.addParameter(WechatOAuth2Constants.CLIENT_ID, config.getApiKey()); + request.addParameter(WechatOAuth2Constants.CLIENT_SECRET, config.getApiSecret()); - request.addParameter(CODE, code); - request.addParameter(GRANT_TYPE, AUTHORIZATION_CODE); + request.addParameter(WechatOAuth2Constants.CODE, code); + request.addParameter(WechatOAuth2Constants.GRANT_TYPE, WechatOAuth2Constants.AUTHORIZATION_CODE); return request; } @@ -44,12 +43,13 @@ protected OAuthRequest createRefreshTokenRequest(String refreshToken) { if (refreshToken == null || refreshToken.isEmpty()) { throw new IllegalArgumentException("The refreshToken cannot be null or empty"); } - final OAuthRequest request = new OAuthRequest(getApi().getAccessTokenVerb(), getApi().getRefreshTokenEndpoint()); + final OAuthRequest request = new OAuthRequest(getApi().getAccessTokenVerb(), + getApi().getRefreshTokenEndpoint()); - request.addParameter(CLIENT_ID, getConfig().getApiKey()); + request.addParameter(WechatOAuth2Constants.CLIENT_ID, getConfig().getApiKey()); - request.addParameter(OAuthConstants.GRANT_TYPE, REFRESH_TOKEN); - request.addParameter(REFRESH_TOKEN, refreshToken); + request.addParameter(OAuthConstants.GRANT_TYPE, WechatOAuth2Constants.REFRESH_TOKEN); + request.addParameter(WechatOAuth2Constants.REFRESH_TOKEN, refreshToken); return request; } diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessToken.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessToken.java index 2b5ffa587..750c4759c 100644 --- a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessToken.java +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessToken.java @@ -6,7 +6,8 @@ public class WechatOAuth2AccessToken extends OAuth2AccessToken { private final String openid; - public WechatOAuth2AccessToken(String accessToken, Integer expiresIn, String refreshToken, String scope, String openid, String response) { + public WechatOAuth2AccessToken(String accessToken, Integer expiresIn, String refreshToken, String scope, + String openid, String response) { super(accessToken, null, expiresIn, refreshToken, scope, response); this.openid = openid; } @@ -27,7 +28,7 @@ public boolean equals(Object o) { return false; } - WechatOAuth2AccessToken that = (WechatOAuth2AccessToken) o; + final WechatOAuth2AccessToken that = (WechatOAuth2AccessToken) o; return openid.equals(that.openid); diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenErrorResponse.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenErrorResponse.java index ec000ddbb..244709f30 100644 --- a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenErrorResponse.java +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenErrorResponse.java @@ -42,7 +42,7 @@ public boolean equals(Object o) { return false; } - WechatOAuth2AccessTokenErrorResponse that = (WechatOAuth2AccessTokenErrorResponse) o; + final WechatOAuth2AccessTokenErrorResponse that = (WechatOAuth2AccessTokenErrorResponse) o; if (errcode != null ? !errcode.equals(that.errcode) : that.errcode != null) { return false; diff --git a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenJsonExtractor.java b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenJsonExtractor.java index a96730898..05e9419b4 100644 --- a/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenJsonExtractor.java +++ b/scribejava-apis/src/main/java/com/github/scribejava/apis/wechat/WechatOAuth2AccessTokenJsonExtractor.java @@ -43,17 +43,20 @@ private void checkError(final String response) { final String errmsg = extractParameter(response, ERRMSG_REGEX_PATTERN, false); if (errcode != null || errmsg != null) { - throw new WechatOAuth2AccessTokenErrorResponse("Obtaining WeChat OAuth2 access_token failed.", errcode, errmsg, response); + throw new WechatOAuth2AccessTokenErrorResponse("Obtaining WeChat OAuth2 access_token failed.", + errcode, errmsg, response); } } @Override public void generateError(String response) { - throw new WechatOAuth2AccessTokenErrorResponse("An unknown failure occurred while obtaining the WeChat OAuth2 access_token."); + throw new WechatOAuth2AccessTokenErrorResponse("An unknown failure occurred" + + " while obtaining the WeChat OAuth2 access_token."); } @Override - protected WechatOAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, String refreshToken, String scope, String response) { + protected WechatOAuth2AccessToken createToken(String accessToken, String tokenType, Integer expiresIn, + String refreshToken, String scope, String response) { final String openid = extractParameter(response, OPENID_REGEX_PATTERN, true); return new WechatOAuth2AccessToken(accessToken, expiresIn, refreshToken, scope, openid, response); } diff --git a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java index e8adb1f97..c6b5303fe 100644 --- a/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java +++ b/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/WechatExample.java @@ -3,7 +3,6 @@ import com.github.scribejava.apis.WechatApi; import com.github.scribejava.apis.wechat.WechatOAuth2AccessToken; import com.github.scribejava.core.builder.ServiceBuilder; -import com.github.scribejava.core.model.OAuth2AccessToken; import com.github.scribejava.core.model.OAuthRequest; import com.github.scribejava.core.model.Response; import com.github.scribejava.core.model.Verb; @@ -19,6 +18,9 @@ public class WechatExample { private static final String NETWORK_NAME = "WeChat"; private static final String PROTECTED_RESOURCE_URL = "https://api.weixin.qq.com/sns/userinfo"; + private WechatExample() { + } + public static void main(String... args) throws IOException, InterruptedException, ExecutionException { // Replace these with your client id and secret final String clientId = "your client id"; @@ -28,7 +30,7 @@ public static void main(String... args) throws IOException, InterruptedException .apiSecret(clientSecret) .scope("snsapi_base") .state(secretState) - .callback("http://www.example.com/oauth_callback/") + .callback("http://www.example.com/oauth_callback") .build(WechatApi.instance()); final Scanner in = new Scanner(System.in, "UTF-8");