# -*- encoding: utf-8 -*- """ @File : ComboCronPushController.py @Time : 2022/7/8 19:52 @Author : stephen @Email : zhangdongming@asj6.wecom.work @Software: PyCharm """ import logging import time import traceback from django.db.models import Q from django.views import View from Model.models import UnicomComboOrderInfo, UnicomDeviceInfo, GatewayPush, SysMsgModel, UnicomFlowPush, Device_User, \ Device_Info from Object.AliyunSmsObject import AliyunSmsObject from Object.ResponseObject import ResponseObject from Service.HuaweiPushService.HuaweiPushService import HuaweiPushObject from Service.PushService import PushObject from AnsjerPush.config import XM_PUSH_CHANNEL_ID class ComboCronPushView(View): def get(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation') return self.validation(request.GET, request, operation) def post(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation') return self.validation(request.POST, request, operation) def validation(self, request_dict, request, operation): print(request_dict) print(request) response = ResponseObject() if operation == 'expire-push': return self.combo_expire_push(response) elif operation == 'warning-push': return self.flow_warning_push(response) else: return response.json(404) @classmethod def combo_expire_push(cls, response): """ 套餐到期预警通知,分别7前3天前消息推送 """ logger = logging.getLogger('info') logger.info('进入流量包过期消息推送') try: now_time = int(time.time()) combo_order_qs = UnicomComboOrderInfo.objects.filter( ~Q(status=2) & Q(expire_time__gt=now_time + 3600 * 144) & Q( expire_time__lte=(now_time + 3600 * 168)), is_del=False).exclude(combo_id=33).values() if combo_order_qs.exists(): cls.phone_msg_push(combo_order_qs) combo_order_qs = UnicomComboOrderInfo.objects.filter( ~Q(status=2) & Q(expire_time__gt=now_time + 3600 * 48) & Q( expire_time__lte=(now_time + 3600 * 72)), is_del=False).exclude(combo_id=33).values() if combo_order_qs.exists(): cls.phone_msg_push(combo_order_qs) return response.json(0) except Exception as e: print(e.args) ex = traceback.format_exc() print(ex) return response.json(177, ex) @classmethod def phone_msg_push(cls, combo_order_qs): """ 消息推送 """ now_time = int(time.time()) for item in combo_order_qs: iccid = item['iccid'] device_info = UnicomDeviceInfo.objects.filter(iccid=iccid).values() if not device_info.exists(): continue nickname = device_info.first()['serial_no'] user_id = device_info.first()['user_id'] if not user_id: continue # 查询推送配置数据 push_qs = GatewayPush.objects.filter(user_id=user_id, logout=False). \ values('user_id', 'app_bundle_id', 'app_type', 'push_type', 'token_val', 'm_code', 'lang', 'tz') if not push_qs.exists(): continue user_list = [] for push_vo in push_qs: kwargs = { 'n_time': now_time, 'event_type': 1, 'nickname': nickname, } push_type = push_vo['push_type'] token_val = push_vo['token_val'] lang = push_vo['lang'] app_bundle_id = push_vo['app_bundle_id'] # 获取推送所需数据 msg_title = PushObject.get_msg_title(nickname) if lang == 'cn': sys_msg_text = "温馨提示:尊敬的客户,您" + nickname + "设备4G流量套餐将在" + time.strftime("%Y-%m-%d", time.localtime( item['expire_time'])) + "到期" else: sys_msg_text = 'Dear customer,the flow package for your device ' + nickname + ' will expire on ' + \ time.strftime('%m-%d-%y', time.localtime(item['expire_time'])) kwargs['app_bundle_id'] = app_bundle_id kwargs['token_val'] = token_val kwargs['msg_title'] = msg_title kwargs['msg_text'] = sys_msg_text if user_id not in user_list: cls.sys_msg_save(user_id, nickname, now_time, sys_msg_text) user_list.append(user_id) if not cls.msg_push(push_type, **kwargs): continue return True @classmethod def sys_msg_save(cls, user_id, serial_no, n_time, text_msg): """ 系统消息存库 """ logger = logging.getLogger('info') try: data = {'addTime': n_time, 'updTime': n_time, 'userID_id': user_id, 'eventType': 0, 'msg': text_msg, 'uid': serial_no} SysMsgModel.objects.create(**data) except Exception as e: logger.info('---4G流量存库异常--- {}'.format(repr(e))) @classmethod def flow_warning_push(cls, response): """ 处理流量到期或使用量预警的消息推送 流程说明: 1. 查询所有待处理的流量推送通知 2. 遍历每个通知,校验设备及用户信息 3. 计算流量使用情况,检查关联套餐 4. 生成推送消息内容,通过短信和系统消息推送 5. 更新通知状态,记录推送日志 Args: response: 响应对象,用于返回处理结果 Returns: response.json(0): 固定返回成功响应 """ logger = logging.getLogger('info') flow_push_qs = UnicomFlowPush.objects.filter(status=0) if not flow_push_qs.exists(): return response.json(0) for item in flow_push_qs: try: user_id = item.user_id if not user_id: continue device_info_qs = Device_Info.objects.filter(userID_id=user_id, serial_number=item.serial_no) \ .values('userID__phone', 'Type') if not device_info_qs.exists(): logger.info('推送4G通知设备未被当前客户添加:{},serial:{}'.format(user_id, item.serial_no)) continue now_time = int(time.time()) usage = cls.flow_split(item.flow_total_usage) total = cls.flow_split(item.flow_total) usable = cls.flow_split(item.flow_total - item.flow_total_usage) # 查询当前套餐并且套餐类型不等于长期无限流量 unicom_order_qs = UnicomComboOrderInfo.objects.filter(id=item.combo_order_id).exclude(combo_id=33) \ .values('combo__combo_name') if unicom_order_qs.exists(): logger.info(f'推送4G通知套餐订单不存在或长期无限流量不通知:{item.combo_order_id}') UnicomFlowPush.objects.filter(id=item.id).update(status=1, updated_time=now_time) continue # 查询推送配置数据 push_qs = GatewayPush.objects.filter(user_id=user_id, logout=False).values('user_id', 'app_bundle_id', 'app_type', 'push_type', 'token_val', 'm_code', 'lang', 'tz').order_by( '-id')[:5] msg = False if item.type != 0 and item.type != 1: # 不等于流量预警通知并且不等于流量到期 combo_name = unicom_order_qs.first()['combo__combo_name'] if unicom_order_qs.exists() else '' sys_msg = cls.get_sys_msg_text(item.serial_no, combo_name, item.type) msg = True else: if device_info_qs[0]['userID__phone']: params = u'{"devname":"' + item.serial_no + '","usage":"流量' + usage + '","usable":"流量' + \ usable + '","total":"流量共' + total + '"}' cls.send_aliyun_sms(device_info_qs[0]['userID__phone'], params, 'SMS_246100414') lang = push_qs[0]['lang'] if push_qs.exists() else 'cn' sys_msg = cls.get_msg_text(item.serial_no, lang, total, usage, usable) cls.sys_msg_save(user_id, item.serial_no, now_time, sys_msg) # 修改推送状态 UnicomFlowPush.objects.filter(id=item.id).update(status=1, updated_time=now_time) if not push_qs.exists(): logger.info('推送4G通知APP未登录:{},serial:{}'.format(user_id, item.serial_no)) continue for push_vo in push_qs: kwargs = { 'n_time': now_time, 'event_type': 1, 'nickname': item.serial_no, } push_type = push_vo['push_type'] token_val = push_vo['token_val'] lang = push_vo['lang'] app_bundle_id = push_vo['app_bundle_id'] # 获取推送所需数据 msg_title = PushObject.get_msg_title(item.serial_no) sys_msg_text = sys_msg if msg else cls.get_msg_text(item.serial_no, lang, total, usage, usable) kwargs['app_bundle_id'] = app_bundle_id kwargs['token_val'] = token_val kwargs['msg_title'] = msg_title kwargs['msg_text'] = sys_msg_text if not cls.msg_push(push_type, **kwargs): continue except Exception as e: logger.info('推送4G通知消息异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) continue return response.json(0) @staticmethod def get_msg_text(serial_no, lang, total, usage, usable): """ app消息推送内容 """ if lang == 'cn': sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前套餐总流量共" + total + ",已使用" + \ usage + "" + ",剩余" + usable + "" else: sys_msg_text = 'Warm tip: Dear customer, the total traffic of your ' + serial_no + \ ' device is ' + total + 'g in the current package. ' + usage + \ ' has been used and ' + usable + ' is left' return sys_msg_text @staticmethod def msg_push(push_type, **kwargs): """ app推送 """ logger = logging.getLogger('info') try: # ios apns if push_type == 0: PushObject.ios_apns_push(**kwargs) # android gcm elif push_type == 1: PushObject.android_fcm_push_v1(**kwargs) # android 极光推送 elif push_type == 2: PushObject.android_jpush(**kwargs) elif push_type == 3: huawei_push_object = HuaweiPushObject() huawei_push_object.send_push_notify_message(**kwargs) # android 小米推送 elif push_type == 4: channel_id = XM_PUSH_CHANNEL_ID['service_reminder'] PushObject.android_xmpush(channel_id=channel_id, **kwargs) # android vivo推送 elif push_type == 5: PushObject.android_vivopush(**kwargs) # android oppo推送 elif push_type == 6: channel_id = 'VALUE_ADDED' PushObject.android_oppopush(channel_id=channel_id, **kwargs) # android 魅族推送 elif push_type == 7: PushObject.android_meizupush(**kwargs) return True except Exception as e: logger.info('流量预警推送异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) return False @staticmethod def send_aliyun_sms(phone, params, temp_code): """ 推送阿里云国内短信通知 """ sign = '周视' ali_sms = AliyunSmsObject() ali_sms.send_code_sms_cloud(phone, params, sign, temp_code) @staticmethod def flow_split(flow): """ 流量保留两位小数并带单位 """ if flow >= 1024: flow = flow / 1024 return str(round(flow, 2)) + "G" else: return str(round(flow, 2)) + "M" @staticmethod def get_sys_msg_text(serial_no, combo_name, sys_type): """ 获取系统消息文本 @return: """ if sys_type == 4: sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前4G" + combo_name + "已到期" elif sys_type == 3: sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前4G" + combo_name + "已激活" else: sys_msg_text = "温馨提示:尊敬的客户,您" + serial_no + "设备当前4G" + combo_name + "已用完" return sys_msg_text