tianan.py 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. # coding=utf-8
  2. from typing import TYPE_CHECKING, Optional
  3. import json
  4. import logging
  5. import datetime
  6. import hashlib
  7. from urlparse import urljoin
  8. import requests
  9. logger = logging.getLogger(__name__)
  10. class TianAnException(Exception):
  11. def __init__(self, errCode, errMsg, client=None, request=None, response=None):
  12. super(TianAnException, self).__init__(errMsg)
  13. self.errCode = errCode
  14. self.errMsg = errMsg
  15. self.client = client
  16. self.request = request
  17. self.response = response
  18. def __str__(self):
  19. if self.client:
  20. _repr = '{klass}(client: {client}, errCode: {errCode}, errMsg: {errMsg})'.format(
  21. klass=self.__class__.__name__,
  22. client=repr(self.client),
  23. errCode=self.errCode,
  24. errMsg=self.errMsg)
  25. else:
  26. _repr = '{klass}(errCode: {errCode}, errMsg: {errMsg})'.format(
  27. klass=self.__class__.__name__,
  28. errCode=self.errCode,
  29. errMsg=self.errMsg)
  30. return _repr
  31. def __repr__(self):
  32. return str(self)
  33. class Constant(object):
  34. COMPANY_CODE = 1009
  35. APP_KEY = "k1009yc83einjr9hpkc21i6hzecqw2n7ou"
  36. class TianAn(object):
  37. URL_BASE = "http://47.96.41.38:8089/api/"
  38. def __init__(self, companyCode, appKey, timeout=None, autoRetry=False):
  39. self._companyCode = companyCode
  40. self._appKey = appKey
  41. self._timeout = timeout
  42. self._autoRetry = autoRetry
  43. def _request(self, method, path, **kwargs):
  44. logger.info("[TianAn request] method = {}, path = {}, kwargs = {}".format(method, path, kwargs))
  45. url = urljoin(self.URL_BASE, path)
  46. headers = {
  47. "Content-Type": "application/x-www-form-urlencoded",
  48. }
  49. kwargs.setdefault("params", {})
  50. kwargs.setdefault("timeout", self._timeout)
  51. processor = kwargs.pop("processor", None)
  52. with requests.sessions.Session() as _session:
  53. res = _session.request(
  54. method=method,
  55. url=url,
  56. headers=headers,
  57. **kwargs
  58. )
  59. try:
  60. res.raise_for_status()
  61. except requests.RequestException as rre:
  62. logger.info("[{} send request] error! status code = {}, error = {}".format(self.__class__.__name__, res.status_code, rre))
  63. raise TianAnException(
  64. errCode='HTTP{}'.format(res.status_code),
  65. errMsg=rre.message,
  66. client=self,
  67. request=rre.request,
  68. response=rre.response
  69. )
  70. return self._handle_result(
  71. res, method, url, processor, **kwargs
  72. )
  73. def _handle_result(self, res, method, url, processor, **kwargs):
  74. result = json.loads(res.content.decode('utf-8', 'ignore'), strict=False)
  75. logger.info("[TianAn _handle_result] method = {}, url = {}, result = {}".format(method, url, result))
  76. if processor:
  77. return processor(self, result)
  78. if "code" in result and result["code"] == "0":
  79. return result
  80. # 重试机制待调试
  81. if self._autoRetry:
  82. return self._request(method, res.request.path_url, processor=processor, **kwargs)
  83. raise TianAnException(
  84. errCode=result.get("code"),
  85. errMsg=result.get("msg"),
  86. client=self
  87. )
  88. def _post(self, **kwargs):
  89. return self._request("post", **kwargs)
  90. def _get(self, **kwargs):
  91. return self._request("get", **kwargs)
  92. def _get_token(self, qydm=None, key=None, timestamp=None):
  93. """
  94. :param qydm: 企业代码 固定
  95. :param key: 固定
  96. :param timestamp: 时间戳 各位为 yyyy-MM-dd hh24:mm:ss
  97. """
  98. qydm = qydm or self._companyCode
  99. key = key or self._appKey
  100. timestamp = timestamp or datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  101. logger.debug("[TianAn get_token] qydm = {}, key = {}, timestamp = {}".format(qydm, key, timestamp))
  102. s = "{qydm}{key}{timestamp}".format(
  103. qydm=qydm, key=key, timestamp=timestamp
  104. )
  105. token = hashlib.md5(s.encode("utf-8")).hexdigest().lower()
  106. logger.debug("[TianAn get_token] token = {}".format(token))
  107. return token
  108. def submit_charge_insurance(self, orderNo, logicalCode, startTime, province, city, area, address, finishTime=None):
  109. qydm, nowtime = self._companyCode, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  110. token = self._get_token(qydm, timestamp=nowtime)
  111. data = {
  112. "qydm": qydm,
  113. "token": token,
  114. "ddh": orderNo,
  115. "sbh": logicalCode,
  116. "kssj": startTime,
  117. "jssj": finishTime or startTime,
  118. "sheng": province,
  119. "shi": city,
  120. "xian": area,
  121. "xxdz": address,
  122. "nowtime": nowtime
  123. }
  124. return self._post(path="adddevdata", data=data)
  125. def submit_site_insurance(self, logicalCode, partNums, addTime, address, devType=1, remarks=None):
  126. """
  127. :param logicalCode: 设备编号
  128. :param partNums: 插座个数
  129. :param addTime: 安装时间
  130. :param address: 安装地址
  131. :param devType: 设备类型 暂时固定为1
  132. :param remarks: 备注 选填
  133. """
  134. qydm, nowtime = self._companyCode, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  135. token = self._get_token(qydm, timestamp=nowtime)
  136. data = {
  137. "qydm": qydm,
  138. "token": token,
  139. "nowtime": nowtime,
  140. "czlx": "add",
  141. "sbbh": logicalCode,
  142. "czgs": partNums,
  143. "azsj": addTime,
  144. "azwz": address,
  145. "sblx": devType,
  146. "beizhu": remarks or ""
  147. }
  148. return self._post(path="sbgl", data=data)
  149. def edit_site_insurance(self, logicalCode, partNums, addTime, address, devType=1, remarks=None):
  150. qydm, nowtime = self._companyCode, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  151. token = self._get_token(qydm, timestamp=nowtime)
  152. data = {
  153. "qydm": qydm,
  154. "token": token,
  155. "nowtime": nowtime,
  156. "czlx": "edit",
  157. "sbbh": logicalCode,
  158. "czgs": partNums,
  159. "azsj": addTime,
  160. "azwz": address,
  161. "sblx": devType,
  162. "beizhu": remarks or ""
  163. }
  164. return self._post(path="sbgl", data=data)
  165. def del_site_insurance(self, logicalCode):
  166. qydm, nowtime = self._companyCode, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  167. token = self._get_token(qydm, timestamp=nowtime)
  168. data = {
  169. "qydm": qydm,
  170. "token": token,
  171. "nowtime": nowtime,
  172. "czlx": "del",
  173. "sbbh": logicalCode,
  174. }
  175. return self._post(path="sbgl", data=data)
  176. def query_site_insurance(self, startTime, endTime): # type: (Optional[datetime.datetime, str], Optional[datetime.datetime, str]) -> list
  177. """
  178. :param startTime: 订单提交的起始日期
  179. :param endTime: 订单提交的结束日期
  180. 放回的rows
  181. [
  182. {
  183. 'aymd': '20230403', 保单生成日期
  184. 'bxdh': 'testbx66', 保单号
  185. 'bxdhsbxxlist': [ # 对应的设备列表
  186. {'sbbh': 'xxx'}, {'sbbh': 'xxxx'}
  187. ],
  188. 'bxjssj': '2024-04-03 14:45:47', # 保险开始时间
  189. 'bxkssj': '2023-04-03 14:45:45', # 保险结束时间
  190. 'bxqx': '1', # 期限 单位年
  191. 'dysbnum': 2, # 对应的设备数量
  192. 'qydm': '1003', # 企业代码 无用
  193. 'sbxxbxdhbid': '2023040314461490434913954', 主键 遇到问题时候查询(售后)
  194. 'scsjendymd': '20230331', 该保险单号对应的上传设备开始日期
  195. 'scsjstartymd': '20230325' 该保险单号对应的上传设备结束日期
  196. }
  197. ]
  198. """
  199. qydm, nowtime = self._companyCode, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  200. token = self._get_token(qydm, timestamp=nowtime)
  201. if isinstance(startTime, (unicode, str)):
  202. try:
  203. startTime = datetime.datetime.strptime(startTime, "%Y-%m-%d")
  204. except ValueError:
  205. raise TianAnException(errCode="", errMsg=u"请传入正确的时间格式:%Y-%m-%d")
  206. startTime = startTime.strftime("%Y%m%d")
  207. if isinstance(endTime, (unicode, str)):
  208. try:
  209. endTime = datetime.datetime.strptime(endTime, "%Y-%m-%d")
  210. except ValueError:
  211. raise TianAnException(errCode="", errMsg=u"请传入正确的时间格式:%Y-%m-%d")
  212. endTime = endTime.strftime("%Y%m%d")
  213. data = {
  214. "qydm": qydm,
  215. "token": token,
  216. "nowtime": nowtime,
  217. "startymd": startTime,
  218. "endymd": endTime,
  219. }
  220. result = self._post(path="getSbglBxdh", data=data)
  221. if "rows" not in result:
  222. raise TianAnException(errCode="", errMsg=u"未获取到数据")
  223. return result["rows"]
  224. def get_client():
  225. return TianAn(Constant.COMPANY_CODE, Constant.APP_KEY)