网站应用实现微信扫码登录

前言

官方文档

https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

微信开放平台:

https://open.weixin.qq.com/

费用:

微信授权登录网页的能力是免费的,只要网页应用审核通过即可使用。

步骤概要

整体步骤大致如下

  1. 获取登录Code
  2. 通过code获取access_token和refresh_token
  3. 根据access_token获取用户信息
  4. 根据refresh_token刷新或续期access_token

其中第4步可以根据业务逻辑周期调用,防止token失效,也可以不调用。

获取Code

为了满足网站更定制化的需求,我们还提供了第二种获取code的方式,支持网站将微信登录二维码内嵌到自己页面中,用户使用微信扫码授权后通过JS将code返回给网站。 JS微信登录主要用途:网站希望用户在网站内就能完成登录,无需跳转到微信域下登录后再返回,提升微信登录的流畅性与成功率。

网站内嵌二维码微信登录JS实现办法:

步骤1:在页面中先引入如下JS文件(支持https):

代码语言:javascript
复制
http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js

步骤2:在需要使用微信登录的地方实例以下JS对象:

代码语言:javascript
复制
var obj = new WxLogin({
    self_redirect:false,
    id:"login_container", 
    appid: "", 
    scope: "snsapi_login", 
    redirect_uri: "",
    state: "",
    style: "",
    href: ""
});

参数说明

参数

是否必须

说明

self_redirect

true:手机点击确认登录后可以在 iframe 内跳转到 redirect_uri,false:手机点击确认登录后可以在 top window 跳转到 redirect_uri。默认为 false。

id

第三方页面显示二维码的容器id

appid

应用唯一标识,在微信开放平台提交应用审核通过后获得

scope

应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可

redirect_uri

重定向地址,需要进行UrlEncode

state

用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验

style

提供”black”、”white”可选,默认为黑色文字描述。详见文档底部FAQ

href

自定义样式链接,第三方可根据实际需求覆盖默认样式,stylelite不为1时有效。详见文档底部FAQ

stylelite

切换二维码登录样式,值为1时二维码登录将切换到新样式。详见文档底部FAQ。

fast_login

启用或禁用快速登录功能,值为0时将禁用快速登录。

用户允许授权后,将会重定向到redirect_uri的网址上,并且带上code和state参数

代码语言:javascript
复制
redirect_uri?code=CODE&state=STATE

若用户禁止授权,则不会发生重定向。

因为重定向的页面是前端的页面,我们可以做一个认证登录的前端页面,在这个页面中调用接口传入code获取用户信息后再跳转到系统主页面。

通过code获取access_token

第一次绑定的时候使用用户信息接口返回的unionid,后续直接用该接口返回的unionid即可。

后台可以判断是否返回了unionid,如果返回了unionid并且系统也已经绑定过了,直接使用系统的信息即可,否则的话再调用获取用户信息的接口。

后端调用 Get请求

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

参数

是否必须

说明

appid

应用唯一标识,在微信开放平台提交应用审核通过后获得

secret

应用密钥AppSecret,在微信开放平台提交应用审核通过后获得

code

填写第一步获取的code参数

grant_type

填authorization_code

返回说明

正确的返回:

代码语言:javascript
复制
{ 
    "access_token":"ACCESS_TOKEN", 
    "expires_in":7200, 
    "refresh_token":"REFRESH_TOKEN",
    "openid":"OPENID", 
    "scope":"SCOPE",
    "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

参数说明

参数

说明

access_token

接口调用凭证

expires_in

access_token接口调用凭证超时时间,单位(秒)

refresh_token

用户刷新access_token

openid

授权用户唯一标识

scope

用户授权的作用域,使用逗号(,)分隔

unionid

当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。

错误返回样例:

代码语言:javascript
复制
{
    "errcode":40029,
    "errmsg":"invalid code"
}

通过access_token获取用户信息

获取access_token后,进行接口调用,有以下前提:

  1. access_token有效且未超时;
  2. 微信用户已授权给第三方应用账号相应接口作用域(scope)。

请求说明

后端调用 Get请求

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

参数说明

参数

是否必须

说明

access_token

调用凭证

openid

普通用户的标识,对当前开发者账号唯一

lang

国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语,默认为en

返回说明

正确的Json返回结果:

代码语言:javascript
复制
{
  "openid": "OPENID",
  "nickname": "NICKNAME",
  "sex": 1,
  "province": "PROVINCE",
  "city": "CITY",
  "country": "COUNTRY",
  "headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
  "privilege": [
    "PRIVILEGE1",
    "PRIVILEGE2"
  ],
  "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

参数

说明

openid

普通用户的标识,对当前开发者账号唯一

nickname

普通用户昵称

sex

普通用户性别,1为男性,2为女性

province

普通用户个人资料填写的省份

city

普通用户个人资料填写的城市

country

国家,如中国为CN

headimgurl

用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空

privilege

用户特权信息,json数组,如微信沃卡用户为(chinaunicom)

unionid

用户统一标识。针对一个微信开放平台账号下的应用,同一用户的unionid是唯一的。

建议:

开发者最好保存用户unionID信息,以便以后在不同应用中进行用户信息互通。

错误的Json返回示例:

代码语言:javascript
复制
{
	"errcode":40003,
    "errmsg":"invalid openid"
}

刷新access_token有效期

只有获取用户信息的时候才使用access_token,我们系统一般只有第一次做用户绑定的时候才获取用户信息,并且获取用户信息也不会超过2小时,所以这个接口就可以不用调用。

access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:

  1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;
  2. 若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。

refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。

请求方法

获取第一步的code后,请求以下链接进行refresh_token:

代码语言:javascript
复制
https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

参数说明

参数

是否必须

说明

appid

应用唯一标识

grant_type

填refresh_token

refresh_token

填写通过access_token获取到的refresh_token参数

返回说明

正确的返回:

代码语言:javascript
复制
{ 
    "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

用户授权的作用域,使用逗号(,)分隔

错误返回样例:

代码语言:javascript
复制
{"errcode":40030,"errmsg":"invalid refresh_token"}

注意:

  1. Appsecret 是应用接口使用密钥,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);
  2. access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;
  3. refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上;
  4. 如无特别业务需求,建议开发者自行管理业务登录态并合理设置过期时间,减少用户重新授权登录次数,优化用户体验。

建议将secret、用户数据(如access_token)放在App云端服务器,由云端中转接口调用请求。

接口作用域

对于接口作用域(scope),能调用的接口有以下:

授权作用域(scope)

接口

接口说明

snsapi_base

/sns/oauth2/access_token

通过code换取access_token、refresh_token和已授权scope

snsapi_base

/sns/oauth2/refresh_token

刷新或续期access_token使用

snsapi_base

/sns/auth

检查access_token有效性

snsapi_userinfo

/sns/userinfo

获取用户个人信息

其中snsapi_base属于基础接口,若应用已拥有其它scope权限,则默认拥有snsapi_base的权限。

使用snsapi_base可以让移动端网页授权绕过跳转授权登录页请求用户授权的动作,直接跳转第三方网页带上授权临时票据(code),但会使得用户已授权作用域(scope)仅为snsapi_base,从而导致无法获取到需要用户授权才允许获得的数据和基础功能。