|
|
@ -4,9 +4,8 @@ import cn.hutool.core.lang.Console; |
|
|
|
import cn.hutool.core.util.StrUtil; |
|
|
|
import cn.hutool.core.util.URLUtil; |
|
|
|
import cn.hutool.http.HttpRequest; |
|
|
|
import com.ccsens.opensource.wxconfigurer.bean.po.WxGzhAuthType; |
|
|
|
import com.ccsens.opensource.wxconfigurer.bean.po.WxGzhMenu; |
|
|
|
import com.ccsens.opensource.wxconfigurer.bean.po.WxAccessToken; |
|
|
|
import cn.hutool.http.HttpUtil; |
|
|
|
import com.ccsens.opensource.wxconfigurer.bean.po.*; |
|
|
|
import com.ccsens.opensource.wxconfigurer.exception.BaseException; |
|
|
|
import com.ccsens.opensource.wxconfigurer.exception.BusinessException; |
|
|
|
import com.ccsens.opensource.wxconfigurer.exception.WxException; |
|
|
@ -54,9 +53,12 @@ public class WxGzhUtil { |
|
|
|
= " https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%1$s"; |
|
|
|
private static final String URL_QUERY_MENU |
|
|
|
= "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=%1$s"; |
|
|
|
|
|
|
|
private static final String GZH_AUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%1$s&redirect_uri=%2$s&response_type=code&scope=%3$s&state=STATE#wechat_redirect"; |
|
|
|
|
|
|
|
private static final String GZH_AUTH_URL |
|
|
|
= "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%1$s&redirect_uri=%2$s&response_type=code&scope=%3$s&state=STATE#wechat_redirect"; |
|
|
|
private static final String URL_GET_OAUTH2_ACCESS_TOKEN |
|
|
|
= "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%1$s&secret=%2$s&code=%3$s&grant_type=authorization_code"; |
|
|
|
private static final String URL_GET_OAUTH2_USERINFO |
|
|
|
= "https://api.weixin.qq.com/sns/userinfo?access_token=%1$s&openid=%2$s"; |
|
|
|
private static final String APPID = "wx7af1bf1e14facf82"; |
|
|
|
private static final String SECRET = "a6613fae11b497639c0224b820aaf6d9"; |
|
|
|
private static final String TOKEN = "nNzkL9KkZUOIS8uU"; |
|
|
@ -66,21 +68,19 @@ public class WxGzhUtil { |
|
|
|
|
|
|
|
/** |
|
|
|
* 数组转字符串 |
|
|
|
* @param arr |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
private static String ArrayToString(String[] arr) { |
|
|
|
StringBuffer bf = new StringBuffer(); |
|
|
|
for (int i = 0; i < arr.length; i++) { |
|
|
|
bf.append(arr[i]); |
|
|
|
private static String arrayToString(String[] arr) { |
|
|
|
StringBuilder bf = new StringBuilder(); |
|
|
|
for (String s : arr) { |
|
|
|
bf.append(s); |
|
|
|
} |
|
|
|
return bf.toString(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* sha1加密 |
|
|
|
* sha1加密 |
|
|
|
*/ |
|
|
|
private static String SHA1Encode(String sourceString) { |
|
|
|
private static String sha1Encode(String sourceString) { |
|
|
|
String resultString = null; |
|
|
|
try { |
|
|
|
MessageDigest md = MessageDigest.getInstance("SHA-1"); |
|
|
@ -91,24 +91,27 @@ public class WxGzhUtil { |
|
|
|
return resultString; |
|
|
|
} |
|
|
|
|
|
|
|
private static final String byte2hexString(byte[] bytes) { |
|
|
|
StringBuffer buf = new StringBuffer(bytes.length * 2); |
|
|
|
for (int i = 0; i < bytes.length; i++) { |
|
|
|
if (((int) bytes[i] & 0xff) < 0x10) { |
|
|
|
/** |
|
|
|
* 字节数组转字符串 |
|
|
|
*/ |
|
|
|
private static String byte2hexString(byte[] bytes) { |
|
|
|
StringBuilder buf = new StringBuilder(bytes.length * 2); |
|
|
|
for (byte aByte : bytes) { |
|
|
|
if (((int) aByte & 0xff) < 0x10) { |
|
|
|
buf.append("0"); |
|
|
|
} |
|
|
|
buf.append(Long.toString((int) bytes[i] & 0xff, 16)); |
|
|
|
buf.append(Long.toString((int) aByte & 0xff, 16)); |
|
|
|
} |
|
|
|
return buf.toString().toUpperCase(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 公众号接入验证 |
|
|
|
* @param signature |
|
|
|
* @param timestamp |
|
|
|
* @param nonce |
|
|
|
* @param echostr |
|
|
|
* @return |
|
|
|
* @param signature signature |
|
|
|
* @param timestamp timestamp |
|
|
|
* @param nonce nonce |
|
|
|
* @param echostr echostr |
|
|
|
* @return true or false |
|
|
|
*/ |
|
|
|
public static boolean checkSignature(String signature,String timestamp,String nonce,String echostr){ |
|
|
|
if(StrUtil.isEmpty(signature) || StrUtil.isEmpty(timestamp) || StrUtil.isEmpty(nonce) || StrUtil.isEmpty(echostr)){ |
|
|
@ -116,7 +119,7 @@ public class WxGzhUtil { |
|
|
|
} |
|
|
|
String[] tmpArr = { TOKEN, timestamp, nonce }; |
|
|
|
Arrays.sort(tmpArr); |
|
|
|
String sign = SHA1Encode( ArrayToString(tmpArr)); |
|
|
|
String sign = sha1Encode( arrayToString(tmpArr)); |
|
|
|
Console.log("sign:{} , signature: {}",sign,signature); |
|
|
|
if (sign.equalsIgnoreCase(signature)) { |
|
|
|
return true; |
|
|
@ -126,12 +129,10 @@ public class WxGzhUtil { |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取Access_token |
|
|
|
* @return |
|
|
|
* @throws BaseException |
|
|
|
*/ |
|
|
|
public static String getAccessToken() throws BaseException { |
|
|
|
if(globalWxAccessToken == null || |
|
|
|
globalWxAccessToken.getCreatedAt() + globalWxAccessToken.getExpires_in() |
|
|
|
globalWxAccessToken.getCreatedAt() + globalWxAccessToken.getExpiresIn() |
|
|
|
>= DateUtil.currentSeconds() - ACCESS_TOKEN_RESERVED_SECONDS){ |
|
|
|
WxAccessToken wxAccessToken = null; |
|
|
|
String url = String.format(URL_GET_ACCESS_TOKEN,"client_credential",APPID,SECRET); |
|
|
@ -148,18 +149,17 @@ public class WxGzhUtil { |
|
|
|
if(null != wxAccessToken.getErrcode()){ |
|
|
|
throw new WxException(wxAccessToken.getErrcode(),wxAccessToken.getErrmsg()); |
|
|
|
} |
|
|
|
if (StrUtil.isEmpty(wxAccessToken.getAccess_token())) { |
|
|
|
if (StrUtil.isEmpty(wxAccessToken.getAccessToken())) { |
|
|
|
throw new BusinessException(-1,"can't find the access_token attribute."); |
|
|
|
} |
|
|
|
globalWxAccessToken = wxAccessToken; |
|
|
|
globalWxAccessToken.setCreatedAt(DateUtil.currentSeconds()); |
|
|
|
} |
|
|
|
return globalWxAccessToken.getAccess_token(); |
|
|
|
return globalWxAccessToken.getAccessToken(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 查询微信公众号底部菜单 |
|
|
|
* @throws BaseException |
|
|
|
*/ |
|
|
|
public static String queryMenu() throws BaseException { |
|
|
|
String url = String.format(URL_QUERY_MENU,getAccessToken()); |
|
|
@ -170,8 +170,6 @@ public class WxGzhUtil { |
|
|
|
|
|
|
|
/** |
|
|
|
* 创建微信公众号底部菜单 |
|
|
|
* @param gzhMenu |
|
|
|
* @throws Exception |
|
|
|
*/ |
|
|
|
public static void createMenu(WxGzhMenu gzhMenu) throws BaseException { |
|
|
|
String url = String.format(URL_CREATE_MENU,getAccessToken()); |
|
|
@ -203,4 +201,72 @@ public class WxGzhUtil { |
|
|
|
public static String getAuthedUrl(String url, WxGzhAuthType wxGzhAuthType){ |
|
|
|
return String.format(GZH_AUTH_URL,APPID, URLUtil.encode(url),wxGzhAuthType.getText()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取网页授权凭证 |
|
|
|
* @param code OAuth2授权码 |
|
|
|
* @return WxOauth2AccessToken |
|
|
|
*/ |
|
|
|
public static WxOauth2AccessToken getOauth2AccessToken(String code) throws BaseException { |
|
|
|
WxOauth2AccessToken wxOauth2AccessToken = null; |
|
|
|
String url = String.format(URL_GET_OAUTH2_ACCESS_TOKEN,APPID,SECRET,code); |
|
|
|
String response = HttpRequest.get(url).execute().body(); |
|
|
|
Console.log("url: {}\nresponse: {}",url,response); |
|
|
|
try { |
|
|
|
if(StrUtil.isEmpty(response) || null == (wxOauth2AccessToken = JacksonUtil.jsonToBean(response,WxOauth2AccessToken.class))) { |
|
|
|
throw new BusinessException(-1,"the response of HttpRequest is empty."); |
|
|
|
} |
|
|
|
} catch (IOException e) { |
|
|
|
throw new BusinessException(-1,e.getMessage()); |
|
|
|
} |
|
|
|
|
|
|
|
if(null != wxOauth2AccessToken.getErrcode()){ |
|
|
|
throw new WxException(wxOauth2AccessToken.getErrcode(),wxOauth2AccessToken.getErrmsg()); |
|
|
|
} |
|
|
|
if (StrUtil.isEmpty(wxOauth2AccessToken.getAccessToken())) { |
|
|
|
throw new BusinessException(-1,"can't find the access_token attribute."); |
|
|
|
} |
|
|
|
wxOauth2AccessToken.setCreatedAt(DateUtil.currentSeconds()); |
|
|
|
return wxOauth2AccessToken; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 通过网页授权获取用户信息 |
|
|
|
* |
|
|
|
* @param accessToken 网页授权接口调用凭证 |
|
|
|
* @param openId 用户标识 |
|
|
|
* @return SNSUserInfo |
|
|
|
*/ |
|
|
|
public static WxOauth2UserInfo getOauth2UserInfo(String accessToken, String openId) throws BaseException { |
|
|
|
WxOauth2UserInfo wxOauth2UserInfo = null; |
|
|
|
String url = String.format(URL_GET_OAUTH2_USERINFO,accessToken,openId); |
|
|
|
String response = HttpRequest.get(url).execute().body(); |
|
|
|
Console.log("url: {}\nresponse: {}",url,response); |
|
|
|
try { |
|
|
|
if(StrUtil.isEmpty(response) || null == (wxOauth2UserInfo = JacksonUtil.jsonToBean(response,WxOauth2UserInfo.class))) { |
|
|
|
throw new BusinessException(-1,"the response of HttpRequest is empty."); |
|
|
|
} |
|
|
|
} catch (IOException e) { |
|
|
|
throw new BusinessException(-1,e.getMessage()); |
|
|
|
} |
|
|
|
|
|
|
|
if(null != wxOauth2UserInfo.getErrcode()){ |
|
|
|
throw new WxException(wxOauth2UserInfo.getErrcode(),wxOauth2UserInfo.getErrmsg()); |
|
|
|
} |
|
|
|
if (StrUtil.isEmpty(wxOauth2UserInfo.getOpenId())) { |
|
|
|
throw new BusinessException(-1,"can't find the openid attribute."); |
|
|
|
} |
|
|
|
return wxOauth2UserInfo; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 通过网页授权code拉取用户信息,封装了getOauth2AccessToken和getOauth2UserInfo(accessToken,openId) |
|
|
|
* @param code 网页授权码 |
|
|
|
* @return WxOauth2UserInfo |
|
|
|
* @throws BaseException 异常 |
|
|
|
*/ |
|
|
|
public static WxOauth2UserInfo getOauth2UserInfo(String code) throws BaseException { |
|
|
|
WxOauth2AccessToken wxOauth2AccessToken = getOauth2AccessToken(code); |
|
|
|
return getOauth2UserInfo(wxOauth2AccessToken.getAccessToken(),wxOauth2AccessToken.getOpenId()); |
|
|
|
} |
|
|
|
} |
|
|
|