H5开发中微信公众号的接口到底有多少个token?


目前我用到的接口涉及到两个token和一个ticket。
access_token用于服务器端的请求鉴权,ticket用于前端的请求鉴权。这两个需要缓存。
获取用户信息这个接口有一个单独的access_token。

1.自定义分享接口信息(文档

前端调用wx.conifg申请自定义分享这类的接口之前,需要先反问我们后端获取一些信息。

wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: ‘’, // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: ‘’, // 必填,生成签名的随机串
signature: ‘’,// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表
});

其中的signature就需要获取一个ticket的信息。

jsapi_ticket
生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。
1.正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):
https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
2.用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

我理解token和ticket的区别是这样的:
token: 用于服务端的请求验证。
ticket: 用于前端的请求验证。

由于这里的config是前端需要使用的,所以我们需要先申请token。微信的服务器验证我们的服务器和公众号的关系后。再使用我们前端上传的信息去申请ticket给前端。前端再拿着ticket作为令牌去找微信服务器申请相关的JS-SDK权限。
config流程图

从后端的视角来看,你需要做的是:

Created with Raphaël 2.3.0 收到请求 ①服务器获取token(过期时间7200秒,需要本地缓存) ②服务器获取ticket(过期时间7200秒,需要本地缓存) ③加工获取秘钥 返回相关参数

我的django代码给大家参考,我没有用redis就直接用文件存储了,真正需要上线的代码用redis用redis可能方便一些:

# 请求处理函数
def weixin_config(request):
    url = request.GET['url']
    config_info = create_string(url)
    config_info['app_id'] = settings.WEIXINAPI["appID"]

    json_str = json.dumps(config_info, ensure_ascii=False)
    res = HttpResponse(json_str, content_type="application/json")
    res.set_cookie('jsapi_ticket', json_str)
    return res

# 生成返回字符串
def create_string(url):
    random_string = randomone('16')
    times = int(time.time()/1000)
    ticket = get_ticket()
    arg_string = "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s" % (ticket, random_string, times, url)
    m = hashlib.sha1()
    m.update(arg_string.encode('utf8'))
    sign = m.hexdigest()

    return {'timestamp': times, 'nonceStr': random_string, 'signature': sign}

# 刷新token函数
def flush_token():
    token_url = settings.WEIXINAPI["tokenUrl"]
    appID = settings.WEIXINAPI["appID"]
    appwd = settings.WEIXINAPI["appwd"]
    url = "%sgrant_type=client_credential&appid=%s&secret=%s" % (token_url, appID, appwd)
    ssl._create_default_https_context = ssl._create_unverified_context
    jsondata = urllib.request.urlopen(url).read().decode()
    json_dic = json.loads(jsondata)
    with open("token.txt", 'w') as f:
        json.dump(json_dic, f)
    return json_dic["access_token"]

# 刷新ticket函数
def flush_ticket(access_token):
    ticket_url = settings.WEIXINAPI["ticketUrl"]
    url = '%saccess_token=%s&type=jsapi' % (ticket_url, access_token)
    jsondata = urllib.request.urlopen(url).read().decode()
    json_dic = json.loads(jsondata)
    json_dic["expires_time"] = time.time()
    with open("ticket.txt", 'w') as f:
        json.dump(json_dic, f)
    return json_dic["ticket"]


# ticket7200秒超时
# ticket用于前端调用微信js-sdk接口的凭据
def get_ticket():
    if os.path.exists("ticket.txt"):
        with open('ticket.txt', 'r') as f:
            ticket_dic = json.load(f)
        expires_time = ticket_dic['expires_time']
        now_time = time.time()
        if now_time - expires_time >= 7200:
            #更新ticket
            access_token = get_token()
            ticket = flush_ticket(access_token)
        else:
            ticket = ticket_dic["ticket"]
    else:
        access_token = get_token()
        ticket = flush_ticket(access_token)
    return ticket


