소스 검색

更新联通4G代码

zhangdongming 3 년 전
부모
커밋
5ccb0ada7e

+ 464 - 0
AdminController/UnicomManageController.py

@@ -0,0 +1,464 @@
+# Copyright (C) 2022 #
+# @Time    : 2022/7/18 16:16
+# @Author  : ghl
+# @Email   : Guanhailogn@asj6.wecom.work
+# @File    : UnicomManageController.py
+# @Software: PyCharm
+import time
+
+from django.db import transaction
+from django.views.generic.base import View
+
+from Model.models import UnicomDeviceInfo, UnicomCombo, Pay_Type, UnicomComboOrderInfo, Device_User
+from Object.ResponseObject import ResponseObject
+
+
+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()
+        print(request)
+        # 获取套餐详细表
+        if operation == 'get/deta/info':
+            return self.get_unicom_info(request_dict, response)
+        # 获取支付类型
+        elif operation == 'get/pay':
+            return self.get_pay_type(response)
+        # 添加和编辑卡套餐
+        elif operation == 'edit/combo':
+            return self.edit_combo(request_dict, response)
+        # 获取卡用户信息
+        elif operation == 'get/user':
+            return self.get_user_combo(request_dict, response)
+        # 获取/筛选设备套餐订单信息
+        elif operation == 'order/info':
+            return self.get_order_info(request_dict, response)
+        # 统计4G套餐
+        elif operation == 'getComboDataList':
+            return self.static_info(request_dict, response)
+        # 删除卡套餐
+        elif operation == 'dele/combo/info':
+            return self.combo_order_info(request_dict, response)
+        # 筛选用户信息
+        elif operation == 'filter/user':
+            return self.get_user_info(request_dict, response)
+
+    def get_user_info(self, request_dict, response):
+        """
+        筛选卡用户信息
+        @param request_dict:
+        @param response:
+        @return:
+        NickName:用户昵称 phone: 电话
+        serial_no: 设备序列号
+        """
+        NickName = request_dict.get('NickName', None)
+        phone = request_dict.get('phone', None)
+        iccid = request_dict.get('iccid', None)
+        serial_no = request_dict.get('serialNo', None)
+        pageSize = request_dict.get('pageSize', None)
+        pageNo = request_dict.get('pageNo', None)
+
+        if not all({pageNo, pageSize}):
+            return response.json(444)
+
+        page = int(pageNo)
+        line = int(pageSize)
+
+        try:
+
+            unicom_device_qs = UnicomDeviceInfo.objects.all()
+            if iccid:
+                unicom_device_qs = unicom_device_qs.filter(iccid=iccid)
+            if serial_no:
+                unicom_device_qs = unicom_device_qs.filter(serial_no=serial_no)
+
+            device_user_qs = Device_User.objects.filter().values(
+                'userID', 'NickName', 'phone')
+            userID = ''
+            if NickName:
+                device_user_qs = device_user_qs.filter(NickName=NickName)
+                if not device_user_qs.exists():
+                    return response.json(0, [])
+                userID = device_user_qs.first()['userID']
+
+            if phone:
+                device_user_qs = device_user_qs.filter(phone=phone)
+                if not device_user_qs.exists():
+                    return response.json(0, [])
+                userID = device_user_qs.first()['userID']
+            if userID:
+                unicom_device_qs.filter(user_id=userID)
+
+            if not unicom_device_qs.exists():
+                return response.json(0, [])
+            total = unicom_device_qs.count()
+            unicom_device_qs = unicom_device_qs[(page - 1) * line:page * line]
+
+            list_data = []
+            for unicom_device in unicom_device_qs:
+                data = {
+                    'iccid': unicom_device.iccid,
+                    'serialNo': unicom_device.serial_no,
+                    'userID': unicom_device.user_id,
+                    'cardType': unicom_device.card_type,
+                    'mainCard': unicom_device.main_card,
+                    'createdTime': unicom_device.created_time,
+                    'NickName': '',
+                    'phone': ''
+                }
+                device_user_qs = Device_User.objects.filter(userID=unicom_device.user_id).values('NickName', 'phone')
+                data['NickName'] = device_user_qs[0]['NickName']
+                data['phone'] = device_user_qs[0]['phone']
+                list_data.append(data)
+            return response.json(0, {'list': list_data, 'total': total})
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def get_user_combo(request_dict, response):
+        """
+        获取卡用户信息
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        pageNo = request_dict.get('pageNo', None)
+        pageSize = request_dict.get('pageSize', None)
+        if not all([pageNo, [pageSize]]):
+            return response.json(444)
+        page = int(pageNo)
+        line = int(pageSize)
+        get_info_qs = UnicomDeviceInfo.objects.filter().values(
+            'iccid', 'serial_no', 'user_id', 'card_type', 'main_card', 'created_time'
+        ).order_by('-created_time')
+        total = get_info_qs.count()
+        get_info_qs = get_info_qs[(page - 1) * line:page * line]
+        try:
+            res_list = []
+            for item in get_info_qs:
+                res = {
+                    'userID': item['user_id'],
+                    'serialNo': item['serial_no'],
+                    'iccid': item['iccid'],
+                    'cardType': item['card_type'],
+                    'mainCard': item['main_card'],
+                    'createdTime': item['created_time']
+                }
+                usreID = get_info_qs[0]['user_id']
+                user_info_qs = Device_User.objects.filter(userID=usreID).values(
+                    'NickName', 'phone')
+                if user_info_qs.exists():
+                    res['userID'] = usreID
+                    res['NickName'] = user_info_qs.first()['NickName']
+                    res['phone'] = user_info_qs.first()['phone']
+                else:
+                    res['userID'] = ''
+                res_list.append(res)
+            return response.json(0, {'list': res_list, 'total': total})
+        except Exception as e:
+            return response.json(500, repr(e))
+
+    @staticmethod
+    def get_order_info(request_dict, response):
+        """
+        获取/筛选设备套餐订单信息
+        @param request_dict:
+        @param response:
+        @return:
+        serial_no 设备序列号
+        """
+        serial_no = request_dict.get('serialNo', None)
+        status = request_dict.get('status', None)
+        pageNo = request_dict.get('pageNo', None)
+        pageSize = request_dict.get('pageSize', None)
+
+        if not all({pageNo, pageSize}):
+            return response.json(444)
+        page = int(pageNo)
+        line = int(pageSize)
+
+        try:
+            combo_order_info_qs = UnicomComboOrderInfo.objects.all()
+            if serial_no:
+                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(0, [])
+                combo_order_info_qs = combo_order_info_qs.filter(iccid=unicom_device_qs[0]['iccid'])
+            if status:
+                status = int(status)
+                unicom_device_qs = UnicomDeviceInfo.objects.filter().values('serial_no', 'user_id',
+                                                                            'iccid').distinct()
+                combo_order_info_qs = combo_order_info_qs.filter(status=status)
+                if not unicom_device_qs.exists():
+                    return response.json(0, [])
+            if not combo_order_info_qs.exists():
+                return response.json(0, [])
+            combo_order_info_qs = combo_order_info_qs.order_by('-created_time')[(page - 1) * line:page * line]
+            total = combo_order_info_qs.count()
+            data_list = []
+            for combo_order in combo_order_info_qs:
+                data = {'nickName': '',
+                        'serialNo': '',
+                        'iccid': combo_order.iccid,
+                        'status': combo_order.status,
+                        'order_id': combo_order.order_id,
+                        'comboName': combo_order.combo.combo_name,
+                        'flow_total_usage': combo_order.flow_total_usage,
+                        'next_month_activate': combo_order.next_month_activate,
+                        'activationTime': combo_order.activation_time,
+                        'expireTime': combo_order.expire_time,
+                        'createdTime': combo_order.created_time,
+                        'updated_time': combo_order.updated_time}
+                iccid = combo_order.iccid
+                unicom_device_qs = UnicomDeviceInfo.objects.filter(iccid=iccid).values('user_id', 'serial_no')
+                # if not unicom_device_qs.exists():
+                #     return response.json(0, [])
+                userID = unicom_device_qs[0]['user_id']
+                if userID:
+                    device_user = Device_User.objects.filter(userID=userID).values('NickName')
+                    nick_name = device_user[0]['NickName']
+                    data['nickName'] = nick_name
+                data['serialNo'] = unicom_device_qs[0]['serial_no']
+                data_list.append(data)
+            return response.json(0, {'list': data_list, 'total': total})
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
+
+    @classmethod
+    def edit_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)
+        status = request_dict.get('status', None)
+        combo_type = request_dict.get('comboType', None)
+        flow_total = request_dict.get('flowTotal', None)
+        expiration_days = request_dict.get('expirationDays', None)
+        expiration_type = request_dict.get('expirationType', None)
+        pay_type = request_dict.get(
+            'payTypes', '')[
+                   1:-1].split(',')  # '[1,2]' -> ['1','2']
+        sort = request_dict.get('sort', None)
+        price = request_dict.get('price', None)
+        remark = request_dict.get('remark', None)
+        is_show = request_dict.get('isShow', None)
+
+        if not all([pay_type, price, is_show, status, combo_type, flow_total, expiration_days, expiration_type]):
+            return response.json(444)
+        flow_total = int(flow_total)
+        expiration_days = int(expiration_days)
+        expiration_type = int(expiration_type)
+        status = int(status)
+        combo_type = int(combo_type)
+        is_show = int(is_show)
+        sort = int(sort)
+
+        if combo_type == 1:
+            combo_type_qs = UnicomCombo.objects.filter(combo_type=1, is_del=False)
+            if combo_type_qs.exists():
+                if combo_id:
+                    combo_id = int(combo_id)
+                    combo_id_qs = combo_type_qs.first().id
+                    if combo_id != combo_id_qs:
+                        return response.json(174)
+                else:
+                    return response.json(174)
+        unicom_combo_qs = UnicomCombo.objects.all()
+
+        try:
+            with transaction.atomic():
+                re_data = {
+                    'combo_name': combo_name,
+                    'status': status,
+                    'combo_type': combo_type,
+                    'flow_total': flow_total,
+                    'expiration_days': expiration_days,
+                    'expiration_type': expiration_type,
+                    'price': price,
+                    'sort': sort,
+                    'remark': remark if remark else '',
+                    'is_show': is_show
+                }
+                if unicom_combo_qs.filter(id=combo_id).exists():
+                    re_data['updated_time'] = int(time.time())
+                    UnicomCombo.objects.filter(id=combo_id).update(**re_data)
+                    UnicomCombo.objects.get(id=combo_id).pay_type.set(pay_type)
+                else:
+                    re_data['updated_time'] = int(time.time())
+                    re_data['created_time'] = int(time.time())
+                    UnicomCombo.objects.create(**re_data).pay_type.set(pay_type)
+                return response.json(0)
+
+        except Exception as e:
+            print(repr(e))
+            return response.json(500)
+
+    @staticmethod
+    def get_unicom_info(request_dict, response):
+        """
+        获取套餐详细表
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        pageNo = request_dict.get('pageNo', None)
+        pageSize = request_dict.get('pageSize', None)
+        if not all([pageNo, pageSize]):
+            return response.json(444)
+        page = int(pageNo)
+        line = int(pageSize)
+        try:
+            combo_qs = UnicomCombo.objects.filter(is_del=False) \
+                           .order_by('sort').values('id', 'status', 'combo_name',
+                                                    'flow_total', 'combo_type',
+                                                    'expiration_days',
+                                                    'expiration_type', 'price', 'is_unlimited',
+                                                    'updated_time', 'created_time',
+                                                    'remark', 'is_show', 'sort')[(page - 1) * line:page * line]
+            if not combo_qs.exists():
+                return response.json(0, [])
+            total = combo_qs.count()
+            combo_list = []
+            for item in combo_qs:
+                # 获取支付方式列表
+                pay_type_list = [pay_type['id'] for pay_type in
+                                 UnicomCombo.objects.get(id=item['id']).pay_type.values('id')]
+                combo_list.append({
+                    'id': item['id'],
+                    'status': item['status'],
+                    'comboType': item['combo_type'],
+                    'comboName': item['combo_name'],
+                    'flowTotal': item['flow_total'],
+                    'expirationDays': item['expiration_days'],
+                    'expirationType': item['expiration_type'],
+                    'price': item['price'],
+                    'sort': item['sort'],
+                    'isUnlimited': item['is_unlimited'],
+                    'updatedTime': item['updated_time'],
+                    'createdTime': item['created_time'],
+                    'remark': item['remark'],
+                    'isShow': item['is_show'],
+                    'payTypes': pay_type_list,
+                })
+            return response.json(0, {'list': combo_list, 'total': total})
+        except Exception as e:
+            return response.json(177, repr(e))
+
+    @classmethod
+    def get_pay_type(cls, response):
+        """
+        获取支付类型
+        @param response:
+        @return:
+        """
+        pay_type_qs = Pay_Type.objects.all().values('id', 'payment')
+        if not pay_type_qs.exists():
+            return response.json(444)
+        try:
+            pay_type_list = []
+            for pay_type in pay_type_qs:
+                pay_type_qs.exists()
+                pay_type_list.append(pay_type)
+            return response.json(0, pay_type_list)
+        except Exception as e:
+            return response.json(500, e)
+
+    @classmethod
+    def combo_order_info(cls, request_dict, response):
+        """
+        删除卡套餐信息(修改状态)
+        @param request_dict
+        @param response
+        @return:
+        """
+        combo_id = request_dict.get('id', None)
+
+        if not combo_id:
+            return response.json(444)
+        try:
+            combo_qs = UnicomCombo.objects.filter(id=combo_id)
+            if combo_qs.exists():
+                combo_qs.update(is_del=True)
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
+
+    def static_info(self, request_dict, response):
+        """
+        统计联通套餐
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        year = request_dict.get('year', None)
+        Jan = int(time.mktime(time.strptime(year + '-1-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Feb = int(time.mktime(time.strptime(year + '-2-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Mar = int(time.mktime(time.strptime(year + '-3-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Apr = int(time.mktime(time.strptime(year + '-4-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        May = int(time.mktime(time.strptime(year + '-5-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Jun = int(time.mktime(time.strptime(year + '-6-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Jul = int(time.mktime(time.strptime(year + '-7-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Aug = int(time.mktime(time.strptime(year + '-8-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Sep = int(time.mktime(time.strptime(year + '-9-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Oct = int(time.mktime(time.strptime(year + '-10-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Nov = int(time.mktime(time.strptime(year + '-11-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Dec = int(time.mktime(time.strptime(year + '-12-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+        Jan_next = int(time.mktime(time.strptime(str(int(year) + 1) + '-1-1 00:00:00', "%Y-%m-%d %H:%M:%S")))
+
+        list_data = []
+        unicom_combo_qs = UnicomCombo.objects.filter().values('id', 'combo_type', 'combo_name')
+
+        if not unicom_combo_qs.exists():
+            return response.json(173)
+        try:
+            for unicom_combo in unicom_combo_qs:
+                name = unicom_combo['combo_name']
+                combo_order = UnicomComboOrderInfo.objects.filter(combo_id=unicom_combo['id'])
+                if not combo_order.exists():
+                    continue
+                Jan_count = combo_order.filter(created_time__range=[Jan, Feb]).count()
+                Feb_count = combo_order.filter(created_time__range=[Feb, Mar]).count()
+                Mar_count = combo_order.filter(created_time__range=[Mar, Apr]).count()
+                Apr_count = combo_order.filter(created_time__range=[Apr, May]).count()
+                May_count = combo_order.filter(created_time__range=[May, Jun]).count()
+                Jun_count = combo_order.filter(created_time__range=[Jun, Jul]).count()
+                Jul_count = combo_order.filter(created_time__range=[Jul, Aug]).count()
+                Aug_count = combo_order.filter(created_time__range=[Aug, Sep]).count()
+                Sep_count = combo_order.filter(created_time__range=[Sep, Oct]).count()
+                Oct_count = combo_order.filter(created_time__range=[Oct, Nov]).count()
+                Nov_count = combo_order.filter(created_time__range=[Nov, Dec]).count()
+                Dec_count = combo_order.filter(created_time__range=[Dec, Jan_next]).count()
+                data = [Jan_count, Feb_count, Mar_count, Apr_count, May_count, Jun_count, Jul_count, Aug_count,
+                        Sep_count,
+                        Oct_count, Nov_count, Dec_count]
+
+                cloud_data = {
+                    'name': name,
+                    'type': 'line',
+                    'data': data,
+                }
+                list_data.append(cloud_data)
+
+            return response.json(0, {'list': list_data})
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))

+ 5 - 1
Ansjer/server_urls/unicom_url.py

@@ -8,8 +8,12 @@
 """
 from django.urls import re_path
 
