微信网页授权功能实现

wechat oap message service

微信网页授权功能就是当用户在微信客户端访问第三方网页的时候,通过用户授权可以获取用户的相关信息,如ID、昵称、性别等数据,从而在网页功能中实现一些同具体用户相关的业务逻辑

一、配置回调域名

这里以测试号为例(普通公众号的方法类似),到微信公众号管理后台,选择“开发者工具-公众平台测试号”,在下方列表中找到“网页服务-网页账号(网页授权获取用户基本信息)”,点击修改,在弹出的对话框中输入自己服务器的域名,微信将用这个域名同服务器交换信息。

二、选择获取用户信息的授权方式

两种获取用户信息的授权方式,一种叫做“snsapi_base”,也是缺省的授权方式,第二种方式叫做“snsapi_userinfo”。这两种方式的区别是得到的用户数据不一样,第一种只能获取用户的ID,第二种可以获取用户完整的数据

第一种也叫做静默授权用户无感知,微信直接回调第三方网页,同时把一些数据传给网页所在的服务器。比如下面要提到的 code。第二种授权需要用户确认,才能进入到第三方网页,如果用户关注了公众号,而且从公众号界面进入第三方网页,比如公众号中的菜单消息链接等,这时也是静默方式,授权页面不会出现,也将直接进入到第三方的网页。

三、实现流程

1、引导用户进入授权

就是放置授权链接在需要的地方,比如公众号中的菜单、消息中的链接,这个授权链接带有回调第三方网页地址的参数,通过用户授权后,微信会回调这个网址

两种授权链接分别是:

(1)snsapi_base

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect

(2)snsapi_userinfo

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

其中的appid可以在公众号管理后台查到,redirect_rui 就是授权后要回调的第三方网页地址state 可以根据自己需求来设置,微信回调的时候会原封不动地回传这个state参数值,同时还要传送code,后面的操作需要这个code。

2、用户同意授权,获取code

用户同意授权后,微信按照上面设置好的回调地址(第三方网页)进入到相关的网页链接,同时发送 codestate 两个数值,其中拿到的 code 用来获取一个访问用户信息的令牌(access_token)。这个 code 有期限,5分钟不使用将过期。

3、获取访问用户信息的令牌(access_token)

使用这个令牌才能拿到用户信息,这个令牌和前面文章中讲到的令牌不一样,这个只是用于网页授权获取用户信息的。

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

其中的 code 参数填写第二步拿到的 code,appid 和 secret 在公众号后台可以查到。该步正确完成后,微信会发送返回结果给服务器,其中包括访问令牌(access_toke)和刷新令牌(refresh_token)。这步返回的结果中也含有用户的 ID 数据。

由于访问令牌有2个小时的有效期,过期后需要重新获取,这就要通过返回的刷新令牌(refresh_token)参数来获取。

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

刷新令牌有30天的期限,过期后访问第三方网页获取用户数据就需要重新做用户授权。

4、获取用户信息

通过用户ID(openid)和令牌(access_token)拉取用户数据。

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
5、其它

判断当前令牌(access_token)是否有效的调用方式是:

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

四、实现代码

setupmenu.py #放置授权链接在公众号的菜单上

from wechatpy import WeChatClient
from wechatpy.oauth import WeChatOAuth
from redisclient import redissession
import config

class Menu(object):
    def __init__(self):
        pass
    def create(self):
        client = WeChatClient(config.appId, config.secret, session=redissession)
        client.menu.create({
            "button":[
            {
                "type":"click",
                "name":"微信关注",
                "key":"wx_qr_code"
            },
            {
                "type":"click",
                "name":"微博关注",
                "key":"wb_qr_code"
            },
            {
                "name":"更多精彩",
                "sub_button":[
                {
                    "type":"view",
                    "name":"博客",
                    "url":"https://www.kflyo.com/"
                },
                {
                    "type":"view",
                    "name":"微博",
                    "url":"https://weibo.com/kflyo"
                },
                {
                    "type":"view",
                    "name":"关于",
                    "url":"https://www.kflyo.com/about-me"
                },
                {
                    "type":"view",
                    "name":"微信网页",
                    "url":WeChatOAuth(config.appId, config.secret, config.redirect_url, "snsapi_userinfo", "xxx").authorize_url
                }
                ]
            }
            ]
        })

homepage.py #微信回调网页,获取code、令牌、用户信息等数据。

import web
from wechatpy.oauth import WeChatOAuth
import config
from jssdk import jsSDK

class HomePage:
      def GET(self):
                  code = web.input(code="none").code
                  state = web.input(state="none").state
                  nickname = ""
                  if code!="none" and state=="xxx":
                        wcoa = WeChatOAuth(config.appId, config.secret, config.redirect_url, "snsapi_userinfo", "xxx")
                        wcoa.fetch_access_token(code)
                        if !wcoa.check_access_token():
                              wcoa.refresh_access_token(wcoa.refresh_token)
                        resjson = wcoa.get_user_info()
                        nickname = resjson['nickname'] #用户昵称
                  render = web.template.render('templates', base='base')
                  url = web.ctx.home + web.ctx.fullpath
                  jssdk = jsSDK().getJsSdk(url)
                  return render.home('Hello world ' + nickname, '首页', jssdk)

发表评论

邮箱地址不会被公开。 必填项已用*标注