中国本土应用
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.

199 lines
6.1KB

  1. # -*- coding: utf-8 -*-
  2. import json
  3. import requests
  4. from odoo import api, fields, models, _, SUPERUSER_ID
  5. from odoo.exceptions import UserError
  6. import warnings
  7. class ApiException(Exception):
  8. def __init__(self, errCode, errMsg):
  9. super().__init__(errCode, errMsg)
  10. self.errCode = errCode
  11. self.errMsg = errMsg
  12. class WecomAbstractApi(models.AbstractModel):
  13. _name = "wecom.abstract_api"
  14. _description = "Wecom Abstract API"
  15. code = fields.Integer("API error code", copy=False)
  16. message = fields.Char("API error message", copy=False)
  17. def get_api_debug(self):
  18. """
  19. 获取 API 调试模式
  20. """
  21. ir_config = self.env["ir.config_parameter"].sudo()
  22. return True if ir_config.get_param("wecom.debug_enabled") == "True" else False
  23. def getAccessToken(self):
  24. raise NotImplementedError
  25. def refreshAccessToken(self):
  26. raise NotImplementedError
  27. def getSuiteAccessToken(self):
  28. raise NotImplementedError
  29. def refreshSuiteAccessToken(self):
  30. raise NotImplementedError
  31. def getProviderAccessToken(self):
  32. raise NotImplementedError
  33. def refreshProviderAccessToken(self):
  34. raise NotImplementedError
  35. def httpCall(self, urlType, args=None, include_agentid=False):
  36. """
  37. 调用API
  38. :param urlType : 服务端API类型和请求方式("GET" or "POST")
  39. :param args : 请求参数
  40. :param include_agentid : 标识args含有 "agentid" 关键字,需要进行处理
  41. :returns 返回结果
  42. """
  43. shortUrl = urlType[0]
  44. method = urlType[1]
  45. response = {}
  46. for retryCnt in range(0, 3):
  47. try:
  48. if "POST" == method:
  49. url = self.__makeUrl(shortUrl)
  50. if "agentid" in args and include_agentid:
  51. url = self.__appendArgs(url, {"agentid": args["agentid"]})
  52. del args["agentid"]
  53. response = self.__httpPost(url, args)
  54. elif "GET" == method:
  55. url = self.__makeUrl(shortUrl)
  56. url = self.__appendArgs(url, args)
  57. response = self.__httpGet(url)
  58. else:
  59. raise ApiException(-1, _("unknown method type"))
  60. except Exception as e:
  61. raise ApiException(-2, e) # 其他错误
  62. # 检查令牌是否过期
  63. if self.__tokenExpired(response.get("errcode")):
  64. self.__refreshToken(shortUrl)
  65. retryCnt += 1
  66. continue
  67. else:
  68. break
  69. # 检测响应
  70. return self.__checkResponse(response)
  71. def httpPostFile(self, urlType, args=None, data=None, headers=None):
  72. shortUrl = urlType[0]
  73. response = {}
  74. for retryCnt in range(0, 3):
  75. url = self.__makeUrl(shortUrl)
  76. url = self.__appendArgs(url, args)
  77. response = self.__httpPostFile(url, data, headers)
  78. # 检查令牌是否过期
  79. if self.__tokenExpired(response.get("errcode")):
  80. self.__refreshToken(shortUrl)
  81. retryCnt += 1
  82. continue
  83. else:
  84. break
  85. return self.__checkResponse(response)
  86. @staticmethod
  87. def __appendArgs(url, args):
  88. if args is None:
  89. return url
  90. for key, value in args.items():
  91. if "?" in url:
  92. url += "&" + key + "=" + value
  93. else:
  94. url += "?" + key + "=" + value
  95. return url
  96. @staticmethod
  97. def __makeUrl(shortUrl):
  98. base = "https://qyapi.weixin.qq.com"
  99. if shortUrl[0] == "/":
  100. return base + shortUrl
  101. else:
  102. return base + "/" + shortUrl
  103. def __appendToken(self, url):
  104. if "SUITE_ACCESS_TOKEN" in url:
  105. return url.replace("SUITE_ACCESS_TOKEN", self.getSuiteAccessToken())
  106. elif "PROVIDER_ACCESS_TOKEN" in url:
  107. return url.replace("PROVIDER_ACCESS_TOKEN", self.getProviderAccessToken())
  108. elif "ACCESS_TOKEN" in url:
  109. return url.replace("ACCESS_TOKEN", self.getAccessToken())
  110. else:
  111. return url
  112. def __httpPost(self, url, args):
  113. realUrl = self.__appendToken(url)
  114. if self.get_api_debug() is True:
  115. print("Wecom API POST", realUrl, args)
  116. return requests.post(
  117. realUrl, data=json.dumps(args, ensure_ascii=False).encode("utf-8")
  118. ).json()
  119. def __httpPostFile(self, url, data, headers):
  120. realUrl = self.__appendToken(url)
  121. if self.get_api_debug() is True:
  122. print("Wecom API POST FILE", realUrl, data, headers)
  123. # response = requests.post(url=realUrl, data=data, headers=headers).json()
  124. return requests.post(url=realUrl, data=data, headers=headers).json()
  125. def __post_file(self, url, media_file):
  126. if self.get_api_debug() is True:
  127. print("Wecom API POST FILE", url, media_file)
  128. return requests.post(url, file=media_file).json()
  129. def __httpGet(self, url):
  130. realUrl = self.__appendToken(url)
  131. if self.get_api_debug() is True:
  132. print("Wecom API GET", realUrl)
  133. return requests.get(realUrl).json()
  134. @staticmethod
  135. def __checkResponse(response):
  136. """
  137. 检查 返回 值是否合法,
  138. """
  139. errCode = response.get("errcode")
  140. errMsg = response.get("errmsg")
  141. if errCode == 0:
  142. return response
  143. else:
  144. raise ApiException(errCode, errMsg)
  145. @staticmethod
  146. def __tokenExpired(errCode):
  147. """
  148. 检查 令牌 是否过期
  149. """
  150. if errCode == 40014 or errCode == 42001 or errCode == 42007 or errCode == 42009:
  151. return True
  152. else:
  153. return False
  154. def __refreshToken(self, url):
  155. """
  156. 刷新令牌
  157. """
  158. if "SUITE_ACCESS_TOKEN" in url:
  159. self.refreshSuiteAccessToken()
  160. elif "PROVIDER_ACCESS_TOKEN" in url:
  161. self.refreshProviderAccessToken()
  162. elif "ACCESS_TOKEN" in url:
  163. self.refreshAccessToken()
上海开阖软件有限公司 沪ICP备12045867号-1