You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

50 lines
2.3KB

  1. import threading
  2. import time
  3. from wechatpy.client import WeChatClient
  4. from wechatpy.exceptions import APILimitedException
  5. from channel.wechatmp.common import *
  6. from common.log import logger
  7. class WechatMPClient(WeChatClient):
  8. def __init__(self, appid, secret, access_token=None, session=None, timeout=None, auto_retry=True):
  9. super(WechatMPClient, self).__init__(appid, secret, access_token, session, timeout, auto_retry)
  10. self.fetch_access_token_lock = threading.Lock()
  11. self.clear_quota_lock = threading.Lock()
  12. self.last_clear_quota_time = -1
  13. def clear_quota(self):
  14. return self.post("clear_quota", data={"appid": self.appid})
  15. def clear_quota_v2(self):
  16. return self.post("clear_quota/v2", params={"appid": self.appid, "appsecret": self.secret})
  17. def fetch_access_token(self): # 重载父类方法,加锁避免多线程重复获取access_token
  18. with self.fetch_access_token_lock:
  19. access_token = self.session.get(self.access_token_key)
  20. if access_token:
  21. if not self.expires_at:
  22. return access_token
  23. timestamp = time.time()
  24. if self.expires_at - timestamp > 60:
  25. return access_token
  26. return super().fetch_access_token()
  27. def _request(self, method, url_or_endpoint, **kwargs): # 重载父类方法,遇到API限流时,清除quota后重试
  28. try:
  29. return super()._request(method, url_or_endpoint, **kwargs)
  30. except APILimitedException as e:
  31. logger.error("[wechatmp] API quata has been used up. {}".format(e))
  32. if self.last_clear_quota_time == -1 or time.time() - self.last_clear_quota_time > 60:
  33. with self.clear_quota_lock:
  34. if self.last_clear_quota_time == -1 or time.time() - self.last_clear_quota_time > 60:
  35. self.last_clear_quota_time = time.time()
  36. response = self.clear_quota_v2()
  37. logger.debug("[wechatmp] API quata has been cleard, {}".format(response))
  38. return super()._request(method, url_or_endpoint, **kwargs)
  39. else:
  40. logger.error("[wechatmp] last clear quota time is {}, less than 60s, skip clear quota")
  41. raise e