瀏覽代碼

Merge branches 'dev' and 'lhq' of http://192.168.136.99:3000/SERVER/AnsjerServer into lhq

 Conflicts:
	Ansjer/urls.py
lhq 4 年之前
父節點
當前提交
d6319d25b6

+ 4 - 1
Ansjer/config_local.py

@@ -52,7 +52,10 @@ APNS_CONFIG = {
     },
     'com.ansjer.accloud': {
         'pem_path': 'Ansjer/file/apns_pem/accloud-dev.pem',
-    }
+    },
+    'com.ansjer.customizede': {
+        'pem_path': 'Ansjer/file/apns_pem/ZhouShi-dev.pem',
+    },
 }
 APNS_MODE = 'dev'
 TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'

+ 4 - 1
Ansjer/config_test.py

@@ -61,7 +61,10 @@ APNS_CONFIG = {
     },
     'com.ansjer.accloud': {
         'pem_path': 'Ansjer/file/apns_pem/accloud-dev.pem',
-    }
+    },
+    'com.ansjer.customizede': {
+        'pem_path': 'Ansjer/file/apns_pem/ZhouShi-dev.pem',
+    },
 }
 APNS_MODE = 'dev'
 TUTK_PUSH_DOMAIN = 'http://push.iotcplatform.com/tpns'

+ 68 - 0
Ansjer/file/apns_pem/ZhouShi-dev.pem

@@ -0,0 +1,68 @@
+Bag Attributes
+    friendlyName: Apple Push Services: com.ansjer.customizede
+    localKeyID: F9 76 DF A5 B7 2C 38 04 6E CD FA BF F5 74 9F AD 83 1A E9 8E 
+subject=/UID=com.ansjer.customizede/CN=Apple Push Services: com.ansjer.customizede/OU=772N5HXAR2/O=ZOSI Technology Co. , Ltd/C=CN
+issuer=/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIGOTCCBSGgAwIBAgIIPI2iB4mqqDEwDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
+ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
+aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
+HhcNMjAxMjE5MDY1NDE0WhcNMjIwMTE4MDY1NDE0WjCBpDEmMCQGCgmSJomT8ixk
+AQEMFmNvbS5hbnNqZXIuY3VzdG9taXplZGUxNDAyBgNVBAMMK0FwcGxlIFB1c2gg
+U2VydmljZXM6IGNvbS5hbnNqZXIuY3VzdG9taXplZGUxEzARBgNVBAsMCjc3Mk41
+SFhBUjIxIjAgBgNVBAoMGVpPU0kgVGVjaG5vbG9neSBDby4gLCBMdGQxCzAJBgNV
+BAYTAkNOMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuIhNiP1jkZsf
+HD8nyx6G5DjF4RONEZGMUYph5GFpQSlnY4c1IeHFcNa7qKnvrx3t2ZnIIKaAaMWc
+w+9XiK3KNDpo/A4CEt/Es0Dh5gDze8bG8DK1qORI5XMDUC3r2wRdZ1jSSDcXJ0Fu
+byIkxrOaCe4J0hlJkPbzB/2z9AXMhSh4UhzcHUNMqfWbpzrUCG1nv0woA2MaWrw9
+OiwLy4HckGHXDJEV1eIPsN3v+W5RoP2VJp69gx7M2LH5KcFTvpzhlcXl4elSETgU
+07dqHnoHkSaVVNB8dmPmpHn11Sk8S+fm1qMtNy9PB5gmMaCQt31+YThFp1rl8Zs4
+ERVmbPWtVQIDAQABo4ICeTCCAnUwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBSI
+JxcJqbYYYIvs67r2R1nFUlSjtzCCARwGA1UdIASCARMwggEPMIIBCwYJKoZIhvdj
+ZAUBMIH9MIHDBggrBgEFBQcCAjCBtgyBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlm
+aWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhl
+biBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVz
+ZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHByYWN0aWNl
+IHN0YXRlbWVudHMuMDUGCCsGAQUFBwIBFilodHRwOi8vd3d3LmFwcGxlLmNvbS9j
+ZXJ0aWZpY2F0ZWF1dGhvcml0eTATBgNVHSUEDDAKBggrBgEFBQcDAjAwBgNVHR8E
+KTAnMCWgI6Ahhh9odHRwOi8vY3JsLmFwcGxlLmNvbS93d2RyY2EuY3JsMB0GA1Ud
+DgQWBBT5dt+ltyw4BG7N+r/1dJ+tgxrpjjAOBgNVHQ8BAf8EBAMCB4AwEAYKKoZI
+hvdjZAYDAQQCBQAwEAYKKoZIhvdjZAYDAgQCBQAwgYkGCiqGSIb3Y2QGAwYEezB5
+DBZjb20uYW5zamVyLmN1c3RvbWl6ZWRlMAUMA2FwcAwbY29tLmFuc2plci5jdXN0
+b21pemVkZS52b2lwMAYMBHZvaXAMI2NvbS5hbnNqZXIuY3VzdG9taXplZGUuY29t
+cGxpY2F0aW9uMA4MDGNvbXBsaWNhdGlvbjANBgkqhkiG9w0BAQsFAAOCAQEAOS3j
+rVNOYYSoEYf7OgUl26ubcAMyYwVHhggxtQw0hR63+pdSXWi2/E5IynEf7qmBmbk/
+wTuIkWXnvR5a+sjJy+f94TM9Qe5bXvSuqQn+3HA0XruuBq1A7OGfbORBBZwwNSWZ
+mEjBd9vNdT3ZDksY2XSLvoKOE8gW7i60u4dE5GYqxe3CnICXLlgKjWZx5xbbMl/m
+W6j6ikKOVCqIG6nA8uUwrbznZQAUfQHblB2Yj58zOpCg/0KLqmtQMQJG4kCnZres
+4FElErUr0aEJXPTLqTHLX3PlvFA7Iwb7alTA8a7AFJYxyB184XoKS7rV8MZLuhdd
+wIggtF2b+92ah39F4w==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAuIhNiP1jkZsfHD8nyx6G5DjF4RONEZGMUYph5GFpQSlnY4c1
+IeHFcNa7qKnvrx3t2ZnIIKaAaMWcw+9XiK3KNDpo/A4CEt/Es0Dh5gDze8bG8DK1
+qORI5XMDUC3r2wRdZ1jSSDcXJ0FubyIkxrOaCe4J0hlJkPbzB/2z9AXMhSh4Uhzc
+HUNMqfWbpzrUCG1nv0woA2MaWrw9OiwLy4HckGHXDJEV1eIPsN3v+W5RoP2VJp69
+gx7M2LH5KcFTvpzhlcXl4elSETgU07dqHnoHkSaVVNB8dmPmpHn11Sk8S+fm1qMt
+Ny9PB5gmMaCQt31+YThFp1rl8Zs4ERVmbPWtVQIDAQABAoIBAF9NjfW9IApYOgYF
+nBCsUHBX3eKzjTzQlc6bEJm5sXmE36+oacl459ayIDMoqPAhHfEvGgu60kDKJn+P
+Af9F+lNlA0mCFpIW3WjSjpiSTy3S6HWvSuDSHc/ayZBEVzZDF9ZDKj8/rIaKpXVi
+BepVYa3VMV8/zh2/XJ746VKTGCCAd0fLHHL4A0GRHnNBktLB9Ik3KzMqg+3yh2K3
+gDdl1zP1vVgUHZUw6wSwYVUVycsSxD1uwa4iKs1G6taWK0hm2cZ/UkFHfLylWymx
+ZMU/zXeloIHz2/PwWrczx7lBEgaYNQ3rptgc+BbafHBEIpH36XlU1N2wdQUAkQqC
+VeCxbQECgYEA83imEE5pwCdBxcbg7WXL5GrvQqdzCxkqL8xSsftDklvyHGktc8OU
+XBkVkip+D9FBSNbKYWzCGXBaHg6mdtskmkxsq9rALzIzvVDNJ0r4WzyuRi//AEbV
+Mg+gZ3NeXYx61pwE0tYEC1RocboYGEpYGbJ6+SXG/BySiks7FBukJ8ECgYEAwgc6
+Pcfu7dUmFrj31xjylVgpdhsZNDr200eKgJ1dE3wbrJYz31sVMYULhaoJGKrYKNKY
+ECTDmhywKnM/0Z9MqpG64VWeR10hEbsL+bKrVbPQZkLKGpichNRF7QIOT64cjZt2
+kjMYCWEp+ip8yy9PrVufVqrhG6/a6XxXQGwdCpUCgYEAv4n86vslStwXbGaHcXwS
+KYLO89sUMHj9rVjK/eY0RKI9GIjODzKgNswtIi53ui3fdFQ2JusO0ECJRPg1kW/Z
+neHd5F1VsEuIVLmKjAz40Z4tZF5B+I/BDX8pq/khFet8f/WB/fQMfnVLLZ0/c2yZ
+Xq4A/JzxrEk2J8IDmlAcloECgYEAmawjwr7RS+kfq6uAEAqgRwx2eiZoRefVie0F
+k2wPRdlsCbtFBkgbdwcK4yiS38igP2TcLx0PFsZV+KkjCKGElSuqucGYBKmMAYEF
+sRSDgvNRwUxwybPJc6K0Z0zTjOQ3lShmNtDk3rjoCE0SXdLw5jrE7l2UwNr9JSPn
+7wwxzCkCgYBCRf/n0ID2NcsbVJBhxqel19Pa3vxxvY7Lw1j0kzgXx4a5LrOw6qnZ
+KRQUOK9EMrby63tjrIE9p2xuwXj7r0jMi9GFrk0fd1yLBveqAt/Hq9+DmWU4YDSN
+ZnxCyQ+VQ+wGtVqmuwV0iUWnnhhSLYuaqVgvsnY1QoNmxHIXgSV04g==
+-----END RSA PRIVATE KEY-----

+ 39 - 15
Ansjer/local_settings.py

@@ -78,10 +78,12 @@ SERVER_HOST = '127.0.0.1'
 DATABASES_USER = 'root'
 DATABASES_PASS = '123456'
 