-from Controller.UnicomCombo import UnicomComboController
+from Controller.UnicomCombo import UnicomComboController, UnicomComboPayNotifyController, UnicomComboTaskController
+from AdminController import UnicomManageController
 
 urlpatterns = [
     re_path(r'^api/(?P<operation>.*)$', UnicomComboController.UnicomComboView.as_view()),
+    re_path(r'^wap/pay/(?P<operation>.*)$', UnicomComboPayNotifyController.UnicomComboPayNotifyView.as_view()),
+    re_path(r'^combo/cron/(?P<operation>.*)$', UnicomComboTaskController.UnicomComboTaskView.as_view()),
+    re_path(r'^manage/(?P<operation>.*)$',UnicomManageController.UnicomComboView.as_view()),
 ]

+ 19 - 2
Controller/EquipmentManagerV3.py

@@ -13,7 +13,7 @@ from Controller.DeviceConfirmRegion import Device_Region
 from Object.RedisObject import RedisObject
 from Ansjer.config import OSS_STS_ACCESS_SECRET, OSS_STS_ACCESS_KEY, BASE_DIR
 from Model.models import Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidPushModel, UidChannelSetModel, \
-    Device_User, iotdeviceInfoModel, UIDCompanySerialModel, UIDMainUser, UIDModel
+    Device_User, iotdeviceInfoModel, UIDCompanySerialModel, UIDMainUser, UIDModel, UnicomDeviceInfo
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
@@ -205,9 +205,11 @@ class EquipmentManagerV3(View):
             uid_serial_qs = UIDCompanySerialModel.objects.filter(uid__uid=UID)
             if uid_serial_qs.exists():
                 uid_serial = uid_serial_qs[0]