# token也是7200秒超时
# ticket用于后台调用微信接口的凭据
def get_token():
    if os.path.exists("token.txt"):
        with open('token.txt', 'r') as f:
            ticket_dic = json.load(f)
        expires_time = ticket_dic['expires_time']
        now_time = time.time()
        if now_time - expires_time >= 7200:
            #更新ticket
            access_token = flush_token()
        else:
            access_token = ticket_dic["access_token"]
    else:
        access_token = flush_token()
    return access_token


def randomone(n):
    string = ''
    if n.isdigit():
        for i in range(int(n)):
            if i%2 != 0:
                tmp = random.randint(0,9)
            else:
                tmp = str(chr(random.randint(97, 122)))
            string = "%s%s" % (string, tmp)
    return string

2.判断用户是否关注了公众号(文档

接口参数
接口有三个参数,第一个access_token就是第一点里面的token了。
你看这个接口是后台的请求接口,所以他就不需要再使用ticket,只要用token就行了。
openid的获取可以看第三点。
返回结果中的subscribe标识用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。如果是1就说明关注了该公众号。

3.获取用户信息(文档)

这个接口由于非常常用,而且命名和上面的token是一样的,也叫access_token。也是我一直搞混的原因。

这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。

Created with Raphaël 2.3.0 开始 ①获取用户code ②服务器获取token ③服务器获取用户信息 ④将数据返回给前端 结束

这里就直接上代码了,不废话:
前端:
①重定向至授权界面

var now_href_str = window.location.href ;
var url = 'http://open.weixin.qq.com/connect/oauth2/authorize?appid=APP_ID&redirect_uri=' + encodeURI(now_href_str) + '&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect'
window.location.href = url;

②带上code去后台进行验证

const res = await get(url , {params: { 'code': code }});

后端:

# 获取个人信息接口
# 该接口和公众号后台的token不同,获取的是单独的access_token
# 文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
def get_user_info(request):
    if request.method == 'GET':
        code = request.GET['code']
        access_dict = get_accesstoken(code)

        data_dict = {}

        try:
        	# 尝试返回值中有没有errcode,如果有说明token获取失败。
            errcode = access_dict['errcode']
            data_dict['code'] = 300
            data_dict['msg'] = access_dict
            res = HttpResponse(json.dumps(data_dict, ensure_ascii=False), content_type="application/json")
            return res
        except:
            logger.info('获取token正常')

		# 获取原请求中的认证方式
        data_dict['scope'] = access_dict['scope']
        # 开始请求用户信息
        if access_dict['scope'] == 'snsapi_userinfo':
            user_dict = token_get_user_info(access_dict['access_token'], access_dict['openid'])
            data_dict['code'] = 200
            # 具体信息可以看下面这个地址
            # https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#3
            data_dict['openid'] = user_dict['openid']
            data_dict['nickname'] = user_dict['nickname']
            data_dict['headimgurl'] = user_dict['headimgurl']
            data_dict['sex'] = user_dict['sex']
        elif access_dict['scope'] == 'snsapi_base':
            data_dict['code'] = 201
            data_dict['openid'] = access_dict['openid']
        res = HttpResponse(json.dumps(data_dict, ensure_ascii=False), content_type="application/json")
        return res


def get_accesstoken(code):
    appID = settings.WEIXINAPI["appID"]
    appwd = settings.WEIXINAPI["appwd"]
    url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid={}&secret={}&code={}&grant_type=authorization_code'
    url = url.format(appID, appwd, code)
    jsondata = urllib.request.urlopen(url).read().decode()
    json_dic = json.loads(jsondata)
    return json_dic


def token_get_user_info(access_token, openid):
    url = 'https://api.weixin.qq.com/sns/userinfo?access_token={}&openid={}&lang=zh_CN'
    url = url.format(access_token, openid)
    jsondata = urllib.request.urlopen(url).read().decode()
    json_dic = json.loads(jsondata)
    return json_dic
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值