我们在开发WordPress微信登录插件的时候有这样的功能需求:1,pc端微信扫码登录;2,微信浏览器中的自动登录功能需求,这两种需求就需要用到用户的unionID,这样才能在多个登录点(终端)识别用户,如何在PC端和公众号里面获取unionID呢?下面我一一说明。
以snsapi_login为scope发起网页授权,先拿网站应用的appid和secret用授权接口获取“网页授权access_token”,再利用“网页授权access_token”通过“拉取用户信息的api接口”拉取用户信息从而获得unionId。
此方法适合场景:在不使用微信公众号(订阅号、服务号)的情况下,通过微信开放平台下的网站应用来实现pc端网站的微信扫码登录功能。这个场景需求相对来说比较简单,可参考按照微信开放平台的技术文档“网站应用”–“微信登录功能”一节来实现编码,下面只把用户扫描二维码授权微信登录(用户扫描二维码并在微信客户端弹出的授权窗口点击确认登录后)后如何获取unionID的方法和过程描述下。
用户授权登录后重定向到网站A的登录页,并带回code和state参数。先拿code获取网页授权access_token:
$curl = new Curl(); $wxresponse = $curl->get('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $secret . '&code=' . $code . '&grant_type=authorization_code'); $wxresult = json_decode($wxresponse);
请求参数说明:
1 参数 是否必须 说明 2 appid 是 应用唯一标识,在微信开放平台提交应用审核通过后获得 3 secret 是 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得 4 code 是 填写第一步获取的code参数 5 grant_type 是 填authorization_code
如果请求正确,返回值:
{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" } 参数 说明 access_token 接口调用凭证 expires_in access_token接口调用凭证超时时间,单位(秒) refresh_token 用户刷新access_token openid 授权用户唯一标识 scope 用户授权的作用域,使用逗号(,)分隔
可以看到除access_token外,还可以获得openid。
然后用拿到的access_token和openid获取unionID:
1 //获取用户个人信息 2 $response = $curl->get('https://api.weixin.qq.com/sns/userinfo?access_token=' . $wxresult->access_token 3 . '&openid=' . $wxresult->openid);
返回值就不详细写了,其中就有用户的unionID。
2,再看手机端微信浏览器的解决方案
方法一:以snsapi_userinfo为scope发起网页授权,获取unionID过程与pc端的相同,但要用到微信公众号中的服务号appid和secret获取网页授权access_token。
1 // 用户是从微信访问此页面,直接调用微信验证 2 header('Location: https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $appid 3 . '&redirect_uri=http%3A%2F%2Fwww.host.com%2Fsite%2Fcallback' 4 . '&response_type=code&scope=snsapi_userinfo&state=state#wechat_redirect'); 5 exit;
这种方法在微信浏览器中的体验并不好,因为当用户在微信浏览器中浏览网页时点击了某个网页触发登录功能时会弹出授权窗口,而比较好的体验应该是,用户触发登录功能时应该是无感知的,下面的方法二就可以实现这种需求。
方法二:以snsapi_base为scope发起网页授权,先用公众号的appid和secret获取微信公众号的全局唯一凭证access_token,然后用拿到的access_token调用公众号的“用户管理接口”中的“获取用户信息接口”获得unionID。
发起授权请求,因为以snsapi_base为scope发起网页授权请求,所以授权是静默的,用户是无感知的,微信公众平台开发文档网页授权一节中有说明。
1 header('Location: https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $appid 2 . '&redirect_uri=http%3A%2F%2Fwww.host.com%2Fsite%2Fcallback' 3 . '&response_type=code&scope=snsapi_base&state=state#wechat_redirect'); 4 exit;
获取公众号全局唯一access_token
$curl = new Curl(); $curl->setOption(CURLOPT_SSL_VERIFYPEER, false); $tokenresult = $curl->get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appid . '&secret=' . $secret);
如果请求正确的话,返回值:
1 {"access_token":"ACCESS_TOKEN","expires_in":7200} 2 3 参数 说明 4 access_token 获取到的凭证 5 expires_in 凭证有效时间,单位:秒
调用公众号“获取用户信息接口”:
1 $response = $curl->get('https://api.weixin.qq.com/cgi-bin/user/info?access_token=' . $token . '&openid=' . $wxresult->openid . '&lang=zh_CN');
如果正确的话,返回值示例:
1 { 2 "subscribe": 1, 3 "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", 4 "nickname": "Band", 5 "sex": 1, 6 "language": "zh_CN", 7 "city": "广州", 8 "province": "广东", 9 "country": "中国", 10 11 "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4 12 13 eMsv84eavHiaiceqxibJxCfHe/0", 14 "subscribe_time": 1382694957, 15 "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL" 16 "remark": "", 17 18 "groupid": 0, 19 20 "tagid_list":[128,2] 21 } 22 23 参数说明 24 参数 说明 25 subscribe 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。 26 openid 用户的标识,对当前公众号唯一 27 nickname 用户的昵称 28 sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 29 city 用户所在城市 30 country 用户所在国家 31 province 用户所在省份 32 language 用户的语言,简体中文为zh_CN 33 headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 34 subscribe_time 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间 35 unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 36 remark 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注 37 groupid 用户所在的分组ID(兼容旧的用户分组接口) 38 tagid_list 用户被打上的标签ID列表
3,总结
用户无论从pc端登录网站还是从微信浏览器中访问网站,我们都能获取unionID,从而实现了多点登录的用户识别。