+                serial_number = uid_serial.company_serial.serial_number + uid_serial.company_serial.company.mark
                 Device_Info.objects.filter(UID=UID).update(vodPrimaryUserID=vodPrimaryUserID,
                                                            vodPrimaryMaster=vodPrimaryMaster,
-                                                           serial_number=uid_serial.company_serial.serial_number + uid_serial.company_serial.company.mark)
+                                                           serial_number=serial_number)
+                self.unicom_user_info_save(userID, serial_number)
             else:
                 Device_Info.objects.filter(UID=UID).update(vodPrimaryUserID=vodPrimaryUserID,
                                                            vodPrimaryMaster=vodPrimaryMaster)
@@ -267,6 +269,21 @@ class EquipmentManagerV3(View):
 
             return response.json(0, res)
 
+    @classmethod
+    def unicom_user_info_save(cls, user_id, serial_number):
+        """
+        保存联通与用户信息绑定
+        @param user_id: 用户id
+        @param serial_number: 序列号
+        @return: True | False
+        """
+        unicom_device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_number)
+        if not unicom_device_info_qs.exists():
+            return False
+        if not unicom_device_info_qs[0].user_id:
+            unicom_device_info_qs.update(user_id=user_id)
+        return True
+
     def do_batch_add(self, userID, request_dict, response, request):
         # 批量添加设备
         uidContent = request_dict.get('uidContent', None)

+ 1 - 0
Controller/ShadowController.py

@@ -102,6 +102,7 @@ def update_device_shadow(request):
         is_human = request_dict.get('is_human', None)
         is_custom_voice = request_dict.get('is_custom', None)
         double_wifi = request_dict.get('double_wifi', None)
+        mobile_4g = request_dict.get('mobile4G', None)
         is_ptz = request_dict.get('is_ptz', None)
         us_qs = UidSetModel.objects.filter(uid=uid)
         is_ai = request_dict.get('is_ai', None)

+ 487 - 13
Controller/UnicomCombo/UnicomComboController.py

@@ -6,18 +6,25 @@
 @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.http import HttpResponse
+from django.http import HttpResponse, JsonResponse
 from django.views.generic.base import View
 
-from Model.models import UnicomDeviceInfo, UnicomCombo, Pay_Type
+from Model.models import UnicomDeviceInfo, UnicomCombo, Pay_Type, Order_Model, Store_Meal, AiStoreMeal, \
+    UnicomComboOrderInfo, UnicomComboExperienceHistory, UnicomDeviceStatusChangePush, SysMsgModel, UnicomFlowPush
 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):
