1、配置服务器信息
* 基本配置/ 填写服务器配置 按提示输入信息,这个环节需要注意的是token微信会在线验证,提前写好拦截器
拦截器代码
/***
* 微信验签拦截器
*/
public class WxAuthenticationInterceptor implements HandlerInterceptor {
/**
* 控制验签系统开闭
*/
private final Boolean isOpen;
public WxAuthenticationInterceptor(Boolean isOpen) {
this.isOpen = isOpen;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (isOpen){
// 只拦截method级别的处理器
if (!(handler instanceof HandlerMethod)) return true;
// 只拦截token注解过的方法
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 判断接口是否需要验签
WxSign signAnnotation = method.getAnnotation(WxSign.class);
if (signAnnotation != null){
String url = RequestUtil.getParameters(request);
if (StringUtils.isNotBlank(request.getParameter("signature"))) {
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
//LOGGER.info("signature[{}], timestamp[{}], nonce[{}], echostr[{}]", signature, timestamp, nonce, echostr);
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
System.err.println(url + "数据源为微信后台,将echostr[" + echostr + "]返回!"); return true;
}else{
throw new InfoException("验签错误");
}
}else{
throw new InfoException("验签失败");
}
}
}
return true;
}
}
验证地址
@WxSign@GetMapping(value = {"","wxVerify"})@ResponseBodypublic String index(HttpServletRequest request){ String echostr = request.getParameter("echostr"); return echostr;}
SignUtil.java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class SignUtil {
private static String token = "jiangxinpai";//这里是自定义的token,需和你提交的token一致
/**
* 校验签名
*
* @param signature
* 签名
* @param timestamp
* 时间戳
* @param nonce
* 随机数
* @return 布尔值
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String checktext = null;
if (null != signature) {
// 对ToKen,timestamp,nonce 按字典排序
String[] paramArr = new String[] { token, timestamp, nonce };
Arrays.sort(paramArr);
// 将排序后的结果拼成一个字符串
String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
// 对接后的字符串进行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
checktext = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
// 将加密后的字符串与signature进行对比
return checktext != null ? checktext.equals(signature.toUpperCase()) : false;
}
/**
* 将字节数组转化为16进制字符串
*
* @param byteArrays
* 字符数组
* @return 字符串
*/
private static String byteToStr(byte[] byteArrays) {
String str = "";
for (int i = 0; i < byteArrays.length; i++) {
str += byteToHexStr(byteArrays[i]);
}
return str;
}
/**
* 将字节转化为十六进制字符串
*
* @param myByte
* 字节
* @return 字符串
*/
private static String byteToHexStr(byte myByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] tampArr = new char[2];
tampArr[0] = Digit[(myByte >>> 4) & 0X0F];
tampArr[1] = Digit[myByte & 0X0F];
String str = new String(tampArr);
return str;
}
}
2.获取accessToken, OAuth过程
@GetMapping("/oauth")
public String oauth(HttpServletRequest request, HttpServletResponse response, String code, String state){
//code说明 : code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
/*错误返回码说明如下:
返回码 说明
10003 redirect_uri域名与后台配置不一致
10004 此公众号被封禁
10005 此公众号并没有这些scope的权限
10006 必须关注此测试号
10009 操作太频繁了,请稍后重试
10010 scope不能为空
10011 redirect_uri不能为空
10012 appid不能为空
10013 state不能为空
10015 公众号未授权第三方平台,请检查授权状态
10016 不支持微信开放平台的Appid,请使用公众号Appid*/
WxAccessToken wxAccessToken = WxApiUtil.getAccessToken(code);
if(wxAccessToken != null){
String userIp = RequestUtil.getIp(request);
WxUserInfo userInfo = WxApiUtil.getUserInfo(wxAccessToken.getAccess_token(), wxAccessToken.getOpenid());
if(userInfo != null){
//预注册账号
try {
User user = userFacadeService.registerWithWx(wxAccessToken.getOpenid(), wxAccessToken.getAccess_token()
, userInfo.getNickname(), userInfo.getHeadimgurl(), userIp);
if(user != null) {
try {
response.sendRedirect(Constant.AppUrl + "/pages/user/bootstrap/bind?userId=" + user.getUserId() + "");
} catch (IOException e) {
e.printStackTrace();
}
}
}catch (Exception e){
try {
response.sendRedirect(Constant.AppUrl + "/pages/user/bootstrap/login?pop=" + e.getMessage());
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
try {
response.sendRedirect(Constant.AppUrl + "/pages/user/bootstrap/login?pop=" + "微信登录授权失败");
} catch (IOException e) {
e.printStackTrace();
}
return "ERROR";
}
WxApiUtil.java
public class WxApiUtil {
private final static String appId = "";
private final static String appSecret = "";
public static String getAccessToken(){
/*grant_type 是 获取access_token填写client_credential
appid 是 第三方用户唯一凭证
secret 是 第三方用户唯一凭证密钥,即appsecret*/
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
String response = HttpUtil.get(url, null);
return response;
}
public static void main(String[] args) {
String accessToken = WxApiUtil.getAccessToken();
System.out.println(accessToken);
}
public static WxAccessToken getAccessToken(String code) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret + "&code=" + code+ "&grant_type=authorization_code";
String response = HttpUtil.get(url, null);
/*{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}*/
if(!response.contains("errcode")){
WxAccessToken wxAccessToken = JsonUtil.getModel(response, WxAccessToken.class);
return wxAccessToken;
}else {
System.err.println("getAccessToken:" + response);
}
return null;
}
public static WxUserInfo getUserInfo(String accessToken, String openId){
/*{
"openid":" OPENID",
" nickname": NICKNAME,
"sex":"1",
"province":"PROVINCE"
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege":[ "PRIVILEGE1" "PRIVILEGE2" ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}*/
String url = "https://api.weixin.qq.com/sns/userinfo?access_token="+ accessToken + "&openid=" + openId + "&lang=zh_CN";
String response = HttpUtil.get(url, null);
if(!response.contains("errcode")){
WxUserInfo wxUserInfo = JsonUtil.getModel(response, WxUserInfo.class);
return wxUserInfo;
}else{
System.err.println("getUserInfo:" + response);
}
return null;
}
}
到此就完成任务啦~ 微信用户打开H5后请求获取用户信息,无感预注册账户,等到授权结束后再让用户绑定手机号推广码等等信息,如果报错了就重定向弹窗告知用户。
来源:https://www.cnblogs.com/renhongwei/p/10516850.html