ComboCronPushController.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. # -*- encoding: utf-8 -*-
  2. """
  3. @File : ComboCronPushController.py
  4. @Time : 2022/7/8 19:52
  5. @Author : stephen
  6. @Email : zhangdongming@asj6.wecom.work
  7. @Software: PyCharm
  8. """
  9. import logging
  10. import time
  11. import traceback
  12. from django.db.models import Q
  13. from django.views import View
  14. from Model.models import UnicomComboOrderInfo, UnicomDeviceInfo, GatewayPush, SysMsgModel, UnicomFlowPush, Device_User, \
  15. Device_Info
  16. from Object.AliyunSmsObject import AliyunSmsObject
  17. from Object.ResponseObject import ResponseObject
  18. from Service.HuaweiPushService.HuaweiPushService import HuaweiPushObject
  19. from Service.PushService import PushObject
  20. from AnsjerPush.config import XM_PUSH_CHANNEL_ID
  21. class ComboCronPushView(View):
  22. def get(self, request, *args, **kwargs):
  23. request.encoding = 'utf-8'
  24. operation = kwargs.get('operation')
  25. return self.validation(request.GET, request, operation)
  26. def post(self, request, *args, **kwargs):
  27. request.encoding = 'utf-8'
  28. operation = kwargs.get('operation')
  29. return self.validation(request.POST, request, operation)
  30. def validation(self, request_dict, request, operation):
  31. print(request_dict)
  32. print(request)
  33. response = ResponseObject()
  34. if operation == 'expire-push':
  35. return self.combo_expire_push(response)
  36. elif operation == 'warning-push':
  37. return self.flow_warning_push(response)
  38. else:
  39. return response.json(404)
  40. @classmethod
  41. def combo_expire_push(cls, response):
  42. """
  43. 套餐到期预警通知,分别7前3天前消息推送
  44. """
  45. logger = logging.getLogger('info')
  46. logger.info('进入流量包过期消息推送')
  47. try:
  48. now_time = int(time.time())
  49. combo_order_qs = UnicomComboOrderInfo.objects.filter(
  50. ~Q(status=2) & Q(expire_time__gt=now_time + 3600 * 144) & Q(
  51. expire_time__lte=(now_time + 3600 * 168)), is_del=False).exclude(combo_id=33).values()
  52. if combo_order_qs.exists():
  53. cls.phone_msg_push(combo_order_qs)
  54. combo_order_qs = UnicomComboOrderInfo.objects.filter(
  55. ~Q(status=2) & Q(expire_time__gt=now_time + 3600 * 48) & Q(
  56. expire_time__lte=(now_time + 3600 * 72)), is_del=False).exclude(combo_id=33).values()
  57. if combo_order_qs.exists():
  58. cls.phone_msg_push(combo_order_qs)
  59. return response.json(0)
  60. except Exception as e:
  61. print(e.args)
  62. ex = traceback.format_exc()
  63. print(ex)
  64. return response.json(177, ex)
  65. @classmethod
  66. def phone_msg_push(cls, combo_order_qs):
  67. """
  68. 消息推送
  69. """
  70. now_time = int(time.time())
  71. for item in combo_order_qs:
  72. iccid = item['iccid']
  73. device_info = UnicomDeviceInfo.objects.filter(iccid=iccid).values()
  74. if not device_info.exists():
  75. continue
  76. nickname = device_info.first()['serial_no']
  77. user_id = device_info.first()['user_id']
  78. if not user_id:
  79. continue
  80. # 查询推送配置数据
  81. push_qs = GatewayPush.objects.filter(user_id=user_id, logout=False). \
  82. values('user_id', 'app_bundle_id', 'app_type', 'push_type', 'token_val', 'm_code', 'lang', 'tz')
  83. if not push_qs.exists():
  84. continue
  85. user_list = []
  86. for push_vo in push_qs:
  87. kwargs = {
  88. 'n_time': now_time,
  89. 'event_type': 1,
  90. 'nickname': nickname,
  91. }
  92. push_type = push_vo['push_type']
  93. token_val = push_vo['token_val']
  94. lang = push_vo['lang']
  95. app_bundle_id = push_vo['app_bundle_id']
  96. # 获取推送所需数据
  97. msg_title = PushObject.get_msg_title(nickname)
  98. if lang == 'cn':
  99. sys_msg_text = "温馨提示:尊敬的客户,您" + nickname + "设备4G流量套餐将在" + time.strftime("%Y-%m-%d", time.localtime(
  100. item['expire_time'])) + "到期"
  101. else:
  102. sys_msg_text = 'Dear customer,the flow package for your device ' + nickname + ' will expire on ' + \
  103. time.strftime('%m-%d-%y', time.localtime(item['expire_time']))
  104. kwargs['app_bundle_id'] = app_bundle_id
  105. kwargs['token_val'] = token_val
  106. kwargs['msg_title'] = msg_title
  107. kwargs['msg_text'] = sys_msg_text
  108. if user_id not in user_list:
  109. cls.sys_msg_save(user_id, nickname, now_time, sys_msg_text)
  110. user_list.append(user_id)
  111. if not cls.msg_push(push_type, **kwargs):
  112. continue
  113. return True
  114. @classmethod
  115. def sys_msg_save(cls, user_id, serial_no, n_time, text_msg):
  116. """
  117. 系统消息存库
  118. """
  119. logger = logging.getLogger('info')
  120. try:
  121. data = {'addTime': n_time, 'updTime': n_time, 'userID_id': user_id, 'eventType': 0, 'msg': text_msg,
  122. 'uid': serial_no}
  123. SysMsgModel.objects.create(**data)
  124. except Exception as e:
  125. logger.info('---4G流量存库异常--- {}'.format(repr(e)))
  126. @classmethod
  127. def flow_warning_push(cls, response):
  128. """
  129. 处理流量到期或使用量预警的消息推送
  130. 流程说明:
  131. 1. 查询所有待处理的流量推送通知
  132. 2. 遍历每个通知,校验设备及用户信息
  133. 3. 计算流量使用情况,检查关联套餐
  134. 4. 生成推送消息内容,通过短信和系统消息推送
  135. 5. 更新通知状态,记录推送日志
  136. Args:
  137. response: 响应对象,用于返回处理结果
  138. Returns:
  139. response.json(0): 固定返回成功响应
  140. """
  141. logger = logging.getLogger('info')
  142. flow_push_qs = UnicomFlowPush.objects.filter(status=0)
  143. if not flow_push_qs.exists():
  144. return response.json(0)
  145. for item in flow_push_qs:
  146. try:
  147. user_id = item.user_id
  148. if not user_id:
  149. continue
  150. device_info_qs = Device_Info.objects.filter(userID_id=user_id, serial_number=item.serial_no) \
  151. .values('userID__phone', 'Type')
  152. if not device_info_qs.exists():
  153. logger.info('推送4G通知设备未被当前客户添加:{},serial:{}'.format(user_id, item.serial_no))
  154. continue
  155. now_time = int(time.time())
  156. usage = cls.flow_split(item.flow_total_usage)
  157. total = cls.flow_split(item.flow_total)
  158. usable = cls.flow_split(item.flow_total - item.flow_total_usage)
  159. # 查询当前套餐并且套餐类型不等于长期无限流量
  160. unicom_order_qs = UnicomComboOrderInfo.objects.filter(id=item.combo_order_id).exclude(combo_id=33) \
  161. .values('combo__combo_name')
  162. if unicom_order_qs.exists():
  163. logger.info(f'推送4G通知套餐订单不存在或长期无限流量不通知:{item.combo_order_id}')
  164. UnicomFlowPush.objects.filter(id=item.id).update(status=1, updated_time=now_time)
  165. continue
  166. # 查询推送配置数据
  167. push_qs = GatewayPush.objects.filter(user_id=user_id, logout=False).values('user_id',
  168. 'app_bundle_id',
  169. 'app_type', 'push_type',
  170. 'token_val', 'm_code',
  171. 'lang', 'tz').order_by(
  172. '-id')[:5]
  173. msg = False
  174. if item.type != 0 and item.type != 1: # 不等于流量预警通知并且不等于流量到期
  175. combo_name = unicom_order_qs.first()['combo__combo_name'] if unicom_order_qs.exists() else ''
  176. sys_msg = cls.get_sys_msg_text(item.serial_no, combo_name, item.type)
  177. msg = True
  178. else:
  179. if device_info_qs[0]['userID__phone']:
  180. params = u'{"devname":"' + item.serial_no + '","usage":"流量' + usage + '","usable":"流量' + \
  181. usable + '","total":"流量共' + total + '"}'
  182. cls.send_aliyun_sms(device_info_qs[0]['userID__phone'], params, 'SMS_246100414')
  183. lang = push_qs[0]['lang'] if push_qs.exists() else 'cn'
  184. sys_msg = cls.get_msg_text(item.serial_no, lang, total, usage, usable)
  185. cls.sys_msg_save(user_id, item.serial_no, now_time, sys_msg)
  186. # 修改推送状态
  187. UnicomFlowPush.objects.filter(id=item.id).update(status=1, updated_time=now_time)
  188. if not push_qs.exists():
  189. logger.info('推送4G通知APP未登录:{},serial:{}'.format(user_id, item.serial_no))
  190. continue
  191. for push_vo in push_qs:
  192. kwargs = {
  193. 'n_time': now_time,
  194. 'event_type': 1,
  195. 'nickname': item.serial_no,
  196. }
  197. push_type = push_vo['push_type']
  198. token_val = push_vo['token_val']
  199. lang = push_vo['lang']
  200. app_bundle_id = push_vo['app_bundle_id']
  201. # 获取推送所需数据
  202. msg_title = PushObject.get_msg_title(item.serial_no)
  203. sys_msg_text = sys_msg if msg else cls.get_msg_text(item.serial_no, lang, total, usage, usable)
  204. kwargs['app_bundle_id'] = app_bundle_id
  205. kwargs['token_val'] = token_val
  206. kwargs['msg_title'] = msg_title
  207. kwargs['msg_text'] = sys_msg_text
  208. if not cls.msg_push(push_type, **kwargs):
  209. continue
  210. except Exception as e:
  211. logger.info('推送4G通知消息异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  212. continue
  213. return response.json(0)
  214. @staticmethod
  215. def get_msg_text(serial_no, lang, total, usage, usable):
  216. """
  217. app消息推送内容
  218. """
  219. if lang == 'cn':
  220. sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前套餐总流量共" + total + ",已使用" + \
  221. usage + "" + ",剩余" + usable + ""
  222. else:
  223. sys_msg_text = 'Warm tip: Dear customer, the total traffic of your ' + serial_no + \
  224. ' device is ' + total + 'g in the current package. ' + usage + \
  225. ' has been used and ' + usable + ' is left'
  226. return sys_msg_text
  227. @staticmethod
  228. def msg_push(push_type, **kwargs):
  229. """
  230. app推送
  231. """
  232. logger = logging.getLogger('info')
  233. try:
  234. # ios apns
  235. if push_type == 0:
  236. PushObject.ios_apns_push(**kwargs)
  237. # android gcm
  238. elif push_type == 1:
  239. PushObject.android_fcm_push_v1(**kwargs)
  240. # android 极光推送
  241. elif push_type == 2:
  242. PushObject.android_jpush(**kwargs)
  243. elif push_type == 3:
  244. huawei_push_object = HuaweiPushObject()
  245. huawei_push_object.send_push_notify_message(**kwargs)
  246. # android 小米推送
  247. elif push_type == 4:
  248. channel_id = XM_PUSH_CHANNEL_ID['service_reminder']
  249. PushObject.android_xmpush(channel_id=channel_id, **kwargs)
  250. # android vivo推送
  251. elif push_type == 5:
  252. PushObject.android_vivopush(**kwargs)
  253. # android oppo推送
  254. elif push_type == 6:
  255. channel_id = 'VALUE_ADDED'
  256. PushObject.android_oppopush(channel_id=channel_id, **kwargs)
  257. # android 魅族推送
  258. elif push_type == 7:
  259. PushObject.android_meizupush(**kwargs)
  260. return True
  261. except Exception as e:
  262. logger.info('流量预警推送异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  263. return False
  264. @staticmethod
  265. def send_aliyun_sms(phone, params, temp_code):
  266. """
  267. 推送阿里云国内短信通知
  268. """
  269. sign = '周视'
  270. ali_sms = AliyunSmsObject()
  271. ali_sms.send_code_sms_cloud(phone, params, sign, temp_code)
  272. @staticmethod
  273. def flow_split(flow):
  274. """
  275. 流量保留两位小数并带单位
  276. """
  277. if flow >= 1024:
  278. flow = flow / 1024
  279. return str(round(flow, 2)) + "G"
  280. else:
  281. return str(round(flow, 2)) + "M"
  282. @staticmethod
  283. def get_sys_msg_text(serial_no, combo_name, sys_type):
  284. """
  285. 获取系统消息文本
  286. @return:
  287. """
  288. if sys_type == 4:
  289. sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前4G" + combo_name + "已到期"
  290. elif sys_type == 3:
  291. sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前4G" + combo_name + "已激活"
  292. else:
  293. sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前4G" + combo_name + "已用完"
  294. return sys_msg_text