-# DATABASE_DATA2 = 'asjl'
-# SERVER_HOST2 = '127.0.0.1'
-# DATABASES_USER2 = 'root'
-# DATABASES_PASS2 = '123456'
+DATABASE_DATA2 = 'ansjerpush'
+SERVER_HOST2 = '127.0.0.1'
+DATABASES_USER2 = 'root'
+DATABASES_PASS2 = '123456'
+
+
 
 DATABASES = {
     'default': {
@@ -94,20 +96,20 @@ DATABASES = {
         'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
         'AUTOCOMMIT': True
     },
-    # 'mysql02': {
-    #     'ENGINE': 'django.db.backends.mysql',
-    #     'NAME': DATABASE_DATA2,
-    #     'USER': DATABASES_USER2,
-    #     'PASSWORD': DATABASES_PASS2,
-    #     'HOST': SERVER_HOST2,
-    #     'PORT': '3306',
-    #     'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
-    #     'AUTOCOMMIT': True
-    # }
+    'mysql02': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': DATABASE_DATA2,
+        'USER': DATABASES_USER2,
+        'PASSWORD': DATABASES_PASS2,
+        'HOST': SERVER_HOST2,
+        'PORT': '3306',
+        'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+        'AUTOCOMMIT': True
+    }
 }
 DATABASE_ROUTERS = ['Ansjer.database_router.DatabaseAppsRouter']
 DATABASE_APPS_MAPPING = {
-    'db1': 'default',
+    'Model': 'default',
     'db2': 'mysql02',
 }
 
@@ -195,6 +197,12 @@ LOGGING = {
             # 'format': '{"asctime":"%(asctime)s","thread":"%(threadName)s:%(thread)d","errorline":"%(lineno)d","errorlevel":"%(levelname)s","errorcontent":"%(message)s"}'
             'format': '%(asctime)s %(threadName)s %(thread)d %(lineno)d %(levelname)s %(message)s'
         },
+        'standard': {
+            'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
+                      '[%(levelname)s]- %(message)s'},
+        'simple': {  # 简单格式
+            'format': '%(levelname)s %(message)s'
+        },
     },
     'filters': {
     },
@@ -218,6 +226,16 @@ LOGGING = {
             'class': 'logging.StreamHandler',
             'formatter': 'error_format'
         },
+        # 输出info日志
+        'info': {
+            'level': 'INFO',
+            'class': 'logging.handlers.RotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/info.log',
+            'maxBytes': 1024 * 1024 * 5,
+            'backupCount': 5,
+            'formatter': 'standard',
+            'encoding': 'utf-8',  # 设置默认编码
+        },
     },
     'loggers': {
         'django': {
@@ -227,6 +245,12 @@ LOGGING = {
             'level': 'DEBUG',
             'propagate': True
         },
+        # log 调用时需要当作参数传入
+        'log': {
+            'handlers': ['info', 'console', 'default'],
+            'level': 'INFO',
+            'propagate': True
+        },
         # 'django.db.backends': {
         #     'handlers': ['console'],
         #     'propagate': True,

+ 27 - 0
Ansjer/test_settings.py

@@ -196,6 +196,12 @@ LOGGING = {
             # 'format': '{"asctime":"%(asctime)s","thread":"%(threadName)s:%(thread)d","errorline":"%(lineno)d","errorlevel":"%(levelname)s","errorcontent":"%(message)s"}'
             'format': '%(asctime)s %(threadName)s %(thread)d %(lineno)d %(levelname)s %(message)s'
         },
+        'standard': {
+            'format': '[%(asctime)s] [%(filename)s:%(lineno)d] [%(module)s:%(funcName)s] '
+                      '[%(levelname)s]- %(message)s'},
+        'simple': {  # 简单格式
+            'format': '%(levelname)s %(message)s'
+        },
     },
     'filters': {
     },
@@ -217,14 +223,35 @@ LOGGING = {
             'level': 'ERROR',
             'class': 'logging.StreamHandler',
             'formatter': 'error_format'
+        },# 输出info日志
+        'info': {
+            'level': 'INFO',
+            'class': 'logging.handlers.RotatingFileHandler',
+            'filename': BASE_DIR + '/static/log/info.log',
+            'maxBytes': 1024 * 1024 * 5,
+            'backupCount': 5,
+            'formatter': 'standard',
+            'encoding': 'utf-8',  # 设置默认编码
         },
     },
     'loggers': {
         'django': {
             'handlers': ['default', 'console'],
             # 'handlers': ['mail_admins','default','console'],
+            # 'level': 'ERROR',
             'level': 'ERROR',
             'propagate': False
         },
+        # log 调用时需要当作参数传入
+        'log': {
+            'handlers': ['info', 'console', 'default'],
+            'level': 'INFO',
+            'propagate': True
+        },
+        # 'django.db.backends': {
+        #     'handlers': ['console'],
+        #     'propagate': True,
+        #     'level': 'DEBUG',
+        # },
     }
 }

+ 4 - 1
Ansjer/urls.py

@@ -11,7 +11,7 @@ from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppIn
     AppSetController, \
     ApplicationController, UserExController, CloudStorage, TestApi, UserBrandControllerV2, \
     StatisticsController, Alexa, FAQController, AppLogController, EquipmentVersionLimit, VoicePromptController, CDKController, \
