UnicomObject.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. # -*- encoding: utf-8 -*-
  2. """
  3. @File : UnicomObject.py
  4. @Time : 2022/6/17 11:03
  5. @Author : stephen
  6. @Email : zhangdongming@asj6.wecom.work
  7. @Software: PyCharm
  8. """
  9. import base64
  10. import datetime
  11. import json
  12. from decimal import Decimal
  13. import requests
  14. from Crypto.Cipher import AES
  15. from Ansjer.config import unicomAppUrl, unicomAppId, unicomAppSecret, unicomTenantId, \
  16. unicomEncodeKey, unicomIvKey, unicomUserName, unicomPassword, unicomPushKey
  17. from Object.RedisObject import RedisObject
  18. from Object.utils import SM3Util
  19. from Object.utils.SymmetricCryptoUtil import AESencrypt
  20. """
  21. 联通4Gapi
  22. 具体参数查看接口文档
  23. https://www.showdoc.com.cn/unicomJYHapi/8158648460007467
  24. """
  25. class UnicomObjeect:
  26. def __init__(self):
  27. self.appUrl = unicomAppUrl
  28. self.appId = unicomAppId
  29. self.appSecret = unicomAppSecret
  30. self.tenantId = unicomTenantId
  31. self.encodeKey = unicomEncodeKey
  32. self.ivKey = unicomIvKey
  33. self.username = unicomUserName
  34. self.password = unicomPassword
  35. self.pushKey = unicomPushKey
  36. self.headers = {'Tenant': self.tenantId, 'content-type': 'application/x-www-form-urlencoded'}
  37. # pip install snowland-smx
  38. def createSign(self, reverse=False, **sign_params):
  39. """
  40. 调用接口(API)时需要对请求参数进行签名(sign)验证,
  41. 算法:
  42. 根据参数名称将你的所有请求参数按照字母先后顺序排序: key = value & key = value,对除签名外的所有请求参数按
  43. key
  44. 做的升序排列。
  45. 如:将
  46. foo = 1, bar = 2, baz = 3
  47. 排序为
  48. bar = 2, baz = 3, foo = 1
  49. 参数名和参数值链接后,得到拼装字符串(注意:参数名与参数值左右两边不能包含空格)
  50. bar = 2 & baz = 3 & foo = 1
  51. pushkey拼接到参数字符尾部进行
  52. SM3
  53. 加密,再转化成大写,格式是
  54. (SM3(key1=value1 & key2=value2 &...& key= pushKey)).upcase
  55. @param reverse:
  56. @param sign_params:
  57. @return:
  58. """
  59. dict_2 = dict(sorted(sign_params.items(), key=lambda item: item[0], reverse=reverse))
  60. data_list = []
  61. for item in dict_2.items():
  62. if item[0] and item[1]:
  63. data_list.append("{}={}".format(item[0], item[1]))
  64. val = '&'.join(data_list)
  65. push_key = '&key={}'.format(self.pushKey)
  66. val = val + push_key
  67. return SM3Util.Hash_sm3(val).upper()
  68. def get_login_authorization(self):
  69. """
  70. 获取登录授权
  71. 注意登录认证Authorization和登录后的请求认证不一样
  72. 算法:appId+":"+appSecret base64转码生成 前面加Basic
  73. @return: "Basic " + base64_data
  74. """
  75. voucher = self.appId + ':' + self.appSecret
  76. base64_data = str(base64.b64encode(voucher.encode("utf-8")), "utf-8")
  77. return "Basic " + base64_data
  78. def get_encode_password(self):
  79. """
  80. 获取对称加密
  81. @return: encrypt_pwd
  82. """
  83. aes = AESencrypt(self.encodeKey.encode('utf-8'), AES.MODE_CBC, self.ivKey.encode('utf-8'),
  84. paddingMode="ZeroPadding",
  85. characterSet='utf-8')
  86. encrypt_pwd = aes.encryptFromString(self.password)
  87. return encrypt_pwd
  88. def generate_token(self):
  89. """
  90. 生成令牌
  91. @return: token
  92. """
  93. url = self.appUrl + '/auc/oauth/token'
  94. pwd = self.get_encode_password()
  95. body = {'username': self.username, 'password': pwd, 'grant_type': 'password', 'scope': 'server'}
  96. headers = self.headers
  97. headers['Authorization'] = self.get_login_authorization()
  98. response_data = requests.post(url, data=body, headers=headers)
  99. response_data = json.loads(response_data.text)
  100. return response_data['access_token']
  101. def refresh_token(self, refresh_token):
  102. """
  103. 刷新令牌
  104. @param refresh_token:
  105. @return:
  106. """
  107. url = self.appUrl + '/auc/oauth/token?grant_type=refresh_token'
  108. body = {'refresh_token': refresh_token, 'grant_type': 'refresh_token'}
  109. headers = self.headers
  110. headers['Authorization'] = self.get_login_authorization()
  111. response_data = requests.post(url, data=body, headers=headers)
  112. return response_data.text
  113. def business_unify_headers(self):
  114. """
  115. 业务统一headers
  116. 在请求头中增加key为Authorization,value为"Bearer " + token
  117. @return: headers
  118. """
  119. token = self.generate_token()
  120. headers = self.headers
  121. headers['Authorization'] = 'Bearer ' + token
  122. return headers
  123. # 业务api 注意 get与post 请求数据类型不同 post使用:application/json
  124. def verify_device(self, **re_params):
  125. """
  126. 验证设备
  127. @param re_params:
  128. @return:
  129. """
  130. url = self.appUrl + '/platform/api/device/verify-device'
  131. return requests.get(url, params=re_params, headers=self.business_unify_headers())
  132. def query_device_status(self, **re_params):
  133. """
  134. 查询设备状态
  135. @param re_params:
  136. @return:
  137. """
  138. url = self.appUrl + '/platform/api/device/device-status'
  139. return requests.get(url, params=re_params, headers=self.business_unify_headers())
  140. def update_device_state(self, **re_data):
  141. """
  142. 修改设备状态
  143. @param re_data:
  144. @return:
  145. """
  146. url = self.appUrl + '/platform/api/device/device-state'
  147. headers = self.business_unify_headers()
  148. headers['content-type'] = 'application/json'
  149. return requests.post(url, data=json.dumps(re_data), headers=headers)
  150. def query_device_usage_history(self, **re_params):
  151. """
  152. 查询设备用量历史
  153. @param re_params:
  154. @return:
  155. """
  156. url = self.appUrl + '/platform/api/usage/device-usage-history'
  157. return requests.get(url, params=re_params, headers=self.business_unify_headers())
  158. def query_current_renew_list_usage_details(self, **re_params):
  159. """
  160. 查询设备当前队列用量详情
  161. @param re_params:
  162. @return:
  163. """
  164. url = self.appUrl + '/platform/api/usage/current-renewlist-usage-details'
  165. return requests.get(url, params=re_params, headers=self.business_unify_headers())
  166. def get_device_batch_detail(self, **re_data):
  167. """
  168. 查询设备当前队列用量详情
  169. @return:
  170. """
  171. url = self.appUrl + '/platform/api/device/batch-detail'
  172. headers = self.business_unify_headers()
  173. headers['content-type'] = 'application/json'
  174. return requests.post(url, data=json.dumps(re_data), headers=headers)
  175. def query_package_list(self, **re_params):
  176. """
  177. 查询套餐列表
  178. @return:
  179. """
  180. url = self.appUrl + '/platform/api/package/list'
  181. return requests.get(url, params=re_params, headers=self.business_unify_headers())
  182. def query_renewal_list(self, **re_params):
  183. """
  184. 续费套餐列表
  185. @param re_params:
  186. @return:
  187. """
  188. url = self.appUrl + '/platform/api/package/list'
  189. return requests.get(url, params=re_params, headers=self.business_unify_headers())
  190. def async_buy_package(self, **re_data):
  191. """
  192. 查询设备当前队列用量详情
  193. @return:
  194. """
  195. url = self.appUrl + '/platform/api/package/async-buy-package'
  196. headers = self.business_unify_headers()
  197. headers['content-type'] = 'application/json'
  198. return requests.post(url, data=json.dumps(re_data), headers=headers)
  199. @staticmethod
  200. def get_text_dict(result):
  201. """
  202. 响应结果转字典
  203. @param result:
  204. @return:
  205. """
  206. if result.status_code == 200:
  207. return json.loads(result.text)
  208. return None
  209. @staticmethod
  210. def unicom_flow_usage_cache(key, expire=0, **usage_data):
  211. """
  212. 流量用量历史优先查询缓存
  213. @param key: 缓存key
  214. @param expire: 失效时间
  215. @param usage_data: 查询参数
  216. @return: 返回结果dict
  217. """
  218. redis = RedisObject()
  219. usage_history = redis.get_data(key)
  220. if usage_history:
  221. usage_history = json.loads(usage_history)
  222. else:
  223. usage_history = UnicomObjeect().query_device_usage_history(**usage_data)
  224. usage_history = UnicomObjeect().get_text_dict(usage_history)
  225. redis.set_data(key=key, val=json.dumps(usage_history), expire=expire)
  226. return usage_history
  227. @staticmethod
  228. def get_flow_usage_total(usage_year, usage_month, iccid):
  229. """
  230. 查询当月用量历史
  231. @param usage_year: 使用年
  232. @param usage_month: 使用月
  233. @param iccid: 联通id
  234. @return: flow_total_usage 当月实际使用流量
  235. """
  236. flow_key = 'ASJ:UNICOM:FLOW:{}'
  237. usage_data = {'iccid': iccid}
  238. usage_history = UnicomObjeect().unicom_flow_usage_cache(flow_key.format(iccid), (60 * 10 + 3), **usage_data)
  239. # 当月实际总使用流量
  240. flow_total_usage = 0
  241. if usage_history and usage_history['success']:
  242. device_usage_history_list = usage_history['data']['deviceUsageHistory']
  243. if device_usage_history_list:
  244. for item in device_usage_history_list:
  245. if item['year'] != usage_year or item['month'] != usage_month:
  246. continue
  247. flow_total_usage += item['flowTotalUsage']
  248. return flow_total_usage
  249. @staticmethod
  250. def change_device_to_activate(iccid):
  251. """
  252. 根据iccid判断是否激活,未激活则修改为激活状态
  253. @param iccid:
  254. @return:
  255. """
  256. if iccid:
  257. re_data = {'iccid': iccid}
  258. result = UnicomObjeect().query_device_status(**re_data)
  259. res_dict = UnicomObjeect().get_text_dict(result)
  260. # 状态不等于1(激活)时进行激活 1:激活;2:停用
  261. if res_dict['data']['status'] != 1:
  262. re_data = {"iccid": iccid, "status": 1}
  263. UnicomObjeect().update_device_state(**re_data)
  264. return True
  265. return None
  266. @staticmethod
  267. def change_device_to_disable(iccid):
  268. """
  269. 修改设备为停用,并查看是否修改成功
  270. @param iccid:
  271. @return:
  272. """
  273. if iccid:
  274. re_data = {"iccid": iccid, "status": 2}
  275. UnicomObjeect().update_device_state(**re_data)
  276. # 查询是否停用成功
  277. re_data.pop('status')
  278. result = UnicomObjeect().query_device_status(**re_data)
  279. res_dict = UnicomObjeect().get_text_dict(result)
  280. if res_dict['data']['status'] != 3:
  281. UnicomObjeect().update_device_state(**re_data)
  282. return True
  283. return None
  284. if __name__ == '__main__':
  285. today = datetime.datetime.today()
  286. year = today.year
  287. month = today.month
  288. print(year)
  289. print(month)
  290. print(type(year))
  291. if not '':
  292. print('为空')
  293. price = '12.13'
  294. print(float(price))
  295. discount = '6'
  296. dd = Decimal(price) - Decimal(discount)
  297. print(dd.quantize(Decimal('0.00')))
  298. unicom_api = UnicomObjeect()
  299. data = {'foo': 1, 'bar': 2, 'baz': 3}
  300. print(unicom_api.createSign(**data))
  301. # result = unicom_api.generate_token()
  302. # result = unicom_api.refresh_token('5d0c0f30-99bd-4f17-9614-3524495b05d4')
  303. params = {'iccid': '89860621330065433774', 'status': 2}
  304. # response = unicom_api.verify_device(**params)
  305. # response = unicom_api.query_device_status(**params)
  306. response = unicom_api.update_device_state(**params)
  307. # response = unicom_api.query_device_usage_history(**params)
  308. # response = unicom_api.query_current_renew_list_usage_details(**params)
  309. # unicom_api.get_device_batch_detail()
  310. # response = unicom_api.query_package_list(**params)
  311. # response = unicom_api.query_renewal_list(**params)
  312. if response.status_code == 200:
  313. res = json.loads(response.text)
  314. print(res)
  315. response_json = {
  316. "success": True,
  317. "msg": "操作成功",
  318. "code": 0,
  319. "data": {
  320. "iccid": "8986062018007784202",
  321. "completeIccid": "89860620180077842020",
  322. "status": 1
  323. }
  324. }
  325. print(response_json['data']['iccid'])
  326. print(response.status_code)