zoukankan      html  css  js  c++  java
  • 微信网页授权

    需求:

    • 能获取用户基本信息。
    • 获取微信信息的时候,从哪个页面来,最后到哪个页面去。
    • 调用方式要简单。

    思路:

    因为之前写过几次,思路还是很清楚的,大概有一下几个步骤:

    1. 提供一个链接,带有一个redirect_url参数,代表在获取用户信息后要返回的页面。
    2. 在上一个链接中跳转进行微信网页授权。
    3. 授权成功后获取code。
    4. 通过code调用微信接口获取access_token。
    5. 通过access_token获取用户基本信息。
    6. 将用户信息拼在之前定义的redirect_url中,并重定向到redirect_url。

    实现:

    思路有了下面就开始实现这个思路

    1:

    首先定义一个方法,接收redirect_url参数,并在这个方法中跳转到微信授权页面。

    这里我们需要完成思路中1,2的步骤。

    注意:

    在浏览器中调用方法的时候redirect_url参数要经过 URLEncoder.encode

    在方法中接收的redirect_url参数任然需要经过URLEncoder.encode,因为在作为参数接收到的时候,这个参数已经变成正常的http链接了。

    在拼装微信重定向地址的时候,需要再次URLEncoder.encode

    //微信网页授权地址
    private String getWechatCodeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?" +
            "appid=[APPID]&" +                  //微信appid
            "redirect_uri=[REDIRECT_URI]&" +    //获取网页授权后,微信重定向地址
            "response_type=code&" +
            "scope=snsapi_userinfo&" +          //授权方式
            "state=STATE#wechat_redirect";
    
    //微信授权后返回的地址
    private String getCodeUrl = "项目域名" +
            "redirect/code?redirect_url=";
    
    //提供的获取用户信息的地址
    @GetMapping("/redirect")
        public String redirect(
                @RequestParam(name = "redirect_url", defaultValue = "", required = false) String redirectUrl
        ) throws UnsupportedEncodingException {
            //默认值,前端首页地址
            if (StringUtils.isBlank(redirectUrl)) {
                redirectUrl = webSite;
            }
            //一次编码
            redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
            //二次编码
            redirectUrl = URLEncoder.encode(getCodeUrl + redirectUrl, "utf-8");
            //最终得到的微信获取微信授权地址
            String url = getWechatCodeUrl
                .replace("[APPID]", appid)
                .replace("[REDIRECT_URI]", redirectUrl);
            logger.info("redirecturl: {}", url);
            return "redirect:" + url;
        }

    2:

    这里要在定义一个链接,就是上一步要让微信跳转回来的地址。这里微信会携带一个code参数,由于在上一步我们将redirect_url地址进行了两次编码,所以在这个方法中redirect_url也会传递进来。

    着这个方法中我们需要完成思路中 4,5,6的步骤

    //获取access_token的接口地址,这里还可以获取到openid
    private String getAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
            "appid=[APPID]&" +      //微信的appid
            "secret=[SECRET]&" +    //微信的secret
            "code=[CODE]&" +        //重定向后微信携带的code参数
            "grant_type=authorization_code";
    
    //获取微信用户基本信息的接口地址
    private String getWechatUserUrl = "https://api.weixin.qq.com/sns/userinfo?" +
            "access_token=[ACCESS_TOKEN]&" +    //获取到的 access_token
            "openid=[OPENID]&" +                //公众号的 openid
            "lang=zh_CN";
    
    //这里的地址由微信重定向跳转,携带code参数。
    @GetMapping("/redirect/code")
    public String getCode(
            @RequestParam(name = "redirect_url", defaultValue = "", required = false) String redirectUrl,
            @RequestParam(name = "code", defaultValue = "", required = false) String code
    ) throws UnsupportedEncodingException {
        logger.info("redirect_url: {}", redirectUrl);
        logger.info("code: {}", code);
        if (StringUtils.isBlank(code)) {
            logger.error("获取code失败");
            return "redirect:" + redirectUrl + "?error=code-is-null";
        }
        //解码重定向地址
        redirectUrl = URLDecoder.decode(redirectUrl, "utf-8");
        //根据code获取微信相关信息
        String apiUrl = getAccessTokenUrl
                .replace("[APPID]", appid)
                .replace("[SECRET]", secret)
                .replace("[CODE]", code);
        String res = HttpUtils.doGet(apiUrl, new HashMap<>());
        JSONObject resJson = JSONObject.parseObject(res);
        //请求失败
        if (resJson.containsKey("errmsg")) {
            logger.error("获取access_token失败," + res);
            return "redirect:" + redirectUrl + "?error=" + resJson.getString("errmsg");
        }
        //获取微信用户信息
        String getUserUrl = getWechatUserUrl
                .replace("[ACCESS_TOKEN]", resJson.getString("access_token"))
                .replace("[OPENID]", resJson.getString("openid"));
        String user = HttpUtils.doGet(getUserUrl, new HashMap<>());
        JSONObject userJson = JSONObject.parseObject(user);
        if (userJson.containsKey("errmsg")) {
            logger.error("获取access_token失败," + res);
            return "redirect:" + redirectUrl + "?error=" + userJson.getString("errmsg");
        }
        //这里直接将微信用户信息编码后重定向给最开始的redirect_url
        return "redirect:" + redirectUrl + "?wechat_user=" + URLEncoder.encode(user, "utf-8");
    }

    完成:

    这里就已经开发完成了,发布到线上后访问:

    [域名]/redirect?redirect_url=[需要转到的地址]

    后,在获得用户授权后会跳转

    [需要转到的地址]?wechat_user=[URLEncoder.encode后的微信用户信息]

    https://www.cnblogs.com/hebaibai/p/11089318.html

     

    测试例子:

        //微信网页授权官网 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
    public final String APPID ="APPID";//测试号appid
    public final String APPSECRET =""; //测试号appsecret
    //第一步:用户同意授权,获取code
    public String GET_CODE_URL ="https://open.weixin.qq.com/connect/oauth2/authorize?" +
    "appid=APPID" + //微信appid
    "&redirect_uri=REDIRECT_URI" + //获取网页授权后,微信重定向地址
    "&response_type=code" +
    "&scope=snsapi_userinfo" + //授权方式
    "&state=STATE#wechat_redirect";
    //第二步:通过code换取网页授权access_token
    public String ACCESS_TOKEN_URL="https://api.weixin.qq.com/sns/oauth2/access_token?" +
    "appid=APPID" +
    "&secret=SECRET" +
    "&code=CODE" +
    "&grant_type=authorization_code";
    //第三步:刷新access_token(如果需要)
    public String REFRESH_TOKEN_URL ="https://api.weixin.qq.com/sns/oauth2/refresh_token?" +
    "appid=APPID" +
    "&grant_type=refresh_token" +
    "&refresh_token=REFRESH_TOKEN";
    public String GET_USERINFO_URL="https://api.weixin.qq.com/sns/userinfo?" +
    "access_token=ACCESS_TOKEN" +
    "&openid=OPENID&lang=zh_CN";

    //微信授权后返回的地址
    private String getCodeUrl = "http://zw6kbz.natappfree.cc/studentApi/weChatAccounts";

    //提供的获取用户信息的地址
    @ResponseBody
    @GetMapping("/redirect")
    public void redirect(HttpServletResponse response,
    @RequestParam(name = "redirect_url", defaultValue = "", required = false) String redirectUrl
    ) throws Exception {
    //一次编码
    redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
    //二次编码
    redirectUrl = URLEncoder.encode(getCodeUrl + redirectUrl, "utf-8");
    //最终得到的微信获取微信授权地址
    String url = GET_CODE_URL
    .replace("APPID", APPID)
    .replace("REDIRECT_URI", redirectUrl);
    log.info("redirecturl: {}", url);
    response.sendRedirect(url);
    }

    /**
    *
    * @param code
    * @return
    */
    @GetMapping("/weChatAccounts")
    @ApiOperation("验证消息的确来自微信服务器")
    public String weChatAccounts(@RequestParam(name = "code") String code,
    HttpServletResponse response)
    throws Exception {
    Map<String,Object> map =new HashMap<>();
    QrUser qrUser =new QrUser();
    //第一步:用户同意授权,获取code
    //第二步:通过code换取网页授权access_token
    String access_token_url=ACCESS_TOKEN_URL.replace("APPID",APPID)
    .replace("SECRET",APPSECRET)
    .replace("CODE",code);
    net.sf.json.JSONObject jsonObject = AuthUtil.doGetJson(access_token_url);
    log.info(jsonObject.toString());
    //获取access_token
    String access_token=(String)jsonObject.get("access_token");
    //获取openid
    String openid=(String)jsonObject.get("openid");
    //--------------------------逻辑判断------------------------------------------
    //根据openid获取用户
    QueryWrapper<QrUser> wrapper =new QueryWrapper<>();
    wrapper.eq("open_id",openid);
    QrUser user = qrUserService.getOne(wrapper);
    net.sf.json.JSONObject userinfo=null;
    String token=null;
    String is_perfect="0";
    if(user != null){
    //生成token
    token = JwtUtil.sign(user.getUserName(), user.getPassWord());
    //map.put("success","用户已存在,直接登陆");
    //map.put("user",user);
    //map.put("is_perfect",user.getIsPerfect());
    //System.out.println(user.getIsPerfect());
    //System.out.println(user.getIsPerfect());
    //is_perfect=user.getIsPerfect();

    }else{
    String get_userinfo_url = GET_USERINFO_URL.replace("ACCESS_TOKEN",access_token)
    .replace("OPENID",openid);
    userinfo = AuthUtil.doGetJson(get_userinfo_url);
    //随机生成用户名
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyHHddHHmmss");
    String Number =""+ sdf.format(new Date());//会员编号,不能重复
    String str = "U" + Number;
    qrUser.setUserName(str);
    qrUser.setOpenId(openid);
    qrUser.setNickName((String)jsonObject.get("nickname"));
    qrUser.setImgUrl((String)jsonObject.get("headimgurl"));
    qrUser.setAreaText((String)jsonObject.get("province")+","+(String)jsonObject.get("city"));
    qrUser.setPassWord("123456");
    qrUserService.save(qrUser);
    //生成token
    token = JwtUtil.sign(qrUser.getUserName(), qrUser.getPassWord());
    //map.put("user",qrUser);
    //map.put("success","用户第一次登陆,信息保存在数据库");
    //map.put("is_perfect",0);
    }

    System.err.println("token:"+token);
    redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
    //设置超时时间
    redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME/1000);
    map.put("token",token);
    //-------------------------------------逻辑判断结束----------------------------------------
    //第三步:刷新access_token(如果需要)
    /*String refresh_token_url=REFRESH_TOKEN_URL.replace("APPID",APPID)
    .replace("refresh_token",(String)jsonObject.get("refresh_token"));*/
    //第四步:拉取用户信息(需scope为 snsapi_userinfo)

    //return "redirect:/studentApi/token?token="+token;
    return "redirect:http://www.baidu.com";//跳转百度表示成功
    }

     --------------------------------请多多指教

  • 相关阅读:
    S4全球总决赛(2)南邮NOJ2059
    S4全球总决赛(2)南邮NOJ2059
    S4全球总决赛(1) 南邮NOJ
    S4全球总决赛(1) 南邮NOJ
    S4全球总决赛(1) 南邮NOJ
    【Linux】鸟哥的Linux私房菜基础学习篇整理(五)
    【Linux】鸟哥的Linux私房菜基础学习篇整理(四)
    【HDOJ】2428 Stars
    【Linux】鸟哥的Linux私房菜基础学习篇整理(三)
    【Linux】鸟哥的Linux私房菜基础学习篇整理(二)
  • 原文地址:https://www.cnblogs.com/livedian/p/11410652.html
Copyright © 2011-2022 走看看