@@ -32,25 +39,217 @@ class UnicomComboView(View):
         return self.validation(request.POST, request, operation)
 
     def validation(self, request_dict, request, operation):
-        if operation == 'buy-notify':
-            return self.package_callback_notify(request_dict, request)
+        response = ResponseObject('cn')
+        if operation == 'query-usage-history':
+            return self.query_device_usage_history(request_dict, 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':
             return self.device_status_change_push(request_dict, request)
         elif operation == 'device-bind':
-            response = ResponseObject('cn')
             return self.device_add(request_dict, response)
+        elif operation == 'device-status':
+            return self.update_device_status(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':
+                return self.get_device_info(request_dict, response)
+            elif operation == 'user-combo-query':
+                return self.user_combo_query(user_id, request_dict, response)
+
+    @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:
+                unicom_device_info_qs.update(user_id=user_id)
+            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 = unicom_api.get_flow_usage_total(iccid)
+                flow = flow_total_usage - activate_flow
+                flow_details['usableFlow'] = flow_details['flowTotal'] - flow
+
+                flow_details['usableFlow'] = \
+                    0.00 if flow_details['usableFlow'] <= 0 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:
+            print(e.args)
+            ex = traceback.format_exc()
+            print(ex)
+            return response.json(177, ex)
+
+    @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_dict, response):
+        """
+        修改绑定设备状态,如产生免费套餐用量则删除
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        logger = logging.getLogger('info')
+
+        serial_no = request_dict.get('serialNo', None)
+        iccid = request_dict.get('iccid', None)
+        time_stamp = request_dict.get('timeStamp', None)
+        sign = request_dict.get('sign', None)
+        if not all([iccid, serial_no, sign, time_stamp]):
+            return response.json(444)
+        logger.info('PC工具进入重置ICCID{}'.format(iccid))
+        try:
+            if not CommonService.check_time_stamp_token(sign, time_stamp):
+                return response.json(13)
+            now_time = int(time.time())
+            with transaction.atomic():
+                device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid, serial_no=serial_no)
+                if device_info_qs.exists():
+                    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)
+                    if combo_order_qs.exists():
+                        combo_order_qs.delete()
+                    combo_experience_history_qs = UnicomComboExperienceHistory.objects.filter(iccid=iccid)
+                    if combo_experience_history_qs.exists():
+                        combo_experience_history_qs.delete()
+
+                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)
+
+    @classmethod
+    def get_device_info(cls, request_dict, response):
+        """
+        获取设备信息
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        serial_no = request_dict.get('serialNumber', None)
+        if not serial_no:
+            return response.json(444)
+        unicom_device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no).values()
+        if not unicom_device_info_qs.exists():
+            return response.json(173)
+        return response.json(0, dict(unicom_device_info_qs.first()))
 
     @classmethod
     def device_add(cls, request_dict, response):
@@ -62,14 +261,24 @@ class UnicomComboView(View):
         """
         iccid = request_dict.get('iccid', None)
         serial_no = request_dict.get('serialNo', None)
-        if not all([iccid, serial_no]):
+        time_stamp = request_dict.get('timeStamp', None)
+        sign = request_dict.get('sign', None)
+        logger = logging.getLogger('info')
+        logger.info('--->设备调用4G注册接口')
+        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():
                 # 待完善代码 根据uid与用户id验证系统设备
                 unicom_device_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
                 if unicom_device_qs.exists():
+                    if unicom_device_qs.first().status == 1 and unicom_device_qs.first().serial_no == serial_no:
+                        cls.user_activate_flow(iccid)
                     return response.json(174)
                 unicom_obj = UnicomObjeect()
                 result = unicom_obj.verify_device(iccid=iccid)
@@ -80,14 +289,57 @@ class UnicomComboView(View):
                             return response.json(173)
                         params = {'iccid': iccid, 'serial_no': serial_no, 'updated_time': n_time,
                                   'created_time': n_time}
+                        unicom_obj.change_device_to_activate(iccid)
                         UnicomDeviceInfo.objects.create(**params)
                     return response.json(0)
                 else:
                     return response.json(173)
         except Exception as e:
             print(e)
+            logger.info('--->设备调用4G注册接口异常')
             return response.json(177, repr(e))
 
+    @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)
+                return True
+        except Exception as e:
+            print(e)
+            return False
+
     @classmethod
     def save_unicom_combo(cls, request_dict, response):
         """
@@ -165,19 +417,101 @@ class UnicomComboView(View):
             return response.json(177, repr(e))
 
     @classmethod
-    def buy_package(cls):
+    def buy_unicom_combo(cls, user_id, request_dict, request, response):
         """
-        购买套餐
+        购买联通套餐
         @return:
         """
-        pass
+        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,
+                              }
+
+                params = 'lang=cn' + '&activateType=' + 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, 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):
+    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):
@@ -254,11 +588,151 @@ class UnicomComboView(View):
                 dict_data.pop('sign')
                 unicom_obj = UnicomObjeect()
                 generate_sign = unicom_obj.createSign(**dict_data)
-                logger.info('设备状态变更推送请求签名{}'.format(sign))
-                logger.info('设备状态变更推送生成签名{}'.format(generate_sign))
+                logger.info('联通设备状态变更推送请求签名{}'.format(sign))
+                logger.info('联通设备状态变更推送生成签名{}'.format(generate_sign))
+                assert generate_sign == sign
+                now_time = int(time.time())
+                re_data = {
+                    'iccid': dict_data['iccid'],
+                    'serial_no': dict_data['serialNo'],
+                    'sign': sign,
+                    'type': dict_data['type'],
+                    'previous_val': dict_data['previousVal'],
+                    'current_val': dict_data['currentVal'],
+                    'reason': dict_data['reason'],
+                    'time': dict_data['time'],
+                    '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:
             print(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']
+                        zero_today, end_time = cls.get_data_time(days)
+                        combo_order_data['activation_time'] = now_time
+                        combo_order_data['expire_time'] = end_time
+                        # 联通业务逻辑
+                    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_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})

+ 189 - 0
Controller/UnicomCombo/UnicomComboPayNotifyController.py

