微信公众号获取用户基本信息的方法总结

背景: 折腾了一整个周末,终于把用通过微信进行获取用户信息,以用来进行账号注册登录的问题搞定了, 因为面对的问题比较棘手: 希望通过微信订阅号获取用户信息授权,在自己开放的网站(所谓第三方网站)拿到用户信息, 所以在解决问题的过程中,顺便把自己期望实现的方式,以及现有的方式也稍微了解了一些, 所以趁此机会做一个整理。 因为朋友的网站是 php 开发的,所以下面的代码会以 php 进行举例,尽管我对 php 并不熟悉, 但是现在懒得重新去实现一遍了, 后面再说吧, 如果有后面的话。 其实其他语言理论上可以很容易类比, 因为微信的这些接口都是 restful 的 http 接口。

概述

微信授权登陆, 从使用入口来说,主要是 PC 端网站, 移动端网站和 APP。 这里的“移动端网站”是指从微信浏览器打开的网站,如果从手机浏览器打开, 那么只能与PC端的授权方式一样(实际上操作很麻烦) 基本的授权方式如下:

  • PC 端网站: 打开一个二维码, 用户扫描二维码之后授权 -> 获取用户信息
  • APP: 点击授权后跳转到微信授权页面, 用户点击确认授权 -> 获取用户信息

以上两种方式基本可以通过微信开放平台实现。

对于通过微信打开的移动端(以下简称“移动端”, 通过手机浏览器打开的移动端不在讨论范围内,因为其授权方式无法自动跳转到微信, 所以只能像PC那样进行扫码, 授权操作本身就很不合理), 有以下两种情况:

  1. 打开网页, 或者进行某个动作后, 弹出授权弹窗, 用户点击登陆后授权
  2. 用户在公众号内通过点击菜单等方式打开网站, 网站获取用户信息进行授权

第一种情况,是比较理想的授权方式,但是前提是需要有一个服务号, 订阅号本身没有这个权限, 第二种情况是在只有订阅号的情况下进行的一种妥协方式。

而对于授权的流程基本分 2 步:

  1. 获取 ACCESS_TOKEN , OpenId
  2. 通过 acces_token, 和 OpenId 获取用户基本信息

下面具体说明实现方法。

服务号

授权场景: 用户在网站内进行操作后弹出授权弹窗, 用户点击授权

实现方式: 微信公众平台的文档如下:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

具体来说有以下几个步骤:

  1. 开通权限:

到服务号的管理页面开通网页服务 -> 网页授权获取用户基本信息接口权限 wechat

然后点击该接口右边的修改按钮, 填写回调域名, 这个域名即需要使用这个权限的网站域名, 如: www.example.com , 那么下面的授权代码, 就应该部署在这个域名下面, 否则会报“回调地址与填写的不一致”的错误

  1. 编写授权代码:

网页授权的代码主要分为以下几步:

  1. 请求 https://open.weixin.qq.com/connect/qrconnect 接口获取一个code, 并跳转到回调 api
  2. 回调的 api 获取到 code, 获取 access_token
  3. 通过 assess_token 获取用户基本信息, 具体代码如下:
// 1. 请求 code 服务和回调
// step1.php

<?php
$appid='your appid';
$redirect_uri = urlencode ( 'http://www.example.com/get_user_info.php' );

$appid_param = "appid=$appid&redirect_uri=$redirect_uri";
$const_param = "&response_type=code&scope=snsapi_login";

$url ="https://open.weixin.qq.com/connect/qrconnect?$appid_param$const_param#wechat_redirect";

header("Location:".$url);
?>
// 以上代码, 先请求微信服务后, 获取 code , 并自动回调到 redirece_uri, 即我们部署在 www.example.com 下的 get_user_info.php

// get_user_info.php

<?php
//第一步:取得openid
$oauth2 = get_access_token();

//第二步:根据全局access_token和openid查询用户信息
$userinfo = get_user_info($oauth2);
print_r($userinfo);

function get_access_token () {
    $appid = "your appid";
    $secret = "your secrtet";
    $code = $_GET["code"];
    $oauth2Url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code=$code&grant_type=authorization_code";
    $oauth2 = getJson($oauth2Url);
    return $oauth2;
}
function get_user_info ($oauth2) {
    $access_token = $oauth2["access_token"];
    $openid = $oauth2['openid'];
    $get_user_info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN";
    $userinfo = getJson($get_user_info_url);
    return $userinfo;
    }
    
function getJson($url){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    return json_decode($output, true);
}
?>

完成!

订阅号

授权场景, 用户点击菜单或发送消息后, 返回带授权信息的 Url , 用户点击 Url 后取得授权

首先要明确一点,订阅号获取用户信息, 在微信浏览器内,是无法像订阅号那样直接在网页里面通过获取授权来得到用户的 OpenId, 而 OpenId 是获取用户信息的唯一途径。

既然清楚了OpenId 是获取用户信息的唯一途径, 我们就不妨通过”曲线救国“的办法, 通过订阅号常规的办法获取 OpenId, 然后把 OpenId 转给我们的目标网站。

在微信订阅号开发文档中, 用户发送消息, 点击菜单 等各种跟订阅号后台服务进行交互的渠道都可以获取到 OpenId , 所以我们可以借助这个机制, 实现曲线救国版的授权, 以点击菜单获取授权为例, 具体流程如下:

  1. 用户点击菜单后, 请求微信服务, 微信服务会转发请求到我们的后台服务, 此时会带上 openid 信息
  2. 后台服务把 openid 参数拼接到获取授权的目标 url 中, 并返回给用户(作为返回消息)
  3. 用户再次点击消息后, 跳转到目标 url 并且此时带上了 openid 信息, 目标接口借此获取用户基本信息

