wechatpy.client.api.jsapi 源代码

# -*- coding: utf-8 -*-
"""
    wechatpy.client.jsapi
    ~~~~~~~~~~~~~~~~~~~~

    This module provides some APIs for JS SDK

    :copyright: (c) 2014 by messense.
    :license: MIT, see LICENSE for more details.
"""


import hashlib
import time
from typing import Optional

from wechatpy.utils import WeChatSigner, random_string
from wechatpy.client.api.base import BaseWeChatAPI
from wechatpy.schemes import JsApiCardExt


[文档]class WeChatJSAPI(BaseWeChatAPI):
[文档] def get_ticket(self, type="jsapi"): """ 获取微信 JS-SDK ticket :return: 返回的 JSON 数据包 """ return self._get("ticket/getticket", params={"type": type})
[文档] def get_jsapi_ticket(self): """ 获取微信 JS-SDK ticket 该方法会通过 session 对象自动缓存管理 ticket :return: ticket """ ticket_key = f"{self.appid}_jsapi_ticket" expires_at_key = f"{self.appid}_jsapi_ticket_expires_at" ticket = self.session.get(ticket_key) expires_at = self.session.get(expires_at_key) or 0 if not ticket or expires_at < int(time.time()): jsapi_ticket_response = self.get_ticket("jsapi") ticket = jsapi_ticket_response["ticket"] expires_at = int(time.time()) + int(jsapi_ticket_response["expires_in"]) self.session.set(ticket_key, ticket) self.session.set(expires_at_key, expires_at) return ticket
[文档] def get_jsapi_signature(self, noncestr, ticket, timestamp, url): """ 获取 JSAPI 签名 :param noncestr: nonce string :param ticket: JS-SDK ticket :param timestamp: 时间戳 :param url: URL :return: 签名 """ data = [ f"noncestr={noncestr}", f"jsapi_ticket={ticket}", f"timestamp={timestamp}", f"url={url}", ] signer = WeChatSigner(delimiter=b"&") signer.add_data(*data) return signer.signature
[文档] def get_jsapi_card_ticket(self): """ 获取 api_ticket:是用于调用微信卡券JS API的临时票据, 有效期为7200 秒, 通过access_token 来获取. 微信文档地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#62 该方法会通过 session 对象自动缓存管理 ticket :return: ticket """ jsapi_card_ticket_key = f"{self.appid}_jsapi_card_ticket" jsapi_card_ticket_expire_at_key = f"{self.appid}_jsapi_card_ticket_expires_at" ticket = self.session.get(jsapi_card_ticket_key) expires_at = self.session.get(jsapi_card_ticket_expire_at_key, 0) if not ticket or int(expires_at) < int(time.time()): ticket_response = self.get_ticket("wx_card") ticket = ticket_response["ticket"] expires_at = int(time.time()) + int(ticket_response["expires_in"]) self.session.set(jsapi_card_ticket_key, ticket) self.session.set(jsapi_card_ticket_expire_at_key, expires_at) return ticket
[文档] def get_jsapi_add_card_params( self, card_id: str, code: str = "", openid: str = "", fixed_begintimestamp: Optional[int] = None, outer_str: str = "", nonce_str: str = "", timestamp: int = 0, card_ticket: str = "", ) -> JsApiCardExt: """ 用于生成 jsapi 批量添加卡券接口的 cardList 参数中的 cardExt 参数 参数意义见微信文档地址: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#65 和 https://developers.weixin.qq.com/doc/offiaccount/Cards_and_Offer/WeChat_Coupon_Interface.html#4 :param card_id: 卡券ID. 一个卡券ID对应一类卡券, 包含了相应库存数量的Code码. :param code: 卡券Code码. 一张卡券的唯一标识, 核销卡券时使用此串码, 支持商户自定义. :param openid: 用户在该公众号下的唯一身份. :param fixed_begintimestamp: 卡券在第三方系统的实际领取时间, 为东八区时间戳 (UTC+8,精确到秒) . 当卡券的有效期类型为 DATE_TYPE_FIX_TERM 时专用, 标识卡券的实际生效时间, 用于解决商户系统内起始时间和领取时间不同步的问题. :param outer_str: 领取渠道参数, 用于标识本次领取的渠道值. 支持商户自定义场景值填入card_ext进行卡券投放, 当用户领取时会将相应场景值通过事件通知商户. :param nonce_str: 随机字符串, 由开发者设置传入, 加强安全性 (若不填写可能被重放请求). :param timestamp: unix 时间戳, 不同添加请求的时间戳须动态生成, 若重复将会导致领取失败. :param card_ticket: 用于卡券的微信 api_ticket :return: 卡券的附加信息 card_ext 的 dict """ nonce_str = nonce_str or random_string() timestamp = timestamp or int(time.time()) card_ticket = card_ticket or self.get_jsapi_card_ticket() card_signature_dict = { "nonce_str": nonce_str, "api_ticket": card_ticket, "timestamp": str(timestamp), "code": code, "openid": openid, "card_id": card_id, } list_before_sign = sorted([str(x) for x in card_signature_dict.values()]) str_to_sign = "".join(list_before_sign).encode() card_ext = JsApiCardExt( code=code, openid=openid, timestamp=str(timestamp), fixed_begintimestamp=fixed_begintimestamp, outer_str=outer_str, nonce_str=nonce_str, signature=hashlib.sha1(str_to_sign).hexdigest(), ) return card_ext