jsapi.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. # -*- coding: utf-8 -*-
  2. """
  3. wechatpy.client.jsapi
  4. ~~~~~~~~~~~~~~~~~~~~
  5. This module provides some APIs for JS SDK
  6. :copyright: (c) 2014 by messense.
  7. :license: MIT, see LICENSE for more details.
  8. """
  9. from __future__ import absolute_import, unicode_literals
  10. import hashlib
  11. import time
  12. from wechatpy.utils import WeChatSigner, random_string
  13. from wechatpy.client.api.base import BaseWeChatAPI
  14. class WeChatJSAPI(BaseWeChatAPI):
  15. def get_ticket(self, type='jsapi'):
  16. """
  17. 获取微信 JS-SDK ticket
  18. :return: 返回的 JSON 数据包
  19. """
  20. return self._get(
  21. 'ticket/getticket',
  22. params={'type': type}
  23. )
  24. def get_jsapi_ticket(self):
  25. """
  26. 获取微信 JS-SDK ticket
  27. 该方法会通过 session 对象自动缓存管理 ticket
  28. :return: ticket
  29. """
  30. ticket_key = '{0}_jsapi_ticket'.format(self.appid)
  31. expires_at_key = '{0}_jsapi_ticket_expires_at'.format(self.appid)
  32. ticket = self.session.get(ticket_key)
  33. expires_at = self.session.get(expires_at_key, 0)
  34. if not ticket or expires_at < int(time.time()):
  35. jsapi_ticket_response = self.get_ticket('jsapi')
  36. ticket = jsapi_ticket_response['ticket']
  37. expires_at = int(time.time()) + int(jsapi_ticket_response['expires_in'])
  38. self.session.set(ticket_key, ticket)
  39. self.session.set(expires_at_key, expires_at)
  40. return ticket
  41. def get_jsapi_signature(self, noncestr, ticket, timestamp, url):
  42. """
  43. 获取 JSAPI 签名
  44. :param noncestr: nonce string
  45. :param ticket: JS-SDK ticket
  46. :param timestamp: 时间戳
  47. :param url: URL
  48. :return: 签名
  49. """
  50. data = [
  51. 'noncestr={noncestr}'.format(noncestr=noncestr),
  52. 'jsapi_ticket={ticket}'.format(ticket=ticket),
  53. 'timestamp={timestamp}'.format(timestamp=timestamp),
  54. 'url={url}'.format(url=url),
  55. ]
  56. signer = WeChatSigner(delimiter=b'&')
  57. signer.add_data(*data)
  58. return signer.signature
  59. def get_jsapi_card_ticket(self):
  60. """
  61. 获取 api_ticket:是用于调用微信卡券JS API的临时票据,有效期为7200 秒,通过access_token 来获取。
  62. 微信文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
  63. 该方法会通过 session 对象自动缓存管理 ticket
  64. :return: ticket
  65. """
  66. jsapi_card_ticket_key = '{0}_jsapi_card_ticket'.format(self.appid)
  67. jsapi_card_ticket_expire_at_key = '{0}_jsapi_card_ticket_expires_at'.format(self.appid)
  68. ticket = self.session.get(jsapi_card_ticket_key)
  69. expires_at = self.session.get(jsapi_card_ticket_expire_at_key, 0)
  70. if not ticket or int(expires_at) < int(time.time()):
  71. ticket_response = self.get_ticket('wx_card')
  72. ticket = ticket_response['ticket']
  73. expires_at = int(time.time()) + int(ticket_response['expires_in'])
  74. self.session.set(jsapi_card_ticket_key, ticket)
  75. self.session.set(jsapi_card_ticket_expire_at_key, expires_at)
  76. return ticket
  77. def get_jsapi_card_params(self, card_ticket, card_type, **kwargs):
  78. """
  79. 参数意义见微信文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
  80. :param card_ticket: 用于卡券的微信 api_ticket
  81. :param card_type:
  82. :param kwargs: 非必须参数:noncestr, timestamp, code, openid, fixed_begintimestamp, outer_str
  83. :return: 包含调用jssdk所有所需参数的 dict
  84. """
  85. card_signature_dict = {
  86. 'card_type': card_type,
  87. 'noncestr': kwargs.get('noncestr', random_string()),
  88. 'api_ticket': card_ticket,
  89. 'appid': self.appid,
  90. 'timestamp': kwargs.get('timestamp', str(int(time.time()))),
  91. }
  92. list_before_sign = sorted([str(x) for x in card_signature_dict.values()])
  93. str_to_sign = "".join(list_before_sign).encode()
  94. card_signature_dict['sign'] = hashlib.sha1(str_to_sign).hexdigest()
  95. return card_signature_dict