1. 程式人生 > >微信公眾號開發之授權獲取使用者資訊

微信公眾號開發之授權獲取使用者資訊

微信開發交流群:148540125

系列文章參考地址 極速開發微信公眾號
歡迎留言、轉發

前幾篇文章已講完如何匯入專案,如何啟動配置專案,如何成為開發者,重原始碼分析訊息是如何互動、如何自定義選單(如果以上不是很清楚可以看這裡 極速開發微信公眾號。這篇文章就來聊聊授權獲取使用者資訊

一、什麼是OAuth2.0

二、微信公眾平臺OAuth2.0授權詳細步驟

  1. 使用者關注微信公眾賬號(現在也可以不關注)。
  2. 微信公眾賬號提供使用者請求授權頁面URL。
  3. 使用者點選授權頁面URL,將向伺服器發起請求
  4. 伺服器詢問使用者是否同意授權給微信公眾賬號(scope為snsapi_base時無此步驟)
  5. 使用者同意(scope為snsapi_base時無此步驟,不彈出授權頁面,直接跳轉,只能獲取使用者openid)
  6. 伺服器將code引數通過回撥傳給微信公眾賬號
  7. 微信公眾賬號獲得code引數
  8. 微信公眾賬號通過code引數向伺服器請求Access Token
  9. 伺服器返回Access Token和OpenID給微信公眾賬號
    1. 微信公眾賬號通過Access Token向伺服器請求使用者資訊(scope為snsapi_base時無此步驟)
    2. 伺服器將使用者資訊回送給微信公眾賬號(scope為snsapi_base時無此步驟)

三、配置授權回撥頁面域名

沙盒號(測試號)回撥地址支援域名和ip,正式公眾號回撥地址只支援域名並且域名需使用字母、數字及“-”的組合,須通過ICP備案的驗證,不支援埠號及短鏈。

測試號:找到 網頁授權獲取使用者基本資訊>點選修改>設定域名
服務號:找到 開發>介面許可權>網頁授權獲取使用者基本資訊>>點選修改>設定域名
設定域名不要新增http

詳細介紹參考官方文件

javen_config.txt配置檔案中配置授權域名

四、使用者授權並獲取code ,使用code換取access_token 並使用access_token獲取使用者資訊

授權訪問的URL:

具體封裝實現可以檢視

com.jfinal.weixin.sdk.api.SnsAccessTokenApi.getAuthorizeURL(....) 方法

之前部落格使用Servlet 也寫了一個簡單的授權

參考地址

五、使用封裝的介面實現授權獲取使用者資訊

封裝之後使用就非常的簡單,SnsAccessTokenApi.getAuthorizeURL(....)
- 第一個引數為appId
- 第二個引數為授權後回撥的地址http://域名/oauth
- 第三個引數為state 重定向後會帶上state引數,開發者可以填寫a-zA-Z0-9的引數值,最多128位元組 第四個引數 應用授權作用域,簡單講是否彈出授權頁面 。 true 為不彈出授權頁面

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

具體實現程式碼如下

//跳轉到授權頁面
  public void toOauth(){
    String calbackUrl=PropKit.get("domain")+"/oauth";
    String url=SnsAccessTokenApi.getAuthorizeURL(PropKit.get("appId"), calbackUrl, "111",false);
    redirect(url);
  }

oauth Controller 具體實現步驟如下:
- 當用戶同意授權,獲取code以及state
- 如果code不為null,就可以通過code換取網頁授權access_token

{ 
 "access_token":"ACCESS_TOKEN",    
 "expires_in":7200,    
 "refresh_token":"REFRESH_TOKEN",    
 "openid":"OPENID",    
 "scope":"SCOPE" 
} 
  • 拉取使用者資訊(需scope為 snsapi_userinfo)
{    
 "openid":" OPENID",  
 " nickname": NICKNAME,   
 "sex":"1",   
 "province":"PROVINCE"   
 "city":"CITY",   
 "country":"COUNTRY",    
 "headimgurl":    "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ
4eMsv84eavHiaiceqxibJxCfHe/46",  
"privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],    
 "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" 
} 
  • 獲取使用者資訊之後可以根據上面的state跳轉到不同的頁面

具體實現程式碼如下

public class WeiXinOauthController extends ApiController{
  static Log log = Log.getLog(WeiXinOauthController.class);
  /**
   * 如果要支援多公眾賬號,只需要在此返回各個公眾號對應的  ApiConfig 物件即可
   * 可以通過在請求 url 中掛引數來動態從資料庫中獲取 ApiConfig 屬性值
   */
  public ApiConfig getApiConfig() {
    ApiConfig ac = new ApiConfig();

    // 配置微信 API 相關常量
    ac.setToken(PropKit.get("token"));
    ac.setAppId(PropKit.get("appId"));
    ac.setAppSecret(PropKit.get("appSecret"));

    /**
     *  是否對訊息進行加密,對應於微信平臺的訊息加解密方式:
     *  1:true進行加密且必須配置 encodingAesKey
     *  2:false採用明文模式,同時也支援混合模式
     */
    ac.setEncryptMessage(PropKit.getBoolean("encryptMessage", false));
    ac.setEncodingAesKey(PropKit.get("encodingAesKey", "setting it in config file"));
    return ac;
  }

  public void index() {
    int  subscribe=0;
    //使用者同意授權,獲取code
    String code=getPara("code");
    String state=getPara("state");
    if (code!=null) {
      String appId=ApiConfigKit.getApiConfig().getAppId();
      String secret=ApiConfigKit.getApiConfig().getAppSecret();
      //通過code換取網頁授權access_token
      SnsAccessToken snsAccessToken=SnsAccessTokenApi.getSnsAccessToken(appId,secret,code);
//      String json=snsAccessToken.getJson();
      String token=snsAccessToken.getAccessToken();
      String openId=snsAccessToken.getOpenid();
      //拉取使用者資訊(需scope為 snsapi_userinfo)
      ApiResult apiResult=SnsApi.getUserInfo(token, openId);

      log.warn("getUserInfo:"+apiResult.getJson());
      if (apiResult.isSucceed()) {
        JSONObject jsonObject=JSON.parseObject(apiResult.getJson());
        String nickName=jsonObject.getString("nickname");
        //使用者的性別,值為1時是男性,值為2時是女性,值為0時是未知
        int sex=jsonObject.getIntValue("sex");
        String city=jsonObject.getString("city");//城市
        String province=jsonObject.getString("province");//省份
        String country=jsonObject.getString("country");//國家
        String headimgurl=jsonObject.getString("headimgurl");
        String unionid=jsonObject.getString("unionid");
        //獲取使用者資訊判斷是否關注
        ApiResult userInfo = UserApi.getUserInfo(openId);
        log.warn(JsonKit.toJson("is subsribe>>"+userInfo));
        if (userInfo.isSucceed()) {
          String userStr = userInfo.toString();
          subscribe=JSON.parseObject(userStr).getIntValue("subscribe");
        }

        Users.me.save(openId, WeiXinUtils.filterWeixinEmoji(nickName), unionid, headimgurl, country, city, province, sex);
      }

      setSessionAttr("openId", openId);
      if (subscribe==0) {
        redirect(PropKit.get("subscribe_rul"));
      }else {
        //根據state 跳轉到不同的頁面
        if (state.equals("2222")) {
          redirect("http://www.cnblogs.com/zyw-205520/");
        }else {
          redirect("/login");
        }
      }
    }else {
      renderText("code is  null");
    }
  }
}

六、常見錯誤

1、請在微信客戶端中開啟

授權獲取使用者資訊必須在微信客戶端中開啟或者使用微信提供的測試工具

2、redirect_url 引數錯誤 如下圖
這裡寫圖片描述

請檢查appId對應的公眾平臺中設定的授權域名是否與你專案中配置的域名保持一致

3、測試號測試時提示未關注測試號

測試號測試授權是必須先關注的測試的號,官方這做是為了安全。正式環境使用正式的服務號是不用關注就可以獲取使用者資訊的。

以上是授權獲取使用者資訊的全過程。