微信開放平臺開發第三方授權登陸(四):微信公衆號

 

微信開放平臺開發系列文章:

微信開放平臺開發第三方授權登陸(一):開發前期準備

微信開放平臺開發第三方授權登陸(二):PC網頁端

微信開放平臺開發第三方授權登陸(三):Android客戶端

微信開放平臺開發第三方授權登陸(四):微信公衆號

微信開放平臺開發第三方授權登陸(五):微信小程序

 

 

目錄

一、需求

二、開發流程

三、具體實現步驟

1.引導用戶跳轉到微信授權網頁

2. 通過code換取網頁授權access_token

3.根據token獲取用戶信息

四、參數位置:


一、需求

根據需求,需要擁有第三方微信登錄功能,並獲取到用戶信息。

二、開發流程

微信公衆平臺第三方授權登錄的應用場景在於 : 在微信客戶端(PC或APP)訪問第三方網頁,公衆號可以通過網頁授權機制,獲取用戶基本信息,實現業務邏輯。

1用戶同意授權,獲取code

2通過code換取網頁授權access_token

3通過access_token拉取用戶信息(需scope爲 snsapi_userinfo)

公衆號第三方授權獲取用戶信息基本流程

三、具體實現步驟

1.引導用戶跳轉到微信授權網頁

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

參數

說明

appid

公衆號的唯一標識

redirect_uri

授權後重定向的回調鏈接地址, 請使用 urlEncode 對鏈接進行處理

response_type

返回類型,請填寫code

scope

應用授權作用域,snsapi_base (不彈出授權頁面,直接跳轉,只能獲取用戶openid),snsapi_userinfo (彈出授權頁面,可通過openid拿到暱稱、性別、所在地。並且, 即使在未關注的情況下,只要用戶授權,也能獲取其信息 )

state

重定向後會帶上state參數,開發者可以填寫a-zA-Z0-9的參數值,最多128字節

#wechat_redirect

無論直接打開還是做頁面302重定向時候,必須帶此參數

如果用戶同意授權,頁面將跳轉至 redirect_uri/?code=CODE&state=STATE。

注意:code作爲換取access_token的票據,每次用戶授權帶上的code將不一樣,code只能使用一次,5分鐘未被使用自動過期

 @RequestMapping("/login")
    public String wechatLogin(HttpServletRequest httpServletRequest) {

        // 應用授權作用域:
        // 當爲snsapi_base時,不彈出授權頁面,直接跳轉,只能獲取用戶openid。
        // 當爲snsapi_userinfo時,彈出授權頁面,可通過openid拿到暱稱、性別、所在地。並且, 即使在未關注的情況下,只要用戶授權,也能獲取其信息
        String scope = "snsapi_userinfo";

        String state = UUID.randomUUID().toString().replaceAll("-","");

        // 採用redis等進行緩存state 使用sessionId爲key 30分鐘後過期,可配置
        RedisPoolUtil.setEx("wechat-mp-state-"+httpServletRequest.getSession().getId(), state, Integer.parseInt(env.getProperty("wechat.mp.exTime", "1800")));

        log.info("state= "+state);

        // 微信公衆平臺
        String get_auth_url = "https://open.weixin.qq.com/connect/oauth2/authorize?"
                + "appid="
                + env.getProperty("wechat.mp.appid")
                + "&redirect_uri="
                + env.getProperty("application.url")
                + env.getProperty("wechat.mp.redirect_uri")
                + "&response_type=code"
                + "&scope="
                + scope
                + "&state="
                + state
                + "#wechat_redirect";

        log.info("URL:"+get_auth_url);

        return "redirect:" + get_auth_url;
    }

2. 通過code換取網頁授權access_token

用戶同意授權後,通過code換取網頁授權access_token

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

參數

說明

appid

公衆號的唯一標識

secret

公衆號的appsecret

code

填寫第一步獲取的code參數

grant_type

填寫爲authorization_code

請求正確返回的結果樣例:

{ "access_token":"ACCESS_TOKEN", //網頁授權接口調用憑證,注意:此access_token與基礎支持的access_token不同

"expires_in":7200,  // access_token接口調用憑證超時時間,單位(秒)

"refresh_token":"REFRESH_TOKEN", //用戶刷新access_token

"openid":"OPENID",  //用戶唯一標識

"scope":"SCOPE" }   //用戶授權的作用域,使用逗號(,)分隔

錯誤返回樣例:

{"errcode":40029,"errmsg":"invalid code"}


 

