關於微信公衆號無法獲取用戶信息api unauthorized的踩坑

微信公衆號在獲取用戶信息的時候,一般用到下面寫法:

$url = "https://api.weixin.qq.com/sns/userinfo?access_token={$wx_access_token}&openid={$wx_open_id}";
$wx_info = FHttp::get($url); 
$wx_info = json_decode($wx_info, true);
$data = [
    'openid' => $info['openid'],
];
if ($wx_info) {
    $data['nickname'] = $wx_info['nickname'];
    $data['sex'] = $wx_info['sex'];
    $data['language'] = $wx_info['language'];
    $data['city'] = $wx_info['city'];
    $data['province'] = $wx_info['province'];
    $data['headimgurl'] = $wx_info['headimgurl'];
}

$wx_id = FDB::insert('wx_info', $data);

當然在進行這一步之前,必須獲取接口必要參數:access_token ,而關於獲取用戶這個參數的地方,就有意思了,微信提供了2個方式:

    public function getOauthBaseUrl($callback, $state = '')
    {
        if (!$state) {
            $state = md5(uniqid(rand(), true));
        }

        $callback = urlencode($callback);

        FSession::set('state', $state);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$callback}&response_type=code&scope=snsapi_base&state={$state}#wechat_redirect";
    }

    public function getOauthUserInfoUrl($callback, $state = '')
    {
        if (!$state) {
            $state = md5(uniqid(rand(), true));
        }
        $callback = urlencode($callback);

        FSession::set('state', $state);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$callback}&response_type=code&scope=snsapi_userinfo&state={$state}#wechat_redirect";
    }

之所以寫2個函數,也是爲了方便調用,其實這2個函數中,唯一不同的地方就在與接口的一個參數不一樣:scope,一個是snsapi_base,一個是snsapi_userinfo,那麼我就是這麼掉進坑裏去的。
開始,我呢,用的是 snsapi_userinfo,當然是爲了獲取用戶的頭像和暱稱。
那麼,客戶找我商量,現在打算給其他局的一個所裏做一下試點,但他那邊沒有公衆號,於是打算接入到我局裏,有一個小問題就是每次採集用戶微信頭像時候,就彈出一個我局的公衆號讓點允許,這個能不能去掉一下。

我想了一下,記得還有一個snsapi_base接口,做了一下測試,發現同樣可以獲取到用戶頭像,於是,拍着胸脯說,修改好了。
然後,上線,然後,就掉坑裏了

新用戶登陸後,沒有頭像,沒有暱稱

在獲取用戶信息接口的地方,打了一下log,通過觀察,返回了 48001 錯誤:

{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: YGabOOXIRa-djGckA ]"}
{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: YGabBbwgE-p0U4cA ]"}
{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: zGabA3LnRa-n8clKa ]"}
{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: zGabt24ce-FEx4Da ]"}
{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: zGabuAwgE-PhQmMA ]"}
{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: zGabY24ce-aO4OGa ]"}

這就奇怪,我趕緊拿出我的手機,掃了一下碼,卻發現接口返回正常,拿了同事的手機也是正常,可是採集上來的數據,就很奇怪了。很多 api unauthorized

於是找原因。。。

於是把接口改回到 snsapi_userinfo,寫了個 demo,單獨調用這幾個接口測試,發現換來換去並沒有什麼不同。都可以獲取接口參數。
來來回回不知所蹤了。

就在這時,打掃衛生的小姐姐路過。

“小姐姐,接手機用一下唄,測試一下程序。”
小姐姐瞟了一眼,嫣然一笑,“藉口~”
“啥接口?哦哦,對對對,我就是測試一下接口”
小姐姐貌似很無奈,”我微信就是我手機號,185xxxx“
“額。。。不行啊,我必須掃碼呀。”
“我連手機號都告訴你了,你還想幹啥”
“我真的是借來的測試用的!”
小姐姐一臉懷疑拿出手機遞給我。

奇蹟就這麼出現了。小姐姐的手機掃碼,就報了這個錯!
我去,啥情況啊,不會微信知道我們是搞程序,同樣的接口,程序員的手機能獲取,不是程序員就不能獲取吧,這也太 AI 了吧。

抱着試試看看的態度,把接口換成了 userinfo,理所當然的,通過接口獲得了小姐姐微信信息。
看來這個userinfo接口是沒問題了。問題就處在base上,於是,換上base再測試。。。

奇蹟又出現了,同樣的base接口,之前不能返回信息,現在也能返回信息了。
一天兩次奇蹟,雖然是程序猿的腦袋也經不起這麼大驚喜啊。

縱我試她千百遍,依然待我如初戀。

base接口獲得的 access token,也同樣能獲取用戶微信信息了。

冷靜下來,仔細想想。我要靜靜。。。。
會不會是因爲走過了一次userinfo,就給微信開了綠色通道了呢。

爲了認證這一想法,又搞到了幾部手機,先base,再 userinfo,再base。
一圈走下來,證實了我的想法。

用戶必須要先走一次 userinfo , 用戶在手機上同意了獲取用戶信息,之後便暫時開啓了綠色通道。

所以當你用base也能獲取的時候,不要大意,因爲。。。這是一個坑,你能,並不代表其他的廣大老百姓也都能。

總結
  1. 使用 scope=snsapi_userinfo,用戶微信點擊同意,才能獲取到用戶的基本信息
  2. 沒有點過同意,使用 scope=snsapi_base ,並不能獲取用戶信息,但能得到openid,可以根據這個進行微信登陸
  3. 用戶點過同意後,再一次使用無論是 scope=snsapi_base 還是 scope=snsapi_userinfo 都能獲取用戶的基本信息

當然感覺上用 scope=snsapi_base 還是不保險,雖然能獲取用戶信息,不知道是暫時的,還是永久的。想要獲取用戶基本信息,儘量全都用 scope=snsapi_userinfo 吧。

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