@@ -0,0 +1,189 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : UnicomComboPayNotifyController.py
+@Time    : 2022/6/29 14:31
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+import logging
+import time
+from urllib.parse import parse_qs, unquote
+
+from django.db import transaction
+from django.http import HttpResponse
+from django.views import View
+
+from Controller.UnicomCombo.UnicomComboController import UnicomComboView
+from Model.models import Order_Model, UnicomDeviceInfo
+from Object.AliPayObject import AliPayObject
+from Object.RedisObject import RedisObject
+from Object.WechatPayObject import WechatPayObject
+from Service.CommonService import CommonService
+
+
+class UnicomComboPayNotifyView(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):
+        if operation == 'ali-notify':
+            return self.alipay_notify(request_dict)
+        elif operation == 'wechat-notify':
+            return self.wechat_notify(request)
+
+    @classmethod
+    def alipay_notify(cls, request_dict):
+        """
+        支付宝网页支付异步回调通知
+        参考文档 https://opendocs.alipay.com/open/203/105286
+        @param request_dict: 请求参数
+        @return: success or fail
+        """
+        logger = logging.getLogger('info')
+        logger.info('联通套餐支付---支付宝支付回调')
+        order_id = ''
+        redisObj = RedisObject()
+        notify_key = 'ansjer:unicom:alipay:{}:str'
+        try:
+            re_data = request_dict.dict()
+            passback_params = re_data['passback_params']
+            params = dict([(k, v[0]) for k, v in parse_qs(unquote(passback_params)).items()])
+            activate_type = int(params['activateType'])
+            logger.info('支付宝异步回调参数:{},携带参数{}', re_data, params)
+            signature = re_data['sign']
+            re_data.pop('sign')
+            order_id = re_data['out_trade_no']
+
+            # redis加锁,防止订单重复  命令在指定的 key 不存在时,为 key 设置指定的值。存在则返回0
+            isLock = redisObj.CONN.setnx(notify_key.format(order_id), 1)
+            # 过期时间60秒
+            redisObj.CONN.expire(notify_key.format(order_id), 60)
+            if not isLock:
+                return HttpResponse('fail')
+
+            order_qs = Order_Model.objects.filter(orderID=order_id)
+            if not order_qs.exists():
+                logger.info('系统订单不存在:{}'.format(order_id))
+                return HttpResponse('fail')
+            order_qs = order_qs.filter(status=0)
+            if not order_qs.exists():
+                logger.info('订单已支付或退款{}'.format(order_id))
+                return HttpResponse('success')
+            aliPayObj = AliPayObject()
+            alipay = aliPayObj.conf()
+            # 异步回调验签
+            success = alipay.verify(re_data, signature)
+            if not success or re_data["trade_status"] not in ("TRADE_SUCCESS", "TRADE_FINISHED"):
+                return HttpResponse('fail')
+            return cls.order_pay_notify(order_id, re_data["trade_no"], activate_type, notify_key.format(order_id),
+                                        order_qs, redisObj)
+        except Exception as e:
+            logger.info('联通套餐订单支付宝支付回调异常:{}'.format(repr(e)))
+            redisObj.del_data(key=notify_key.format(order_id))
+            return HttpResponse('fail')
+
+    @classmethod
+    def wechat_notify(cls, request):
+        """
+        微信支付异步回调
+        参考文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
+        @param request: 回调参数 具体参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8
+        @return: SUCCESS or FAIL
+        """
+        logger = logging.getLogger('info')
+        logger.info('联通套餐支付---微信支付回调')
+        order_id = ''
+        redisObj = RedisObject()
+        notify_key = 'ansjer:unicom:wxpay:{}:str'
+        pay = WechatPayObject()
+        try:
+            re_data = pay.weixinpay_call_back(request.body)
+            attach = re_data["attach"]
+            parmap = dict([(k, v[0]) for k, v in parse_qs(unquote(attach)).items()])
+            activate_type = int(parmap['activateType'])
+            logger.info('微信异步回调参数:{},携带参数{}'.format(re_data, parmap))
+            trade_status = re_data['result_code']  # 业务结果  SUCCESS/FAIL
+            order_id = re_data['out_trade_no']  # 商户订单号
+            order_qs = Order_Model.objects.filter(orderID=order_id)
+            if not order_qs.exists():
+                return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
+            order_qs = order_qs.filter(status=0)
+            if not order_qs.exists():
+                logger.info('订单已支付或退款{}'.format(order_id))
+                return cls.wx_return_code()
+
+            if trade_status != 'SUCCESS':
+                logger.info('微信支付回调Fail')
+                order_qs.update(status=10)
+                return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
+            check_sign = pay.get_notifypay(re_data)
+            if not check_sign:
+                logger.info('微信支付回调签名失败')
+                return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': '签名失败'}))
+
+            # redis加锁,防止订单重复
+            redisObj = RedisObject()
+            isLock = redisObj.CONN.setnx(notify_key.format(order_id), 1)
+            redisObj.CONN.expire(notify_key.format(order_id), 60)
+            if not isLock:
+                return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
+
+            return cls.order_pay_notify(order_id, re_data["transaction_id"], activate_type, notify_key.format(order_id),
+                                        order_qs,
+                                        redisObj, True)
+        except Exception as e:
+            redisObj.del_data(key=notify_key.format(order_id))
+            return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': repr(e)}))
+
+    @staticmethod
+    def wx_return_code():
+        return HttpResponse("<xml>\
+                                  <return_code><![CDATA[SUCCESS]]></return_code>\
+                                  <return_msg><![CDATA[OK]]></return_msg>\
+                              </xml>")
+
+    @classmethod
+    def order_pay_notify(cls, order_id, trade_no, activate_type, request_key, order_qs, redisObj, is_wechat_pay=False):
+        """
+        订单支付通知
+        @param trade_no: 第三方交易流水号
+        @param order_id:订单编号
+        @param activate_type: 激活类型
+        @param request_key:访问缓存key
+        @param order_qs:订单对象
+        @param redisObj:缓存对象
+        @param is_wechat_pay:是否微信支付
+        @return: success or fail
+        """
+        logger = logging.getLogger('info')
+        now_time = int(time.time())
+        with transaction.atomic():
+            # 支付宝交易凭证号。
+            order_qs = order_qs.values('UID', 'unify_combo_id', 'userID_id', 'order_type')
+            device_uid = order_qs[0]['UID']
+            combo_id = order_qs[0]['unify_combo_id']
+            serial_no = CommonService.query_serial_with_uid(device_uid)
+            unicom_device_info_qs = UnicomDeviceInfo.objects.filter(serial_no=serial_no).values('iccid')
+            if unicom_device_info_qs.exists():
+                iccid = unicom_device_info_qs[0]['iccid']
+                UnicomComboView.create_combo_order_info(order_id, activate_type,
+                                                        iccid, combo_id)
+            order_qs.update(trade_no=trade_no, status=1, payTime=now_time, updTime=now_time)
+            logger.info('购买联通套餐成功,序列号为:{}'.format(serial_no))
+        redisObj.del_data(key=request_key)
+        if is_wechat_pay:
+            return HttpResponse("<xml>\
+                          <return_code><![CDATA[SUCCESS]]></return_code>\
+                          <return_msg><![CDATA[OK]]></return_msg>\
+                        </xml>")
+        else:
+            return HttpResponse('success')

+ 281 - 0
Controller/UnicomCombo/UnicomComboTaskController.py

