• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
未来的神秘
博客园    首页    新随笔    联系   管理    订阅  订阅

java、JavaScript获取微信用户信息登录优化方案

1.获取微信用户信息要调用微信的好几个接口,再加上自己系统的接口就会变的很慢,影响用户体验,之前走过的弯路我就不赘述了,直接说新的方案。

2.第一步都是向微信发起获取用户code请求:

   请求接口:https://open.weixin.qq.com/connect/oauth2/authorize

   参数:

​

var backUrl = encodeURIComponent("http://test.yitian.com/api/wechat/authBack?id=123");
//拼接微信网页授权url
var loginUrlx = "https://open.weixin.qq.com/connect/oauth2/authorize?";
var appIdParamx = "appid=wxbc236589746505";
var redirectParamx = "redirect_uri=" + backUrl + "&";
var scopeParamx = "scope=snsapi_userinfo&";
var responseParamx = "response_type=code&";
var stateParamx = "state=" + (document.location.toString());
var endingParamx = "#wechat_redirect";
//最终拼接后的授权url
var lastUrlx = loginUrlx + appIdParamx + redirectParamx + scopeParamx + responseParamx + stateParamx + endingParamx;
//跳转到微信网页授权页
window.location.href = lastUrlx;

 

3.前端发起或后端都可以发起,这里就说前端发起了,state参数是当前页面地址,如果页面地址长度太长可以不要携带参数,state的参数主要的后台处理完成后需要重定向的地址。

4.当这些都处理完成后,微信会调用第二步蚕参数指定的redirect_uri接口(之前我们配置的微信授权地址是前端地址,走了弯路),会携带之前的id=123参数,state参数,还有主要的code参数。

/**
 * 微信新授权回调地址
 * @param req
 * @param rsp
 * @param code
 * @param sourceType    
 * @param state
 * @return
 * @throws Exception
 * @return Object
 * @author tyg
 * @date   2019年4月1日下午2:33:35
 */
@RequestMapping(value = "/api/wechat/authBack")
public void authBack(HttpServletRequest req, HttpServletResponse rsp, Long id, Long shareId, Integer sourceType, String code, String state) throws Exception {
    Assert.isBlank(code, "code can't be null!");
    Assert.isBlank(state, "url can't be null!");
    // 获取用户openid和unionid,没有头像、昵称
    JSONObject info = wechatService.getUserOpenId(code);
    // 登录,如果不存在则返回为null,再获取用户的头像和昵称信息
    UserQuery userInfo = userI.weCharLogin(new WeChatUser(shareId, sourceType, info.getString("openid"), info.getString("unionid")));
    if(userInfo == null) {
        // 获取微信用户信息,有头像、昵称
        info = wechatService.getUserInfoByOpenId(info.getString("access_token"), info.getString("openid"));
        // 登录
        userInfo = userI.weCharLogin(new WeChatUser(shareId, sourceType, info.getString("openid"),
                info.getString("unionid"), info.getString("nickname"), info.getString("headimgurl")));
        Assert.isNull(userInfo, "user is null!");
    }
    String encode = URLEncoder.encode(JSON.toJSONString(userInfo), "UTF-8");
    state = URLDecoder.decode(state, "UTF-8");
    state += state.contains("?") ? "&" : "?";
    state = String.format("%sid=%s&shareId=%s&userInfo=%s", state, id == null ? "" : id, shareId == null ? "" : shareId, encode);
    rsp.sendRedirect(state);
}

/**
 * 获取用户的openid
 * @param code
 * @return
 * @throws Exception
 * @return JSONObject
 * @author tyg
 * @date   2019年4月12日上午10:31:46
 */
private JSONObject getUserOpenId(String code) throws Exception {
    Map<String, String> params = new HashMap<String, String>();
    params.put("grant_type", "authorization_code");//
    params.put("appid", WeChatProperties.AppID);
    params.put("secret", WeChatProperties.AppSecret);
    params.put("code", code);

    String jstoken = HttpUtils.sendGet("https://api.weixin.qq.com/sns/oauth2/access_token", params);

    if (jstoken == null) {
        LOG.error("jstoken is null");
        return null;
    }
    JSONObject jsonResult = JSONObject.parseObject(jstoken);
    if (null != jsonResult.get("errcode")) {
        LOG.error("wechat web auth err:" + jsonResult.get("errcode") + ":" + jsonResult.get("errmsg"));
        return null;
    }
    return jsonResult;
}

/**
 * 根据openid获取用户信息,有头像、昵称
 * @param access_token
 * @param openid
 * @return
 * @throws Exception
 * @return JSONObject
 * @author tyg
 * @date   2019年4月9日上午10:00:56
 */
public JSONObject getUserInfoByOpenId(String access_token,String openid) throws Exception {
    Map<String, String> params = new HashMap<String, String>();
    params.put("access_token", access_token);
    params.put("openid", openid);
    params.put("lang", "zh_CN");
    String userinfo = HttpUtils.sendGet("https://api.weixin.qq.com/sns/userinfo", params);
    JSONObject userJson = JSONObject.parseObject(userinfo);
    if (null != userJson.get("errcode")) {
        LOG.error(userJson.get("errmsg") + " get wechat user error:");
    }
    return userJson;
}

 

5.第四步中第二段代码中的APPID和AppSecret要替换成自己公众号的APPID和AppSecret,之所以先获取微信用户的openid信息,查询用户是否存在系统中,不存在的就要调用微信获取用户信息的接口,存在就不在调用,这样可以减少大约300-450毫秒,这个是我在本地测试获得的时间。

6.第四步包含了获取用户信息,注册,登录一起完成了,之前我们都是分开的由前端分次调用,比较慢,用户体验也不好。最后重定向到之前获取微信用户code时指定的state界面,并携带好参数。

7.未绑定开发者的微信服务号是没有unionid的,所以需要注意一下。

8.有什么不对的地方或者还有更多优化方案,欢迎讨论!

posted @ 2019-11-20 17:29  朝如青丝·暮成雪  阅读(666)  评论(2)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3