-    DeviceTypeController, Cloudsum
+    DeviceTypeController, CloudTest, Cloudsum
 
 
 urlpatterns = [
@@ -181,6 +181,7 @@ urlpatterns = [
     # 删除云存视频
     # path('cv/del', CloudVod.deleteVodHls),
     path('cv/del', CloudStorage.deleteVodHls),
+    path('cv/deleteExpiredUidBucket', CloudStorage.deleteExpiredUidBucket),
     url(r'^equipment/judge', EquipmentManager.judgeInterface),
 
     # ap模式,新增设备表
@@ -253,6 +254,8 @@ urlpatterns = [
 
     # cdk(激活码)
     url(r'^cdk/(?P<operation>.*)$', CDKController.CDKView.as_view()),
+    # cdk(云存新增功能测试)
+    url(r'^cloudTest/(?P<operation>.*)$', CloudTest.cloudTestView.as_view()),
 
     # app 设备消息模板
     # 路由加参数参考

文件差異過大導致無法顯示
+ 429 - 285
Controller/CloudStorage.py


+ 149 - 0
Controller/CloudTest.py

@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+"""
+@Time : 2020/12/16 8:44
+@Auth : Locky
+@File :CloudTest.py
+@IDE :PyCharm
+"""
+import time
+from django.db import transaction
+from django.db.models import Q
+from django.views.generic.base import View
+
+from Model.models import Device_User, Device_Info, Order_Model, UID_Bucket, StsCrdModel, VodHlsModel
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+
+
+class cloudTestView(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()
+        if operation is None:
+            return response.json(444, 'error path')
+        else:
+            token = request_dict.get('token', None)
+            # 设备主键uid
+            tko = TokenObject(token)
+            response.lang = tko.lang
+            if tko.code != 0:
+                return response.json(tko.code)
+            userID = tko.userID
+            if operation == 'deviceTransfer':
+                return self.deviceTransfer(request_dict, response)
+            elif operation == 'mealTransfer':
+                return self.mealTransfer(request_dict, response, userID)
+            elif operation == 'expireMeal':
+                return self.expireMeal(request_dict, response)
+
+    def deviceTransfer(self, request_dict, response):
+        # 设备转移
+        oldUserID = request_dict.get("oldUserID", None)
+        loginName = request_dict.get("username", None)
+        uid = request_dict.get('uid', None)
+
+        try:
+            # 查询该userID下是否存在此设备
+            old_deviceInfo_qs = Device_Info.objects.filter(userID_id=oldUserID, UID=uid, isExist=1)
+            if not old_deviceInfo_qs.exists():
+                return response.json(10008)
+            # 登录方式可能为用户名,手机号或邮箱登录
+            deviceUser_qs = Device_User.objects.filter(
+                Q(username=loginName) | Q(phone=loginName) | Q(userEmail=loginName)).values('userID')
+            newUserID = deviceUser_qs[0]['userID']
+            # 判断新用户的userID是否跟旧用户的一样
+            if newUserID == oldUserID:
+                return response.json(10009)
+            # 判断新用户是否已有此设备UID
+            new_deviceInfo_qs = Device_Info.objects.filter(userID_id=newUserID, UID=uid, isExist=1)
+            if new_deviceInfo_qs:
+                return response.json(10009)
+            # 分享的设备不能转移
+            isShare = Device_Info.objects.get(userID_id=oldUserID, UID=uid).isShare
+            if isShare:
+                return response.json(10015)
+            # 获取旧设备的username
+            oldUserName = Device_User.objects.get(userID=oldUserID).username
+            with transaction.atomic():
+                # 更新设备信息
+                old_deviceInfo_qs.update(userID=newUserID, vodPrimaryUserID=newUserID, vodPrimaryMaster=oldUserName)
+                VodHlsModel.objects.filter(uid=uid).delete()
+        except Exception as e:
+            # print(e)
+            return response.json(500, repr(e))
+        else:
+            return response.json(0)
+
+    def mealTransfer(self, request_dict, response, userID):
+        # 云存套餐转移
+        old_uid = request_dict.get("old_uid", None)
+        new_uid = request_dict.get("new_uid", None)
+        nowTime = int(time.time())
+
+        try:
+            # 查询两个UID是否在同一账号下
+            old_deviceInfo_qs = Device_Info.objects.filter(userID_id=userID, UID=old_uid).values('isExist')
+            new_deviceInfo_qs = Device_Info.objects.filter(userID_id=userID, UID=new_uid).values('isExist')
+            if not (old_deviceInfo_qs.exists() and new_deviceInfo_qs.exists()):
+                return response.json(10010)
+
+            new_isExist = new_deviceInfo_qs[0]['isExist']
+            if not new_isExist:
+                return response.json(10011)
+
+            # 查询转出设备正在使用的套餐
+            old_using_uid_bucket = UID_Bucket.objects.filter(uid=old_uid, endTime__gte=nowTime).values('id').order_by('addTime')
+            if not old_using_uid_bucket.exists():
+                return response.json(10013)
+
+            # 首次转移,根据订单判断是否为购买的套餐
+            old_orderModel_qs = Order_Model.objects.filter(userID_id=userID, UID=old_uid)
+            if old_orderModel_qs.exists():
+                old_UIDbucket_id = old_using_uid_bucket[0]['id']
+                # 只能转移购买的的套餐(支付类型为体验套餐和激活码不能转移,即pay_type不能为10,11)
+                old_orderModel_qs = Order_Model.objects.filter(uid_bucket_id=old_UIDbucket_id).values('payType')
+                payType = old_orderModel_qs[0]['payType']
+                if payType == 10 or payType == 11:
+                    return response.json(10012)
+
+            # # 查询转入设备正在使用的套餐
+            new_using_uid_bucket = UID_Bucket.objects.filter(uid=new_uid, endTime__gte=nowTime)
+            if new_using_uid_bucket.exists():
+                return response.json(10014)
+
+            with transaction.atomic():
+                # vod_uid_bucket表更新uid
+                old_using_uid_bucket_id = old_using_uid_bucket[0]['id']
+                UID_Bucket.objects.filter(id=old_using_uid_bucket_id).update(uid=new_uid)
+                # 删除转出设备stscrd表关联数据
+                StsCrdModel.objects.filter(uid=old_uid).delete()
+        except Exception as e:
+            # print(e)
+            return response.json(500, repr(e))
+        else:
+            return response.json(0)
+
+    def expireMeal(self, request_dict, response):
+        UID_Bucket_id = request_dict.get("UID_Bucket_id", None)
+
+        # 修改endTime让当前设备套餐过期
+        if UID_Bucket_id:
+            nowTime = int(time.time())
+            try:
+                UID_Bucket.objects.filter(id=UID_Bucket_id).update(endTime=nowTime-1)
+            except Exception as e:
+                # print(e)
+                return response.json(500, repr(e))
+            else:
+                return response.json(0)
+        response.json(404)

+ 20 - 229
Controller/CloudVod.py

@@ -128,7 +128,7 @@ class CloudVodView(View):
             elif operation == 'aliPayCreateOrder':
                 return self.do_pay_by_ali(request_dict, userID, response)
             elif operation == 'orderStatus':
-                return self.do_pay_status(request_dict, userID)
+                return self.do_pay_status(request_dict, userID, response)
             elif operation == 'createPayOrder':
                 return self.do_create_pay_order(request_dict, userID, response)
             # elif operation == 'queryAlipayOrder':
@@ -1114,239 +1114,30 @@ class CloudVodView(View):
                 {'name': vod['time'], 'sign_url': vod_play_url, 'thumb': thumb, 'sec': vod['sec'], 'id': vod['id']})
         return response.json(0, vod_play_list)
 
-    def do_pay_status(self, request_dict, userID):
+    def do_pay_status(self, request_dict, userID, response):
         orderID = request_dict.get('orderID', None)
-        om_qs = Order_Model.objects.filter(userID_id=userID, orderID=orderID).values('status')
-        response = HttpResponse()
-        success_pay_content = '''
-
-                <!DOCTYPE html>
-                <html>
-                <head>
-                	<!--浏览器不缓存-->
-                	<meta http-equiv="Pragma" content="no-cache">
-                	<meta http-equiv="Cache-Control" content="no-cache">
-                	<meta http-equiv="Expires" content="0">
-                	<!--utf-8-->
-                    <meta http-equiv="content-type" content="text/html;charset=utf-8">
-                    <!-- viewport的<meta>标签,这个标签可以修改在大部分的移动设备上面的显示,为了确保适当的绘制和触屏缩放。-->
-                    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-                    <link rel="shortcut icon" href="https://test.dvema.com/web/images/favicon.ico" type="image/x-icon"  charset="utf-8"/>  
-                    <title>Trading particulars</title>
-                    <style>
-                    	.title_head{
-                    		height: 50px;
-                    		border-radius: 5px;
-                    		background-color: #c3c6c7; 
-                    		text-align: center;
-                    		line-height: 50px;
-                    	}
-                    	.content{
-                    		text-align: center;
-                    		margin-top: 50px;
-                    		font-size: 20px;
-                    		color : green
-                    	}
-                    	.content_img{
-                    		width: 60px; 
-                    		height: 60px;
-                    	}
-                    	.bottom{
-                    		 margin-bottom: 10px; 
-                    		 margin-top: 250px; 
-                    		 color : green
-                    	}
-                    	.bottom_div{
-                    		border: 1px solid green; 
-                    		line-height: 38px; 
-                    		text-align: center; 
-                    		width: 100px; 
-                    		height: 38px;
-                    		border-radius: 5px;
-                    	}
-
-                    	.bottom_div:hover{
-                    		background-color: #dde4e2;
-                    	}
-                    </style>
-                </head>
-                <body>
-                	<div class="title_head">Trading particulars</div>
-                    <div class="content">
-                    	<p >
-                    		<img src="https://test.dvema.com/web/images/timg.jpg" class="content_img">
-                    		<br />
-                    		Successful payment
-                    	</p>
-                    </div>
-                    <center class="bottom">
-                    	<div class="bottom_div" onclick="payOKButton()"> 
-                    	 Finish
-                    	</div>
-                    </center>
-                    <script> 	    // 点击付款成功按钮
-                    function payOKButton() {
-                        // 复杂数据
-                        console.log('success')
-                        window.webkit.messageHandlers.jsCallOC.postMessage({"status": 1});
-                    }
-                	</script>
-                </body> 
-                </html>
-                        '''
-        falil_pay_content = '''
-        <!DOCTYPE html>
-        <html>
-        <head>
-        	<!--浏览器不缓存-->
-        	<meta http-equiv="Pragma" content="no-cache">
-        	<meta http-equiv="Cache-Control" content="no-cache">
-        	<meta http-equiv="Expires" content="0">
-        	<!--utf-8-->
-            <meta http-equiv="content-type" content="text/html;charset=utf-8">
-            <!-- viewport的<meta>标签,这个标签可以修改在大部分的移动设备上面的显示,为了确保适当的绘制和触屏缩放。-->
-            <meta name="viewport" content="width=device-width, initial-scale=1.0">
-            <link rel="shortcut icon" href="https://test.dvema.com/web/images/favicon.ico" type="image/x-icon"  charset="utf-8"/>  
-            <title>Trading particulars</title>
-            <style>
-            	.title_head{
-            		height: 50px;
-            		border-radius: 5px;
-            		background-color: #c3c6c7; 
-            		text-align: center;
-            		line-height: 50px;
-            	}
-            	.content{
-            		text-align: center;
-            		margin-top: 50px;
-            		font-size: 20px;
-            		color : #ec7648
-            	}
-            	.content_img{
-            		width: 60px; 
-            		height: 60px;
-            	}
-            	.bottom{
-            		 margin-bottom: 10px; 
-            		 margin-top: 250px; 
-            		 color : #ec7648
-            	}
-            	.bottom_div{
-            		border: 1px solid #ec7648; 
-            		line-height: 38px; 
-            		text-align: center; 
-            		width: 100px; 
-            		height: 38px;
-            		border-radius: 5px;
-            	}
-
-            	.bottom_div:hover{
-            		background-color: #dde4e2;
-            	}
-            </style>
-        </head>
-        <body>
-        	<div class="title_head">Trading particulars</div>
-            <div class="content">
-            	<p >
-            		<img src="https://test.dvema.com/web/images/failed.jpg" class="content_img">
-            		<br />
-            		Payment failure
-            	</p>
-            </div>
-            <center class="bottom">
-            	<div class="bottom_div" onclick="payOKButton()"> 
-            	 Finish
-            	</div>
-            </center>
-            <script> 	    // 点击付款成功按钮
-            function payOKButton() {
-                // 复杂数据
-                console.log('success')
-                window.webkit.messageHandlers.jsCallOC.postMessage({"status": 0});
-            }
-        	</script>
-        </body> 
-        </html>
-                        '''
+        om_qs = Order_Model.objects.filter(orderID=orderID).values('status')
+        # response = HttpResponse()
+        # success_pay_content = '''
+        #                 '''
+        # falil_pay_content = '''
+        #
+        #                 '''
+
+        status = 0
+        url = "{SERVER_DOMAIN}web/paid2/fail.html".format(SERVER_DOMAIN=SERVER_DOMAIN)
+
         if om_qs.exists():
-            if om_qs[0]['status'] == 1:
-                response.content = success_pay_content
-                return response
+            status = om_qs[0]['status']
+            if status == 1:
+
+                url = "{SERVER_DOMAIN}web/paid2/success.html".format(SERVER_DOMAIN=SERVER_DOMAIN)
             else:
-                # response.content = falil_pay_content
-                # return response
-                # exit()
-                # 如果未支付则调用查询订单是否支付成功
-                aliPayObj = AliPayObject()
-                alipay = aliPayObj.conf()
-                # check order status
-                print("now sleep 3s")
-                # time.sleep(3)
-                result = alipay.api_alipay_trade_query(out_trade_no=orderID)
-                if result.get("trade_status", "") == "TRADE_SUCCESS":
-                    print('paid')
-                    print("trade succeed")
-                    order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
-                    if order_qs.exists():
-                        nowTime = int(time.time())
-                        order_list = order_qs.values("UID", "rank__id", "channel")
-                        rank_id = order_list[0]['rank__id']
-                        print(rank_id)
-                        UID = order_list[0]['UID']
-                        channel = order_list[0]['channel']
-                        order_qs.update(status=1, updTime=nowTime)
-
-                        smqs = Store_Meal.objects.filter(id=rank_id).values("day", "bucket_id", "bucket__storeDay")
-                        bucketId = smqs[0]['bucket_id']
-                        if not smqs.exists():
-                            response.content = falil_pay_content
-                            return response
-                        addTime = int(smqs[0]["day"]) * 24 * 3600
-                        ubqs = UID_Bucket.objects.filter(uid=UID, channel=channel). \
-                            values("bucket_id", "endTime", "bucket__storeDay")
-                        nowTime = int(time.time())
-                        if ubqs.exists():
-                            # 判断是否过期了
-                            if nowTime > ubqs[0]['endTime']:
-                                ubqs.update(endTime=nowTime + addTime)
-                            else:
-                                # 同一个bucket续费
-                                if bucketId == ubqs[0]['bucket_id']:
-                                    ubqs.update(endTime=ubqs[0]['endTime'] + addTime)
-                                else:
-                                    if ubqs[0]['bucket__storeDay'] > smqs[0]['bucket__storeDay']:
-                                        response.content = falil_pay_content
-                                        return response
-                                    else:
-                                        # 升级
-                                        origin_storeDay = int(ubqs[0]['bucket__storeDay'])
-                                        upgrade_storeDay = int(smqs[0]['bucket__storeDay'])
-                                        ctcTime = ubqs[0]['endTime'] - nowTime
-                                        multiple = math.ceil(upgrade_storeDay / origin_storeDay)
-                                        ubqs.update(endTime=ctcTime / multiple + addTime + ubqs[0]['endTime'],
-                                                    bucket_id=bucketId)
-                                        # 付款成功把oss token删除
-                                        OssCrdModel.objects.filter(uid=UID, channel=channel).delete()
-                        # 新增模式
-                        else:
-                            print('create')
-                            UID_Bucket.objects.create(uid=UID, channel=channel,
-                                                      bucket_id=bucketId, endTime=nowTime + addTime)
 
-                        response.content = success_pay_content
-                        return response
-                    else:
-                        response.content = falil_pay_content
-                        return response
-                else:
-                    print("not paid...")
-                    response.content = falil_pay_content
-                    return response
+                url = "{SERVER_DOMAIN}web/paid2/fail.html".format(SERVER_DOMAIN=SERVER_DOMAIN)
 
-        else:
-            response.content = falil_pay_content
-            return response
+        res = {'status': status, 'url': url}
+        return response.json(0, res)
 
     def query_alipay_order(self, request_dict, userID, response):
         out_trade_no = request_dict.get('out_trade_no', None)

+ 20 - 3
Controller/DeviceTypeController.py

@@ -9,6 +9,7 @@ from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET
 from Model.models import DeviceTypeModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
+from Service.CommonService import CommonService
 from Service.ModelService import ModelService
 
 
@@ -41,13 +42,29 @@ class DeviceTypeView(View):
             return self.do_query(request_dict, response)
         elif operation == 'delete':
             return self.do_admin_delete(token.userID, request_dict, response)
+        elif operation == 'getUploadUrl':
+            return self.get_upload_url(request_dict, response)
         else:
             return response.json(404)
 
+    def get_upload_url(self, request_dict, response):
+        upload_type = request_dict.get('upload_type', None)
+
+        if upload_type:
+            auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+            bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
+            name = CommonService.createOrderID()
+            filename = str(name) + '.' + upload_type
+            obj = 'device_type/' + filename
+            url = bucket.sign_url('PUT', obj, 7200)
+            return response.json(0, {'put_url': url, 'filename': filename})
+        else:
+            return response.json(444)
+
     def do_admin_add(self, userID, request_dict, response):
-        # own_perm = ModelService.check_perm(userID, 10)
-        # if not own_perm:
-        #     return response.json(404)
+        own_perm = ModelService.check_perm(userID, 10)
+        if not own_perm:
+            return response.json(404)
 
         name = request_dict.get('name', None)
         model = request_dict.get('model', None)

+ 18 - 4
Controller/EquipmentManager.py

@@ -387,6 +387,20 @@ def addInterface(request):
                 # # 判断是否有已绑定用户
                 # if is_bind:
                 #     return response.json(15)
+
+                main_exist = Device_Info.objects.filter(UID=UID, vodPrimaryUserID='', vodPrimaryMaster='')
+                pk = CommonService.getUserID(getUser=False)
+                vodPrimaryUserID = ''
+                vodPrimaryMaster = ''
+                if not main_exist:
+
+                    duq = Device_User.objects.filter(userID=userID).values('username')
+                    if duq.exists():
+                        username = duq[0]['username']
+                        vodPrimaryUserID = username
+                        vodPrimaryMaster = userID
+
+
                 try:
                     # 判断是否有用户绑定
                     nowTime = int(time.time())
@@ -403,10 +417,10 @@ def addInterface(request):
                         UidSetModel.objects.create(**uid_set_create_dict)
                     else:
                         us_qs.update(nickname=NickName)
-                    pk = CommonService.getUserID(getUser=False)
+
                     userDevice = Device_Info(id=pk, userID_id=userID, UID=UID,
                                              NickName=NickName, View_Account=View_Account,
-                                             View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex)
+                                             View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex, vodPrimaryUserID=vodPrimaryUserID, vodPrimaryMaster=vodPrimaryMaster)
                     userDevice.save()
                     # redisObj = RedisObject(db=8)
                     # redisObj.del_data(key='uid_qs_' + userID)
@@ -417,7 +431,7 @@ def addInterface(request):
                                                                     'View_Account',
                                                                     'View_Password', 'ChannelIndex', 'Type',
                                                                     'isShare',
-                                                                    'primaryUserID', 'primaryMaster',
+                                                                    'primaryUserID', 'primaryMaster', 'vodPrimaryUserID', 'vodPrimaryMaster', 'userID__userEmail',
                                                                     'data_joined', 'version',
                                                                     'isVod', 'isExist')
                     dvql = CommonService.qs_to_list(dvqs)
@@ -752,7 +766,7 @@ def queryInterface(request):
         # count = dvqs.count()
         dvql = dvqs[(page - 1) * line:page * line].values('id', 'userID', 'NickName', 'UID', 'View_Account',
                                                           'View_Password', 'ChannelIndex', 'Type', 'isShare',
-                                                          'primaryUserID', 'primaryMaster', 'data_joined', 'version',
+                                                          'primaryUserID', 'primaryMaster', 'data_joined', 'version', 'vodPrimaryUserID', 'vodPrimaryMaster', 'userID__userEmail',
                                                           'isVod', 'isExist', 'NotificationMode')
         dvls = CommonService.qs_to_list(dvql)
         uid_list = []

+ 1 - 1
Controller/EquipmentManagerV2.py

@@ -146,7 +146,7 @@ class EquipmentManagerV2(View):
             dvql = dvqs[(page - 1) * line:page * line]. \
                 values('id', 'userID', 'NickName', 'UID', 'View_Account',
                        'View_Password', 'ChannelIndex', 'Type', 'isShare',
-                       'primaryUserID', 'primaryMaster', 'data_joined',
+                       'primaryUserID', 'primaryMaster', 'data_joined', 'vodPrimaryUserID', 'vodPrimaryMaster', 'userID__userEmail',
                        'version',
                        'isVod', 'isExist', 'NotificationMode')
             dvls = CommonService.qs_to_list(dvql)

+ 186 - 14
Controller/EquipmentManagerV3.py

@@ -11,12 +11,14 @@ from django.db.models import Q
 from django.views.generic.base import View
 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
+from Model.models import Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidPushModel, UidChannelSetModel, \
+    Device_User
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
 from Service.ModelService import ModelService
-import time,json
+import time, json
+
 
 class EquipmentManagerV3(View):
 
@@ -46,6 +48,8 @@ class EquipmentManagerV3(View):
                 return self.do_query(userID, request_dict, response)
             elif operation == 'modify':
                 return self.do_modify(userID, request_dict, response, request)
+            elif operation == 'fuzzyQuery':
+                return self.do_fuzzy_query(userID, request_dict, response)
             else:
                 return response.json(414)
         else:
@@ -85,6 +89,18 @@ class EquipmentManagerV3(View):
                     # # 判断是否有已绑定用户
                     # if is_bind:
                     #     return response.json(15)
+
+                    main_exist = Device_Info.objects.filter(UID=UID, vodPrimaryUserID='', vodPrimaryMaster='')
+                    pk = CommonService.getUserID(getUser=False)
+                    vodPrimaryUserID = ''
+                    vodPrimaryMaster = ''
+                    if not main_exist:
+
+                        duq = Device_User.objects.filter(userID=userID).values('username')
+                        if duq.exists():
+                            username = duq[0]['username']
+                            vodPrimaryUserID = userID
+                            vodPrimaryMaster = username
                     try:
                         # 判断是否有用户绑定
                         nowTime = int(time.time())
@@ -101,10 +117,11 @@ class EquipmentManagerV3(View):
                             UidSetModel.objects.create(**uid_set_create_dict)
                         else:
                             us_qs.update(nickname=NickName)
-                        pk = CommonService.getUserID(getUser=False)
+
                         userDevice = Device_Info(id=pk, userID_id=userID, UID=UID,
                                                  NickName=NickName, View_Account=View_Account,
-                                                 View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex)
+                                                 View_Password=View_Password, Type=Type, ChannelIndex=ChannelIndex,
+                                                 vodPrimaryUserID=vodPrimaryUserID, vodPrimaryMaster=vodPrimaryMaster)
                         userDevice.save()
 
                         if not us_qs.exists():
