java、JavaScript獲取微信用戶信息登陸優化方案

1.獲取微信用戶信息要調用微信的好幾個接口,再加上本身系統的接口就會變的很慢,影響用戶體驗,以前走過的彎路我就不贅述了,直接說新的方案。前端

2.第一步都是向微信發起獲取用戶code請求:web

   請求接口:https://open.weixin.qq.com/connect/oauth2/authorizejson

   參數:後端

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的參數主要的後臺處理完成後須要重定向的地址。api

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毫秒,這個是我在本地測試得到的時間。app

6.第四步包含了獲取用戶信息,註冊,登陸一塊兒完成了,以前咱們都是分開的由前端分次調用,比較慢,用戶體驗也很差。最後重定向到以前獲取微信用戶code時指定的state界面,並攜帶好參數。測試

7.未綁定開發者的微信服務號是沒有unionid的,因此須要注意一下。優化

8.有什麼不對的地方或者還有更多優化方案,歡迎討論!url

相關文章
相關標籤/搜索