@@ -0,0 +1,281 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : UnicomComboTaskController.py
+@Time    : 2022/6/30 16:23
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+import datetime
+import logging
+import time
+from decimal import Decimal
+
+from django.db import transaction
+from django.db.models import Q
+from django.views import View
+
+from Model.models import UnicomComboOrderInfo, UnicomCombo, Order_Model, UnicomDeviceInfo, UnicomFlowPush
+from Object.ResponseObject import ResponseObject
+from Object.UnicomObject import UnicomObjeect
+
+
+class UnicomComboTaskView(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()
+        print(request)
+        if operation == 'check-activate':
+            return self.check_activate_combo(request_dict, response)
+        elif operation == 'check-flow':
+            return self.check_flow_usage(response)
+        elif operation == 'check-flow-expire':
+            return self.check_flow_expire(response)
+        elif operation == 'check-expire':
+            today = datetime.datetime.today()
+            year = today.year
+            month = today.month
+            self.query_unused_combo_and_activate(request_dict.get('iccid'), year, month, '666')
+            return response.json(0)
+
+    @classmethod
+    def check_activate_combo(cls, request_dict, response):
+        """
+        定时检查是否有次月激活套餐
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        logger = logging.getLogger('info')
+        print(request_dict)
+        logger.info('--->进入监控次月激活联通套餐')
+        now_time = int(time.time())
+        combo_order_info_qs = UnicomComboOrderInfo.objects.filter(status=0, next_month_activate=True,
+                                                                  activation_time__lte=now_time,
+                                                                  expire_time__gte=now_time, is_del=0).values()
+        if not combo_order_info_qs.exists():
+            return response.json(0)
+        try:
+            today = datetime.datetime.today()
+            year = today.year
+            month = today.month
+            with transaction.atomic():
+                unicom_api = UnicomObjeect()
+                for item in combo_order_info_qs:
+                    if item['order_id']:
+                        order_id = item['order_id']
+                        order_qs = Order_Model.objects.filter(orderID=order_id, status=1)
+                        if not order_qs.exists():
+                            continue
+                        combo_order_qs = UnicomComboOrderInfo.objects.filter(status=1, iccid=item['iccid'])
+                        # 当前已有套餐正在使用则跳出当前循环
+                        if combo_order_qs.exists():
+                            continue
+                        combo_id = item['combo_id']
+                        combo_qs = UnicomCombo.objects.filter(id=combo_id).values()
+                        if not combo_qs.exists():
+                            continue
+                        # 查询当月用量情况
+                        flow_total_usage = unicom_api.get_flow_usage_total(item['iccid'])
+                        flow_total_usage = Decimal(flow_total_usage).quantize(
+                            Decimal('0.00')) if flow_total_usage > 0 else 0
+                        flow_total_usage = str(flow_total_usage)
+                        iccid = item['iccid']
+                        # 检查激活iccid
+                        unicom_api.change_device_to_activate(iccid)
+                        cls.query_unused_combo_and_activate(iccid, year, month, flow_total_usage)
+                        logger.info('激活成功,订单编号:{}'.format(order_id))
+            return response.json(0)
+        except Exception as e:
+            logger.info('出错了~次月激活套餐异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(177, repr(e))
+
+    @classmethod
+    def check_flow_usage(cls, response):
+        """
+        检查流量使用情况
+        @return:
+        """
+        logger = logging.getLogger('info')
+        logger.info('--->进入监控流量使用情况')
+        try:
+            unicom_api = UnicomObjeect()
+            combo_order_qs = UnicomComboOrderInfo.objects.filter(status=1, is_del=False, combo__is_unlimited=0).values()
+            if not combo_order_qs.exists():
+                return response.json(0)
+            today = datetime.datetime.today()
+            year = today.year
+            month = today.month
+            now_time = int(time.time())
+            for item in combo_order_qs:
+                iccid = item['iccid']
+                u_device_info_qs = UnicomDeviceInfo.objects.filter(iccid=iccid)
+                if not u_device_info_qs.exists():
+                    continue
+                u_device_info_qs = u_device_info_qs.first()
+                activate_usage_flow = float(item['flow_total_usage']) if item['flow_total_usage'] else 0.0
+                combo_id = item['combo_id']
+                combo_qs = UnicomCombo.objects.filter(id=combo_id).values()
+                if not combo_qs.exists():
+                    continue
+                combo_qs = combo_qs.first()
+                flow_total = combo_qs['flow_total']
+                # 队列已使用总流量总量
+                flow_total_usage = unicom_api.get_flow_usage_total(iccid)
+                logger.info('--->iccid:{};套餐总值:{},激活时队列已用总流量:{},当前最新套餐队列已使用流量量:{}'
+                            .format(iccid, flow_total, activate_usage_flow, flow_total_usage))
+                is_expire = False
+                flow = activate_usage_flow + flow_total
+                if flow_total_usage > 0:
+                    # 初始套餐已使用流量 + 套餐总流量
+                    if flow_total_usage >= flow:
+                        is_expire = True
+                    usage = (flow_total_usage - activate_usage_flow) if flow_total_usage > activate_usage_flow else 0
+                    cls.flow_warning_push(u_device_info_qs.user_id, u_device_info_qs.serial_no, item['id'], flow_total,
+                                          usage)
+
+                # 检查是否有当月未使用套餐 没有则停卡
+                if is_expire:
+                    flow_exceed = flow_total_usage - flow
+                    UnicomComboOrderInfo.objects.filter(id=item['id']) \
+                        .update(status=2, updated_time=now_time, flow_exceed=flow_exceed)
+                    activate_status = cls.query_unused_combo_and_activate(iccid, year, month,
+                                                                          flow_total_usage)
+                    if not activate_status:
+                        # 停用
+                        unicom_api.change_device_to_disable(iccid)
+
+            return response.json(0)
+        except Exception as e:
+            logger.info('出错了~检测流量用量详情异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(177, repr(e))
+
+    @staticmethod
+    def flow_warning_push(app_user_id, serial_no, combo_order_id, flow_total, flow_usage):
+        """
+        监控流量使用大于85%and小于96%进行消息推送提醒
+        @param app_user_id: app用户id
+        @param serial_no: 序列号
+        @param combo_order_id: 当前套餐订单id
+        @param flow_total: 套餐流量总量
+        @param flow_usage: 套餐已使用流量
+        @return:
+        """
+        logger = logging.getLogger('info')
+        try:
+            if not app_user_id:
+                return False
+            now_time = int(time.time())
+            push_data = {'combo_order_id': str(combo_order_id), 'serial_no': serial_no,
+                         'flow_total_usage': flow_usage, 'flow_total': flow_total, 'status': 0,
+                         'updated_time': now_time,
+                         'created_time': now_time, 'user_id': app_user_id}
+            if 0 < flow_total and 0 < flow_usage < flow_total:
+                res = flow_usage / flow_total * 100
+                if 85 < res <= 95:
+                    flow_push = UnicomFlowPush.objects.filter(serial_no=serial_no, combo_order_id=combo_order_id)
+                    if not flow_push.exists():
+                        UnicomFlowPush.objects.create(**push_data)
+            elif flow_usage >= flow_total:
+                push_data['flow_total_usage'] = flow_total
+                push_data['type'] = 1
+                UnicomFlowPush.objects.create(**push_data)
+            return True
+        except Exception as e:
+            logger.info('出错了~异常流量监控,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def query_unused_combo_and_activate(iccid, year, month, usage_flow):
+        """
+        查询未使用套餐并激活
+        @param iccid:
+        @param year:
+        @param month:
+        @param usage_flow:
+        @return:
+        """
+        logger = logging.getLogger('info')
+        try:
+            now_time = int(time.time())
+            combo_order_qs = UnicomComboOrderInfo.objects \
+                .filter(expire_time__gt=now_time, activation_time__lte=now_time, status=0, iccid=iccid) \
+                .order_by('created_time')
+            if not combo_order_qs.exists():
+                return False
+
+            combo_order = combo_order_qs.first()
+            if not combo_order.order_id:
+                return False
+            order_qs = Order_Model.objects.filter(orderID=combo_order.order_id, status=1)
+            if not order_qs.exists():
+                return False
+            upd_data = {
+                'status': 1,
+                'year': year,
+                'month': month,
+                'flow_total_usage': str(usage_flow),
+                'updated_time': now_time,
+            }
+            UnicomComboOrderInfo.objects.filter(id=combo_order.id).update(**upd_data)
+            return True
+        except Exception as e:
+            logger.info('出错了~检测流量用量详情异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return False
+
+    @classmethod
+    def check_flow_expire(cls, response):
+        """
+        检查流量到期停卡操作
+        @param response:
+        @return:
+        """
+        logger = logging.getLogger('info')
+        logger.info('--->进入监控流量到期停卡或激活叠加包')
+        now_time = int(time.time())
+        combo_order_qs = UnicomComboOrderInfo.objects.filter(~Q(status=2), expire_time__lte=now_time,
+                                                             is_del=False).values()
+        today = datetime.datetime.today()
+        year = today.year
+        month = today.month
+        if not combo_order_qs.exists():
+            return response.json(0)
+        iccid_list = []
+        with transaction.atomic():
+            for item in combo_order_qs:
+                try:
+                    icc_id = item['iccid']
+                    um_device_qs = UnicomDeviceInfo.objects.filter(iccid=icc_id)
+                    if not um_device_qs.exists():
+                        continue
+                    UnicomComboOrderInfo.objects.filter(id=item['id']).update(status=2)
+                    iccid_list.append(icc_id)
+                    logger.info('--->当前流量套餐已过期,iccid:{}'.format(icc_id))
+                except Exception as e:
+                    logger.info('出错了~监控流量到期异常,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+                    continue
+        # set无序不重复元素集
+        iccid_list = list(set(iccid_list))
+        unicom_api = UnicomObjeect()
+        for item in iccid_list:
+            activate_combo_qs = UnicomComboOrderInfo.objects.filter(iccid=item, status=1, expire_time__gt=now_time,
+                                                                    is_del=False).values()
+            if activate_combo_qs.exists():
+                continue
+            usage_flow = unicom_api.get_flow_usage_total(item)
+            result = cls.query_unused_combo_and_activate(item, year, month, usage_flow)
+            if not result:
+                # 停用设备
+                unicom_api.change_device_to_disable(item)
+            else:
+                unicom_api.change_device_to_activate(item)
+        return response.json(0)

+ 31 - 1
Controller/UserController.py

@@ -15,6 +15,7 @@ import datetime
 import traceback
 import time
 import logging
+import threading
 import jwt
 import simplejson
 import simplejson as json
@@ -32,7 +33,8 @@ from ratelimit.decorators import ratelimit
 from Ansjer.config import AuthCode_Expire, SERVER_DOMAIN, APNS_CONFIG, JPUSH_CONFIG, FCM_CONFIG, TUTK_PUSH_DOMAIN
 from Controller.CheckUserData import DataValid, date_handler, RandomStr
 from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
-    UserAppFrequencyModel, CountryIPModel, CountryModel, UidChannelSetModel, Order_Model, UID_Bucket, Unused_Uid_Meal
+    UserAppFrequencyModel, CountryIPModel, CountryModel, UidChannelSetModel, Order_Model, UID_Bucket, Unused_Uid_Meal, \
+    GatewayPush
 from Object.AWS.SesClassObject import SesClassObject
 from Object.AliSmsObject import AliSmsObject
 from Object.RedisObject import RedisObject
@@ -2194,6 +2196,9 @@ class InitInfoView(View):
                     return response.json(904)
             else:
                 return response.json(444, 'push_type')
+            asy = threading.Thread(target=self.save_push_config,
+                                   args=(userID, appBundleId, push_type, token_val, m_code, lang, tz))
+            asy.start()
             if m_code:
                 # 获取设备推送状态
                 update_dict = {
@@ -2237,6 +2242,31 @@ class InitInfoView(View):
         res = {'usmsg': 0}  # 预留字段, 有版本app该字段去掉会报错
         return response.json(0, res)
 
+    @staticmethod
+    def save_push_config(user_id, app_bundle_id, push_type, token_val, m_code, lang, tz):
+        """
+        异步保存新推送配置
+        @param user_id: 用户id
+        @param app_bundle_id: app版本包id
+        @param push_type: 推送类型 0:Ios,1:Google,2:国内极光
+        @param token_val: 推送token
+        @param m_code: 手机唯一标识
+        @param lang: 语言
+        @param tz: 时区
+        @return: None
+        """
+        try:
+            app_type = 1 if push_type == 0 else 2
+            gateway_push_qs = GatewayPush.objects.filter(user_id=user_id, m_code=m_code)
+            if gateway_push_qs.exists():
+                gateway_push_qs.update(token_val=token_val, logout=False)
+            else:
+                GatewayPush.objects.create(user_id=user_id, app_bundle_id=app_bundle_id, app_type=app_type,
+                                           push_type=push_type, token_val=token_val, m_code=m_code, lang=lang, tz=tz)
+        except Exception as e:
+            print('出错了~异步保存配置信息错误,errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+
     def update_country(self, request_dict, response, request):
         username = request_dict.get('unique', None)
         appBundleId = request_dict.get('appBundleId', None)

+ 101 - 7
Object/UnicomObject.py

@@ -7,15 +7,17 @@
 @Software: PyCharm
 """
 import base64
+import datetime
 import json
+from decimal import Decimal
 
 import requests
 from Crypto.Cipher import AES
-from decimal import Decimal
-from Object.utils import SM3Util
 
 from Ansjer.config import unicomAppUrl, unicomAppId, unicomAppSecret, unicomTenantId, \
     unicomEncodeKey, unicomIvKey, unicomUserName, unicomPassword, unicomPushKey
+from Object.RedisObject import RedisObject
+from Object.utils import SM3Util
 from Object.utils.SymmetricCryptoUtil import AESencrypt
 
 """
@@ -216,8 +218,100 @@ class UnicomObjeect:
         headers['content-type'] = 'application/json'
         return requests.post(url, data=json.dumps(re_data), headers=headers)
 
+    @staticmethod
+    def get_text_dict(result):
+        """
+        响应结果转字典
+        @param result:
+        @return:
+        """
+        if result.status_code == 200:
+            return json.loads(result.text)
+        return None
+
+    @staticmethod
+    def get_flow_total_usage(key, expire=0, **usage_data):
+        """
+        设备当前队列用量详情(实现缓存)
+        @param key: 缓存key
+        @param expire: 失效时间
+        @param usage_data: 查询参数
+        @return: 返回结果dict
+        """
+        redis = RedisObject()
+        flow_usage_details = redis.get_data(key)
+        if flow_usage_details:
+            flow_usage_details = json.loads(flow_usage_details)
+        else:
+            flow_usage_details = UnicomObjeect().query_current_renew_list_usage_details(**usage_data)
+            flow_usage_details = UnicomObjeect().get_text_dict(flow_usage_details)
+            redis.set_data(key=key, val=json.dumps(flow_usage_details), expire=expire)
+        return flow_usage_details
+
+    @staticmethod
+    def get_flow_usage_total(iccid):
+        """
+        获取实时当前套餐队列总已用流量
+        @param iccid: 联通id
+        @return: flow_total_usage 当前套餐总已使用流量
+        """
+        flow_key = 'ASJ:UNICOM:FLOW:{}'
+        usage_data = {'iccid': iccid, 'realTime': True}
+        flow_usage_details = UnicomObjeect().get_flow_total_usage(flow_key.format(iccid), (60 * 10 + 3), **usage_data)
+        # 当月实际总使用流量
+        flow_total_usage = 0
+        if flow_usage_details and flow_usage_details['success']:
+            flow_total_usage = flow_usage_details['data']['flowTotalUsage']
+        return flow_total_usage
+
+    @staticmethod
+    def change_device_to_activate(iccid):
+        """
+        根据iccid判断是否激活,未激活则修改为激活状态
+        @param iccid:
+        @return:
+        """
+        if iccid:
+            re_data = {'iccid': iccid}
+            result = UnicomObjeect().query_device_status(**re_data)
+            res_dict = UnicomObjeect().get_text_dict(result)
+            # 状态不等于1(激活)时进行激活 1:激活;2:停用
+            if res_dict['data']['status'] != 1:
+                re_data = {"iccid": iccid, "status": 1}
+                UnicomObjeect().update_device_state(**re_data)
+            return True
+        return None
+
+    @staticmethod
+    def change_device_to_disable(iccid):
+        """
+        修改设备为停用,并查看是否修改成功
+        @param iccid:
+        @return:
+        """
+        if iccid:
+            re_data = {"iccid": iccid, "status": 2}
+            UnicomObjeect().update_device_state(**re_data)
+            # 查询是否停用成功
+            re_data.pop('status')
+            result = UnicomObjeect().query_device_status(**re_data)
+            res_dict = UnicomObjeect().get_text_dict(result)
+            if res_dict['data']['status'] != 3:
+                UnicomObjeect().update_device_state(**re_data)
+            return True
+        return None
+
 
 if __name__ == '__main__':
+
+    today = datetime.datetime.today()
+    year = today.year
+    month = today.month
+    print(year)
+    print(month)
+    print(type(year))
+    if not '':
+        print('为空')
     price = '12.13'
     print(float(price))
     discount = '6'
@@ -229,10 +323,10 @@ if __name__ == '__main__':
     print(unicom_api.createSign(**data))
     # result = unicom_api.generate_token()
     # result = unicom_api.refresh_token('5d0c0f30-99bd-4f17-9614-3524495b05d4')
-    params = {'iccid': '89860620170009628001'}
-    response = unicom_api.verify_device(**params)
+    params = {'iccid': '89860621330065433774', 'status': 2}
+    # response = unicom_api.verify_device(**params)
     # response = unicom_api.query_device_status(**params)
-    # response = unicom_api.update_device_state(**params)
+    response = unicom_api.update_device_state(**params)
     # response = unicom_api.query_device_usage_history(**params)
     # response = unicom_api.query_current_renew_list_usage_details(**params)
     # unicom_api.get_device_batch_detail()
@@ -240,8 +334,8 @@ if __name__ == '__main__':
     # response = unicom_api.query_renewal_list(**params)
 
     if response.status_code == 200:
-        res_dict = json.loads(response.text)
-        print(res_dict)
+        res = json.loads(response.text)
+        print(res)
     response_json = {
         "success": True,
         "msg": "操作成功",

+ 80 - 0
Object/utils/PayUtil.py

@@ -0,0 +1,80 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : PayUtil.py
+@Time    : 2022/6/29 11:41
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+from urllib.parse import quote
+
+from Ansjer.config import SERVER_DOMAIN_SSL
+from Object.AliPayObject import AliPayObject
+from Object.WechatPayObject import WechatPayObject
+
+"""
+支付服务
+"""
+
+
+class PayService:
+
+    @staticmethod
+    def create_alipay_payment(passback_params, order_id, price, title, notify_url, content, response):
+        """
+        创建支付宝支付
+        @param passback_params: 携带参数支付宝回调原样返回
+        @param order_id: 订单编号
+        @param price: 价格
+        @param title: 标题
+        @param notify_url: 异步回调通知URL
+        @param content: 内容
+        @param response: 响应结果
+        @return: 网站支付链接
+        """
+        aliPayObj = AliPayObject()
+        alipay = aliPayObj.conf()
+        subject = title + content
+        order_string = alipay.api_alipay_trade_wap_pay(
+            out_trade_no=order_id,
+            total_amount=price,
+            subject=subject,
+            return_url="{}web/paid2/success.html".format(SERVER_DOMAIN_SSL),
+            notify_url="{}{}".format(SERVER_DOMAIN_SSL, notify_url),
+            quit_url="{}web/paid2/fail.html".format(SERVER_DOMAIN_SSL),
+            passback_params=quote(passback_params)
+        )
+        if not order_string:
+            return response.json(10, '生成订单错误.')
+        return aliPayObj.alipay_prefix + order_string
+
+    @staticmethod
+    def create_wechat_payment(attach, order_id, price, ip, notify_url, content, response):
+        """
+        创建微信支付
+        @param attach: 参数微信回调通知原样返回
+        @param order_id: 订单编号
+        @param price: 价格
+        @param ip: 用户支付ip地址
+        @param notify_url: 异步通知回调URL
+        @param content: 内容
+        @param response: 响应结果
+        @return: 网站支付链接
+        """
+        notify_url = "{}{}".format(SERVER_DOMAIN_SSL, notify_url)
+        pay = WechatPayObject()
+        # 统一调用接口
+        pay.get_parameter(order_id, content, float(price) * 100, ip, notify_url, quote(attach))
+        sign_params = pay.re_finall(orderid=order_id)
+        if not sign_params:
+            return response.json(10, '生成订单错误.')
+        return sign_params
+
+    @staticmethod
+    def get_two_float(f_str, n):
+        # f_str = '{}'.format(f_str) 也可以转换为字符串
+        f_str = str(f_str)
+        a, b, c = f_str.partition('.')
+        # 如论传入的函数有几位小数,在字符串后面都添加n为小数0
+        c = (c + "0" * n)[:n]
+        return ".".join([a, c])