@@ -124,6 +141,8 @@ class EquipmentManagerV3(View):
                                                                         'View_Password', 'ChannelIndex', 'Type',
                                                                         'isShare',
                                                                         'primaryUserID', 'primaryMaster',
+                                                                        'vodPrimaryUserID', 'vodPrimaryMaster',
+                                                                        'userID__userEmail',
                                                                         'data_joined', 'version',
                                                                         'isVod', 'isExist')
                         dvql = CommonService.qs_to_list(dvqs)
@@ -202,7 +221,6 @@ class EquipmentManagerV3(View):
                 di_qs = Device_Info.objects.filter(UID=uid)
                 di_qs.update(NickName=nickname)
                 if deviceData is not None and deviceData.__contains__('NickName') and us_qs[0].is_alexa == 1:
-
                     asy = threading.Thread(target=ModelService.notify_alexa_add, args=(uid, userID, nickname))
                     asy.start()
             # redisObj = RedisObject(db=8)
@@ -232,7 +250,8 @@ class EquipmentManagerV3(View):
             dvqs = dvqs.filter(~Q(isExist=2))
             dvql = dvqs.values('id', 'userID', 'NickName', 'UID', 'View_Account',
                                'View_Password', 'ChannelIndex', 'Type', 'isShare',
-                               'primaryUserID', 'primaryMaster', 'data_joined',
+                               'primaryUserID', 'primaryMaster', 'data_joined', 'vodPrimaryUserID', 'vodPrimaryMaster',
+                               'userID__userEmail',
                                'version', 'isVod', 'isExist', 'NotificationMode')
             dvls = CommonService.qs_to_list(dvql)
             uid_list = []
