微信公众号授权登录

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"})
@ResponseBody
public 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后请求获取用户信息,无感预注册账户,等到授权结束后再让用户绑定手机号推广码等等信息,如果报错了就重定向弹窗告知用户。

posted on 2019-03-12 18:24  東風missile  阅读(1364)  评论(0编辑  收藏  举报

导航