使用koa2开发微信公众号之网页授权

最近做需求要对接微信公众号,看了两天文档,基本算是理清楚了,在这里做下记录。

准备工作

了解公众号类型和接口权限

微信公众号分为订阅号服务号,两种账号都可以进行微信认证以获取更多接口权限(个人注册的订阅号不能进行微信认证)。

具体接口权限见:官方文档 >>

获取微信公众平台测试号

如果没有申请好的公众号,可以使用官方提供的测试账号,使用自己微信号扫描登录即可。

登录地址:微信公众平台测试号 >>

网页授权回调域名设置

我们要想在我们的网页中获取用户信息,就必须通过网页授权来实现。网页回调域名是指获取用户信息后需要跳转的域名地址,因为获取用户信息是微信提供的链接,获取后需要再重定向到我们自己的页面。

  1. 使用之前需要到公众号里把我们的域名设置成网页授权域名。
    设置方法:登录微信公众平台 > 设置 > 公众号设置 > 功能设置 > 网页授权域名

  2. 配置规范为全域名(不需要加http://https://),设置后可以在该域名下所有的页面使用,但不能在该域名的二级域名下使用。

如:设置了 www.raydom.wanghttp://www.raydom.wang/index.html 中可以使用,但 http://note.raydom.wang 中不能使用。

后台环境搭建

为了安全起见,微信的接口调用都需要放到后台进行。这里使用的是基于node环境的koa2服务环境。


开始

第一步:用户同意授权,获取code

引导用户打开如下链接:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

参数说明:

参数 必填 说明
appid 公众号的唯一标识
redirect_uri 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
response_type 返回类型,请填写code
scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect 无论直接打开还是做页面302重定向时候,必须带此参数

注意:redirect_uri 的值需要经过 urlEncode 处理。
js中没有提供原生方法,可以使用工具处理以后使用: urlEncode处理工具 >>

如果用户关注了公众号,scope 使用 snsapi_userinfo 获取用户信息时,也不会弹出授权框(测试公众号每次都会弹)

第二步:通过code获取用户信息
  1. 跳转到我们自己的页面以后,url中会自动添加code。
    示例:http://test.raydom.wang/?code=081tRRYX1Bk2IT0JNqVX16RAYX1tRRYT&state=123

  2. 获取url中的code到后台
    前端代码示例:

// 获取url中的参数
function GetQueryString(name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    var r = window.location.search.substr(1).match(reg);
    if (r != null) return unescape(r[2]);
    return null;
}

// 这里使用的axios进行ajax请求
axios.get("http://testapi.raydom.wang/login", {
        params: {
            code: GetQueryString("code")
        }
    })
    .then((res) => {
        console.log(res)
    })

  1. 在后台用拿到的 code 获取 ACCESS_TOKENopenid和更多信息
    后台代码示例:
const router = require('koa-router')()  // 引入router
const superagent = require('superagent') // 一个node环境http(s)请求中间件
const cache = require('memory-cache')  // 缓存处理中间件

const appid = "xxxxxxxxxxxxxxx"  // appid
const appsecret = "xxxxxxxxxxxxxxxxxxx"  // appsecret

router.get("/login", async(ctx, next) => {
    let ACCESS_TOKEN = "",
        openid = "";
    
    // 使用code获取openid和access_token 
    await superagent
        .get("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + 
            appid + "&secret=" + 
            appsecret + "&code=" + 
            ctx.query.code + "&grant_type=authorization_code")
        .then(res => {
            // 此处本来应该用res.body获取返回的json数据,但总是获取不到,只能用text代替
            let result = JSON.parse(res.text)
            ACCESS_TOKEN = result.access_token
            openid = result.openid
        })
        .catch(res => {
            console.log(res)
        })
    
    // 使用ACCESS_TOKEN和openid
    await superagent
        .get("https://api.weixin.qq.com/sns/userinfo?access_token=" + 
        access_token + "&openid=" + openid + "&lang=zh_CN")
        .then(res => {
            console.log(JSON.parse(res.text))
            ctx.body = {
                state: 1,
                msg: '获取access_token成功!'
            }
        })
        .catch(res => {
            console.log(res)
        })
})
  1. 刷新access_token(如果需要)
    由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token有效期为30天,当refresh_token失效之后,需要用户重新授权。
    请求方法:
    获取第二步的refresh_token后,请求以下链接获取access_token:https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
    返回结果:
参数 描述
access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔
关于UnionID机制(测试账号无法获取)
  1. 如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。

  2. 获取 unionid 需要 scope 使用 snsapi_userinfo

检验授权凭证(access_token)是否有效

请求接口:http:GET(请使用https协议) https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID

有效返回的JSON结果:

{ "errcode":0,"errmsg":"ok"}

错误时的JSON返回示例:

{ "errcode":40003,"errmsg":"invalid openid"}

你可能感兴趣的:(使用koa2开发微信公众号之网页授权)