# -*- encoding: utf-8 -*- """ @File : WXTechController.py @Time : 2023/5/6 16:40 @Author : stephen @Email : zhangdongming@asj6.wecom.work @Software: PyCharm """ import time from django.http import QueryDict from django.views import View from Ansjer.config import LOGGER from Controller.UnicomCombo.UnicomComboController import UnicomComboView from Model.models import UnicomDeviceInfo, Order_Model, UnicomComboExperienceHistory, UnicomCombo, ExchangeCode, \ LogModel, SerialNumberPackage from Object.Enums.WXOperatorEnum import WXOperatorEnum from Object.Enums.WXStartTypeEnum import WXStartTypeEnum from Object.ResponseObject import ResponseObject from Object.WXTechObject import WXTechObject from Service.CommonService import CommonService # 五兴科技电信套餐编码 1G-15天流量包 COMBO_ID = 'DX-DX-FDX-JCB-1G-15天-4DX-ASJ-YTC-AT-2022123020221230144615' class WXTechControllerView(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 delete(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation') delete = QueryDict(request.body) if not delete: delete = request.GET return self.validation(delete, request, operation) def put(self, request, *args, **kwargs): request.encoding = 'utf-8' operation = kwargs.get('operation') put = QueryDict(request.body) return self.validation(put, request, operation) def validation(self, request_dict, request, operation): if operation == 'deleteCardPackage': return self.delete_card_package(request_dict, ResponseObject('cn')) elif operation == 'packageRefund': return self.wx_package_refund(request_dict, ResponseObject('cn')) token_code, user_id, response = CommonService \ .verify_token_get_user_id(request_dict, request) if token_code != 0: return response.json(token_code) if operation == 'getCardsInfo': return self.get_cards_info(request_dict, response) elif operation == 'getExperiencePackage': return self.get_experience_package(request_dict, response) elif operation == 'createOrder': return self.create_order_package(user_id, request_dict, response, request) elif operation == 'exchangePackage': return self.wx_exchange_package(request_dict, response, request, user_id) elif operation == 'getPackageBySerialNumber': return self.get_package_by_serial_number(request_dict, response, request, user_id) elif operation == 'create4GFlowPackage': return self.create_4G_flow_package(request_dict, response, request, user_id) @classmethod def wx_package_refund(cls, request_dict, response): """ 五兴套餐退订 """ try: serial_number = request_dict.get('serialNumber', None) if not serial_number: return response(444) device_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number).values('iccid') if not device_qs.exists(): return response(173) uid = CommonService.get_uid_by_serial_number(serial_number) order_info_qs = Order_Model.objects.filter(UID=uid, order_type=3).values('trade_no') \ .order_by('-payTime') if not order_info_qs.exists(): return response(173) iccid = device_qs[0]['iccid'] trade_no = order_info_qs[0]['trade_no'] data = {'iccid': iccid, 'operator': 3, 'orderNumber': trade_no} wx_tech = WXTechObject() res = wx_tech.package_refund(**data) if res['code'] == '0': return response.json(0) return response.json(10059) except Exception as e: LOGGER.info('*****WXTechController.get_cards_info:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))) @classmethod def get_cards_info(cls, request_dict, response): """ 五兴单卡获取信息 """ try: LOGGER.info('*****WXTechController.get_cards_info:params:{}'.format(request_dict)) iccid = request_dict.get('iccid', None) operator = int(request_dict.get('operator', 3)) if not iccid: return response.json(444) data = {'iccid': iccid, 'operator': operator} wx_tech = WXTechObject() return response.json(0, wx_tech.get_cards_info(**data)) except Exception as e: LOGGER.info('*****WXTechController.get_cards_info:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))) @classmethod def get_experience_package(cls, request_dict, response): """ 获取体验套餐 """ try: LOGGER.info('*****WXTechController.get_experience_package:params{}'.format(request_dict)) serial_no = request_dict.get('serialNo', None) if not serial_no: return response.json(444) serial_no = serial_no[0:9] # 查询是否注册iccid unicom_device_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no) \ .values('serial_no', 'user_id', 'iccid') if not unicom_device_qs.exists(): return response.json(173) unicom_device_qs = unicom_device_qs.first() iccid = unicom_device_qs['iccid'] # 查看是否体验过免费套餐 experience_history_qs = UnicomComboExperienceHistory.objects.filter(iccid=iccid) if experience_history_qs.exists(): return response.json(10062) combo_info_qs = UnicomCombo.objects.filter(combo_type=1, status=0, is_del=False) \ .values('combo_name') if not combo_info_qs.exists(): return response.json(173) result = {'comboName': combo_info_qs[0]['combo_name']} return response.json(0, result) except Exception as e: LOGGER.info('*****WXTechController.get_experience_package:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))) @classmethod def create_order_package(cls, user_id, request_dict, response, request): """ 五兴电信领取1G15天流量体验包 """ try: LOGGER.info('*****WXTechController.create_order_package:params:{}'.format(request_dict)) serial_no = request_dict.get('serialNo', None) operator = request_dict.get('operator', None) if not all([operator, serial_no]): return response.json(444) serial_no = serial_no[0:9] unicom_device_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no) \ .values('serial_no', 'user_id', 'iccid', 'card_type') if not unicom_device_qs.exists(): return response.json(173) unicom_device_qs = unicom_device_qs.first() iccid = unicom_device_qs['iccid'] # 查看是否体验过免费套餐 experience_history_qs = UnicomComboExperienceHistory.objects.filter(iccid=iccid) if experience_history_qs.exists(): return response.json(10062) ip = CommonService.get_ip_address(request) experience_history_vo = {'iccid': iccid, 'experience_type': 0, 'do_time': int(time.time())} app_user_id = unicom_device_qs['user_id'] if unicom_device_qs['user_id'] else user_id if unicom_device_qs['card_type'] == 0: # 珠海联通 flow_combo_qs = UnicomCombo.objects.filter(combo_type=1, is_del=False, status=0).order_by('sort') free_result = False if flow_combo_qs.exists(): # 生成免费体验套餐 free_result = UnicomComboView() \ .generate_flow_package(serial_no, flow_combo_qs.first().id, app_user_id) UnicomComboExperienceHistory.objects.create(**experience_history_vo) if not unicom_device_qs['user_id']: UnicomDeviceInfo.objects.filter(iccid=iccid) \ .update(user_id=app_user_id, updated_time=int(time.time())) factory_result = cls.activate_flow_package(serial_no, ip, app_user_id) # 检测并激活出厂无限流量 cls.save_log(ip, 0, '{}激活免费套餐{},出厂无限流量{}'.format(serial_no, free_result, factory_result)) return response.json(0) elif unicom_device_qs['card_type'] == 1: # 五兴电信 data = {'iccid': iccid, 'operator': WXOperatorEnum(int(operator)).value, 'startType': str(WXStartTypeEnum.EFFECTIVE_IMMEDIATELY.value), 'packageCode': COMBO_ID} wx_tech = WXTechObject() # 请求五兴API创建套餐接口 res = wx_tech.create_order_package(**data) LOGGER.info('*****五兴创建体验套餐信息:{}'.format(res)) if res['code'] == '0': trade_no = res['data']['orderNumber'] UnicomComboExperienceHistory.objects.create(**experience_history_vo) order_res = cls.created_order(serial_no, user_id, trade_no, pay_type=10) UnicomDeviceInfo.objects.filter(serial_no=serial_no) \ .update(user_id=user_id, updated_time=int(time.time())) LOGGER.info('*****系统创建体验订单:{}'.format(order_res)) factory_result = cls.activate_flow_package(serial_no, ip, app_user_id) # 检测并激活出厂无限流量 cls.save_log(ip, 0, '{}激活免费套餐{},出厂无限流量{}'.format(serial_no, True, factory_result)) return response.json(0) return response.json(10063) except Exception as e: LOGGER.info('*****WXTechController.create_order_package:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))) @classmethod def created_order(cls, serial_no, user_id, trade_no, combo_id=None, pay_type=10, order_type=3): """ 创建系统订单 """ combo_info_qs = UnicomCombo.objects.filter(is_del=False) if combo_id: combo_info_qs = combo_info_qs.filter(id=int(combo_id)) else: combo_info_qs = combo_info_qs.filter(combo_type=1, status=0) combo_info_qs = combo_info_qs.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] n_time = int(time.time()) # 根据序列号获取UID uid = CommonService.get_uid_by_serial_number(serial_no) order_id = CommonService.createOrderID() # 生成订单必须添加该字段 rank_id, ai_rank_id = UnicomComboView().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': pay_type, 'payTime': n_time, 'price': combo_info_vo['price'], 'addTime': n_time, 'updTime': n_time, 'status': 1, 'currency': 'CNY', 'unify_combo_id': str(combo_info_vo['id']), 'order_type': order_type, 'store_meal_name': combo_info_vo['combo_name'], 'trade_no': trade_no} Order_Model.objects.create(**order_dict) return order_id @classmethod def delete_card_package(cls, request_dict, response): """ PC工具清空卡片的所有套餐订购记录 """ try: LOGGER.info('*****WXTechController.delete_card_package:params:{}'.format(request_dict)) sign = request_dict.get('sign', None) serial_no = request_dict.get('serialNo', None) time_stamp = request_dict.get('timeStamp', None) if not CommonService.check_time_stamp_token(sign, time_stamp): return response.json(13) # 查询是否注册iccid unicom_device_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no) \ .values('serial_no', 'user_id', 'iccid') if not unicom_device_qs.exists(): return response.json(173) iccid = unicom_device_qs[0]['iccid'] data = {'iccids': iccid, 'operator': WXOperatorEnum.TELECOM.value} wx_tech = WXTechObject() res = wx_tech.delete_card_package(**data) if res['code'] == '0': UnicomComboExperienceHistory.objects.filter(iccid=iccid).delete() return response.json(0) return response.json(177) except Exception as e: LOGGER.info('*****WXTechController.delete_card_package:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))) @classmethod def wx_exchange_package(cls, request_dict, response, request, user_id): """ 使用兑换码订购五兴五年流量套餐包 """ ip = CommonService.get_ip_address(request) try: code = request_dict.get('code') serial_number = request_dict.get('serialNumber') LOGGER.info('*****WXTechController.wx_exchange_package:params,{}'.format(request_dict)) if not all([code, serial_number]): return response.json(444) # 参数缺失 # 校验兑换码格式是否正确 if not (code.isalnum() and len(code) == 10): return response.json(10067) # 兑换码格式错误 device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number) \ .values('iccid', 'card_type') if not device_info_qs.exists(): return response.json(173) # 设备信息不存在 # 查询兑换码信息 exchange_code_qs = ExchangeCode.objects.filter(code=code, status=False) \ .values('package_id', 'expire_time', 'package_type') if not exchange_code_qs.exists(): return response.json(10066) # 兑换码无效 combo_id = exchange_code_qs[0]['package_id'] # 获取五兴套餐套餐编码 package_info_qs = UnicomCombo.objects.filter(id=combo_id, is_del=False) \ .values('package_id') if not package_info_qs.exists(): return response.json(173) package_code = package_info_qs[0]['package_id'] iccid = device_info_qs[0]['iccid'] # 兑换码套餐类型 card_type = device_info_qs[0]['card_type'] if card_type == 0: # 联通无限流量兑换码 result = cls.exchange_unicom_package(serial_number, iccid, user_id, combo_id) if result: exchange_code_qs.update(status=True, updated_time=int(time.time())) # 校验是否两个重叠无限流量套餐 修改套餐数据 UnicomComboView().update_flow_package_order_by_iccid(iccid) cls.save_log(ip, 10065, '兑换成功{},{}'.format(serial_number, code)) return response.json(10065) elif card_type == 1: # 五兴电信无限流量兑换码 # 五兴订购流量包请求参数 data = {'iccid': iccid, 'operator': WXOperatorEnum.TELECOM.value, 'startType': str(WXStartTypeEnum.EFFECTIVE_IMMEDIATELY.value), 'packageCode': package_code} wx_tech = WXTechObject() # 请求五兴API订购套餐接口 res = wx_tech.create_order_package(**data) LOGGER.info('*****五兴订购年卡套餐结果:{}'.format(res)) if res['code'] == '0': trade_no = res['data']['orderNumber'] cls.created_order(serial_number, user_id, trade_no, combo_id, 11) exchange_code_qs.update(status=True, updated_time=int(time.time())) cls.save_log(ip, 10065, '兑换成功{},{}'.format(serial_number, code)) return response.json(10065) cls.save_log(ip, 10068, '兑换失败{},{}'.format(serial_number, code)) return response.json(10068) except Exception as e: LOGGER.info('*****WXTechController.wx_exchange_package:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) cls.save_log(ip, 500, '兑换内部错误') return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))) @classmethod def exchange_unicom_package(cls, serial_number, iccid, user_id, combo_id): try: # 通过兑换码创建订单记录 order_id = cls.created_order(serial_number, user_id, 'ansjer', combo_id, 11, 2) # 根据订单信息创建流量套餐包 UnicomComboView.create_combo_order_info(order_id, 0, iccid, combo_id) return True except Exception as e: LOGGER.info('*****WXTechController.exchange_unicom_package:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) return False @staticmethod def save_log(ip, code, operation): """ 保存操作日志 @param ip: ip地址 @param code: 状态码 @param operation: 操作说明 @return: 保存结果 """ try: log = { 'ip': ip, 'user_id': 1, 'status': code, 'time': int(time.time()), 'operation': operation, 'url': 'unicom/open/wxtech/exchangePackage', } LogModel.objects.create(**log) return True except Exception as e: LOGGER.info('*****WXTechController.save_log:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) return False @classmethod def get_package_by_serial_number(cls, request_dict, response, request, user_id): """ 根据序列号获取无限流量套餐信息 """ try: serial_number = request_dict.get('serialNumber', None) if not serial_number: return response.json(444) serial_package_qs = SerialNumberPackage.objects.filter(serial_number=serial_number, status=1) data = {} if not serial_package_qs: return response.json(0, data) serial_package = serial_package_qs.first() package_id = serial_package.package_id package_info_qs = UnicomCombo.objects.filter(id=package_id).values('combo_name') if not package_info_qs.exists(): return response.json(0, data) result = {'comboName': package_info_qs[0]['combo_name']} return response.json(110, result) except Exception as e: LOGGER.info('*****WXTechController.get_package_by_serial_number:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) return response.json(503) @classmethod def create_4G_flow_package(cls, request_dict, response, request, user_id): """ 创建4G流量套餐(出厂序列号绑定套餐) """ ip = CommonService.get_ip_address(request) serial_number = '' try: serial_number = request_dict.get('serialNumber') if not serial_number: return response.json(0) device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number) \ .values('iccid', 'card_type') if not device_info_qs.exists(): return response.json(173) # 设备信息不存在 serial_package_qs = SerialNumberPackage.objects.filter(serial_number=serial_number, status=1) if not serial_package_qs: return response.json(10064) combo_id = serial_package_qs.first().package_id # 获取餐套餐信息 package_info_qs = UnicomCombo.objects.filter(id=combo_id, is_del=False) \ .values('package_id', 'combo_name') if not package_info_qs.exists(): return response.json(173) # 得到五兴电信运营商套餐编码 package_code = package_info_qs[0]['package_id'] combo_name = package_info_qs[0]['combo_name'] iccid = device_info_qs[0]['iccid'] n_time = int(time.time()) # 兑换码套餐类型 card_type = device_info_qs[0]['card_type'] if card_type == 0: # 订购联通流量套餐 result = cls.exchange_unicom_package(serial_number, iccid, user_id, combo_id) serial_package_qs.update(status=2, updated_time=n_time, updated_by=user_id) if result: cls.save_log(ip, 10071, '{}领取{}成功{}'.format(serial_number, combo_name, user_id)) return response.json(10071) elif card_type == 1: # 订购五兴电信流量套餐 # 五兴订购流量包请求参数 data = {'iccid': iccid, 'operator': WXOperatorEnum.TELECOM.value, 'startType': str(WXStartTypeEnum.EFFECTIVE_IMMEDIATELY.value), 'packageCode': package_code} wx_tech = WXTechObject() # 请求五兴API订购套餐接口 res = wx_tech.create_order_package(**data) LOGGER.info('*****五兴订购套餐结果:{}'.format(res)) if res['code'] == '0': trade_no = res['data']['orderNumber'] cls.created_order(serial_number, user_id, trade_no, combo_id, 11) serial_package_qs.update(status=2, updated_time=n_time, updated_by=user_id) cls.save_log(ip, 10071, '{}领取{}成功{}'.format(serial_number, combo_name, user_id)) return response.json(10071) cls.save_log(ip, 10064, '无效卡类型{}领取{}失败{}'.format(serial_number, combo_name, user_id)) return response.json(10064) except Exception as e: LOGGER.info('*****WXTechController.wx_exchange_package:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) cls.save_log(ip, 500, f'{serial_number}领取流量套餐异常') return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))) @classmethod def activate_flow_package(cls, serial_number, ip, user_id): """ 激活序列号出厂绑定无限流量套餐 @param serial_number: 9位序列号 @param ip: ip地址 @param user_id: 用户id @return: True | False """ try: if not serial_number: return False serial_package_qs = SerialNumberPackage.objects.filter(serial_number=serial_number, status=1) if not serial_package_qs: return False device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number) \ .values('iccid', 'card_type') if not device_info_qs.exists(): LOGGER.info('*****激活无限流量iccid不存在:{}'.format(serial_number)) return False combo_id = serial_package_qs.first().package_id # 获取餐套餐信息 package_info_qs = UnicomCombo.objects.filter(id=combo_id, is_del=False) \ .values('package_id', 'combo_name') if not package_info_qs.exists(): return False # 得到五兴电信运营商套餐编码 n_time = int(time.time()) iccid = device_info_qs[0]['iccid'] package_code = package_info_qs[0]['package_id'] combo_name = package_info_qs[0]['combo_name'] # 兑换码套餐类型 card_type = device_info_qs[0]['card_type'] if card_type == 0: # 订购联通流量套餐 result = cls.exchange_unicom_package(serial_number, iccid, user_id, combo_id) serial_package_qs.update(status=2, updated_time=n_time, updated_by=user_id) if result: cls.save_log(ip, 10071, '{}领取{}成功{}'.format(serial_number, combo_name, user_id)) return True elif card_type == 1: # 订购五兴电信流量套餐 # 五兴订购流量包请求参数 data = {'iccid': iccid, 'operator': WXOperatorEnum.TELECOM.value, 'startType': str(WXStartTypeEnum.EFFECTIVE_IMMEDIATELY.value), 'packageCode': package_code} wx_tech = WXTechObject() # 请求五兴API订购套餐接口 res = wx_tech.create_order_package(**data) LOGGER.info('*****五兴订购套餐结果:{}'.format(res)) if res['code'] == '0': trade_no = res['data']['orderNumber'] cls.created_order(serial_number, user_id, trade_no, combo_id, 11) serial_package_qs.update(status=2, updated_time=n_time, updated_by=user_id) cls.save_log(ip, 10071, '{}领取{}成功{}'.format(serial_number, combo_name, user_id)) return True cls.save_log(ip, 10064, '无效卡类型{}领取{}失败{}'.format(serial_number, combo_name, user_id)) return False except Exception as e: LOGGER.info('*****WXTechController.activate_flow_package:errLine:{}, errMsg:{}' .format(e.__traceback__.tb_lineno, repr(e))) cls.save_log(ip, 500, f'{serial_number}领取流量套餐异常') return False