关于微信公众号无法获取用户信息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 吧。

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