No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

126 líneas
4.2KB

  1. import time
  2. import json
  3. import requests
  4. import threading
  5. from channel.wechatmp.common import *
  6. from common.log import logger
  7. from config import conf
  8. class WechatMPClient:
  9. def __init__(self):
  10. self.app_id = conf().get("wechatmp_app_id")
  11. self.app_secret = conf().get("wechatmp_app_secret")
  12. self.access_token = None
  13. self.access_token_expires_time = 0
  14. self.access_token_lock = threading.Lock()
  15. self.get_access_token()
  16. def wechatmp_request(self, method, url, **kwargs):
  17. r = requests.request(method=method, url=url, **kwargs)
  18. r.raise_for_status()
  19. r.encoding = "utf-8"
  20. ret = r.json()
  21. if "errcode" in ret and ret["errcode"] != 0:
  22. raise WeChatAPIException("{}".format(ret))
  23. return ret
  24. def get_access_token(self):
  25. # return the access_token
  26. if self.access_token:
  27. if self.access_token_expires_time - time.time() > 60:
  28. return self.access_token
  29. # Get new access_token
  30. # Do not request access_token in parallel! Only the last obtained is valid.
  31. if self.access_token_lock.acquire(blocking=False):
  32. # Wait for other threads that have previously obtained access_token to complete the request
  33. # This happens every 2 hours, so it doesn't affect the experience very much
  34. time.sleep(1)
  35. self.access_token = None
  36. url = "https://api.weixin.qq.com/cgi-bin/token"
  37. params = {
  38. "grant_type": "client_credential",
  39. "appid": self.app_id,
  40. "secret": self.app_secret,
  41. }
  42. ret = self.wechatmp_request(method="get", url=url, params=params)
  43. self.access_token = ret["access_token"]
  44. self.access_token_expires_time = int(time.time()) + ret["expires_in"]
  45. logger.info("[wechatmp] access_token: {}".format(self.access_token))
  46. self.access_token_lock.release()
  47. else:
  48. # Wait for token update
  49. while self.access_token_lock.locked():
  50. time.sleep(0.1)
  51. return self.access_token
  52. def send_text(self, receiver, reply_text):
  53. url = "https://api.weixin.qq.com/cgi-bin/message/custom/send"
  54. params = {"access_token": self.get_access_token()}
  55. json_data = {
  56. "touser": receiver,
  57. "msgtype": "text",
  58. "text": {"content": reply_text},
  59. }
  60. self.wechatmp_request(
  61. method="post",
  62. url=url,
  63. params=params,
  64. data=json.dumps(json_data, ensure_ascii=False).encode("utf8"),
  65. )
  66. def send_voice(self, receiver, media_id):
  67. url="https://api.weixin.qq.com/cgi-bin/message/custom/send"
  68. params = {"access_token": self.get_access_token()}
  69. json_data = {
  70. "touser": receiver,
  71. "msgtype": "voice",
  72. "voice": {
  73. "media_id": media_id
  74. }
  75. }
  76. self.wechatmp_request(
  77. method="post",
  78. url=url,
  79. params=params,
  80. data=json.dumps(json_data, ensure_ascii=False).encode("utf8"),
  81. )
  82. def send_image(self, receiver, media_id):
  83. url="https://api.weixin.qq.com/cgi-bin/message/custom/send"
  84. params = {"access_token": self.get_access_token()}
  85. json_data = {
  86. "touser": receiver,
  87. "msgtype": "image",
  88. "image": {
  89. "media_id": media_id
  90. }
  91. }
  92. self.wechatmp_request(
  93. method="post",
  94. url=url,
  95. params=params,
  96. data=json.dumps(json_data, ensure_ascii=False).encode("utf8"),
  97. )
  98. def upload_media(self, media_type, media_file):
  99. url="https://api.weixin.qq.com/cgi-bin/media/upload"
  100. params={
  101. "access_token": self.get_access_token(),
  102. "type": media_type
  103. }
  104. files={"media": media_file}
  105. logger.info("[wechatmp] media {} uploaded".format(media_file))
  106. ret = self.wechatmp_request(
  107. method="post",
  108. url=url,
  109. params=params,
  110. files=files
  111. )
  112. return ret["media_id"]