Browse Source

issue #39 添加oauth2的支持

master
Daniel Qian 10 years ago
parent
commit
7b92a14f1c
7 changed files with 273 additions and 0 deletions
  1. +8
    -0
      weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java
  2. +47
    -0
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/URIUtil.java
  3. +2
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java
  4. +10
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java
  5. +48
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
  6. +94
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java
  7. +64
    -0
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java

+ 8
- 0
weixin-java-common/src/main/java/me/chanjar/weixin/common/api/WxConsts.java View File

@@ -128,4 +128,12 @@ public class WxConsts {
/** 弹出地理位置选择器 */
public static final String LOCATION_SELECT = "location_select";

///////////////////////
// oauth2网页授权的scope
///////////////////////
/** 不弹出授权页面,直接跳转,只能获取用户openid */
public static final String OAUTH2_SCOPE_BASE = "snsapi_base";
/** 弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息 */
public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo";

}

+ 47
- 0
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/URIUtil.java View File

@@ -0,0 +1,47 @@
package me.chanjar.weixin.common.util.http;

import me.chanjar.weixin.common.util.StringUtils;

import java.io.UnsupportedEncodingException;

public class URIUtil {

private static final String ALLOWED_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()";

public static String encodeURIComponent(String input) {
if (StringUtils.isEmpty(input)) {
return input;
}

int l = input.length();
StringBuilder o = new StringBuilder(l * 3);
try {
for (int i = 0; i < l; i++) {
String e = input.substring(i, i + 1);
if (ALLOWED_CHARS.indexOf(e) == -1) {
byte[] b = e.getBytes("utf-8");
o.append(getHex(b));
continue;
}
o.append(e);
}
return o.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return input;
}

private static String getHex(byte buf[]) {
StringBuilder o = new StringBuilder(buf.length * 3);
for (int i = 0; i < buf.length; i++) {
int n = (int) buf[i] & 0xff;
o.append("%");
if (n < 0x10) {
o.append("0");
}
o.append(Long.toString(n, 16).toUpperCase());
}
return o.toString();
}
}

+ 2
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java View File

@@ -25,6 +25,8 @@ public interface WxMpConfigStorage {

public int getExpiresIn();

public String getOauth2redirectUrl();

public String getHttp_proxy_host();

public int getHttp_proxy_port();


+ 10
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java View File

@@ -20,6 +20,7 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
protected int http_proxy_port;
protected String http_proxy_username;
protected String http_proxy_password;
protected String oauth2redirectUrl;

public void updateAccessToken(WxAccessToken accessToken) {
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
@@ -78,6 +79,15 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
this.expiresIn = expiresIn;
}

@Override
public String getOauth2redirectUrl() {
return this.oauth2redirectUrl;
}

public void setOauth2redirectUrl(String oauth2redirectUrl) {
this.oauth2redirectUrl = oauth2redirectUrl;
}

public String getHttp_proxy_host() {
return http_proxy_host;
}


+ 48
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java View File

@@ -329,6 +329,54 @@ public interface WxMpService {
*/
WxMpSemanticQueryResult semanticQuery(WxMpSemanticQuery semanticQuery) throws WxErrorException;

/**
* <pre>
* 构造oauth2授权的url连接
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
* </pre>
* @param scope
* @param state
* @return code
*/
public String oauth2buildAuthorizationUrl(String scope, String state);

/**
* <pre>
* 用code换取oauth2的access token
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=网页授权获取用户基本信息
* </pre>
* @param code
* @return
*/
public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException;

/**
* <pre>
* 刷新oauth2的access token
* </pre>
* @param refreshToken
* @return
*/
public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException;

/**
* <pre>
* 用oauth2获取用户信息, 当前面引导授权时的scope是snsapi_userinfo的时候才可以
* </pre>
* @param oAuth2AccessToken
* @param lang zh_CN, zh_TW, en
*/
public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException;

/**
* <pre>
* 验证oauth2的access token是否有效
* </pre>
* @param oAuth2AccessToken
* @return
*/
public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken);

/**
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求
* @param url


+ 94
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java View File

@@ -27,11 +27,13 @@ import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import javax.print.DocFlavor;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -297,6 +299,98 @@ public class WxMpServiceImpl implements WxMpService {
return WxMpSemanticQueryResult.fromJson(responseContent);
}

@Override
public String oauth2buildAuthorizationUrl(String scope, String state) {
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?" ;
url += "appid=" + wxMpConfigStorage.getAppId();
url += "&redirect_uri=" + URIUtil.encodeURIComponent(wxMpConfigStorage.getOauth2redirectUrl());
url += "&response_type=code";
url += "&scope=" + scope;
if (state != null) {
url += "&state=" + state;
}
url += "#wechat_redirect";
return url;
}

@Override
public WxMpOAuth2AccessToken oauth2getAccessToken(String code) throws WxErrorException {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?";
url += "appid=" + wxMpConfigStorage.getAppId();
url += "&secret=" + wxMpConfigStorage.getSecret();
url += "&code=" + code;
url += "&grant_type=authorization_code";

try {
RequestExecutor<String, String> executor = new SimpleGetRequestExecutor();
String responseText = executor.execute(getHttpclient(), httpProxy, url, null);
return WxMpOAuth2AccessToken.fromJson(responseText);
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public WxMpOAuth2AccessToken oauth2refreshAccessToken(String refreshToken) throws WxErrorException {
String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?";
url += "appid=" + wxMpConfigStorage.getAppId();
url += "&grant_type=refresh_token";
url += "&refresh_token=" + refreshToken;

try {
RequestExecutor<String, String> executor = new SimpleGetRequestExecutor();
String responseText = executor.execute(getHttpclient(), httpProxy, url, null);
return WxMpOAuth2AccessToken.fromJson(responseText);
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public WxMpUser oauth2getUserInfo(WxMpOAuth2AccessToken oAuth2AccessToken, String lang) throws WxErrorException {
String url = "https://api.weixin.qq.com/sns/userinfo?";
url += "access_token=" + oAuth2AccessToken.getAccessToken();
url += "&openid=" + oAuth2AccessToken.getOpenId();
if (lang == null) {
url += "&lang=zh_CN";
} else {
url += "&lang=" + lang;
}

try {
RequestExecutor<String, String> executor = new SimpleGetRequestExecutor();
String responseText = executor.execute(getHttpclient(), httpProxy, url, null);
return WxMpUser.fromJson(responseText);
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Override
public boolean oauth2validateAccessToken(WxMpOAuth2AccessToken oAuth2AccessToken) {
String url = "https://api.weixin.qq.com/sns/auth?";
url += "access_token=" + oAuth2AccessToken;
url += "&openid=" + oAuth2AccessToken.getOpenId();

try {
RequestExecutor<String, String> executor = new SimpleGetRequestExecutor();
executor.execute(getHttpclient(), httpProxy, url, null);
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (WxErrorException e) {
return false;
}
return true;
}

public String get(String url, String queryParam) throws WxErrorException {
return execute(new SimpleGetRequestExecutor(), url, queryParam);
}


+ 64
- 0
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/result/WxMpOAuth2AccessToken.java View File

@@ -0,0 +1,64 @@
package me.chanjar.weixin.mp.bean.result;

import me.chanjar.weixin.common.util.json.WxGsonBuilder;

/**
* Created by qianjia on 14/11/26.
*/
public class WxMpOAuth2AccessToken {

private String accessToken;

private int expiresIn = -1;

private String refreshToken;

private String openId;

private String scope;

public String getRefreshToken() {
return refreshToken;
}

public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}

public String getOpenId() {
return openId;
}

public void setOpenId(String openId) {
this.openId = openId;
}

public String getScope() {
return scope;
}

public void setScope(String scope) {
this.scope = scope;
}

public String getAccessToken() {
return accessToken;
}

public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}

public int getExpiresIn() {
return expiresIn;
}

public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}

public static WxMpOAuth2AccessToken fromJson(String json) {
return WxGsonBuilder.create().fromJson(json, WxMpOAuth2AccessToken.class);
}

}

Loading…
Cancel
Save