@RequestMapping("/getInfo")
    public String getInfo(HttpServletRequest httpServletRequest, Model model) {

        String code = httpServletRequest.getParameter("code");
        String state = httpServletRequest.getParameter("state");

        String value = RedisPoolUtil.get("wechat-mp-state-"+httpServletRequest.getSession().getId());

        log.info("Code = " + code+"  . State="+state+"    value="+value);

        /* 如果state值不匹配,則爲非法請求,拋出異常 */
        if (StringUtils.isEmpty(code)||StringUtils.isEmpty(state)||value==null || !state.equals(value)){
            throw new RuntimeException("非法請求");
        }

        // 通過code換取網頁授權access_token
        String get_access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "appid=" +
                env.getProperty("wechat.mp.appid") +
                "&secret=" +
                env.getProperty("wechat.mp.secret") +
                "&code=" +
                code +
                "&grant_type=authorization_code";

        log.info(get_access_token_url);


        JSONObject accessTokenJsonObject = HttpClientUtils.httpGet(get_access_token_url);

        checkResult(accessTokenJsonObject);
        // 成功獲取
        String access_token = (String) accessTokenJsonObject.get("access_token");
        Integer expires_in = (Integer) accessTokenJsonObject.get("expires_in");//access_token接口調用憑證超時時間,單位(秒)
        String userOpenid = (String) accessTokenJsonObject.get("openid");//用戶唯一標識
        String scope = (String) accessTokenJsonObject.get("scope");//用戶授權的作用域,使用逗號(,)分隔

        // TODO:文檔沒有寫返回unionid,需要在實際公衆號中進行測試(綁定開放平臺的會有),如果沒有unionid,則用openid存儲用戶,雖然這並不是合理的做法。因爲openid僅僅該公衆號下的用戶唯一標識。。。

//        access_token擁有較短的有效期,當access_token超時後,可以使用refresh_token進行刷新,
//        refresh_token有效期爲30天,當refresh_token失效之後,需要用戶重新授權

        WeChatUserInfo weChatUserInfo = null;

        weChatUserInfo = null; //FIXME: 根據unionid從數據庫中查詢
        if (weChatUserInfo == null){
            weChatUserInfo = getMPWeChatUserInfo(access_token,userOpenid);
            // insert into database

        }

        if (weChatUserInfo.getUnionid()!=null){
            // 當前是綁定開放平臺的公衆號.Union將成爲唯一標識

        }

        model.addAttribute(weChatUserInfo);
        return "wechatUser";
    }

3.根據token獲取用戶信息

http:GET(請使用https協議) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

參數

描述

access_token

網頁授權接口調用憑證,注意:此access_token與基礎支持的access_token不同

openid

用戶的唯一標識

lang

返回國家地區語言版本,zh_CN 簡體,zh_TW 繁體,en 英語

正確時返回的JSON數據包如下:

{

"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"
}

private WeChatUserInfo getMPWeChatUserInfo(String accessToken, String openId){

        String get_userInfo_url = "https://api.weixin.qq.com/sns/userinfo?" +
                "access_token=" +
                accessToken +
                "&openid=" +
                openId +
                "&lang=zh_CN";

        JSONObject userInfoJsonObject = HttpClientUtils.httpGet(get_userInfo_url);

        checkResult(userInfoJsonObject);

        String user_openid = (String) userInfoJsonObject.get("openid");
        String user_nickname = (String) userInfoJsonObject.get("nickname");
        Integer user_sex = (Integer) userInfoJsonObject.get("sex");//用戶的性別,值爲1時是男性,值爲2時是女性,值爲0時是未知
        String user_province = (String) userInfoJsonObject.get("province");
        String user_city = (String) userInfoJsonObject.get("city");
        String user_country = (String) userInfoJsonObject.get("country");//國家,如中國爲CN,最後一個數值代表正方形頭像大小(有0、46、64、96、132數值可選,0代表640*640正方形頭像),用戶沒有頭像時該項爲空。若用戶更換頭像,原有頭像URL將失效。
        String user_headimgurl = (String) userInfoJsonObject.get("headimgurl");//頭像
        List user_privilege = (List) userInfoJsonObject.get("privilege");//用戶特權信息,json 數組,如微信沃卡用戶爲(chinaunicom)
        String user_unionid = (String) userInfoJsonObject.get("unionid");


        WeChatUserInfo weChatUserInfo = new WeChatUserInfo();
        weChatUserInfo.setOpenid(user_openid);
        weChatUserInfo.setNickname(user_nickname);
        weChatUserInfo.setSex(user_sex);
        weChatUserInfo.setProvince(user_province);
        weChatUserInfo.setCity(user_city);
        weChatUserInfo.setCountry(user_country);
        weChatUserInfo.setHeadimgurl(user_headimgurl);
        weChatUserInfo.setPrivilege(StringTools.listToString(user_privilege));
        weChatUserInfo.setUnionid(user_unionid);

        log.info("用戶信息如下:" +
                "   opeinId:" + user_openid +
                "   用戶暱稱:" + user_nickname +
                "   用戶的性別:" + user_sex +
                "   省份:" + user_province +
                "   城市:" + user_city +
                "   國家:" + user_country +
                "   頭像:" + user_headimgurl +
                "   用戶特權信息:" + user_privilege +
                "   UnionId:" + user_unionid
        );

        return weChatUserInfo;
    }

四、參數位置:

開放平臺綁定公衆號:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章