@@ -278,10 +297,19 @@ class EquipmentManagerV3(View):
                     'DetectorRank': us['DetectorRank']
                 }
                 # 从uid_channel里面取出通道配置信息
-                ucs_qs = UidChannelSetModel.objects.filter(uid__id=us['id']).values()
+                ucs_qs = UidChannelSetModel.objects.filter(uid__id=us['id']).values('channel', 'pir_audio', 'mic_audio',
+                                                                                    'battery_status', 'battery_level',
+                                                                                    'sleep_status', 'sleep_time',
+                                                                                    'light_night_model',
+                                                                                    'light_alarm_type',
+                                                                                    'light_alarm_level',
+                                                                                    'light_alarm_man_en',
+                                                                                    'light_alarm_vol',
+                                                                                    'light_long_light'
+                                                                                    )
                 channels = []
                 for ucs in ucs_qs:
-                    channel = {
+                    channels_dict = {
                         'channel': ucs['channel'],
                         'pir_audio': ucs['pir_audio'],
                         'mic_audio': ucs['mic_audio'],
@@ -296,7 +324,7 @@ class EquipmentManagerV3(View):
                         'light_alarm_vol': ucs['light_alarm_vol'],
                         'light_long_light': ucs['light_long_light']
                     }
-                    channels.append(channel)
+                    channels.append(channels_dict)
                 uv_dict[us['uid']]['channels'] = channels
 
             for p in dvls:
@@ -375,17 +403,161 @@ class EquipmentManagerV3(View):
         else:
             return response.json(tko.code)
 
+    def do_fuzzy_query(self, userID, request_dict, response):
+        fuzzy = request_dict.get('fuzzy', None)
+        page = request_dict.get('page', None)
+        line = request_dict.get('line', None)
+
+        if page and line:
+            page = int(page)
+            line = int(line)
+            device_qs = Device_Info.objects.filter(userID=userID)
+            device_qs = device_qs.filter(~Q(isExist=2))
+            if device_qs.exists():
+                if fuzzy:
+                    device_qs = device_qs.filter(Q(UID__contains=fuzzy) | Q(NickName__contains=fuzzy))
+
+                device_qs = device_qs.values('id', 'userID', 'NickName', 'UID', 'View_Account',
+                                             'View_Password', 'ChannelIndex', 'Type', 'isShare',
+                                             'primaryUserID', 'primaryMaster', 'data_joined', 'vodPrimaryUserID',
+                                             'vodPrimaryMaster', 'userID__userEmail',
+                                             'version', 'isVod', 'isExist', 'NotificationMode')
+
+                dvls = CommonService.qs_to_list(device_qs)
+                uid_list = []
+                for dvl in dvls:
+                    uid_list.append(dvl['UID'])
+                ubqs = UID_Bucket.objects.filter(uid__in=uid_list). \
+                    values('bucket__content', 'status', 'channel', 'endTime', 'uid')
+                upqs = UID_Preview.objects.filter(uid__in=uid_list).order_by('channel').values('id', 'uid', 'channel')
+                auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+                bucket = oss2.Bucket(auth, 'oss-cn-hongkong.aliyuncs.com', 'statres')
+                nowTime = int(time.time())
+                data = []
+                # 设备拓展信息表
+                us_qs = UidSetModel.objects.filter(uid__in=uid_list).values('id', 'uid', 'version', 'nickname', 'ucode',
+                                                                            'detect_status', 'detect_group',
+                                                                            'detect_interval',
+                                                                            'region_alexa', 'is_alexa', 'deviceModel',
+                                                                            'TimeZone', 'TimeStatus', 'SpaceUsable',
+                                                                            'SpaceSum', 'MirrorType', 'RecordType',
+                                                                            'OutdoorModel', 'WIFIName', 'isDetector',
+                                                                            'DetectorRank')
+                uv_dict = {}
+                for us in us_qs:
+                    uv_dict[us['uid']] = {
+                        'version': us['version'],
+                        'nickname': us['nickname'],
+                        'ucode': us['ucode'],
+                        'detect_interval': us['detect_interval'],
+                        'detect_group': us['detect_group'],
+                        'detect_status': us['detect_status'],
+                        'region_alexa': us['region_alexa'],
+                        'is_alexa': us['is_alexa'],
+                        'deviceModel': us['deviceModel'],
+                        'TimeZone': us['TimeZone'],
+                        'TimeStatus': us['TimeStatus'],
+                        'SpaceUsable': us['SpaceUsable'],
+                        'SpaceSum': us['SpaceSum'],
+                        'MirrorType': us['MirrorType'],
+                        'RecordType': us['RecordType'],
+                        'OutdoorModel': us['OutdoorModel'],
+                        'WIFIName': us['WIFIName'],
+                        'isDetector': us['isDetector'],
+                        'DetectorRank': us['DetectorRank']
+                    }
+                    # 从uid_channel里面取出通道配置信息
+                    ucs_qs = UidChannelSetModel.objects.filter(uid__id=us['id']).values()
+                    channels = []
+                    for ucs in ucs_qs:
+                        channel = {
+                            'channel': ucs['channel'],
+                            'pir_audio': ucs['pir_audio'],
+                            'mic_audio': ucs['mic_audio'],
+                            'battery_status': ucs['battery_status'],
+                            'battery_level': ucs['battery_level'],
+                            'sleep_status': ucs['sleep_status'],
+                            'sleep_time': ucs['sleep_time'],
+                            'light_night_model': ucs['light_night_model'],
+                            'light_alarm_type': ucs['light_alarm_type'],
+                            'light_alarm_level': ucs['light_alarm_level'],
+                            'light_alarm_man_en': ucs['light_alarm_man_en'],
+                            'light_alarm_vol': ucs['light_alarm_vol'],
+                            'light_long_light': ucs['light_long_light']
+                        }
+                        channels.append(channel)
+                    uv_dict[us['uid']]['channels'] = channels
+
+                for p in dvls:
+                    p['vod'] = []
+                    for dm in ubqs:
+                        if p['UID'] == dm['uid']:
+                            if dm['endTime'] > nowTime:
+                                p['vod'].append(dm)
+                    p['preview'] = []
+                    for up in upqs:
+                        if p['UID'] == up['uid']:
+                            obj = 'uid_preview/{uid}/channel_{channel}.png'.format(uid=up['uid'], channel=up['channel'])
+                            img_sign = bucket.sign_url('GET', obj, 300)
+                            p['preview'].append(img_sign)
+                    p_uid = p['UID']
+                    if p_uid in uv_dict:
+                        # 设备版本号
+                        p['uid_version'] = uv_dict[p_uid]['version']
+                        p['ucode'] = uv_dict[p_uid]['ucode']
+                        p['detect_interval'] = uv_dict[p_uid]['detect_interval']
+                        p['detect_status'] = uv_dict[p_uid]['detect_status']
+                        p['detect_group'] = uv_dict[p_uid]['detect_group']
+                        p['region_alexa'] = uv_dict[p_uid]['region_alexa']
+                        p['is_alexa'] = uv_dict[p_uid]['is_alexa']
+                        p['deviceModel'] = uv_dict[p_uid]['deviceModel']
+                        p['TimeZone'] = uv_dict[p_uid]['TimeZone']
+                        p['TimeStatus'] = uv_dict[p_uid]['TimeStatus']
+                        p['SpaceUsable'] = uv_dict[p_uid]['SpaceUsable']
+                        p['SpaceSum'] = uv_dict[p_uid]['SpaceSum']
+                        p['MirrorType'] = uv_dict[p_uid]['MirrorType']
+                        p['RecordType'] = uv_dict[p_uid]['RecordType']
+                        p['OutdoorModel'] = uv_dict[p_uid]['OutdoorModel']
+                        p['WIFIName'] = uv_dict[p_uid]['WIFIName']
+                        p['isDetector'] = uv_dict[p_uid]['isDetector']
+                        p['DetectorRank'] = uv_dict[p_uid]['DetectorRank']
+                        p['channels'] = uv_dict[p_uid]['channels']
+                        # 设备昵称 调用影子信息昵称,先阶段不可
+                        if uv_dict[p_uid]['nickname']:
+                            p['NickName'] = uv_dict[p_uid]['nickname']
+                    else:
+                        # 设备版本号
+                        p['uid_version'] = ''
+                        p['ucode'] = ''
+                    data.append(p)
+                result = data
+                items = []
+                # print('缓存分页')
+                for index, item in enumerate(result):
+                    if (page - 1) * line <= index:
+                        if index < page * line:
+                            # 加密
+                            item['View_Password'] = self.encrypt_pwd(item['View_Password'])
+                            print(item)
+                            items.append(item)
+                print(items)
+                return response.json(0, items)
+            else:
+                return response.json(0, [])
+        else:
+            return response.json(444)
+
     # 加密
-    def encrypt_pwd(self,userPwd):
+    def encrypt_pwd(self, userPwd):
         for i in range(1, 4):
             if i == 1:
-                userPwd = RandomStr(3, False)+userPwd+RandomStr(3, False)
+                userPwd = RandomStr(3, False) + userPwd + RandomStr(3, False)
                 userPwd = base64.b64encode(str(userPwd).encode("utf-8")).decode('utf8')
             if i == 2:
-                userPwd = RandomStr(2, False)+str(userPwd)+RandomStr(2, False)
+                userPwd = RandomStr(2, False) + str(userPwd) + RandomStr(2, False)
                 userPwd = base64.b64encode(str(userPwd).encode("utf-8")).decode('utf8')
             if i == 3:
-                userPwd = RandomStr(1, False)+str(userPwd)+RandomStr(1, False)
+                userPwd = RandomStr(1, False) + str(userPwd) + RandomStr(1, False)
                 userPwd = base64.b64encode(str(userPwd).encode("utf-8")).decode('utf8')
         return userPwd
 
@@ -410,4 +582,4 @@ class EquipmentManagerV3(View):
                 password = password.decode('utf-8')
                 # 去前3位,后3位
                 password = password[3:-3]
-        return password
+        return password

+ 19 - 1
Controller/EquipmentOTA.py

@@ -7,7 +7,8 @@ from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import View
 
 from Ansjer.config import BASE_DIR, SERVER_DOMAIN
-from Model.models import Equipment_Version
+from Model.models import Equipment_Version, EquipmentVersionLimitModel, CountryIPModel
+from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Object.UrlTokenObject import UrlTokenObject
@@ -284,6 +285,23 @@ class EquipmentVersionView(View):
             # 判断大小
             if ov > eqs[0].softwareVersion:
                 return response.json(0, {'softwareVersion': ov})
+        equipment = eqs[0]
+        redisObject = RedisObject()
+        key = 'limit_{eid}'.format(eid=equipment.eid)
+
+        evl_qs = redisObject.get_data(key=key)
+        if evl_qs:
+            evl_qs = json.loads(evl_qs)
+        else:
+            evl_qs = EquipmentVersionLimitModel.objects.filter(equipment_version_id=equipment.eid, status=1).values()
+            if evl_qs.exists():
+                redisObject.set_data(key=key, val=json.dumps(list(evl_qs.values())), expire=600)
+        if evl_qs and len(evl_qs) > 0:
+            evl = evl_qs[0]
+            if evl['type'] == 1:  # uid限制
+                uids = json.loads(evl['content'])
+                if not uids.__contains__(uid):
+                    return response.json(902)
         file_path = eqs[0].filePath
         if file_path.find('static/Upgrade/') != -1:
             path = file_path.replace('static/Upgrade/', '').replace('\\', '/')

+ 21 - 4
Controller/MealManage.py

@@ -81,6 +81,12 @@ class MealManage(View):
         bucketID = request_dict.get('bucketID', None)
         paytype = request_dict.get('paytype', None)
         virtual_price = request_dict.get('virtual_price', None)
+        is_discounts = request_dict.get('is_discounts', None)
+        discount_price = request_dict.get('discount_price', None)
+        discount_content = request_dict.get('discount_content', None)
+        expire = request_dict.get('expire', None)
+        symbol = request_dict.get('symbol', None)
+
         if not title or not id or not price or not day or not content:
             return response.json(444, 'title,id,price,content,day,bucketID')
         own_perm = ModelService.check_perm(userID=userID, permID=40)
@@ -91,7 +97,8 @@ class MealManage(View):
             if Store_Meal.objects.filter(id=id):
                 return response.json(10, '已存在')
             store_meal = Store_Meal(id=id, title=title, price=price, content=content, day=day, bucket_id=bucketID,
-                                    currency=currency, virtual_price=virtual_price)
+                                    currency=currency, virtual_price=virtual_price, is_discounts=is_discounts,
+                                    discount_price=discount_price, discount_content=discount_content, expire=expire, symbol=symbol)
             store_meal.save()
             paytype = paytype.split(',')
             if len(paytype) > 0:
@@ -122,7 +129,7 @@ class MealManage(View):
             return response.json(444)
         qs = Store_Meal.objects.values("id", "title", "price", "content", "day", "add_time", "update_time", "currency"
                                        , "bucket_id", "bucket__bucket", "bucket__area", "commodity_type", "commodity_code",
-                                       "bucket__storeDay", "virtual_price")
+                                       "bucket__storeDay", "virtual_price", "is_discounts", "discount_price", "discount_content", "expire", "symbol")
         res = {}
         if qs.exists():
             ql = list(qs)
@@ -153,6 +160,11 @@ class MealManage(View):
         commodity_type = request_dict.get('commodity_type', None)
         commodity_code = request_dict.get('commodity_code', None)
         virtual_price = request_dict.get('virtual_price', None)
+        is_discounts = request_dict.get('is_discounts', None)
+        discount_price = request_dict.get('discount_price', None)
+        discount_content = request_dict.get('discount_content', None)
+        expire = request_dict.get('expire', None)
+        symbol = request_dict.get('symbol', None)
         type = request_dict.get('type', None)
         if not id or not title or not price or not content or not day or not type:
             return response.json(444, 'id, title, price, content, day,type')
@@ -169,6 +181,11 @@ class MealManage(View):
             store_meal.commodity_type = commodity_type
             store_meal.commodity_code = commodity_code
             store_meal.virtual_price = virtual_price
+            store_meal.is_discounts = is_discounts
+            store_meal.discount_price = discount_price
+            store_meal.discount_content = discount_content
+            store_meal.expire = expire
+            store_meal.symbol = symbol
             store_meal.day = day
             if bucketID:
                 store_meal.bucket_id = bucketID
@@ -265,12 +282,12 @@ class MealView(View):
             qs = Store_Meal.objects.filter(bucket__mold=1). \
                 values("id", "title", "content", "price", "day", "currency",
                        "bucket__storeDay", "bucket__bucket", "bucket__area",
-                       "type")
+                       "type", "symbol")
         else:
             qs = Store_Meal.objects.all(). \
                 values("id", "title", "content", "price", "day", "currency",
                        "bucket__storeDay", "bucket__bucket", "bucket__area",
-                       "type")
+                       "type", "symbol")
         if qs.exists():
             ql = list(qs)
             from operator import itemgetter

+ 2 - 2
Controller/OrderContrller.py

@@ -104,7 +104,7 @@ class OrderView(View):
         count = omqs.count()
         order_ql = omqs[(page - 1) * line:page * line].values("orderID", "UID", "channel", "desc", "price", "currency",
                                                               "addTime",
-                                                              "updTime", "endTime", "paypal", "rank__day", "payType",
+                                                              "updTime", "paypal", "rank__day", "payType",
                                                               "rank__price", "status",
                                                               "rank__content", "rank__title", "rank__currency",
                                                               "rank_id")
