# -*- encoding: utf-8 -*- """ @File : UnicomComboController.py @Time : 2022/6/23 9:18 @Author : stephen @Email : zhangdongming@asj6.wecom.work @Software: PyCharm """ import datetime import json import logging import time import traceback from decimal import Decimal from django.db import transaction from django.db.models import Q from django.http import HttpResponse, JsonResponse from django.views.generic.base import View from Model.models import UnicomDeviceInfo, UnicomCombo, Pay_Type, Order_Model, Store_Meal, AiStoreMeal, \ UnicomComboOrderInfo, UnicomComboExperienceHistory, UnicomDeviceStatusChangePush, SysMsgModel, UnicomFlowPush, \ LogModel from Object.EIoTClubObject import EIoTClubObject from Object.RedisObject import RedisObject from Object.ResponseObject import ResponseObject from Object.TokenObject import TokenObject from Object.UnicomObject import UnicomObjeect from Object.utils import LocalDateTimeUtil from Object.utils.PayUtil import PayService from Service.CommonService import CommonService class UnicomComboView(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): response = ResponseObject('cn') if operation == 'query-usage-history': return self.query_device_usage_history(request_dict, response) elif operation == 'sim-order': # 用户套餐信息查询 return self.create_experience_order(response) elif operation == 'test-notify': order_id = request_dict.get('orderId', None) activate_type = request_dict.get('activateType', 0) iccid = request_dict.get('iccid', None) combo_id = request_dict.get('comboId', None) self.create_combo_order_info(order_id, int(activate_type), iccid, int(combo_id)) return HttpResponse('SUCCESS') elif operation == 'device-queue-monitoring': return self.device_queue_monitoring_push(request_dict, request) elif operation == 'device-status-change': # SIM卡修改状态,异步通知接口 return self.device_status_change_push(request_dict, request) elif operation == 'device-bind': # 服务器保存设备的ICCID return self.iccid_bind_serial_no(request, request_dict, response) elif operation == 'device-status': # PC调用解绑SIM卡用户,清除流量套餐数据 return self.update_device_status(request, request_dict, response) elif operation == 'update-card': # 更新SIM类型 return self.update_device_card_type(request_dict, response) elif operation == 'xxx-sign': # 获取签名用于测试 return self.get_test_sign(request_dict, response) else: token = TokenObject(request.META.get('HTTP_AUTHORIZATION')) lang = request_dict.get('lang', token.lang) response = ResponseObject(lang) if token.code != 0: return response.json(token.code) user_id = token.userID if operation == 'combo-save': # 创建套餐 return self.save_unicom_combo(request_dict, response) elif operation == 'combo-pay': # 套餐支付 return self.buy_unicom_combo(user_id, request_dict, request, response) elif operation == 'combo-list': # 获取套餐列表 return self.query_package_list(response) elif operation == 'get-device-info': # 获取SIM卡信息 return self.get_device_info(request_dict, response) elif operation == 'user-combo-query': # 用户套餐信息查询 return self.user_combo_query(user_id, request_dict, response) else: return response.json(0) @classmethod def user_combo_query(cls, user_id, request_dict, response): """ 查询套餐流量列表与正在使用流量详情 @param user_id: @param request_dict: @param response: @return: """ try: iccid = request_dict.get('iccid', None) if not iccid: return response.json(444) unicom_device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid) if not unicom_device_info_qs.exists(): return response.json(173) if not unicom_device_info_qs[0].user_id: # 用户SIM卡未绑定用户则进行自动绑定 serial_no = unicom_device_info_qs[0].serial_no cls.experience_order_4G(iccid, serial_no, user_id) # 生成4G体验订单 unicom_api = UnicomObjeect() combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=iccid, status=1, is_del=False) \ .values('iccid', 'status', 'combo__status', 'combo__combo_name', 'combo__combo_type', 'combo__flow_total', 'combo__remark', 'combo__expiration_days', 'combo__expiration_type', 'year', 'month', 'flow_total_usage', 'expire_time', 'activation_time', 'combo__is_unlimited') if combo_order_qs.exists(): combo_order = combo_order_qs.first() flow_details = { 'flowInvalid': 0, 'iccid': iccid, 'status': combo_order['status'], 'isUnlimited': combo_order['combo__is_unlimited'], 'comboName': combo_order['combo__combo_name'], 'comboType': combo_order['combo__combo_type'], 'flowTotal': combo_order['combo__flow_total'], 'comboRemark': combo_order['combo__remark'], 'expirationDays': combo_order['combo__expiration_days'], 'expirationType': combo_order['combo__expiration_type'], 'flowTotalUsage': combo_order['flow_total_usage'], 'activationTime': combo_order['activation_time'], 'expireTime': combo_order['expire_time'], 'year': combo_order['year'], 'month': combo_order['month'], } activate_flow = float(flow_details['flowTotalUsage']) flow_total_usage = float(unicom_api.get_flow_usage_total(iccid)) flow = 0 if flow_total_usage <= 0 else flow_total_usage - activate_flow # 因APP问题,usableFlow可用流量替换为,已用流量值 flow_details['usableFlow'] = 0 if flow == 0 else flow flow_details['usableFlow'] = flow_details['flowTotal'] \ if flow_details['usableFlow'] > flow_details['flowTotal'] \ else flow_details['usableFlow'] flow_details['usableFlow'] = Decimal(flow_details['usableFlow']).quantize(Decimal('0.00')) flow_details.pop('flowTotalUsage') cls.update_combo_order_sort(iccid) flow_details['comboList'] = cls.get_combo_order_list(iccid) return response.json(0, flow_details) else: flow_details = {'iccid': iccid, 'flowInvalid': 1, 'comboList': cls.get_combo_order_list(iccid)} cls.update_combo_order_sort(iccid) return response.json(0, flow_details) except Exception as e: logging.info('异常错误,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) return response.json(177, e) @classmethod def experience_order_4G(cls, icc_id, serial_no, user_id, is_user=True): """ 保存订单信息 @param is_user: 是否真实用户 @param icc_id: SIM卡20位iccid @param serial_no: 序列号 @param user_id: userID @return: True | False """ try: while transaction.atomic(): n_time = int(time.time()) # 获取套餐信息 combo_info_qs = UnicomCombo.objects.filter(combo_type=1, status=0, is_del=False) \ .values('id', 'combo_name', 'price', 'virtual_price', 'remark').order_by('sort') if not combo_info_qs.exists(): return False combo_info_vo = combo_info_qs[0] # 获取套餐订单信息 combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=icc_id, combo_id=combo_info_vo['id']) if not combo_order_qs.exists(): return False c_time = combo_order_qs[0].created_time # 根据序列号获取UID uid = CommonService.query_uid_with_serial(serial_no) order_id = CommonService.createOrderID() rank_id, ai_rank_id = cls.get_cloud_or_ai_combo() # 生成订单必须添加该字段 order_dict = {'orderID': order_id, 'UID': uid, 'rank_id': rank_id, 'ai_rank_id': ai_rank_id, 'userID_id': user_id, 'desc': combo_info_vo['combo_name'], 'payType': 10, 'payTime': c_time, 'price': combo_info_vo['price'], 'addTime': c_time, 'updTime': c_time, 'status': 1, 'unify_combo_id': str(combo_info_vo['id']), 'order_type': 2, 'store_meal_name': combo_info_vo['combo_name'] } order_qs = Order_Model.objects.filter(UID=uid, userID=user_id, order_type=2, unify_combo_id=str(combo_info_vo['id'])) if not order_qs.exists(): Order_Model.objects.create(**order_dict) combo_order_qs.update(order_id=order_id) if is_user: UnicomDeviceInfo.objects.filter(iccid=icc_id).update(user_id=user_id, updated_time=n_time) return True except Exception as e: print('生成4G体验订单异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) logging.info('生成4G体验订单异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) return False @classmethod def get_combo_order_list(cls, iccid): """ 查询套餐列表 @param iccid: @return: """ combo_list = [] now_time = int(time.time()) before_days = LocalDateTimeUtil.get_before_days_timestamp(now_time, 90) combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=iccid, is_del=False, created_time__gt=before_days) \ .values('iccid', 'status', 'combo__combo_name', 'combo__flow_total', 'combo__remark', 'combo__expiration_days', 'combo__expiration_type', 'flow_total_usage', 'expire_time', 'combo__is_unlimited').order_by('sort') for item in combo_order_qs: combo_list.append({ 'iccid': iccid, 'status': item['status'], 'comboName': item['combo__combo_name'], 'isUnlimited': item['combo__is_unlimited'], 'flowTotal': item['combo__flow_total'], 'comboRemark': item['combo__remark'], 'expirationDays': item['combo__expiration_days'], 'expirationType': item['combo__expiration_type'], 'expireTime': item['expire_time'], }) return combo_list @classmethod def update_combo_order_sort(cls, iccd): """ 修改套餐排序 @param iccd: 联通20位ICCID @return: """ combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=iccd, is_del=False) if combo_order_qs.exists(): unused_qs = combo_order_qs.filter(status=0) if unused_qs.exists(): unused_qs.update(sort=50) used_qs = combo_order_qs.filter(status=1) if used_qs.exists(): used_qs.update(sort=1) expire_qs = combo_order_qs.filter(status=2) if expire_qs.exists(): expire_qs.update(sort=100) @classmethod def update_device_status(cls, request, request_dict, response): """ 重置SIM卡绑定状态修改为测试完成,以及重置流量,删除订单信息、删除系统消息 """ logger = logging.getLogger('info') serial_no = request_dict.get('serialNo', None) time_stamp = request_dict.get('timeStamp', None) sign = request_dict.get('sign', None) if not all([serial_no, sign, time_stamp]): return response.json(444) logger.info('PC工具进入重置SIM卡{}'.format(serial_no)) try: if not CommonService.check_time_stamp_token(sign, time_stamp): return response.json(13) now_time = int(time.time()) redis = RedisObject() with transaction.atomic(): device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no) if not device_info_qs.exists(): # 首先查询SIM卡绑定信息是否存在 return response.json(173) iccid = device_info_qs.first().iccid if device_info_qs.first().card_type == 1: cls.reset_telecom_user(serial_no) device_info_qs.update(updated_time=now_time, user_id='') return response.json(0) key = 'ASJ:UNICOM:RESET:{}'.format(serial_no) flow_push_qs = UnicomFlowPush.objects.filter(serial_no=serial_no) if flow_push_qs.exists(): # 删除流量预警推送 flow_push_qs.delete() sys_msg_qs = SysMsgModel.objects.filter(uid=serial_no) if sys_msg_qs.exists(): # 删除有关系统消息数据 sys_msg_qs.delete() device_info_qs.update(status=1, updated_time=now_time, user_id='') combo_order_qs = UnicomComboOrderInfo.objects.filter(iccid=iccid) order_list = [] if combo_order_qs.exists(): for item in combo_order_qs: if item.order_id: order_list.append(item.order_id) combo_order_qs.delete() combo_experience_history_qs = UnicomComboExperienceHistory.objects.filter(iccid=iccid) if combo_experience_history_qs.exists(): combo_experience_history_qs.delete() redis.set_data(key, iccid, 60 * 30) # 缓存当前SIM卡,记录为半个小时内无法赠送免费流量套餐。 UnicomObjeect().change_device_to_disable(iccid) logger.info('4GResetFlow相关订单号:{}'.format(order_list)) describe = '重置4G流量序列号{},iccid:{}'.format(serial_no, iccid) ip = CommonService.get_ip_address(request) cls.create_operation_log('unicom/api/device-status', ip, request_dict, describe) return response.json(0) except Exception as e: print(e.args) ex = traceback.format_exc() print(ex) logger.info('PC工具重置异常ICCID{},msg={}'.format(iccid, ex)) return response.json(177, ex) @staticmethod def reset_telecom_user(serial_no): """ 重置电信用户 消息记录 @param serial_no: @return: """ sys_msg_qs = SysMsgModel.objects.filter(uid=serial_no) if sys_msg_qs.exists(): sys_msg_qs.delete() return True @classmethod def update_device_card_type(cls, request_dict, response): """ 修改设备卡类型(0:内置卡,1:外插卡) """ serial_no = request_dict.get('serialNo', None) time_stamp = request_dict.get('timeStamp', None) sign = request_dict.get('sign', None) main_card = request_dict.get('type', None) if not all([serial_no, main_card, sign, time_stamp]): return response.json(444) try: if not CommonService.check_time_stamp_token(sign, time_stamp): return response.json(13) now_time = int(time.time()) with transaction.atomic(): unicom_device_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no) if not unicom_device_qs.exists(): return response.json(173) unicom_device_qs.update(main_card=int(main_card), updated_time=now_time) return response.json(0) except Exception as e: print(e.args) ex = traceback.format_exc() print(ex) return response.json(177, ex) @classmethod def get_device_info(cls, request_dict, response): """ 获取设备信息 @param request_dict: @param response: @return: """ iccid = request_dict.get('iccid', None) if not iccid: return response.json(444) unicom_device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid).values() if not unicom_device_info_qs.exists(): return response.json(173) return response.json(0, dict(unicom_device_info_qs.first())) @classmethod def iccid_bind_serial_no(cls, request, request_dict, response): """ iccid绑定设备序列号 """ iccid = request_dict.get('iccid', None) serial_no = request_dict.get('serialNo', None) time_stamp = request_dict.get('timeStamp', None) sign = request_dict.get('sign', None) sim = int(request_dict.get('sim', 1)) logger = logging.getLogger('info') logger.info('--->设备调用4G注册接口') logger.info('iccid:{},serial_no:{}'.format(iccid, serial_no)) if not all([iccid, serial_no, sign, time_stamp]): return response.json(444) # 时间戳token校验 if not CommonService.check_time_stamp_token(sign, time_stamp): return response.json(13) n_time = int(time.time()) try: logger.info('--->参数验证通过,sign验证通过') with transaction.atomic(): ip = CommonService.get_ip_address(request) # 待完善代码 根据uid与用户id验证系统设备mdcmd unicom_device_qs = UnicomDeviceInfo.objects.filter(iccid=iccid) if unicom_device_qs.exists(): if unicom_device_qs.first().serial_no != serial_no: unicom_device_qs.update(main_card=sim, updated_time=n_time, serial_no=serial_no) cls.create_operation_log('unicom/api/device-bind', ip, request_dict, '4G序列号{}新绑定{}'.format(serial_no, iccid)) elif unicom_device_qs.first().main_card != sim: unicom_device_qs.update(main_card=sim, updated_time=n_time) return response.json(0) if sim == 0: return response.json(0, '外置卡不保存相关信息{}'.format(serial_no)) params = {'iccid': iccid, 'serial_no': serial_no, 'updated_time': n_time, 'created_time': n_time, 'main_card': sim} if cls.is_unicom_sim(iccid): # 联通卡 UnicomDeviceInfo.objects.create(**params) cls.create_operation_log('unicom/api/device-bind', ip, request_dict, '4G序列号{}绑定{}'.format(serial_no, iccid)) return response.json(0) elif cls.is_dingxin_iot(iccid): # 鼎芯物联卡 params['card_type'] = 5 # 国际 params['status'] = 2 UnicomDeviceInfo.objects.create(**params) return response.json(0) elif cls.check_iccid(iccid): # 五兴物联卡 params['card_type'] = 1 params['status'] = 2 UnicomDeviceInfo.objects.create(**params) return response.json(0) else: logger.info('--->设备请求绑定{}验证失败'.format(iccid)) return response.json(173) except Exception as e: print(e) ex = traceback.format_exc() logger.info('--->设备调用4G注册接口异常:{}'.format(ex)) return response.json(177, repr(e)) @classmethod def is_unicom_sim(cls, iccid): """ 判断是否联通SIM卡 @param iccid: iccid @return: 是否联通卡结果 """ result = UnicomObjeect().verify_device(iccid=iccid) if result.status_code == 200 and result.text: res_dict = json.loads(result.text) if res_dict['success'] and res_dict['data']['status'] != 0: return True return False @classmethod def is_dingxin_iot(cls, iccid): """ 根据iccid判断是否鼎芯国际卡 """ try: dx_iot = EIoTClubObject() params = {'iccid': iccid} result = dx_iot.get_cards_info('v3', **params) assert result['code'] == '200' return True except Exception as e: print(repr(e)) return False @classmethod def check_iccid(cls, iccid): """ 检查ICCID是否是五兴科技卡 @return: True or False """ if not iccid: return False iccid = iccid[0:6] arr_list = ['898603', '898611'] if iccid in arr_list: return True return False @classmethod def user_activate_flow(cls, iccid): """ 用户激活初始化流量套餐 @param iccid: @return: """ logger = logging.getLogger('info') try: while transaction.atomic(): now_time = int(time.time()) unicom_device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid) if not unicom_device_info_qs.exists(): return False unicom_device_info_qs = unicom_device_info_qs.first() if unicom_device_info_qs.status != 1: logger.info('---->用户激活iccid={},业务系统状态为{}'.format(iccid, unicom_device_info_qs.status)) return False # 联通业务逻辑 unicom_api = UnicomObjeect() unicom_api.change_device_to_activate(iccid) # 查看是否体验过免费套餐 experience_history_qs = UnicomComboExperienceHistory.objects.filter(iccid=iccid) if not experience_history_qs.exists(): logger.info('---->用户首次激活iccid={}'.format(iccid)) combo_qs = UnicomCombo.objects.filter(combo_type=1, status=0, is_del=False) \ .values('id', 'expiration_type', 'expiration_days', 'combo_type') if combo_qs.exists(): combo_qs = combo_qs.first() # 保存体验记录 experience_history_vo = {'iccid': iccid, 'experience_type': 0, 'do_time': now_time} UnicomComboExperienceHistory.objects.create(**experience_history_vo) # 保存套餐激活信息 cls.create_combo_order_info('', 0, iccid, combo_qs['id']) # 修改业务联通卡设备激活信息 UnicomDeviceInfo.objects.filter(iccid=iccid).update(status=2, updated_time=now_time, created_time=now_time) return True except Exception as e: print(e) ex = traceback.format_exc() logger.info('--->用户首次激活异常:{}'.format(ex)) return False @classmethod def save_unicom_combo(cls, request_dict, response): """ 联通套餐保存 @param request_dict: @param response: @return: """ combo_id = request_dict.get('id', None) combo_name = request_dict.get('comboName', None) flow_total = request_dict.get('flowTotal', None) expiration_days = request_dict.get('expirationDays', None) expiration_type = request_dict.get('expirationType', None) price = request_dict.get('price', None) remark = request_dict.get('remark', None) pay_type = request_dict.get('payType', '').split(',') if not all([pay_type, combo_name, flow_total, expiration_days, expiration_type, price]): return response.json(444) try: flow_total = int(flow_total) expiration_days = int(expiration_days) expiration_type = int(expiration_type) with transaction.atomic(): re_data = { 'combo_name': combo_name, 'flow_total': flow_total, 'expiration_days': expiration_days, 'expiration_type': expiration_type, 'price': price, } if remark: re_data['remark'] = remark if combo_id: UnicomCombo.objects.filter(id=combo_id).update(**re_data) UnicomCombo.objects.get(id=combo_id).pay_type.set(pay_type) return response.json(0) UnicomCombo.objects.create(**re_data).pay_type.set(pay_type) return response.json(0) except Exception as e: print(e) return response.json(177, repr(e)) @classmethod def query_package_list(cls, response): """ 查询套餐列表 @return: """ try: combo_qs = UnicomCombo.objects.filter(is_show=1, status=0, is_del=False) \ .order_by('sort').values('id', 'combo_name', 'flow_total', 'expiration_days', 'expiration_type', 'price', 'remark', 'virtual_price') if not combo_qs.exists(): return response.json(0, []) combo_list = [] for item in combo_qs: # 获取支付方式列表 pay_type_qs = Pay_Type.objects.filter(unicomcombo=item['id']).values('id', 'payment') combo_list.append({ 'id': item['id'], 'comboName': item['combo_name'], 'flowTotal': item['flow_total'], 'expirationDays': item['expiration_days'], 'expirationType': item['expiration_type'], 'price': item['price'], 'virtualPrice': item['virtual_price'] if item['virtual_price'] else '', 'remark': item['remark'], 'payTypes': list(pay_type_qs), }) return response.json(0, combo_list) except Exception as e: print(e) return response.json(177, repr(e)) @classmethod def buy_unicom_combo(cls, user_id, request_dict, request, response): """ 购买联通套餐 @return: """ logger = logging.getLogger('info') try: with transaction.atomic(): iccid = request_dict.get('iccid', None) combo_id = request_dict.get('id', None) pay_type = request_dict.get('payType', None) activate_type = request_dict.get('activateType', 0) if not all([iccid, combo_id, pay_type]): return response.json(444) combo_id = int(combo_id) pay_type = int(pay_type) now_time = int(time.time()) unicom_combo_qs = UnicomCombo.objects.filter(id=combo_id, pay_type=pay_type, is_show=1, is_del=False, status=0) \ .values('id', 'combo_name', 'price', 'remark') if not unicom_combo_qs.exists(): return response.json(173) unicom_device_qs = UnicomDeviceInfo.objects.filter(iccid=iccid) \ .values('serial_no') if not unicom_device_qs.exists(): return response.json(173) unicom_combo_qs = unicom_combo_qs.first() price = unicom_combo_qs['price'] if not price: return response.json(173) unicom_device_qs = unicom_device_qs.first() device_uid = CommonService.query_uid_with_serial(unicom_device_qs['serial_no']) order_id = CommonService.createOrderID() rank_id, ai_rank_id = cls.get_cloud_or_ai_combo() order_dict = {'rank_id': rank_id, 'ai_rank_id': ai_rank_id, 'orderID': order_id, 'UID': device_uid, 'userID_id': user_id, 'desc': unicom_combo_qs['combo_name'], 'payType': pay_type, 'payTime': now_time, 'price': price, 'currency': 'CNY', 'addTime': now_time, 'updTime': now_time, 'unify_combo_id': str(unicom_combo_qs['id']), 'order_type': 2, 'store_meal_name': unicom_combo_qs['combo_name'] } params = 'lang=cn' + '&activateType=' + activate_type logger.info('激活类型:{}'.format(activate_type)) result = {'result_code': 0, 'reason': 'success', 'error_code': 0} if pay_type == 2: # 支付宝 pay_price = PayService.get_two_float(price, 2) notify_url = 'unicom/wap/pay/ali-notify' order_dict['pay_url'] = PayService.create_alipay_payment(params, order_id, pay_price, unicom_combo_qs['combo_name'], notify_url, unicom_combo_qs['remark'], response) res_data = {'redirectUrl': order_dict['pay_url'], 'orderID': order_id} elif pay_type == 3: # 微信支付 notify_url = 'unicom/wap/pay/wechat-notify' ip = CommonService.get_ip_address(request) params = 'activateType=' + activate_type sign_params = PayService.create_wechat_payment(params, order_id, price, ip, notify_url, unicom_combo_qs['remark'], response) result['result'] = sign_params else: return response.json(444, {'param': 'pay_type'}) Order_Model.objects.create(**order_dict) if pay_type == 3: return JsonResponse(status=200, data=result) return response.json(0, res_data) except Exception as e: print(e) return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))) @staticmethod def get_cloud_or_ai_combo(): """ 获取云存或者AI套餐id @return: """ rank_id = Store_Meal.objects.all().order_by('sort').values().first()['id'] ai_rank_id = AiStoreMeal.objects.all().values().first()['id'] return rank_id, ai_rank_id @classmethod def query_device_usage_history(cls, request_dict, response): """ 查询实时已用总流量API @return: """ iccid = request_dict.get('iccid', None) if not iccid: return response.json(444) unicom_api = UnicomObjeect() flow = unicom_api.get_flow_usage_total(iccid) return response.json(0, flow) @staticmethod def package_callback_notify(request_dict, request): """ 异步套餐订购回调 @param request_dict: @param request: @return: """ logger = logging.getLogger('info') try: logger.info('联通异步套餐订购回调参数{}'.format(request_dict)) body = request.body.decode("utf-8") if body: dict_data = json.loads(body) sign = dict_data['sign'] logger.info('设备订购异步回调请求参数{}'.format(dict_data)) dict_data.pop('sign') unicom_obj = UnicomObjeect() generate_sign = unicom_obj.createSign(**dict_data) logger.info('设备订购请求签名{}'.format(sign)) logger.info('设备订购生成签名{}'.format(generate_sign)) r_data = {'success': True, 'msg': '成功'} return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8") except Exception as e: print(repr(e)) r_data = {'success': False, 'msg': '失败'} return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8") @staticmethod def device_queue_monitoring_push(request_dict, request): """ 设备套餐队列用完或者到期推送 @param request_dict: @param request: @return: """ logger = logging.getLogger('info') try: logger.info('设备套餐队列推送{}'.format(request_dict)) body = request.body.decode("utf-8") if body: dict_data = json.loads(body) sign = dict_data['sign'] logger.info('设备套餐队列回调请求参数{}'.format(dict_data)) dict_data.pop('sign') unicom_obj = UnicomObjeect() generate_sign = unicom_obj.createSign(**dict_data) logger.info('设备套餐队列请求签名{}'.format(sign)) logger.info('设备套餐队列生成签名{}'.format(generate_sign)) r_data = {'success': True, 'msg': '成功'} return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8") except Exception as e: print(repr(e)) r_data = {'success': False, 'msg': '失败'} return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8") @staticmethod def device_status_change_push(request_dict, request): """ 设备状态变更推送执行场景说明 @param request_dict: @param request: @return: """ logger = logging.getLogger('info') try: logger.info('设备状态变更推送{}'.format(request_dict)) body = request.body.decode("utf-8") if body: dict_data = json.loads(body) sign = dict_data['sign'] logger.info('设备状态变更推送请求参数{}'.format(dict_data)) dict_data.pop('sign') unicom_obj = UnicomObjeect() generate_sign = unicom_obj.createSign(**dict_data) logger.info('联通设备状态变更推送请求签名{}'.format(sign)) logger.info('联通设备状态变更推送生成签名{}'.format(generate_sign)) # assert generate_sign == sign now_time = int(time.time()) re_data = { 'iccid': dict_data['iccid'], 'sign': sign, 'type': dict_data['status'], 'time': dict_data['time'], 'serial_no': dict_data['operationId'], 'updated_time': now_time, 'created_time': now_time } UnicomDeviceStatusChangePush.objects.create(**re_data) r_data = {'success': True, 'msg': '成功'} return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8") except Exception as e: logger.info('异常详情,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) r_data = {'success': False, 'msg': '失败'} return HttpResponse(json.dumps(r_data, ensure_ascii=False), content_type="application/json,charset=utf-8") @classmethod def create_combo_order_info(cls, order_id, activate_type, iccid, combo_id): """ 创建套餐生效记录 @param order_id: 订单id @param activate_type: 激活类型 @param iccid: 联通20位iccid @param combo_id: 套餐id @return: True Or False """ logger = logging.getLogger('info') logger.info('创建联通订单套餐信息,订单id{}'.format(order_id)) try: today = datetime.datetime.today() year = today.year month = today.month with transaction.atomic(): unicom_combo_qs = UnicomCombo.objects.filter(id=int(combo_id)).values() if unicom_combo_qs.exists(): unicom_combo = unicom_combo_qs.first() now_time = int(time.time()) combo_order_qs = UnicomComboOrderInfo.objects.filter(status=1, iccid=iccid) status = 0 if not combo_order_qs.exists(): status = 1 combo_order_data = {'iccid': iccid, 'status': status, 'combo_id': int(combo_id), 'updated_time': now_time, 'created_time': now_time, 'year': year, 'month': month} if order_id: combo_order_data['order_id'] = order_id # 有效期类型 1 等于自然月,0天数 if unicom_combo['expiration_type'] == 1: # 激活类型 1=下月激活 否则等于当月激活 if activate_type == 1: combo_order_data['next_month_activate'] = True next_start_time, end_time = cls.get_next_month_data_time() combo_order_data['activation_time'] = next_start_time combo_order_data['expire_time'] = end_time combo_order_data['status'] = 0 else: start_time, month_end_time = cls.get_month_start_and_end_time() combo_order_data['activation_time'] = now_time combo_order_data['expire_time'] = month_end_time elif unicom_combo['expiration_type'] == 0: days = unicom_combo['expiration_days'] if activate_type == 1: combo_order_data['next_month_activate'] = True start_time, end_time = cls.get_times(days) combo_order_data['activation_time'] = start_time combo_order_data['expire_time'] = end_time combo_order_data['status'] = 0 else: zero_today, end_time = cls.get_data_time(days) combo_order_data['activation_time'] = now_time combo_order_data['expire_time'] = end_time logger.info('激活类型{}'.format(activate_type)) # 调用联通API查询物联卡是否已激活,未激活则修改为激活状态 unicom_api = UnicomObjeect() if status == 1: unicom_api.change_device_to_activate(iccid) flow_total_usage = unicom_api.get_flow_usage_total(iccid) if flow_total_usage > 0: flow_total_usage = Decimal(flow_total_usage) flow_total_usage = flow_total_usage.quantize(Decimal('0.00')) else: flow_total_usage = 0 combo_order_data['flow_total_usage'] = str(flow_total_usage) UnicomComboOrderInfo.objects.create(**combo_order_data) logger.info('保存套餐支付信息success') return True except Exception as e: print(e) return False @staticmethod def get_next_month_data_time(): """ 获取下个月开始时间与结束时间戳 @return: next_start_time,end_time """ next_month_start = LocalDateTimeUtil.get_next_month_start() next_start_time, next_end_time = LocalDateTimeUtil.get_start_and_end_time(next_month_start, '%Y-%m-%d') next_month_end = LocalDateTimeUtil.get_next_month_end() start_time, end_time = LocalDateTimeUtil.get_start_and_end_time(next_month_end, '%Y-%m-%d') return next_start_time, end_time @staticmethod def get_data_time(days): """ 获取今天开始时间以及days后日期结束时间戳 @return: next_start_time,end_time """ zero_today, last_today = LocalDateTimeUtil.get_today_date(True) now_time = int(time.time()) after_time = LocalDateTimeUtil.get_after_days_timestamp(now_time, days) time_array = time.localtime(after_time) start_time, end_time = LocalDateTimeUtil.get_start_and_end_time(time.strftime("%Y-%m-%d", time_array), '%Y-%m-%d') return zero_today, end_time @staticmethod def get_times(days_after): """ 获取下月开始时间与指定天数后结束时间 @return: """ next_start_time, end_time = UnicomComboView.get_next_month_data_time() after_time = LocalDateTimeUtil.get_after_days_timestamp(next_start_time, days_after) time_array = time.localtime(after_time) start_time, end_time = LocalDateTimeUtil.get_start_and_end_time(time.strftime("%Y-%m-%d", time_array), '%Y-%m-%d') return next_start_time, end_time @staticmethod def get_month_start_and_end_time(): """ 获取当天开始时间与当月结束时间戳 @return: """ zero_today, last_today = LocalDateTimeUtil.get_today_date(True) month_end = LocalDateTimeUtil.get_cur_month_end() start_time, month_end_time = LocalDateTimeUtil.get_start_and_end_time(month_end, '%Y-%m-%d') return zero_today, month_end_time @classmethod def get_test_sign(cls, request_dict, response): """ 测试盐加密解密 @param request_dict: @param response: @return: """ verify = request_dict.get('verify', False) if verify: sign = request_dict.get('sign') time_stamp = request_dict.get('timeStamp') sign = CommonService.check_time_stamp_token(sign, time_stamp) if not sign: return response.json(13) return response.json(0) now_time = int(time.time()) sign = CommonService.encode_data(str(now_time)) return response.json(0, {'sign': sign, 'timeStamp': now_time}) @classmethod def create_experience_order(cls, response): """ 创建体验订单 """ u_order_qs = UnicomComboOrderInfo.objects.filter(Q(order_id__isnull=True) | Q(order_id='')) u_order_qs = u_order_qs.filter(combo__combo_type=1).values('id', 'iccid') if not u_order_qs.exists(): return response.json(0) for item in u_order_qs: u_device_qs = UnicomDeviceInfo.objects.filter(iccid=item['iccid'], status=2) \ .values('serial_no', 'user_id') if not u_device_qs.exists() or not u_device_qs[0]['user_id']: continue cls.experience_order_4G(item['iccid'], u_device_qs[0]['serial_no'], u_device_qs[0]['user_id'], False) return response.json(0) @classmethod def create_operation_log(cls, url, ip, request_dict, describe): """ 创建操作日志 @param url: 请求路径 @param describe: 描述 @param ip: 当前IP @param request_dict: 请求参数 @return: True | False """ try: # 记录操作日志 content = json.loads(json.dumps(request_dict)) log = { 'ip': ip, 'user_id': 1, 'status': 200, 'time': int(time.time()), 'content': json.dumps(content), 'url': url, 'operation': describe, } LogModel.objects.create(**log) return True except Exception as e: print('日志异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e))) return False