由于微信订阅号接口开发,需要定义的消息格式比较繁琐, 这里直接用了 netputer 的 wechat-php-sdk 进行开发。

注意, 如果要使用点击菜单来获取的话, 首先要通过请求自定义菜单接口获新建自定义菜单, 其中会设置菜单的 key 接口: 【POST】https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN Body: (body只创建授权的菜单, key为“login) , 更多用法请参考文档

     {
        "button": [
            {
                "name": "登录论坛",
                "type": "click",
                "key": "login"
            }
        ]
    }

以上 获取 ACCESS_TOKEN创建自定义菜单 均可通过在线调试工具完成

下面是实现上面所示, 通过点击菜单获取用户信息的方法:

  1. 先从 github 克隆 sdk 代码到本地 (可以单独把 src 文件夹移动到自己开发目录下)
  2. 修改 src -> config.php 将自己的订阅号相关信息填补完整
  3. 修改 example -> server.php, 如果是自定义开发目录, 可仿照 server.php 进行开发, 修改自定义菜单方法即可, 参考代码如下
/**
* 收到自定义菜单消息时触发,回复菜单的EventKey
*
* @return void
*/
protected function onClick() {
    // $this->responseText('你点击了菜单:' . $this->getRequest('EventKey'));
    $items = array(
        new NewsResponseItem(
        '吾爱诗词',
        '点击跳转并登录吾爱诗词社区',
        'http://www.example.com/example.png',
        'http://www.example.com/login.php?openid='.$this->getRequest('FromUserName'))
    );
    $this->responseNews($items);
}

这样, 用户点击菜单后就会收到一条类似这样的消息

image

点击消息后, 会跳转到 www.example.com/login.php 下, 并且带有 openid 信息, login.php 获取用户信息代码如下:

与服务号获取用户信息代码相似, 但是请求的接口和部分参数的获取逻辑各不一样


<?php
    //第一步:取得openid
    $oauth2 = get_access_token();
    
    //第二步:根据全局access_token和openid查询用户信息
    $userinfo = get_user_info($oauth2);
    print_r($userinfo);
    
    function get_access_token () {
        $appid = "your appid";
        $secret = "your secret";
        $oauth2Url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$secret";
        $oauth2 = getJson($oauth2Url);
        return $oauth2;
    }
    
    function get_user_info ($oauth2) {
        $access_token = $oauth2["access_token"];
        $openid = $_GET["openid"];
        $get_user_info_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=$access_token&openid=$openid&lang=zh_CN";
        $userinfo = getJson($get_user_info_url);
        return $userinfo;
    }

    function getJson($url){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($ch);
        curl_close($ch);
        return json_decode($output, true);
    }
?>

完成 !

开放平台

事实上开放平台是最方便, 开放工作最小的授权登陆方式, 而且其可以实现大部分的应用:

  • 在电脑网站通过扫描二维码进行登录 - 网站应用
  • 在自己的APP通过跳转微信授权进行登录 - 移动应用

具体的使用方法可以看官方文档, 这一节不是本篇文章的重点,只大概了解以下

网站应用

授权场景: 打开一个二维码, 用户扫码后授权

微信开放平台的 网站应用 主要解决PC端网站的问题, 其主要登录方式为扫码登陆, 具体实现如下:

  1. 申请一个“网站应用”, 此时会拿到一个 appid
  2. 请求Code, 会跳到一个二维码扫码页面, 扫码后跳转到回调URL, 这一步, 类似于服务号的第一步, 只不过是通过扫码的方式跳转:
[POST]  
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

其中: 

REDIRCT_URI: 为扫码后验证的目标 url, 用户扫码后微信会跳转到该 url, 
code 和 state 参数

APPID: 为申请的网站应用的 APPID, 注意不是订阅号的 APPID

SCOPE: snsapi_login (根据需求可以添加其他值, 具体看文档)

STATE: 自定义校验参数
  1. 通过 code 获取 ACCES_TOKEN, 进一步获取用户信息。 后面的步骤与服务号类似

具体请求步骤可参考服务号的开发流程和官方文档

移动应用

授权场景: APP 跳转授权

移动应用主要用于在开发的 APP 中使用微信进行授权登陆, 具体来说,点击“微信登陆”后, 跳转到手机微信进行授权, 授权完成后, 返回 APP 并带上 code 信息, APP 内借此获取 access_token 和用户信息。授权流程如下:

image

不同的操纵系统有不同的开发方式, 具体说分为两步:

  1. SDK 接入: 参考文档
  2. 授权登陆:与网站应用或者服务号类似 参考文档

总结

对于常见的几种用户场景下的微信授权登陆, 即获取用户基本信息, 对应的登陆方式如下:

  1. PC 端网站登录 , 开放平台网站应用, 扫码登录
  2. 移动端网站登录, 在微信浏览器内进行访问和登录, 推荐申请服务号, 并使用“网页授权获取用户信息”接口, 或者,是使用上文订阅号通过点击菜单或发送消息等方式进行授权。
  3. APP 授权登录, 开放平台移动应用。

参考链接:

https://segmentfault.com/a/1190000017494890

https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&lang=zh_CN&tab=dev

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839