@@ -159,7 +159,7 @@ class OrderView(View):
                 return response.json(0, [])
             count = omqs.count()
             order_ql = omqs[(page - 1) * line:page * line].values("orderID", "UID", "channel", "desc", "price",
-                                                                  "currency", "addTime", "updTime", "endTime", "paypal",
+                                                                  "currency", "addTime", "updTime", "paypal",
                                                                   "payType",
                                                                   "rank__day",
                                                                   "rank__price", "status",

+ 28 - 1
Controller/UidSetController.py

@@ -23,7 +23,7 @@ from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import View
 
 from Model.models import UidSetModel, Device_User, Device_Info, UidPushModel, Equipment_Info, UID_Preview, UID_Bucket, \
-    VodHlsModel, Order_Model, OssCrdModel, UidUserModel, UidChannelSetModel, User_Brand
+    VodHlsModel, Order_Model, OssCrdModel, UidUserModel, UidChannelSetModel, User_Brand, ExperienceContextModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
@@ -89,6 +89,8 @@ class UidSetView(View):
             return self.do_update_channel_set(request_dict, response)
         elif operation == 'setVoicePrompt':
             return self.do_set_voice(userID, request_dict, response)
+        elif operation == 'vod_reset':
+            return self.vod_reset(request_dict, response)
         # elif operation == 'test':
         #     return self.do_test(response)
         else:
@@ -425,6 +427,8 @@ class UidSetView(View):
         end_y = request_dict.get('end_y', None)
         start_time = request_dict.get('start_time', None)
         end_time = request_dict.get('end_time', None)
+        repeat_day = request_dict.get('repeat_day', None)
+        direction = request_dict.get('direction', None)
 
         if uid and channel:
             channel = int(channel)
@@ -462,6 +466,12 @@ class UidSetView(View):
                 if end_time:
                     ucs['voice_end_time'] = end_time
 
+                if repeat_day:
+                    ucs['voice_repeat_day'] = repeat_day
+
+                if direction:
+                    ucs['voice_direction'] = direction
+
                 uid_channel_set_qs = UidChannelSetModel.objects.filter(uid__uid=uid, channel=channel)
                 if not uid_channel_set_qs.exists():
                     uidObject = UidSetModel.objects.filter(uid=uid)
@@ -476,6 +486,23 @@ class UidSetView(View):
             else:
                 return response.json(0)
 
+    # 重置设备云存
+    def vod_reset(self, request_dict, response):
+        uid = request_dict.get('uid', None)
+        if uid:
+            try:
+                with transaction.atomic():
+                    # 删除和更新设备云存相关数据
+                    UID_Bucket.objects.filter(uid=uid).delete()
+                    Order_Model.objects.filter(UID=uid).delete()
+                    VodHlsModel.objects.filter(uid=uid).delete()
+                    ExperienceContextModel.objects.filter(uid=uid).delete()
+                    Device_Info.objects.filter(UID=uid).update(vodPrimaryUserID='', vodPrimaryMaster='')
+            except Exception as e:
+                print(e)
+                return response.json(500, repr(e))
+            else:
+                return response.json(0)
 
     # def do_test(self, response):
     #     di_qs = Device_Info.objects.values('Type').annotate(c=Count('UID', distinct=True)).order_by()

+ 1 - 1
Controller/UserController.py

@@ -14,7 +14,7 @@
 import datetime
 import traceback
 import time
-
+import logging
 import jwt
 import simplejson
 import simplejson as json

+ 165 - 18
Controller/VoicePromptController.py

@@ -44,8 +44,18 @@ class VoicePromptView(View):
             return self.do_delete(token.userID, request_dict, response)
         elif operation == 'query':
             return self.do_query(request_dict, response)
+        elif operation == 'update':
+            return self.do_update(token.userID, request_dict, response)
+        elif operation == 'adminGetUploadUrl':
+            return self.admin_get_upload_url(token.userID, request_dict, response)
         elif operation == 'adminAdd':
-            return self.do_admin_add(request_dict, response)
+            return self.do_admin_add(token.userID, request_dict, response)
+        elif operation == 'adminQuery':
+            return self.do_admin_query(token.userID, request_dict, response)
+        elif operation == 'adminUpdate':
+            return self.do_admin_update(token.userID, request_dict, response)
+        elif operation == 'adminDelete':
+            return self.do_admin_delete(token.userID, request_dict, response)
         else:
             return response.json(404)
 
@@ -53,9 +63,10 @@ class VoicePromptView(View):
         upload_type = request_dict.get('upload_type', None)
         uid = request_dict.get('uid', None)
         channel = request_dict.get('channel', None)
+        type = request_dict.get('type', None)
 
         if upload_type and uid and channel:
-            count = VoicePromptModel.objects.filter(uid=uid, channel=channel).count()
+            count = VoicePromptModel.objects.filter(uid=uid, channel=channel, type=type).count()
             if count >= 3:
                 return response.json(201)
 
@@ -89,7 +100,40 @@ class VoicePromptView(View):
             voice_prompt.channel = channel
             voice_prompt.add_time = int(time.time())
             voice_prompt.save()
-            return response.json(0)
+
+            res = {
+                'id': voice_prompt.id,
+                'filename': filename,
+                'title': title,
+                'type': type,
+            }
+            auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+            bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
+            filename = res['filename']
+            obj = 'voice_prompt/uid/channel/'.format(uid=uid, channel=channel) + filename
+            url = bucket.sign_url('GET', obj, 3600)
+            res['url'] = url
+            del res['filename']
+            return response.json(0, res)
+        else:
+            return response.json(444)
+
+    def do_update(self, userID, request_dict, response):
+        id = request_dict.get('id', None)
+        title = request_dict.get('title', None)
+
+        if id and title:
+            voice_qs = VoicePromptModel.objects.filter(id=id)
+            if voice_qs.exists():
+                uid = voice_qs[0].uid
+                device_qs = Device_Info.objects.filter(UID=uid, userID=userID)
+                if device_qs.exists():
+                    voice_qs.update(title=title)
+                    return response.json(0)
+                else:
+                    return response.json(404)
+            else:
+                return response.json(173)
         else:
             return response.json(444)
 
@@ -119,7 +163,7 @@ class VoicePromptView(View):
 
         if uid and channel and lang:
             voice_qs = VoicePromptModel.objects.filter(uid=uid, channel=channel, classification=1)
-            system_qs = VoicePromptModel.objects.filter(classification=0, language=lang)
+            system_qs = VoicePromptModel.objects.filter(classification=0, language=lang, status=1)
             channel_qs = UidChannelSetModel.objects.filter(uid__uid=uid, channel=channel)
 
             res = {
@@ -131,10 +175,11 @@ class VoicePromptView(View):
             if channel_qs.exists():
                 channel_qs = channel_qs.values('voice_prompt_enter', 'voice_prompt_leave', 'voice_prompt_status',
                                                'voice_prompt_intelligent_mute', 'voice_start_x', 'voice_start_y',
-                                               'voice_end_x', 'voice_end_y', 'voice_start_time', 'voice_end_time')
+                                               'voice_end_x', 'voice_end_y', 'voice_start_time', 'voice_end_time',
+                                               'voice_repeat_day', 'voice_direction')
                 print(channel_qs)
-                res['enter_voice'] = channel_qs[0]['voice_prompt_enter']
-                res['leave_voice'] = channel_qs[0]['voice_prompt_leave']
+                res['enter_voice'] = int(channel_qs[0]['voice_prompt_enter'])
+                res['leave_voice'] = int(channel_qs[0]['voice_prompt_leave'])
                 res['voice_status'] = channel_qs[0]['voice_prompt_status']
                 res['voice_mute'] = channel_qs[0]['voice_prompt_intelligent_mute']
                 res['start_x'] = channel_qs[0]['voice_start_x']
@@ -143,6 +188,8 @@ class VoicePromptView(View):
                 res['end_y'] = channel_qs[0]['voice_end_y']
                 res['start_time'] = channel_qs[0]['voice_start_time']
                 res['end_time'] = channel_qs[0]['voice_end_time']
+                res['repeat_day'] = channel_qs[0]['voice_repeat_day']
+                res['direction'] = channel_qs[0]['voice_direction']
 
             enter_systems = []
             leave_systems = []
@@ -157,16 +204,16 @@ class VoicePromptView(View):
                 system_qs = system_qs.values('id', 'title', 'filename', 'type')
                 for system in system_qs:
                     filename = system['filename']
-                    obj = 'voice_prompt/' + uid + '/' + channel + '/' + filename
+                    obj = 'voice_prompt/system/' + filename
                     url = bucket.sign_url('GET', obj, 3600)
                     system['url'] = url
                     del system['filename']
-                    if system['type'] == 1:
+                    if system['type'] == 0:
                         enter_systems.append(system)
                         if res['enter_voice'] == system['id']:
                             res['enter_voice'] = system
 
-                    elif system['type'] == 2:
+                    elif system['type'] == 1:
                         leave_systems.append(system)
                         if res['leave_voice'] == system['id']:
                             res['leave_voice'] = system
@@ -180,15 +227,20 @@ class VoicePromptView(View):
                     url = bucket.sign_url('GET', obj, 3600)
                     voice['url'] = url
                     del voice['filename']
-                    if voice['type'] == 1:
+                    if voice['type'] == 0:
                         enter_customs.append(voice)
                         if res['enter_voice'] == voice['id']:
                             res['enter_voice'] = voice
-                    elif voice['type'] == 2:
+                    elif voice['type'] == 1:
                         leave_customs.append(voice)
                         if res['leave_voice'] == voice['id']:
                             res['leave_voice'] = voice
 
+            if res['leave_voice'] == 0:
+                res['leave_voice'] = {}
+            if res['enter_voice'] == 0:
+                res['enter_voice'] = {}
+
             res['system']['enter'] = enter_systems
             res['system']['leave'] = leave_systems
             res['custom']['enter'] = enter_customs
@@ -199,16 +251,35 @@ class VoicePromptView(View):
         else:
             return response.json(444)
 
-    def do_admin_add(self, request_dict, response):
+    def admin_get_upload_url(self, userID, request_dict, response):
+        own_perm = ModelService.check_perm(userID, 10)
+        if not own_perm:
+            return response.json(404)
+
+        upload_type = request_dict.get('upload_type', None)
+
+        if upload_type:
+            auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+            bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
+            name = CommonService.createOrderID()
+            filename = str(name) + '.' + upload_type
+            obj = 'voice_prompt/system/' + filename
+
+            url = bucket.sign_url('PUT', obj, 7200)
+            return response.json(0, {'put_url': url, 'filename': filename})
+        else:
+            return response.json(444)
+
+    def do_admin_add(self, userID, request_dict, response):
+        own_perm = ModelService.check_perm(userID, 10)
+        if not own_perm:
+            return response.json(404)
+
         filename = request_dict.get('filename', None)
         title = request_dict.get('title', None)
         type = request_dict.get('type', None)
         lang = request_dict.get('lang', '')
 
-        # own_perm = ModelService.check_perm(userID, 10)
-        # if not own_perm:
-        #     return response.json(404)
-
         if filename and title and type:
             voice_prompt = VoicePromptModel()
             voice_prompt.filename = filename
@@ -217,7 +288,83 @@ class VoicePromptView(View):
             voice_prompt.language = lang
             voice_prompt.classification = 0
             voice_prompt.add_time = int(time.time())
+            voice_prompt.status = 0
             voice_prompt.save()
+
+            return response.json(0)
+        else:
+            return response.json(444)
+
+    def do_admin_query(self, userID, request_dict, response):
+        own_perm = ModelService.check_perm(userID, 10)
+        if not own_perm:
+            return response.json(404)
+
+        type = request_dict.get('type', 0)
+        page = request_dict.get('page', None)
+        line = request_dict.get('line', None)
+
+        if page is None or line is None:
+            return response.json(444)
+
+        voice_qs = VoicePromptModel.objects.filter(classification=0, type=type)
+        res = {
+            'count': 0
+        }
+
+        if voice_qs.exists():
+            page = int(page)
+            line = int(line)
+
+            start = (page - 1) * line
+            end = start + line
+            count = voice_qs.count()
+            res['count'] = count
+
+            voice_qs = voice_qs.values('id', 'title', 'type', 'language', 'status', 'filename')[start:end]
+
+            auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+            bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'ansjer-static-resources')
+
+            for item in voice_qs:
+                filename = item['filename']
+                obj = 'voice_prompt/system/' + filename
+                url = bucket.sign_url('GET', obj, 3600)
+                item['url'] = url
+                del item['filename']
+            res['data'] = list(voice_qs)
+            return response.json(0, res)
+        else:
+            res['data'] = []
+            return response.json(0, res)
+
+    def do_admin_update(self, userID, request_dict, response):
+        own_perm = ModelService.check_perm(userID, 10)
+        if not own_perm:
+            return response.json(404)
+
+        id = request_dict.get('id', None)
+        status = request_dict.get('status', None)
+        title = request_dict.get('title', None)
+
+        if id and status and title:
+            VoicePromptModel.objects.filter(id=id, classification=0).update(status=status, title=title)
+            return response.json(0)
+        else:
+            return response.json(444)
+
+    def do_admin_delete(self, userID, request_dict, response):
+        own_perm = ModelService.check_perm(userID, 10)
+        if not own_perm:
+            return response.json(404)
+
+        id = request_dict.get('id', None)
+        if id:
+            VoicePromptModel.objects.filter(id=id, classification=0).delete()
             return response.json(0)
         else:
-            return response.json(444)
+            return response.json(444)
+
+
+
+

+ 16 - 8
Model/models.py

@@ -205,6 +205,7 @@ class Device_User(AbstractBaseUser):
 
 # 设备表是建项目开发者设计的,自己看着办
 # 谢谢提醒!我选择凉拌。
+# 我选择狗带
 class Device_Info(models.Model):
     id = models.CharField(blank=True, max_length=32, primary_key=True)
     userID = models.ForeignKey(Device_User, blank=True, to_field='userID', on_delete=models.CASCADE)
@@ -227,6 +228,8 @@ class Device_Info(models.Model):
                                   help_text=u'是否为共享获取的设备', default=False)
     primaryUserID = models.CharField(blank=True, verbose_name='主用户id', max_length=32, default='')
     primaryMaster = models.CharField(max_length=64, verbose_name=u'主用户名', default='')
+    vodPrimaryUserID = models.CharField(blank=True, verbose_name='云存主用户id', max_length=32, default='')
+    vodPrimaryMaster = models.CharField(max_length=64, verbose_name=u'云存主用户名', default='')
     data_joined = models.DateTimeField(blank=True, verbose_name=u'设备添加时间', auto_now_add=True)
     update_time = models.DateTimeField(blank=True, verbose_name=u'更新时间', auto_now=True, null=True)
 
@@ -414,7 +417,8 @@ class VodBucketModel(models.Model):
 class Store_Meal(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增ID')
     title = models.CharField(blank=True, max_length=32, verbose_name=u'标题')
-    currency = models.CharField(blank=True, default='USD', max_length=32, verbose_name=u'货币')
+    currency = models.CharField(blank=True, default='$', max_length=32, verbose_name=u'货币符号')
+    symbol = models.CharField(blank=True, default='$', max_length=32, verbose_name=u'符号')
     price = models.CharField(blank=True, max_length=32, verbose_name=u'价格')
     virtual_price = models.CharField(blank=True, max_length=32, verbose_name=u'虚拟价格')
     is_discounts = models.SmallIntegerField(default=0, verbose_name=u'该套餐是否有优惠 [0=否,1是]')   # 0没有;1有
@@ -540,12 +544,12 @@ class Order_Model(models.Model):
     channel = models.SmallIntegerField(default=0, verbose_name=u'通道数')
     desc = models.CharField(max_length=50, default='', verbose_name='商品描述')
     price = models.CharField(default='', max_length=16, verbose_name='价格')
-    currency = models.CharField(blank=True, default='USD', max_length=32, verbose_name=u'货币')
+    currency = models.CharField(blank=True, default='$', max_length=32, verbose_name=u'货币')
     addTime = models.IntegerField(verbose_name='添加时间', default=0)
     updTime = models.IntegerField(verbose_name='更新时间', default=0)
     # endTime = models.IntegerField(verbose_name='结束时间', default=0)
     isSelectDiscounts = models.SmallIntegerField(default=0, verbose_name=u'用户是否选择了第二年优惠 [0=否,1是]')
-    status = models.SmallIntegerField(default=0, verbose_name='付款状态')  # 0:待支付,1:成功,2:取消,3:已退款
+    status = models.SmallIntegerField(default=0, verbose_name='付款状态')  # 0:待支付,1:成功,2:取消,3:已退款, 9:处理中,10:付款失败
     payType = models.SmallIntegerField(default=0, verbose_name='付款类型0:paypal,1:alipay')
     payTime = models.IntegerField(verbose_name='支付成功时间', default=0)
     rank = models.ForeignKey(Store_Meal, to_field='id', default='', on_delete=models.CASCADE, verbose_name='套餐类型')
@@ -553,7 +557,7 @@ class Order_Model(models.Model):
     uid_bucket_id = models.IntegerField(default=0, verbose_name='关联uid_bucket的字段')
     commodity_type = models.SmallIntegerField(default=0, verbose_name='云存储套餐类型')
     commodity_code = models.CharField(default='', max_length=32, verbose_name='套餐规格码')
-    pay_url = models.CharField(max_length=1000, default='', verbose_name='支付url')
+    pay_url = models.CharField(max_length=2000, default='', verbose_name='支付url')
     paypal = models.CharField(max_length=500, null=True, blank=True, verbose_name='支付批准url')
 
 
@@ -576,7 +580,7 @@ class VodHlsModel(models.Model):
     sec = models.IntegerField(verbose_name='秒数', default=0)
     bucket = models.ForeignKey(VodBucketModel, blank=True, to_field='id', on_delete=models.CASCADE, default=1,
                                verbose_name='存储空间')
-    fg = models.IntegerField(default=0,verbose_name='时间描述片段数') # 阿里为时间片段数,亚马逊为一个32bit整型,前28bit代表ts文件的时长
+    fg = models.CharField(max_length=20,verbose_name='ts个数,时间描述片段数') # 阿里为时间片段数,亚马逊为一个32bit整型,前28bit代表ts文件的时长
 
 
     def __str__(self):
@@ -634,8 +638,10 @@ class UID_Bucket(models.Model):
     channel = models.SmallIntegerField(default=0, verbose_name='通道')
     bucket = models.ForeignKey(VodBucketModel, blank=True, to_field='id', on_delete=models.CASCADE, verbose_name='存储空间')
     status = models.SmallIntegerField(default=0, verbose_name='状态[0:开启,1:关闭]')
-    endTime = models.IntegerField(verbose_name='套餐结束时间', default=0)
-    is_use = models.IntegerField(verbose_name='是否使用中[0:未使用,1:使用中]', default=0)
+    endTime = models.BigIntegerField(verbose_name='套餐结束时间', default=0)
+    addTime = models.IntegerField(verbose_name='添加时间', default=0)
+    updateTime = models.BigIntegerField(verbose_name='更新时间', default=0)
+    # is_use = models.IntegerField(verbose_name='是否使用中[0:未使用,1:使用中]', default=0)
 
     class Meta:
         db_table = 'vod_uid_bucket'
@@ -772,6 +778,7 @@ class UidChannelSetModel(models.Model):
     voice_start_time = models.IntegerField(default=0, verbose_name='语音执行的起始时间')
     voice_end_time = models.IntegerField(default=0, verbose_name='语音执行的结束时间')
     voice_repeat_day = models.IntegerField(default=0, verbose_name='语音执行的日期,周几')
+    voice_direction = models.IntegerField(default=0, verbose_name='语音方向。')
 
     class Meta:
         db_table = 'uid_channel'
@@ -1133,13 +1140,14 @@ class CDKcontextModel(models.Model):
 class VoicePromptModel(models.Model):
     id = models.AutoField(primary_key=True)
     title = models.CharField(max_length=128, default='', verbose_name='语音标题')
-    type = models.SmallIntegerField(default=0, verbose_name='语音类型。1:进入语音,2:离开语音')
+    type = models.SmallIntegerField(default=0, verbose_name='语音类型。0:进入语音,1:离开语音')
     filename = models.CharField(max_length=120, default='', verbose_name='文件名')
     language = models.CharField(max_length=16, default='', verbose_name='语言类型')
     classification = models.SmallIntegerField(default=1, verbose_name='语音分类。0:系统,1:自定义')
     add_time = models.IntegerField(default=0, verbose_name='添加时间')
     uid = models.CharField(max_length=20, default='0', verbose_name='关联设备UID')
     channel = models.IntegerField(default=0, verbose_name='通道号')
+    status = models.SmallIntegerField(default=1, verbose_name='是否启用。0:不启用,1:启用')
 
     class Meta:
         db_table = 'voice_prompt'

+ 33 - 1
Object/ResponseObject.py

@@ -74,6 +74,22 @@ class ResponseObject(object):
             10004: 'The request method is incorrect. Please contact the developer',
             10005: 'Wrong configuration, wrong customer number',
             10006: 'Configuration error. The path value is incorrect',
+            10007: 'This device is not an experience package and cannot be reset',
+            10008: 'The user does not have this device and cannot transfer',
+            10009: 'The user already owns the device and cannot transfer it',
+            10010: 'Devices that are not under the same account cannot be transferred',
+            10011: 'Receiving transfer device does not exist and cannot be transferred',
+            10012: 'Experience packages cannot be transferred',
+            10013: 'Original equipment package has expired and cannot be transferred',
+            10014: 'Accept transfer of equipment packages that have not expired and cannot be transferred',
+            10015: 'Shared devices cannot be transferred',
+            10030: 'No purchase of cloud storage',
+            10031: 'The cloud storage has expired',
+            10032: 'The switched cloud storage package ID cannot be the same as the one in use',
+            10033: 'The primary user of the device cannot purchase it',
+            10034: 'Non device primary users cannot view cloud storage',
+            10035: 'Non device primary users cannot experience cloud storage',
+            10036: 'Non device primary users cannot exchange for cloud storage',
         }
         data_cn = {
             0: '成功',
@@ -142,7 +158,23 @@ class ResponseObject(object):
             10004: '请求方法不正确。请联系开发者',
             10005: '配置错误,客户编号这个值是错误的',
             10006: '配置错误,路径这个值是错误的',
-            10007: '此设备不是体验套餐,无法重置'
+            10007: '此设备不是体验套餐,无法重置',
+            10008: '用户没有此设备,无法转移',
+            10009: '用户已拥有此设备,无法转移',
+            10010: '不是同一账户下的设备,无法转移',
+            10011: '接受转移设备不存在,无法转移',
+            10012: '体验套餐无法转移',
+            10013: '原设备套餐已过期,无法转移',
+            10014: '接受转移设备套餐未过期,无法转移',
+            10015: '分享的设备无法转移',
+            10030: '未购买云存',
+            10031: '云存已过期',
+            10032: '切换的云存套餐ID不能与正在使用中的相同',
+            10033: '非设备主用户无法购买',
+            10034: '非设备主用户无法查看云存',
+            10035: '非设备主用户无法体验云存',
+            10036: '非设备主用户无法兑换云存',
+
         }
         if self.lang == 'cn':
             msg = data_cn

+ 50 - 3
Object/WechatPayObject.py

@@ -124,9 +124,8 @@ class WechatPayObject:
         return sign_again_params  # 返回给app
 
     def get_notifypay(self, data):
-        dictdata = dict(data)
-        _dictdata = dict(dictdata['xml'])
-        success = self.get_sign(_dictdata)
+
+        success = self.get_sign(data)
         # print('success', success)
         if success:
             success.pop("sign", None)
@@ -136,6 +135,54 @@ class WechatPayObject:
         else:
             return False
 
+    def weixinpay_call_back(self, data):
+
+        args = str(data, 'utf-8')
+
+        if args is None:
+            return None
+
+        print(args)
+
+        # 验证平台签名
+
+        resp_dict = self.handle_wx_response_xml(args)
+        if resp_dict is None:
+            print('签名验证失败!!!')
+            return None
+
+        return resp_dict
+
+    def handle_wx_response_xml(self, params):
+
+        """
+
+        处理微信支付返回的xml格式数据
+
+        """
+
+        try:
+
+            resp_dict = xmltodict.parse(params)['xml']
+
+            if not resp_dict or len(resp_dict) < 1:
+                print('resp_dict is zero+++++++++')
+
+                return None
+
+            return_code = resp_dict.get('return_code')
+
+            if return_code == 'SUCCESS':  # 仅仅判断通信标识成功,非交易标识成功,交易需判断result_code
+                return resp_dict
+
+
+        except Exception as e:
+            print(e)
+
+            return None
+
+        return None
+
     @staticmethod
     def xml_to_dict(params):
         """

部分文件因文件數量過多而無法顯示