Browse Source

Merge remote-tracking branch 'remotes/origin/dev' into test

chenshibin 4 năm trước cách đây
mục cha
commit
37e69a17eb
39 tập tin đã thay đổi với 2885 bổ sung276 xóa
  1. 33 0
      Ansjer/config.py
  2. 9 0
      Ansjer/config_formal.py
  3. 8 6
      Ansjer/config_local.py
  4. 5 0
      Ansjer/config_test.py
  5. 67 0
      Ansjer/file/apns_pem/apns-dis-adcloud.pem
  6. 2 1
      Ansjer/formal_settings.py
  7. 27 0
      Ansjer/formal_statistics_push_day_task.py
  8. 27 0
      Ansjer/formal_statistics_push_month_task.py
  9. 1 1
      Ansjer/local_settings.py
  10. 1 1
      Ansjer/test_settings.py
  11. 27 0
      Ansjer/test_statistics_push_day_task.py
  12. 27 0
      Ansjer/test_statistics_push_month_task.py
  13. 34 3
      Ansjer/urls.py
  14. 2 0
      Controller/AccessLog.py
  15. 426 2
      Controller/AdminManage.py
  16. 132 0
      Controller/Alexa.py
  17. 145 0
      Controller/AppLogController.py
  18. 154 4
      Controller/CloudVod.py
  19. 2 2
      Controller/DetectController.py
  20. 2 2
      Controller/DeviceManage.py
  21. 4 2
      Controller/DeviceShare.py
  22. 40 28
      Controller/EquipmentManager.py
  23. 5 0
      Controller/EquipmentManagerV2.py
  24. 145 152
      Controller/EquipmentManagerV3.py
  25. 324 0
      Controller/FAQController.py
  26. 149 1
      Controller/OrderContrller.py
  27. 258 0
      Controller/StatisticsController.py
  28. 6 3
      Controller/TestApi.py
  29. 4 4
      Controller/UIDPreview.py
  30. 85 19
      Controller/UidSetController.py
  31. 6 6
      Controller/UidUser.py
  32. 88 0
      Controller/UserBrandControllerV2.py
  33. 556 38
      Controller/UserController.py
  34. 2 0
      Controller/shareUserPermission.py
  35. 2 0
      Model/models.py
  36. 10 0
      Object/ResponseObject.py
  37. 41 1
      Service/CommonService.py
  38. 28 0
      Service/ModelService.py
  39. 1 0
      Service/TemplateService.py

+ 33 - 0
Ansjer/config.py

@@ -32,6 +32,7 @@ SES_COMPANY_EMAIL = 'user_server@nsst.com'
 AWS_SES_ACCESS_ID = 'AKIAJKPU23EU5QWHFPKQ'
 AWS_SES_ACCESS_SECRET = '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'
 AWS_SES_ACCESS_REGION = 'us-east-1'
+AWS_SES_ACCESS_REGION_WEST = 'us-west-1'
 AWS_BUCKET = 'ansjertest'
 # 设定离线时间为5分钟
 OFF_LINE_TIME_DELTA = 5
@@ -126,3 +127,35 @@ FCM_CONFIG = {
     'com.ansjer.accloud_a': 'AAAAb9YP3rk:APA91bFm06w8b9OKQ0gz0iaWFuRqRIkvgAz6z7Gp3dBU_X-LNGJQd1hc1QR2W7QzBglF8SHtERA45a2lbdLRa5qv7hxfd6W_sJLBK7dA8jklsOQBvy505oUzTwMKWy4TwH-exps9KrhO',
     'com.ansjer.zccloud_ab': 'AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I',
 }
+
+DEVICE_TYPE = {
+    0: 'UNKOWN',
+    1: 'DVR',
+    2: 'NVR',
+    3: 'POENVR',
+    4: 'WIRELESSNVR',
+    5: 'POEIPC',
+    6: 'BOLTIPC',
+    7: 'IPC',
+    8: 'KAPIANJI',
+    9: 'FISHEYE',
+    10: 'C512',
+    11: 'C611',
+    12: 'C612',
+    13: 'C199',
+    14: 'C190',
+    15: 'C199_PRO',
+    17: 'C289',
+    10001: 'DVRPTZ'
+}
+
+APP_FREQUENT = {
+    0: 'UNKOWN',
+    1: '每天',
+    2: '三天',
+    3: '一周',
+    4: '两周',
+    5: '一个月',
+    6: '一个月以上',
+
+}

+ 9 - 0
Ansjer/config_formal.py

@@ -36,6 +36,12 @@ APNS_CONFIG = {
     'com.ansjer.customizedb': {
         'pem_path': 'Ansjer/file/apns_pem/customizedb.pem',
     },
+    'com.ansjer.customizedd': {
+        'pem_path': 'Ansjer/file/apns_pem/customizedd.pem',
+    },
+    'com.ansjer.customizede': {
+        'pem_path': 'Ansjer/file/apns_pem/customizede.pem',
+    },
     'com.ansjer.customizeda': {
         'pem_path': 'Ansjer/file/apns_pem/customizeda.pem',
     },
@@ -44,6 +50,9 @@ APNS_CONFIG = {
     },
     'com.ansjer.accloud': {
         'pem_path': 'Ansjer/file/apns_pem/accloud-dev.pem',
+    },
+    'com.ansjer.adcloud': {
+        'pem_path': 'Ansjer/file/apns_pem/apns-dis-adcloud.pem',
     }
 }
 APNS_MODE = 'prod'

+ 8 - 6
Ansjer/config_local.py

@@ -15,12 +15,14 @@
 OAUTH_ACCESS_TOKEN_SECRET = 'local_a+jbgnw%@1%zy^=@dn62%'
 OAUTH_REFRESH_TOKEN_SECRET = 'local_r+jbgnw%@1%zy^=@dn62%'
 
-NGINX_RTMP_STAT = 'http://192.168.136.45:8077/stat'
-SERVER_DOMAIN = 'http://192.168.136.45:8077/'
-SERVER_DOMAIN_SSL = 'http://192.168.136.45:8077/'
-SERVER_HOST = '192.168.136.45'
-DOMAIN_HOST = '192.168.136.45'
-RTMP_PUSH_URL = 'rtmp://192.168.136.45:1935/hls'
+NGINX_RTMP_STAT = 'http://192.168.136.99:8077/stat'
+SERVER_DOMAIN = 'http://192.168.136.99:8077/'
+SERVER_DOMAIN_SSL = 'http://192.168.136.99:8077/'
+SERVER_HOST = '192.168.136.99'
+DOMAIN_HOST = '192.168.136.99'
+# SERVER_HOST = '127.0.0.1'
+# DOMAIN_HOST = '192.168.136.99'
+RTMP_PUSH_URL = 'rtmp://192.168.136.99:1935/hls'
 PAYPAL_CRD = {
     "mode": "sandbox",  # sandbox or live
     "client_id": "AeuhR7FHisO-lOd2OwtzyDu7PSLMmDZoDLgmzuEQ12WCtTu_8Z1AzcD4gG5SnymnuvJs-n5KBB8H9Z_G",

+ 5 - 0
Ansjer/config_test.py

@@ -33,6 +33,11 @@ PAYPAL_CRD = {
     "client_id": "AVLoQVq3xHZ6FrF4mxHwlCPgVBAw4Fw5RtMkuxmYd23SkUTIY643n2g3KdK-Al8wV05I28lza5uoQbAA",
     "client_secret": "EO8kRc8yioDk0i2Qq-QMcVFfwkmyMJorTvBSLDTnxDJJ_wb9VoM_0jkUY9iEng2Flp1ze8wQOGpH5nB2"
 }
+# PAYPAL_CRD = {
+#     "mode": "sandbox",  # sandbox or live
+#     "client_id": "ATXTpWs8sajNYeU46jNs1yzpy4H_o3RRrGVIJ8Tscc312BjMx12cpRgCucfWX07a4G6GbK8hzElB04Pd",
+#     "client_secret": "EHcnfrpL1o1ev9WnlQ-C1uymeRKDoJ6li6Y0d6iHoRGj4u8Sx5lSEEH774XphP4LQZ0DrDUdvxbux0T2"
+# }
 DETECT_PUSH_DOMAIN = 'http://test.push.dvema.com/'
 # 数据库dyanamo品牌日志数据库
 USER_BRAND = 'test_user_brand'

+ 67 - 0
Ansjer/file/apns_pem/apns-dis-adcloud.pem

@@ -0,0 +1,67 @@
+Bag Attributes
+    friendlyName: Apple Push Services: com.ansjer.adcloud
+    localKeyID: 9A 3D 96 76 52 35 8D 36 A0 21 06 AA CC 49 63 8C 8D 7A AD 8A 
+subject=/UID=com.ansjer.adcloud/CN=Apple Push Services: com.ansjer.adcloud/OU=66PK439G56/O=side zhang/C=US
+issuer=/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority
+-----BEGIN CERTIFICATE-----
+MIIGFTCCBP2gAwIBAgIIR4506q9hVmswDQYJKoZIhvcNAQELBQAwgZYxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
+ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
+aWRlIERldmVsb3BlciBSZWxhdGlvbnMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
+HhcNMTkwOTA5MDIyMjU3WhcNMjAxMDA4MDIyMjU3WjCBjTEiMCAGCgmSJomT8ixk
+AQEMEmNvbS5hbnNqZXIuYWRjbG91ZDEwMC4GA1UEAwwnQXBwbGUgUHVzaCBTZXJ2
+aWNlczogY29tLmFuc2plci5hZGNsb3VkMRMwEQYDVQQLDAo2NlBLNDM5RzU2MRMw
+EQYDVQQKDApzaWRlIHpoYW5nMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBALivar615v3P55uc/t0Oxxvu57hAUPrWuoReT1z3tobQ
+JmFqDcO6xk69UeYIOl6kNz3fdH7GJJbFErLUHOFC3lvkHVNmA6oUgGOJghMkrtX4
+kbHsES3hAWOcuyGiNISG19b5P4L3KsOaQWwrXSKTYzUkAtUcAxmTXJ/jokKIPsMu
+lXZwXSjaF4SLjCcT9rpGGSskDhLaDY5Xy4QAcYI8rtJi+nrN7DcwLAMIQlPWOilG
+OOOzu6QVENJLkW0v5uxZAoqHrWZFyNv4uoR0BhKzFcn2O6se7iNMV3TXCuR2ieuI
+wMiPs8om+QItGbrZ3NS+NWHWjd7H7p4Zp63N/0igc7UCAwEAAaOCAmwwggJoMAwG
+A1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUiCcXCam2GGCL7Ou69kdZxVJUo7cwggEc
+BgNVHSAEggETMIIBDzCCAQsGCSqGSIb3Y2QFATCB/TCBwwYIKwYBBQUHAgIwgbYM
+gbNSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1
+bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0
+ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRlIHBvbGljeSBh
+bmQgY2VydGlmaWNhdGlvbiBwcmFjdGljZSBzdGF0ZW1lbnRzLjA1BggrBgEFBQcC
+ARYpaHR0cDovL3d3dy5hcHBsZS5jb20vY2VydGlmaWNhdGVhdXRob3JpdHkwEwYD
+VR0lBAwwCgYIKwYBBQUHAwIwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL2NybC5h
+cHBsZS5jb20vd3dkcmNhLmNybDAdBgNVHQ4EFgQUmj2WdlI1jTagIQaqzEljjI16
+rYowDgYDVR0PAQH/BAQDAgeAMBAGCiqGSIb3Y2QGAwEEAgUAMBAGCiqGSIb3Y2QG
+AwIEAgUAMH0GCiqGSIb3Y2QGAwYEbzBtDBJjb20uYW5zamVyLmFkY2xvdWQwBQwD
+YXBwDBdjb20uYW5zamVyLmFkY2xvdWQudm9pcDAGDAR2b2lwDB9jb20uYW5zamVy
+LmFkY2xvdWQuY29tcGxpY2F0aW9uMA4MDGNvbXBsaWNhdGlvbjANBgkqhkiG9w0B
+AQsFAAOCAQEAt1hrHRDNCspHkLrIiJoRzXDQUM/TjWgaNne3XOBY5WAX34fnUe57
+y8MPtuc317BJOi/s56u5cZ742qbJ9yOvzHr04o4D+8+MqLpL0BZ5qU48WV43o+bw
+uNg2u+WW4qVKXDfAjBojEpDt4Pc/1+lZiBHYsqVIrjTkmyuaq/YSPfnB0tABaHOk
+g4QPg9dV5x3IebysrcykTPStIw9noIu4QleD34V74Npw6/F6aqDRGvaX2xjB/Gas
+rGpYL/Aq7F/Vy9yUD+u2iNl3LF9ITJddTd1q+09PAKgy5VG5sPQC/KRyW2DEU+dd
+eYhp+zzv+r66mPG4NFOt4g/F1/5NxUvMWA==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAuK9qvrXm/c/nm5z+3Q7HG+7nuEBQ+ta6hF5PXPe2htAmYWoN
+w7rGTr1R5gg6XqQ3Pd90fsYklsUSstQc4ULeW+QdU2YDqhSAY4mCEySu1fiRsewR
+LeEBY5y7IaI0hIbX1vk/gvcqw5pBbCtdIpNjNSQC1RwDGZNcn+OiQog+wy6VdnBd
+KNoXhIuMJxP2ukYZKyQOEtoNjlfLhABxgjyu0mL6es3sNzAsAwhCU9Y6KUY447O7
+pBUQ0kuRbS/m7FkCioetZkXI2/i6hHQGErMVyfY7qx7uI0xXdNcK5HaJ64jAyI+z
+yib5Ai0Zutnc1L41YdaN3sfunhmnrc3/SKBztQIDAQABAoIBACQUSNM28AhXjFSP
+KA8Baw5e7q/FCMzoFAn17qUn02Wk1kqjkErTexg4zf4VT2nbxNr2g2icxtsZZty+
+qWGsUYo8FyqKvF6GoMpRO7MHsIwmgjfy+SwwT7gpDzmz2XSmbxYVHT41kQojYXKD
+Si+OAYyJG3CMh2KAslCeBL3gpfo1E2bKjF/SaDMqtxBky6SUcw3huAUKJm+LFBXz
+m9HGFflXSyRXnpRoscJFeBE3cwFo69J6B2WH9LeqKQVaIpE40CCuqJK09UC+3syk
+cpmkm0Tg9hIYFR8NktQjEkBYbFBctExLg0g8JaDPQfV/G6xl1V5GBHsHW7vesMBN
+mPk3xWUCgYEA57tBIyFVxb+bDpR8H2YX7HKZxuW2yhitj4qEImjSjNjGaMBJqdW3
+t8zqSNZvOXSyvt1oz29c1arDxwf6ost4cE1bR0cglCwM4r7o6JZimZJqkZ1EXu7e
+T+qFVEkT+ow3lqYPG3NyBN82sTXGkfgFtsuc//AlLQeDQ+YPjXyrPGcCgYEAzAbZ
+Bgi9r37wAYoeMFxG0PSrrBPXHKKGMK01pm5gZmkUgvB4APScTVx2qsEtF4XZNzZY
+KYAYTbe4FehLUpPxUgENQte2IfUfYT/KMg8YikOUANpIY6wbnHOBrJ74feF3V6oD
+rD00SVuC9cBrjGBwjldKtx8gq+OFXICInJIEPYMCgYEAo9MiTa+3b8Hx4PDgf2Ix
+75tlU9P60g14Rk5q89ifYauvOUcXzNWmuG5KA4x1vWzfIUhuXJgiTXwYRJFDg+vN
+DbfinBWQ1q/9vB+zkRsgQendJWzFdUfyKxVlhRzU3wBaHErxyzpmlUMo60dVRsTN
+ZVm1eMtRvO/ewRXYUPKeLGkCgYA2WkCold2KiiOAFX5zXbHT6sptHh/5VeavwwT+
+4Hq37Zh0RYGCp6eYCGDonmvXz2WNiuGztJdE5QOaenbOefEY6oTQ4Mx5gWaprqe7
+7D+aXeRo0b3lJ613YWITTYpfZpg3d2hhEzEBtepOc8Ny8yIpGWIjJJy8jfEyMl+y
+bkfI5wKBgFOf0I1SmlmUYW2fcGs3IeXnITpLHyTEaesWLuJ8rEVmuzxKO79zVwjC
+N2ZkRJAW3bD5+VBH4kxKZqhzIQGcgm3xUG1DsJITD9JSYHlSzIlJC8+QjVMihpX0
+bjQVuem5KpGn7jTu6URTB9cBGLywPFEwOK3N5Md66FZu98KiOsm/
+-----END RSA PRIVATE KEY-----

+ 2 - 1
Ansjer/formal_settings.py

@@ -77,7 +77,8 @@ WSGI_APPLICATION = 'Ansjer.formal_wsgi.application'
 # DATABASES_USER = 'ansjer'
 # DATABASES_PASS = '1234'
 DATABASE_DATA = 'Ansjer81'
-SERVER_HOST = 'azrdsinstance.clraczw4p0yj.us-west-1.rds.amazonaws.com'
+# SERVER_HOST = 'azrdsinstance.clraczw4p0yj.us-west-1.rds.amazonaws.com'
+SERVER_HOST = 'database-2.clraczw4p0yj.us-west-1.rds.amazonaws.com'
 DATABASES_USER = 'azrds'
 DATABASES_PASS = 'azrds.x.x'
 

+ 27 - 0
Ansjer/formal_statistics_push_day_task.py

@@ -0,0 +1,27 @@
+import json
+
+import requests
+
+
+base_url = 'http://dvema.com'
+username='13800138001'
+password='ansjer123456'
+
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data)
+res = res.json()
+print(res)
+
+if res['result_code'] == 0:
+    statistics_url = base_url + 'statistcs/pushDay'
+    data = {
+        'token': res['result']['access_token']
+    }
+    res = requests.post(url=statistics_url, data=data)
+    print(res.json())
+

+ 27 - 0
Ansjer/formal_statistics_push_month_task.py

@@ -0,0 +1,27 @@
+import json
+
+import requests
+
+
+# url = 'http://test.dvema.com'
+base_url = 'http://dvema.com/'
+username='13800138001'
+password='ansjer123456'
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data)
+res = res.json()
+print(res)
+
+if res['result_code'] == 0:
+    statistics_url = base_url + 'statistcs/pushMonth'
+    data = {
+        'token': res['result']['access_token']
+    }
+    res = requests.post(url=statistics_url, data=data)
+    print(res.json())
+

+ 1 - 1
Ansjer/local_settings.py

@@ -74,7 +74,7 @@ WSGI_APPLICATION = 'Ansjer.local_wsgi.application'
 
 # 服务器类型
 DATABASE_DATA = 'AnsjerLocal'
-SERVER_HOST = '192.168.136.45'
+SERVER_HOST = '192.168.136.99'
 DATABASES_USER = 'ansjer'
 DATABASES_PASS = 'ansjer.x.x'
 

+ 1 - 1
Ansjer/test_settings.py

@@ -74,7 +74,7 @@ WSGI_APPLICATION = 'Ansjer.test_wsgi.application'
 
 # 服务器类型
 DATABASE_DATA = 'AnsjerTest'
-SERVER_HOST = 'azrdsinstance.clraczw4p0yj.us-west-1.rds.amazonaws.com'
+SERVER_HOST = 'database-2.clraczw4p0yj.us-west-1.rds.amazonaws.com'
 DATABASES_USER = 'azrds'
 DATABASES_PASS = 'azrds.x.x'
 # 服务器类型

+ 27 - 0
Ansjer/test_statistics_push_day_task.py

@@ -0,0 +1,27 @@
+import json
+
+import requests
+
+
+# url = 'http://test.dvema.com'
+base_url = 'http://test.dvema.com/'
+username='13800138001'
+password='ansjer999999'
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data)
+res = res.json()
+print(res)
+
+if res['result_code'] == 0:
+    statistics_url = base_url + 'statistcs/pushDay'
+    data = {
+        'token': res['result']['access_token']
+    }
+    res = requests.post(url=statistics_url, data=data)
+    print(res.json())
+

+ 27 - 0
Ansjer/test_statistics_push_month_task.py

@@ -0,0 +1,27 @@
+import json
+
+import requests
+
+
+# url = 'http://test.dvema.com'
+base_url = 'http://test.dvema.com/'
+username='13800138001'
+password='ansjer999999'
+login_url = base_url + 'account/login'
+
+data = {
+    'userName': username,
+    'userPwd': password
+}
+res = requests.post(url=login_url, data=data)
+res = res.json()
+print(res)
+
+if res['result_code'] == 0:
+    statistics_url = base_url + 'statistcs/pushMonth'
+    data = {
+        'token': res['result']['access_token']
+    }
+    res = requests.post(url=statistics_url, data=data)
+    print(res.json())
+

+ 34 - 3
Ansjer/urls.py

@@ -3,12 +3,14 @@ from django.urls import path, re_path
 
 from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppInfo, \
     AccessLog, DynamoDBLog, Test, MealManage, DeviceManage, EquipmentStatus, SysManage, DeviceLog, LogAccess, \
-    AppColophon, DateController,\
+    AppColophon, DateController, \
     EquipmentManager, LogManager, PermissionManager, OTAEquipment, shareUserPermission, UidSetController, \
     UserManger, CheckUserData, \
     UserController, CloudVod, OrderContrller, VodBucket, DetectController, DeviceShare, UserBrandController, \
-    StsOssController, UIDPreview, OssCrd, SysMsg, UidUser, EquipmentManagerV2,EquipmentManagerV3, PushDeploy, AppSetController,\
-    ApplicationController, UserExController, CloudStorage, TestApi
+    StsOssController, UIDPreview, OssCrd, SysMsg, UidUser, EquipmentManagerV2, EquipmentManagerV3, PushDeploy, \
+    AppSetController, \
+    ApplicationController, UserExController, CloudStorage, TestApi, UserBrandControllerV2, \
+    StatisticsController, Alexa, FAQController, AppLogController
 
 urlpatterns = [
     url(r'^testApi/(?P<operation>.*)$', TestApi.testView.as_view()),
@@ -120,6 +122,15 @@ urlpatterns = [
     url(r'^v2/account/logout$', UserController.V2LogoutView.as_view()),
     url(r'^v2/account/login$', UserController.v3LoginView.as_view()),
     url(r'^v3/account/login$', UserController.v3LoginView.as_view()),
+
+    # 验证码登录
+    url(r'^account/loginCode$', UserController.loginCodeView.as_view()),
+    url(r'^v3/account/loginByCode$', UserController.v3LoginByCodeView.as_view()),
+
+    # 指纹登录
+    url(r'^v3/account/loginByFingerprint$', UserController.v3LoginByFingerprintView.as_view()),
+    url(r'^v3/account/setFingerprint$', UserController.v3SetFingerprintView.as_view()),
+
     # 新增
     url(r'^detect/detect_group_push$',DetectController.NotificationView.detect_group_push),
     url(r'^detect/add$', DetectController.PushNotificationView.as_view()),
@@ -203,6 +214,26 @@ urlpatterns = [
     url(r'^date/(?P<operation>.*)$', DateController.DateConView.as_view()),
 
     url(r'^equipment/flow_test$', EquipmentManager.uid_status_test),
+    url(r'^account/appFrequency/(?P<operation>.*)$', UserController.UserAppFrequencyView.as_view()),
+    url(r'^v2/userbrand/(?P<operation>.*)$', UserBrandControllerV2.UserBrandV2.as_view()),
+    url(r'^statistcs/appFrequencyMonth$', StatisticsController.statistcsAppFrequency),
+    url(r'^statistcs/appFrequencyYear$', StatisticsController.statistcsAppFrequencyYear),
+    url(r'^statistcs/pushDay$', StatisticsController.statistcsPushDay),
+    url(r'^statistcs/pushMonth$', StatisticsController.statistcsPushMonth),
+
+    #统计alexa连接数
+    url(r'^alexa/(?P<operation>.*)$', Alexa.AlexaConnectNum.as_view()),
+
+    # FAQ
+    url(r'^faq/upload', FAQController.FAQUploadView.as_view()),
+    url(r'^faq/image/(?P<filePath>.*)$', FAQController.getFAQImage.as_view()),
+    url(r'^faq/(?P<operation>.*)$', FAQController.FAQView.as_view()),
+
+    # 苹果登录
+    url(r'^ios/authsign', UserController.AppleAuthLogin.as_view()),
+    url(r'^appLog/(?P<operation>.*)$', AppLogController.AppLogView.as_view()),
+
+
     # app 设备消息模板
     # 路由加参数参考
     # url(r'^(?P<path>.*)/(?P<UID>.*)/lls$', Test.Test.as_view(), name=u'gg'),

+ 2 - 0
Controller/AccessLog.py

@@ -19,6 +19,8 @@ http://192.168.136.40:8077/accesslog?operation=queryByAdmin&token=test&page=1&li
 http://192.168.136.40:8077/accesslog?operation=truncateByAdmin&token=test
 http://192.168.136.40:8077/accesslog?operation=searchByAdmin&token=test&page=1&line=10&content={"status":20}&order=-id
 
+
+
 http://192.168.136.40:8077/accesslog/staticPath/?token=stest
 '''
 

+ 426 - 2
Controller/AdminManage.py

@@ -1,16 +1,23 @@
 # -*- coding: utf-8 -*-
+import time
+from datetime import date, timedelta, timezone as asj_timezone
+
+import boto3
+from django.db.models import Count,Q
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
 from django.utils.decorators import method_decorator
 from django.contrib.auth.hashers import make_password  # 对密码加密模块
-from Model.models import Device_Info, Role, UserExModel
+from Model.models import Device_Info, Role, UserExModel, User_Brand, UidSetModel, AppFrequencyYearStatisticsModel, \
+    AppFrequencyStatisticsModel, EquipmentInfoExStatisticsModel, Equipment_Info
 from Service.ModelService import ModelService
 from django.utils import timezone
 from Model.models import Access_Log, Device_User
 from django.views.decorators.http import require_http_methods
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
-from Ansjer.config import OFF_LINE_TIME_DELTA
+from Ansjer.config import OFF_LINE_TIME_DELTA, DEVICE_TYPE, AWS_SES_ACCESS_ID, AWS_SES_ACCESS_SECRET, \
+    AWS_SES_ACCESS_REGION_WEST
 import datetime, simplejson as json
 from Service.CommonService import CommonService
 from Object.RedisObject import RedisObject
@@ -64,6 +71,22 @@ class AdminManage(TemplateView):
             return self.getAllUID(userID, response)
         if operation == 'getAllDeviceArea':
             return self.getAllDeviceArea(userID, response)
+        if operation == 'getUserBrand':
+            return self.getUserBrand(userID, response)
+        if operation == 'getAreaDeviceType':
+            return self.getAreaDeviceType(userID, response)
+        if operation == 'getDeviceType':
+            return self.getDeviceType(userID, response)
+        if operation == 'getAppFrequency':
+            return self.getAppFrequency(userID, request_dict, response)
+        if operation == 'getHistoryAppFrequency':
+            return self.getAllAppFrequency(userID, response)
+        if operation == 'getPushStatistics':
+            return self.query_push_by_level(userID, request_dict, response)
+        if operation == 'getPushFailures':
+            return self.query_failures_push(userID, request_dict, response)
+        if operation == 'getPushServerCPUUsage':
+            return self.query_push_server_cpu_usage(userID, request_dict, response)
 
     def resetUserPwd(self, request_dict, userID, response):
         own_permission = ModelService.check_perm(userID=userID, permID=50)
@@ -213,6 +236,406 @@ class AdminManage(TemplateView):
             res = {'count': uid_list.count(), 'uid_list': list(uid_list)}
         return response.json(0, res)
 
+    def getUserBrand(self, userID, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+        # 手机型号统计
+        print('手机型号统计:')
+        ub_qs = User_Brand.objects.values('deviceSupplier', 'deviceModel').annotate(value=Count('id')).order_by()
+        res = {
+            'value': 0,
+            'data': []
+        }
+        data = res['data']
+        tmpDict = {}
+        for ub in ub_qs:
+            deviceSupplier = ub['deviceSupplier']
+            if not tmpDict.__contains__(deviceSupplier):
+                tmpDict[deviceSupplier] = {
+                    'name': deviceSupplier,
+                    'value': 0,
+                    'children': []
+                }
+
+            item = tmpDict[deviceSupplier]
+            item['value'] = item['value'] + ub['value']
+            res['value'] = res['value'] + item['value']
+            model = {
+                'name': ub['deviceModel'],
+                'value': ub['value']
+            }
+            item['children'].append(model)
+
+        for k, v in tmpDict.items():
+            data.append(v)
+
+        print(res)
+        return response.json(0, res)
+
+    def getAreaDeviceType(self, userID, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+        print('区域设备类型统计:')
+        di_qs = Device_Info.objects.values('area', 'Type').annotate(value=Count('UID', distinct=True)).order_by()
+        res = {
+            'quantity': 0,
+            'data': []
+        }
+        data = res['data']
+        tmpDict = {}
+        tmpDict['null'] = {
+            'area': '未知',
+            'quantity': 0,
+            'models': []
+        }
+        for di in di_qs:
+            area = di['area']
+            if area is None or area == '':
+                area = 'null'
+
+            if not tmpDict.__contains__(area):
+                tmpDict[area] = {
+                    'area': area,
+                    'quantity': 0,
+                    'models': []
+                }
+
+            item = tmpDict[area]
+            item['quantity'] = item['quantity'] + di['value']
+            res['quantity'] = res['quantity'] + item['quantity']
+            device_model = None
+            if DEVICE_TYPE.__contains__(di['Type']):
+                device_model = DEVICE_TYPE[di['Type']]
+            else:
+                device_model = DEVICE_TYPE[0]
+            model = {
+                'model': device_model,
+                'quantity': di['value']
+            }
+            item['models'].append(model)
+
+        for k, v in tmpDict.items():
+            data.append(v)
+        return response.json(0, res)
+
+    def getDeviceType(self, userID, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+        # 设备类型统计
+        di_qs = Device_Info.objects.values('Type').annotate(quantity=Count('UID', distinct=True)).order_by()
+
+        # 设备型号统计
+        us_qs = UidSetModel.objects.values('deviceModel').annotate(quantity=Count('id')).order_by()
+
+        res = {
+            'type_data': {
+                'quantity': 0,
+                'data': []
+            },
+            'model_data': {
+                'quantity': 0,
+                'data': []
+            }
+        }
+        type_data = res['type_data']
+        data = type_data['data']
+        quantity = 0
+        for di in di_qs:
+            if DEVICE_TYPE.__contains__(di['Type']):
+                device_model = DEVICE_TYPE[di['Type']]
+            else:
+                device_model = DEVICE_TYPE[0]
+            di['Type'] = device_model
+            quantity += di['quantity']
+            data.append(di)
+        type_data['quantity'] = quantity
+
+        model_data = res['model_data']
+        data = model_data['data']
+        quantity = 0
+        for us in us_qs:
+            data.append(us)
+            quantity += us['quantity']
+        model_data['quantity'] = quantity
+        return response.json(0, res)
+
+    def getAppFrequency(self, userID, request_dict, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+
+        # 当前的年份
+        current_time = int(time.time())
+        localtime = time.localtime(current_time)
+        current_year = localtime.tm_year
+        current_month = localtime.tm_mon
+
+        start_year = end_year = current_year
+        end_month = current_month
+        start_month = 1
+
+        result = []
+        if end_month != 12:
+            start_month = end_month + 1
+            start_year = current_year - 1
+
+        time_struct = [start_year, start_month, 0, 0, 0, 0, 0, 0, 0]
+        key_formal = '{year}{month}'
+        for i in range(12):
+            result.append({
+                'date_time': key_formal.format(year=time_struct[0], month=str(time_struct[1]).zfill(2)),
+                'data': None
+            })
+
+            month = time_struct[1] + 1
+            if month > 12:
+                time_struct[0] = time_struct[0] + 1
+                time_struct[1] = 1
+            else:
+                time_struct[1] = month
+        #
+        afs_qs = {}
+        if start_year == end_year:
+            afs_qs = list(AppFrequencyStatisticsModel.objects.filter(year=start_year, month__gte=start_month, month__lte=end_month).values().order_by('-year', 'month'))
+        else:
+            afs_qs = list(AppFrequencyStatisticsModel.objects.filter(year=start_year, month__gte=start_month).values().order_by('-year', 'month'))
+            tmps_qs = list(AppFrequencyStatisticsModel.objects.filter(year=end_year, month__lte=end_month).values().order_by('-year', 'month'))
+            for tmp in tmps_qs:
+                afs_qs.append(tmp)
+
+        tmp_dict = {}
+
+        for afs in afs_qs:
+            key = key_formal.format(year=afs['year'], month=str(afs['month']).zfill(2))
+            tmp_dict[key] = json.loads(afs['data'])
+
+        for res in result:
+            if tmp_dict.__contains__(res['date_time']):
+                res['data'] = tmp_dict[res['date_time']]
+        print(result)
+
+        return response.json(0, result)
+
+    def getAllAppFrequency(self, userID, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+
+        # 取出请求年份的统计好的数据
+        print('start')
+        time_struct = time.localtime()
+        current_year = time_struct.tm_year
+        start_year = current_year - 5 + 1
+        afs_qs = AppFrequencyYearStatisticsModel.objects.filter(year__gte=start_year, year__lt=current_year).order_by(
+            '-year')
+        if afs_qs.exists():
+            afs_qs = afs_qs.values('id', 'data', 'num', 'year')
+            res = []
+            for afs in afs_qs:
+                res.append({
+                    'year': afs['year'],
+                    'data': json.loads(afs['data'])
+                })
+            return response.json(0, res)
+        else:
+            return response.json(0, [])
+
+    def query_push_by_level(self, userID, request_dict, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+
+        level = request_dict.get('level', None)
+        print(level)
+        if level is None:
+            return response.json(444)
+
+        level = int(level)
+        if level < 0:
+            return response.json(444)
+        elif level < 3:
+            return self.query_push_day_statistics(level, response)
+        else:
+            return response.json(404)
+
+    def query_push_day_statistics(self, level, response):
+        start_time = 0
+
+        gmtime = time.gmtime(int(time.time()) + 28800)
+        current_day = gmtime.tm_mday
+        time_struct = [gmtime.tm_year, gmtime.tm_mon, current_day, 0, 0, 0, 0, 0, 0]
+        current_time = int(time.mktime(tuple(time_struct))) - 28800
+
+        count = 0
+        if level == 0: # 七天
+            start_time = current_time - 6 * 24 * 3600
+            count = 6
+        elif level == 1:
+            start_time = current_time - 13 * 24 * 3600
+            count = 13
+        elif level == 2:
+            start_time = current_time - 29 * 24 * 3600
+            count = 29
+
+        end_time = current_time
+
+        eqx_qs = EquipmentInfoExStatisticsModel.objects.filter(statistics_date__gte=start_time, statistics_date__lte=end_time, date_type=0, push_type=-1).values()
+        data = []
+
+        for i in range(count + 1):
+            data.append({
+                'date_time': int(start_time),
+                'data': None
+            })
+            start_time += (24 * 60 * 60)
+
+        tmp_dict = {}
+        successes = 0
+        failures = 0
+        for eqx in eqx_qs:
+            successes += eqx['number_of_successes']
+            failures += eqx['number_of_failures']
+            tmp_dict[eqx['statistics_date']] = {
+                'number_of_successes': eqx['number_of_successes'],
+                'number_of_failures': eqx['number_of_failures'],
+                'total': (eqx['number_of_successes'] + eqx['number_of_failures'])
+            }
+
+        # 取出当前的推送数据
+        start_time = current_time
+        current_time = int(time.time())
+        eq_qs = Equipment_Info.objects.filter(addTime__gte=start_time, addTime__lte=current_time)
+        print(eq_qs.values())
+        # 0:APNS推送,1:谷歌推送,2:极光推送
+        tmp = {
+            'number_of_successes': 0,
+            'number_of_failures': 0,
+            'total': 0
+        }
+        for eq in eq_qs:
+            if eq.push_server_status == 200:
+                tmp['number_of_successes'] += 1
+                successes += 1
+            else:
+                tmp['number_of_failures'] += 1
+                failures += 1
+            tmp['total'] += 1
+
+        tmp_dict[current_time] = tmp
+
+        for item in data:
+            if tmp_dict.__contains__(item['date_time']):
+                item['data'] = tmp_dict[item['date_time']]
+
+        success_rate = round(successes / (successes + failures), 2)
+        arrival_rate = success_rate
+
+        res = {
+            'data': data,
+            'successes': successes,
+            'failures': failures,
+            'success_rate': success_rate,
+            'arrival_rate': arrival_rate
+        }
+
+        return response.json(0, res)
+
+    # def query_push_month_statistics(self, level, response):
+    #     start_time = 0
+    #     end_time = 0
+    #     localtime = time.localtime()
+    #     current_month = localtime.tm_mon
+    #
+    #     time_struct = [localtime.tm_year, current_month, 1, 0, 0, 0, 0, 0, 0]
+    #     current_time = int(time.mktime(tuple(time_struct)))
+    #     current_time = current_time - time.timezone - 8 * 60 * 60
+    #     count = 0
+    #     start_month = 0
+    #     if level == 3:  # 6个月
+    #         start_month = current_month - 5
+    #         count = 5
+    #     elif level == 4:
+    #         start_month = current_month - 11
+    #         count = 10
+    #
+    #
+    #     return
+
+    def query_failures_push(self, userID, request_dict, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+
+        start_time = request_dict.get('start_time', None)
+        end_time = request_dict.get('end_time', None)
+        page = request_dict.get('page', None)
+        line = request_dict.get('line', None)
+
+        if not start_time or not end_time or not page or not line:
+            return response.json(444)
+
+        start_time = int(start_time)
+        end_time = int(end_time)
+        page = int(page)
+        line = int(line)
+        if page <= 0 or line < 0:
+            return response.json(444, 'page, line')
+
+        eq_qs = Equipment_Info.objects.filter(addTime__gte=start_time, addTime__lte=end_time)\
+            .filter(~Q(push_server_status=200)).values('id', 'devUid', 'devNickName', 'Channel', 'alarm', 'eventType', 'eventTime', 'receiveTime', 'push_server_status', 'userID__username')
+        if eq_qs.exists():
+            count = eq_qs.count()
+            eq_qs = eq_qs[(page-1)*line: page * line]
+            return response.json(0, {'count': count, 'data': list(eq_qs)})
+        else:
+            return response.json(0, {'count': 0, 'data': []})
+
+    def query_push_server_cpu_usage(self, userID, request_dict, response):
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+
+        start_time = request_dict.get('start_time', None)
+        end_time = request_dict.get('end_time', None)
+        tz = request_dict.get('tz', None)
+
+        if start_time is None or end_time is None or tz is None:
+            return response.json(444)
+
+        date = datetime.datetime(2020, 9, 15)
+        start_time = date.fromtimestamp((int(start_time)))
+        end_time = date.fromtimestamp(int(end_time))
+        tz = int(tz)
+
+        cloudwatch = boto3.client('cloudwatch', region_name=AWS_SES_ACCESS_REGION_WEST, aws_access_key_id=AWS_SES_ACCESS_ID,
+                                  aws_secret_access_key=AWS_SES_ACCESS_SECRET)
+        try:
+            result = cloudwatch.get_metric_statistics(Namespace='AWS/EC2', MetricName='CPUUtilization',
+                                                      StartTime=start_time,
+                                                      EndTime=end_time, Period=60,
+                                                      Statistics=['Average'],
+                                                      Dimensions=[
+                                                          {'Name': 'InstanceId', 'Value': 'i-0596e00c9af077027'}])
+            datas = result['Datapoints']
+            datas.sort(key=getCompareKey)
+            result = []
+            for data in datas:
+                tmp = data
+                utcdt = data['Timestamp']
+                time1 = str(utcdt.astimezone(asj_timezone(timedelta(hours=int(-tz)))))
+                tmp['Timestamp'] = time1[0:time1.find('+')]
+                result.append(tmp)
+            return response.json(0, result)
+        except Exception as e:
+            print(repr(e))
+            return response.json(10, 'AWS Server Error')
+
+
+def getCompareKey(item):
+    return item['Timestamp']
 
 @require_http_methods(["GET"])
 def getUserIds(request):
@@ -299,3 +722,4 @@ def search_user_by_content(request):
         sqlDict['count'] = count
         return response.json(0, sqlDict)
     return response.json(0, {'datas': [], 'count': 0})
+

+ 132 - 0
Controller/Alexa.py

@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+@Copyright (C) ansjer cop Video Technology Co.,Ltd.All rights reserved.
+@AUTHOR: ASJRD018
+@NAME: Ansjer
+@software: PyCharm
+@DATE: 2020/8/14 10:13
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: AlexaConnectNum.py
+@Contact: sonalh@foxmail.com
+"""
+from django.views.generic.base import View
+import os
+
+import json
+import math
+import time
+import urllib
+import logging
+import logging
+import requests
+import time
+import datetime
+from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
+from Model.models import AlexaConnectStatisticsModel
+from django.views.generic import TemplateView
+from django.utils.decorators import method_decorator
+from django.views.decorators.csrf import csrf_exempt
+from django.views.generic.base import View
+from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from Service.ModelService import ModelService
+from django.db import connection
+
+rtspServer = "rtsp.zositech.org,3.16.66.144"
+
+# 获取alexa连接数接口
+class AlexaConnectNum(TemplateView):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(AlexaConnectNum, self).dispatch(*args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        response = ResponseObject()
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        #每隔十分钟定时保存每天最高连接数,crontab 在alexa_oauth2_oserver
+        if operation == 'saveConnectNum':
+            today = datetime.date.today()
+            today_start_time = int(time.mktime(time.strptime(str(today), '%Y-%m-%d')))
+            today_end_time = int(time.mktime(time.strptime(str(today), '%Y-%m-%d'))) + 86399
+             #获取当前连接数
+            current_connect_num = self.currentConnect()
+            today_data = AlexaConnectStatisticsModel.objects.\
+                filter(data_time__lte=today_end_time,data_time__gte=today_start_time).values('num','data_time')
+            if today_data.exists():
+                num = list(today_data)[0]['num']
+                if current_connect_num > num:
+                    today_data.update(num=current_connect_num, data_time=time.time())
+            else:
+                today_data.create(num=current_connect_num, data_time=time.time())
+            return response.json(0)
+        return response.json(10006)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        response = ResponseObject()
+        operation = kwargs.get('operation')
+        post_data = request.POST
+        token = post_data.get('token', None)
+        # tko = TokenObject()
+        # newToken = tko.generate( data={'userID': '158943594633713800138000', 'lang': 'cn', 'user': '597471180@qq.com', 'm_code': '123413243214'})
+        # return response.json(0, {'data': newToken})
+        tko = TokenObject(token)
+        response.lang = tko.lang
+        if tko.code != 0:
+            return response.json(tko.code)
+        userID = tko.userID
+        own_permission = ModelService.check_perm(userID=userID, permID=30)
+        if own_permission is not True:
+            return response.json(404)
+
+        #获取当前连接数
+        current_connect_num = self.currentConnect()
+        res = []
+        #最近三十天每天最高连接数
+        if operation == 'thirtyDays':
+            query_num = AlexaConnectStatisticsModel.objects.\
+                extra(select={"data_time": "FROM_UNIXTIME(data_time, '%%m-%%d')"}).\
+                values('num', 'data_time').order_by('-data_time')[:30]
+            res = list(query_num)
+
+        #最近十二个月每月最高连接数
+        if operation == 'years':
+            cursor=connection.cursor()
+            cursor.execute("SELECT FROM_UNIXTIME(data_time,'%Y-%m') as month, max(num) as max_num FROM alexa_statistics GROUP BY month order by month asc LIMIT 12")
+            res_query = cursor.fetchall()
+            for max_num, month in res_query:
+                res.append({'num':month, 'month':max_num})
+
+        res_desc = {'result_code': 0, 'reason': '成功', 'current_num':current_connect_num, 'top_num': res, 'error_code': 0}
+        result_json = json.dumps(res_desc, ensure_ascii=False)
+        return HttpResponse(result_json)
+
+    def currentConnect(self):
+        urls = rtspServer.split(',')
+        httpPrefix = 'http://'
+        postfix = ':10008/api/v1/pushers'
+        current_connect_num = 0
+        for url in urls:
+            apiUrl = httpPrefix + url + postfix
+            try:
+                selectRtsp = requests.get(url=apiUrl, timeout=5)
+                current_connect_num += selectRtsp.json()['total']
+            except Exception as e:
+                continue
+        return current_connect_num
+
+
+
+
+
+
+
+
+
+
+
+

+ 145 - 0
Controller/AppLogController.py

@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+import time
+
+import oss2
+from django.views.generic.base import View
+
+from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET
+from Model.models import AppLogModel
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from Service.CommonService import CommonService
+from Service.ModelService import ModelService
+
+
+class AppLogView(View):
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation', None)
+        return self.validate(request.GET, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation', None)
+        return self.validate(request.POST, operation)
+
+    def validate(self, request_dict, operation):
+        token = request_dict.get('token', None)
+        response = ResponseObject()
+        if token is None:
+            return response.json(444)
+
+        token = TokenObject(token)
+        if token.code != 0:
+            return response.json(token.code)
+
+        if operation == 'getUploadUrl':
+            return self.get_upload_url(token.userID, request_dict, response)
+        elif operation == 'add':
+            return self.do_add(token.userID, request_dict, response)
+        elif operation == 'queryByAdmin':
+            return self.do_query_by_admin(token.userID, request_dict, response)
+        elif operation == 'deleteByAdmin':
+            return self.do_delete_by_admin(token.userID, request_dict, response)
+        elif operation == 'downloadByAdmin':
+            return response.json(404)
+        else:
+            return response.json(414)
+
+    def get_upload_url(self, userID, 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-hongkong.aliyuncs.com', 'statres')
+            name = CommonService.createOrderID()
+            filename = str(name) + '.' + upload_type
+            obj = 'app_log/{userID}/'.format(userID=userID) + filename
+
+            url = bucket.sign_url('PUT', obj, 7200)
+            return response.json(0, {'put_url': url, 'filename': filename})
+        else:
+            return response.json(444)
+
+    def do_add(self, userID, request_dict, response):
+        uid = request_dict.get('uid', None)
+        average_delay = request_dict.get('average_delay', None)
+        status = request_dict.get('status', None)
+        filename = request_dict.get('filename', None)
+
+        if uid is None or average_delay is None or status is None or filename is None:
+            return response.json(444)
+        else:
+            now_time = int(time.time())
+            data = {
+                'uid': uid,
+                'average_delay': average_delay,
+                'status': status,
+                'filename': filename,
+                'add_time': now_time,
+                'user_id': userID,
+            }
+            AppLogModel.objects.create(**data)
+            return response.json(0)
+
+    def do_query_by_admin(self, userID, request_dict, response):
+        own_perm = ModelService.check_perm(userID, 30)
+        if own_perm:
+            page = request_dict.get('page', None)
+            line = request_dict.get('line', None)
+            status = request_dict.get('status', None)
+            uid = request_dict.get('uid', None)
+
+            if page and line:
+                page = int(page)
+                line = int(line)
+                filter_data = {}
+                if status:
+                    filter_data['status'] = status
+                if uid:
+                    filter_data['uid'] = uid
+
+                al_qs = AppLogModel.objects.filter(**filter_data).order_by('-add_time')
+
+                if al_qs.exists():
+                    count = al_qs.count()
+                    start = (page - 1) * line
+                    al_qs = al_qs[start: (start + line)].values()
+
+                    res = []
+                    auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+                    bucket = oss2.Bucket(auth, 'oss-cn-hongkong.aliyuncs.com', 'statres')
+                    for al in al_qs:
+                        filename = al['filename']
+                        obj = 'app_log/' + al['user_id'] + '/' + filename
+                        url = bucket.sign_url('GET', obj, 3600)
+                        al['url'] = url
+                        del al['filename']
+                        res.append(al)
+
+                    return response.json(0, {'datas': res, 'count': count})
+                else:
+                    return response.json(0, {'datas': [], 'count': 0})
+            else:
+                return response.json(444, 'page, line')
+        else:
+            return response.json(404)
+
+    def do_delete_by_admin(self, userID, request_dict, response):
+        own_perm = ModelService.check_perm(userID, 10)
+        if own_perm:
+            id = request_dict.get('id', None)
+            if id:
+                try:
+                    AppLogModel.objects.filter(id=id).delete()
+                except Exception as e:
+                    print(repr(e))
+                    return response.json(500, repr(e))
+                else:
+                    return response.json(0)
+            else:
+                return response.json(444)
+        else:
+            return response.json(404)
+

+ 154 - 4
Controller/CloudVod.py

@@ -128,6 +128,12 @@ class CloudVodView(View):
                 return self.do_pay_status(request_dict, userID)
             elif operation == 'createPayOrder':
                 return self.do_create_pay_order(request_dict, userID, response)
+            # elif operation == 'queryAlipayOrder':
+            #     return self.query_alipay_order(request_dict, userID, response)
+            # elif operation == 'alipayCancel':
+            #     return self.do_alipay_cancel(request_dict, userID, response)
+            # elif operation == 'alipayRefund':
+            #     return self.do_alipay_refund(request_dict, userID, response)
             else:
                 return response.json(414)
 
@@ -157,7 +163,7 @@ class CloudVodView(View):
             print(rank_id)
             UID = order_list[0]['UID']
             channel = order_list[0]['channel']
-            order_qs.update(status=1, updTime=nowTime)
+            order_qs.update(status=1, updTime=nowTime, trade_no=data['trade_no'])
 
             smqs = Store_Meal.objects.filter(id=rank_id).values("day", "bucket_id", "bucket__storeDay")
             bucketId = smqs[0]['bucket_id']
@@ -207,7 +213,7 @@ class CloudVodView(View):
         if not channel or not rank:
             return response.json(444, 'channel,rank')
         smqs = Store_Meal.objects.filter(id=rank). \
-            values("currency", "price", "content", "day", "bucket__storeDay", "bucket__region", "type")
+            values("title", "currency", "price", "content", "day", "bucket__storeDay", "bucket__region", "type")
         if not smqs.exists():
             # 套餐不存在
             return response.json(173)
@@ -236,12 +242,13 @@ class CloudVodView(View):
             order_string = alipay.api_alipay_trade_wap_pay(
                 out_trade_no=orderID,
                 total_amount=price,
-                subject="测试哟",
+                subject=smqs[0]['title'],
                 return_url="{SERVER_DOMAIN_SSL}cloudVod/payOK".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL),
                 notify_url="{SERVER_DOMAIN_SSL}cloudVod/aliPayCallback".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
                 # return_url="http://192.168.136.40/cloudVod/payOK",
                 # notify_url="http://192.168.136.40/cloudVod/aliPayCallback"
             )
+            print(order_string)
         except Exception as e:
             print(repr(e))
             return response.json(10, repr(e))
@@ -675,7 +682,7 @@ class CloudVodView(View):
             if link.rel == "approval_url":
                 approval_url = str(link.href)
                 print("Redirect for approval: %s" % (approval_url))
-                Order_Model.objects.create(orderID=orderID, UID=uid, channel=channel, userID_id=userID, desc=content,
+                Order_Model.objects.create(orderID=orderID, UID=uid, trade_no=payment['id'], channel=channel, userID_id=userID, desc=content,
                                            price=price, currency=currency, addTime=nowTime, updTime=nowTime,
                                            endTime=nowTime + int(day) * 3600 * 24,
                                            rank_id=rank,
@@ -777,6 +784,7 @@ class CloudVodView(View):
         paypalrestsdk.configure(PAYPAL_CRD)
         # ID of the payment. This ID is provided when creating payment.
         payment = paypalrestsdk.Payment.find(paymentId)
+        print(payment)
         payres = payment.execute({"payer_id": PayerID})
         print(payres)
         if not payres:
@@ -1188,6 +1196,148 @@ class CloudVodView(View):
             response.content = falil_pay_content
             return response
 
+    def query_alipay_order(self, request_dict, userID, response):
+        out_trade_no = request_dict.get('out_trade_no', None)
+
+        if out_trade_no is None:
+            return response.json(444)
+
+        try:
+            aliPayObj = AliPayObject()
+            alipay = aliPayObj.conf()
+            result = alipay.api_alipay_trade_query(out_trade_no=out_trade_no)
+            print(result)
+        except Exception as e:
+            print(repr(e))
+            return response.json(10, repr(e))
+        return response.json(0, {'result': result})
+
+    def do_alipay_cancel(self, request_dict, userID, response):
+        out_trade_no = request_dict.get('out_trade_no', None)
+
+        if out_trade_no is None:
+            return response.json(444)
+
+        order_qs = Order_Model.objects.filter(orderID=out_trade_no)
+        if not order_qs.exists():
+            return response.json(800)
+
+        order = order_qs[0]
+
+        # 交易状态:
+        # WAIT_BUYER_PAY(交易创建,等待买家付款)
+        # TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)
+        # TRADE_SUCCESS(交易支付成功)
+        # TRADE_FINISHED(交易结束,不可退款)
+
+        try:
+            aliPayObj = AliPayObject()
+            alipay = aliPayObj.conf()
+            result = alipay.api_alipay_trade_query(out_trade_no=out_trade_no)
+            result = result['result']
+
+            if result['code'] == '100000':
+                trade_status = result['trade_status']
+                if trade_status == 'TRADE_CLOSED' or trade_status == 'WAIT_BUYER_PAY':
+                    order.status = 2
+                    order.updTime = int(time.time())
+                    order.save()
+                    return response.json(0)
+                else:
+                    order.status = 1
+                    order.updTime = int(time.time())
+                    order.save()
+                    return response.json(802)
+            else:
+                return response.json(10, result['sub_msg'])
+
+        except Exception as e:
+            print(repr(e))
+            return response.json(10, repr(e))
+
+    def do_alipay_refund(self, request_dict, userID, response):
+        out_trade_no = request_dict.get('out_trade_no', None)
+        refund_amount = request_dict.get('refund_amount', None)
+        reason = request_dict.get('reason', '正常退款')
+
+        if out_trade_no is None:
+            return response.json(444)
+
+        order_qs = Order_Model.objects.filter(orderID=out_trade_no)
+
+        if not order_qs.exists():
+            return response.json(800)
+
+        order = order_qs[0]
+        if refund_amount > order.price:
+            return response.json(801)
+
+        try:
+            # extra = {
+            #     'refund_currency': order[0].currency
+            # }
+            aliPayObj = AliPayObject()
+            alipay = aliPayObj.conf()
+            result = alipay.api_alipay_trade_refund(refund_amount=refund_amount, out_trade_no=out_trade_no)
+            result = result['result']
+            print(result)
+            if result['code'] == '10000':
+                order.status = 3
+                order.updTime = int(time.time())
+                order.save()
+                return response.json(0)
+            else:
+                return response.json(10, result['sub_msg'])
+
+        except Exception as e:
+            print(repr(e))
+            return response.json(10, repr(e))
+
+    def do_paypal_refund(self, request_dict, userID, response):
+        out_trade_no = request_dict.get('out_trade_no', None)
+        refund_amount = request_dict.get('refund_amount', None)
+
+        order_qs = Order_Model.objects.filter(orderID=out_trade_no, userID__userID=userID)
+
+        if not order_qs.exists():
+            return response.json(800)
+
+        order = order_qs[0]
+
+        refund_amount = float(refund_amount)
+        if order.price < refund_amount:
+            return response.json(801)
+
+        paypalrestsdk.configure(PAYPAL_CRD)
+        payment = paypalrestsdk.Payment.find(order.trade_no)
+        transactions = payment['transactions']
+        transaction = transactions[0]
+        related_resources = transaction['related_resources']
+        if len(related_resources) > 0:
+            related_resource = related_resources[0]
+            sale = related_resource['sale']
+            id = sale['id']
+
+            if sale['state'] == 'completed':
+                paypalSale = paypalrestsdk.Sale.find(id)
+                refund = paypalSale.refund({
+                    'amount': {
+                        'total': refund_amount,
+                        'currency': order.currency
+                    }
+                })
+
+                if refund.success():
+                    return response.json(0)
+                else:
+                    return response.json(10, refund.error)
+            elif sale['state'] == 'refunded':
+                return response.json(804)
+        else:
+            return response.json(804)
+
+
+
 
 def deleteVodHls(request):
     response = ResponseObject()

+ 2 - 2
Controller/DetectController.py

@@ -301,8 +301,8 @@ class DetectControllerView(View):
         if dvqs.exists():
             uid_set_qs = UidSetModel.objects. \
                 filter(uid=uid, uidpushmodel__userID_id=userID)
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
             if uid_set_qs.exists():
                 uid_set_qs.update(interval=int(interval))
             else:

+ 2 - 2
Controller/DeviceManage.py

@@ -102,8 +102,8 @@ class DeviceManage(View):
 
     def delete(self, request_dict, userID, response):
         own_perm = ModelService.check_perm(userID=userID, permID=10)
-        redisObj = RedisObject(db=8)
-        redisObj.del_data(key='uid_qs_' + userID)
+        # redisObj = RedisObject(db=8)
+        # redisObj.del_data(key='uid_qs_' + userID)
         if own_perm is True:
             id = request_dict.get('id', None)
             if id:

+ 4 - 2
Controller/DeviceShare.py

@@ -167,6 +167,8 @@ class DeviceShareView(View):
                     sharerDvqs.primaryMaster = primaryMaster
                     sharerDvqs.data_joined = None
                     sharerDvqs.save()
+                    # redisObj = RedisObject(db=8)
+                    # redisObj.del_data(key='uid_qs_' + userID)
                 except Exception as e:
                     return response.json(10, repr(e))
                 else:
@@ -225,8 +227,8 @@ class DeviceShareView(View):
         id = request_dict.get('id', None)
         if id:
             try:
-                redisObj = RedisObject(db=8)
-                redisObj.del_data(key='uid_qs_' + userID)
+                # redisObj = RedisObject(db=8)
+                # redisObj.del_data(key='uid_qs_' + userID)
                 Device_Info.objects.filter(id=id, primaryUserID=userID).update(isExist=0)
             except Exception as e:
                 return response.json(10, repr(e))

+ 40 - 28
Controller/EquipmentManager.py

@@ -2,6 +2,8 @@ import re
 import time
 import traceback
 import threading
+
+import requests
 import simplejson as json
 from django.utils import timezone
 from Model.models import Device_User, Device_Info, UID_Bucket, UID_Preview, UidSetModel, UidPushModel
@@ -10,11 +12,12 @@ from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
 from Service.ModelService import ModelService
-from Ansjer.config import OSS_STS_ACCESS_SECRET, OSS_STS_ACCESS_KEY
+from Ansjer.config import OSS_STS_ACCESS_SECRET, OSS_STS_ACCESS_KEY, BASE_DIR
 from Object.ETkObject import ETkObject
 import oss2
 from django.http import JsonResponse
 from Object.RedisObject import RedisObject
+import logging
 
 
 #     查询用户设备
@@ -85,8 +88,8 @@ def addNewUserEquipmentInterface(request):
         if dValid:
             return response.json(174)
         else:
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
             UID = deviceData.get('UID', '')
             re_uid = re.compile(r'^[A-Za-z0-9]{20}$')
             if re_uid.match(UID):
@@ -151,8 +154,8 @@ def delUserEquipmentInterface(request):
     # 主用户删除设备全部删除
     try:
         dv_qs = Device_Info.objects.filter(userID_id=userID, id=id)
-        redisObj = RedisObject(db=8)
-        redisObj.del_data(key='uid_qs_' + userID)
+        # redisObj = RedisObject(db=8)
+        # redisObj.del_data(key='uid_qs_' + userID)
         if dv_qs.exists():
             uid = dv_qs[0].UID
             print('删除')
@@ -160,6 +163,7 @@ def delUserEquipmentInterface(request):
             dv_qs.delete()
             asy = threading.Thread(target=ModelService.del_eq_info, args=(userID, uid))
             asy.start()
+
     except Exception as e:
         errorInfo = traceback.format_exc()
         print('删除数据库记录错误: %s' % errorInfo)
@@ -224,8 +228,8 @@ def modifyUserEquipmentInterface(request):
                 }
                 UidSetModel.objects.create(**uid_set_create_dict)
             Device_Info.objects.filter(UID=uid).update(NickName=nickname)
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
         return response.json(0, res)
 
 
@@ -371,13 +375,15 @@ def addInterface(request):
                             'nickname': NickName,
                         }
                         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)
                     userDevice.save()
-                    redisObj = RedisObject(db=8)
-                    redisObj.del_data(key='uid_qs_' + userID)
+                    # redisObj = RedisObject(db=8)
+                    # redisObj.del_data(key='uid_qs_' + userID)
                 except Exception as e:
                     return response.json(10, repr(e))
                 else:
@@ -457,6 +463,7 @@ def admin_addInterface(request):
         return response.json(444)
     token = request_dict.get('token', None)
     deviceContent = request_dict.get('content', None)
+    ipdizhi = request_dict.get('ipdizhi', None)
     username = request_dict.get('username', None)
     if not username:
         return response.json(444, 'username')
@@ -491,13 +498,19 @@ def admin_addInterface(request):
         else:
             UID = deviceData.get('UID', '')
             re_uid = re.compile(r'^[A-Za-z0-9]{20}$')
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
             if re_uid.match(UID):
                 userDevice = Device_Info(id=CommonService.getUserID(getUser=False), userID_id=userID,
                                          **deviceData)
                 userDevice.save()
+                file_path = '/'.join((BASE_DIR, 'static/test.log'))
 
+                file = open(file_path, 'a+')
+                file.write(ipdizhi+"; username:"+username+"; time:"+time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
+                file.write('\n')
+                file.flush()
+                file.close()
                 # is_bind = Device_Info.objects.filter(UID=UID, isShare=False)
                 # # 判断是否有已绑定用户
                 # if not is_bind.exists():
@@ -565,8 +578,8 @@ def admin_modifyInterface(request):
 
     deviceData = json.loads(deviceContent)
     print(deviceData['UID'])
-    redisObj = RedisObject(db=8)
-    redisObj.del_data(key='uid_qs_' + userID)
+    # redisObj = RedisObject(db=8)
+    # redisObj.del_data(key='uid_qs_' + userID)
     dValid = Device_Info.objects.filter(userID_id=userID, UID=deviceData['UID'])
     if dValid.exists():
         dValid_dict = CommonService.qs_to_dict(dValid)
@@ -659,8 +672,8 @@ def deleteInterface(request):
                 # 异步删除推送消息
             asy = threading.Thread(target=ModelService.del_eq_info, args=(userID, uid))
             asy.start()
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
         else:
             return response.json(14)
     except Exception as e:
@@ -915,8 +928,8 @@ def update_uid_set(request):
         userID = tko.userID
         nowTime = int(time.time())
         dvqs = Device_Info.objects.filter(userID_id=userID)
-        redisObj = RedisObject(db=8)
-        redisObj.del_data(key='uid_qs_' + userID)
+        # redisObj = RedisObject(db=8)
+        # redisObj.del_data(key='uid_qs_' + userID)
         if dvqs.exists():
             us_qs = UidSetModel.objects.filter(uid=uid)
             if us_qs.exists():
@@ -957,10 +970,9 @@ def update_device_shadow(request):
         request_dict = request.GET
     else:
         return response.json(444)
-    # etk = request_dict.get('etk', None)
-    # eto = ETkObject(etk)
-    # uid = eto.uid
-    uid = request_dict.get('uid', None)
+    etk = request_dict.get('etk', None)
+    eto = ETkObject(etk)
+    uid = eto.uid
     if uid:
         # 重置按钮
         is_reset = request_dict.get('is_reset', None)
@@ -971,13 +983,13 @@ def update_device_shadow(request):
             di_qs = Device_Info.objects.filter(UID=uid)
             di_qs.update(isExist=2)
             # 清除redis缓存
-            data = di_qs.values()
-            redisObj = RedisObject(db=8)
-            for di in data:
-                key = 'uid_qs_' + di['userID_id']
-                redis_value = redisObj.get_data(key=key)
-                if redis_value is not False:
-                    redisObj.del_data(key)
+            # data = di_qs.values()
+            # redisObj = RedisObject(db=8)
+            # for di in data:
+            #     key = 'uid_qs_' + di['userID_id']
+            #     redis_value = redisObj.get_data(key=key)
+            #     if redis_value is not False:
+            #         redisObj.del_data(key)
 
         ucode = request_dict.get('ucode', None)
         version = request_dict.get('version', None)

+ 5 - 0
Controller/EquipmentManagerV2.py

@@ -86,6 +86,8 @@ class EquipmentManagerV2(View):
                                 'nickname': NickName,
                             }
                             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,
@@ -121,6 +123,9 @@ class EquipmentManagerV2(View):
         page = request_dict.get('page', None)
         line = request_dict.get('line', None)
         NickName = request_dict.get('NickName', None)
+        if not token or not page or not line:
+            return response.json(444)
+
         page = int(page)
         line = int(line)
         uid = request_dict.get('uid', None)

+ 145 - 152
Controller/EquipmentManagerV3.py

@@ -2,6 +2,9 @@ import re
 import threading
 import time
 import traceback
+
+import requests
+
 from Controller.CheckUserData import RandomStr
 import oss2, base64
 from django.db.models import Q
@@ -24,6 +27,7 @@ class EquipmentManagerV3(View):
 
     def post(self, request, *args, **kwargs):
         request.encoding = 'utf-8'
+
         operation = kwargs.get('operation')
         return self.validation(request.POST, request, operation)
 
@@ -89,13 +93,17 @@ class EquipmentManagerV3(View):
                                 'nickname': NickName,
                             }
                             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)
                         userDevice.save()
-                        redisObj = RedisObject(db=8)
-                        redisObj.del_data(key='uid_qs_' + userID)
+                        asy = threading.Thread(target=ModelService.notify_alexa_add, args=(UID, userID, NickName))
+                        asy.start()
+                        # redisObj = RedisObject(db=8)
+                        # redisObj.del_data(key='uid_qs_' + userID)
                     except Exception as e:
                         return response.json(10, repr(e))
                     else:
@@ -133,17 +141,22 @@ class EquipmentManagerV3(View):
         userID = tko.userID
         if userID is None:
             return response.json(309)
+        deviceData = None
+        dev_info_qs = None
         try:
-            deviceData = json.loads(deviceContent)
+            # deviceData = json.loads(deviceContent)
+            deviceData = eval(deviceContent)
             # print(deviceData['View_Password'])
             if deviceData.__contains__('View_Password'):
                 deviceData['View_Password'] = self.decode_pwd(deviceData['View_Password'])
             dev_info_qs = Device_Info.objects.filter(userID_id=userID, id=id)
             dev_info_qs.update(**deviceData)
         except Exception as e:
+            print(e)
             return response.json(177, repr(e))
         else:
-            qs = Device_Info.objects.filter(userID_id=userID, id=id)
+            # qs = Device_Info.objects.filter(userID_id=userID, id=id)
+            qs = dev_info_qs
             res = CommonService.qs_to_dict(qs)
             if qs.exists():
                 uid = qs[0].UID
@@ -151,7 +164,8 @@ class EquipmentManagerV3(View):
                 # 增加设备影子信息修改昵称 start
                 us_qs = UidSetModel.objects.filter(uid=uid)
                 if us_qs.exists():
-                    us_qs.update(nickname=nickname)
+                    if deviceData.__contains__('NickName'):
+                        us_qs.update(nickname=nickname)
                 else:
                     ChannelIndex = qs[0].ChannelIndex
                     nowTime = int(time.time())
@@ -159,14 +173,15 @@ class EquipmentManagerV3(View):
                         'uid': uid,
                         'addTime': nowTime,
                         'updTime': nowTime,
-                        'ip': CommonService.get_ip_address(request),
+                        # 'ip': CommonService.get_ip_address(request),
                         'channel': ChannelIndex,
                         'nickname': nickname,
                     }
                     UidSetModel.objects.create(**uid_set_create_dict)
-                Device_Info.objects.filter(UID=uid).update(NickName=nickname)
-                redisObj = RedisObject(db=8)
-                redisObj.del_data(key='uid_qs_' + userID)
+                di_qs = Device_Info.objects.filter(UID=uid)
+                di_qs.update(NickName=nickname)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
             return response.json(0, res)
 
     # 新查询设备字段
@@ -175,6 +190,9 @@ class EquipmentManagerV3(View):
         page = request_dict.get('page', None)
         line = request_dict.get('line', None)
         NickName = request_dict.get('NickName', None)
+        if not token or not page or not line:
+            return response.json(444)
+
         page = int(page)
         line = int(line)
         uid = request_dict.get('uid', None)
@@ -183,149 +201,122 @@ class EquipmentManagerV3(View):
         if page <= 0:
             return response.json(0)
         if tko.code == 0:
-            redisObj = RedisObject(db=8)
-            redis_value = redisObj.get_data(key='uid_qs_'+userID)
-            result = []
-            if redis_value == False:
-                # print('缓存不存在就开始添加到缓存')
-                userID = tko.userID
-                dvqs = Device_Info.objects.filter(userID_id=userID)
-                # # 过滤已重置的设备
-                dvqs = dvqs.filter(~Q(isExist=2))
-                dvql = dvqs.values('id', 'userID', 'NickName', 'UID', 'View_Account',
-                           'View_Password', 'ChannelIndex', 'Type', 'isShare',
-                           'primaryUserID', 'primaryMaster', 'data_joined',
-                           'version', 'isVod', 'isExist', 'NotificationMode')
-                dvls = CommonService.qs_to_list(dvql)
-                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']
+            userID = tko.userID
+            dvqs = Device_Info.objects.filter(userID_id=userID)
+            # # 过滤已重置的设备
+            dvqs = dvqs.filter(~Q(isExist=2))
+            dvql = dvqs.values('id', 'userID', 'NickName', 'UID', 'View_Account',
+                               'View_Password', 'ChannelIndex', 'Type', 'isShare',
+                               'primaryUserID', 'primaryMaster', 'data_joined',
+                               'version', 'isVod', 'isExist', 'NotificationMode')
+            dvls = CommonService.qs_to_list(dvql)
+            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']
                     }
-                    # 从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
+                    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)
-                # 缓存时间为一个钟
-                redisObj.set_data(key='uid_qs_'+userID, val=data, expire=3600)
-                result = data
-                print('分页')
-                # items=[]
-                # for index, item in enumerate(data):
-                #     if (page - 1) * line <= index:
-                #         if index < page * line:
-                #             item['View_Password']=self.encrypt_pwd(item['View_Password'])
-                #             items.append(item)
-                # return response.json(0, items)
-            else:
-                # print('去缓存找数据')
-                redis_value = redis_value.replace("'", '"')
-                redis_value = redis_value.replace('"isShare": True', '"isShare": true')
-                redis_value = redis_value.replace('"isShare": False', '"isShare": false')
-                redis_value = redis_value.replace('"isDetector": False', '"isDetector": false')
-                redis_value = redis_value.replace('"isDetector": True', '"isDetector": true')
-                redis_value = redis_value.replace('"version": None', '"version": ""')
-                try:
-                    redis_value = json.loads(redis_value)
-                except Exception as e:
-                    print(repr(e))
-                    return response.json(0, {'data': redis_value})
-                result = redis_value
+            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
 
             if NickName:
                 # print('NickName搜索缓存')
@@ -342,7 +333,7 @@ class EquipmentManagerV3(View):
                 for index, item in enumerate(result):
                     if uid == item['UID']:
                         # 加密
-                        item['View_Password'] = self.encrypt_pwd(item['View_Password'])
+                        item['View_Password'] = self.encrypt_pwd(item['View_Password']) 
                         data.append(item)
                         return response.json(0, data)
             items = []
@@ -394,4 +385,6 @@ class EquipmentManagerV3(View):
                 password = password.decode('utf-8')
                 # 去前3位,后3位
                 password = password[3:-3]
-        return password
+        return password
+
+

+ 324 - 0
Controller/FAQController.py

@@ -0,0 +1,324 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+import json
+import os
+import shutil
+import time
+import traceback
+
+from django.http import HttpResponse
+from django.utils.decorators import method_decorator
+from django.views.decorators.csrf import csrf_exempt
+from django.views.generic.base import View
+
+import Ansjer
+from Ansjer.config import BASE_DIR, SERVER_TYPE
+from Ansjer.config_formal import SERVER_DOMAIN
+from Model.models import FAQModel
+from Object.RedisObject import RedisObject
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from var_dump import var_dump
+
+from Service.ModelService import ModelService
+
+
+class FAQUploadView(View):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, request, *args, **kwargs):
+        return super(FAQUploadView, self).dispatch(request, *args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        fileName = request.FILES.get('fileName', None)
+        return self.validate(fileName, request_dict)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        fileName = request.FILES.get('fileName', None)
+        return self.validate(fileName, request_dict)
+
+    def validate(self, fileName, request_dict):
+
+        token = TokenObject(request_dict.get('token', None))
+
+        response = ResponseObject()
+        if token.code != 0:
+            return response.json(token.code)
+
+        own_permission = ModelService.check_perm(userID=token.userID, permID=120)
+        if own_permission is not True:
+            return response.json(404)
+
+        try:
+            redisObject = RedisObject()
+            path = '/'.join((BASE_DIR, 'static/FAQImages/tmp')).replace('\\', '/') + '/'
+            # path = '/'.join((BASE_DIR, 'static/{user}/FAQImages'.format(user=token.userID))).replace('\\', '/') + '/'
+            if not os.path.exists(path):
+                os.makedirs(path)
+
+            # 先从redis中取出token对应的图片信息
+            images = redisObject.get_data(key=token.token)
+            if images is not False:
+                images = json.loads(images)
+                # 判断此次编辑是否已经存在对应的图片
+                if images.__contains__(str(fileName)):
+                    file_name = images[str(fileName)]
+                    index = file_name.find('static/')
+                    filePath = file_name[index:]
+                    if SERVER_TYPE == "Ansjer.formal_settings":
+                        filePath = 'http://www.dvema.com/faq/image/' + filePath
+                    else:
+                        filePath = 'http://test.www.dvema.com/faq/image/' + filePath
+                    # filePath = "http://192.168.136.35:8000/" + 'faq/image/' + filePath
+                    return response.json(0, {'filePath': filePath})
+
+            # redis中没有对应的图片信息
+            tmp_name = str(fileName)
+            suffix = tmp_name[tmp_name.find('.'):]
+            tmp_file_name = int(time.time())
+            tmp_file_name = '{file_name}{suffix}'.format(file_name=tmp_file_name, suffix=suffix)
+
+            file_name = path + str(tmp_file_name)
+            if os.path.exists(file_name):
+                os.remove(file_name)
+
+            destination = open(file_name, 'wb+')
+            for chunk in fileName.chunks():
+                destination.write(chunk)
+            destination.close()
+
+            # 把图片信息保存到redis中
+            images = redisObject.get_data(token.token)
+            if images is False:
+                images = json.dumps({})
+
+            images = json.loads(images)
+            images[tmp_name] = file_name
+            redisObject.set_data(key=token.token, val=json.dumps(images), expire=3600)
+
+        except Exception as e:
+            errorInfo = traceback.format_exc()
+            print('上传文件错误: %s' % errorInfo)
+            return response.json(700, {'details': repr(e)})
+        else:
+            index = file_name.find('static/')
+            filePath = file_name[index:]
+            if SERVER_TYPE == "Ansjer.formal_settings":
+                filePath = 'http://www.dvema.com/faq/image/' + filePath
+            else:
+                filePath = 'http://test.www.dvema.com/faq/image/' + filePath
+            # filePath = "http://192.168.136.35:8000/" + 'faq/image/' + filePath
+            return response.json(0, {'filePath': filePath})
+
+
+class getFAQImage(View):
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        filePath = kwargs.get('filePath', None)
+        filePath.encode(encoding='utf-8', errors='strict')
+        response = ResponseObject()
+        return self.getFile(filePath, response)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'gb2312'
+        filePath = kwargs.get('filePath', None)
+        response = ResponseObject()
+        filePath.encode(encoding='gb2312', errors='strict')
+        return self.getFile(filePath, response)
+
+    def getFile(self, filePath, response):
+        if filePath:
+            pass
+        else:
+            return response.json(800)
+        fullPath = os.path.join(BASE_DIR, filePath).replace('\\', '/')
+
+        var_dump(fullPath)
+        if os.path.isfile(fullPath):
+            try:
+                Imagedata = open(fullPath, 'rb').read()
+            except Exception as e:
+                return response.json(906, repr(e))
+            else:
+                return HttpResponse(Imagedata, content_type="image/jpeg")
+        else:
+            return response.json(907)
+
+
+class FAQView(View):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(FAQView, self).dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        operation = kwargs.get('operation', None)
+        return self.validate(request_dict, operation)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        operation = kwargs.get('operation', None)
+        return self.validate(request_dict, operation)
+
+    def validate(self, request_dict, operation):
+        token = TokenObject(request_dict.get('token', None))
+        response = ResponseObject()
+        if token.code != 0:
+            return response.json(token.code)
+
+        if operation == 'add':
+            return self.do_add(token, request_dict, response)
+        elif operation == 'query':
+            return self.do_query(token.userID, request_dict, response)
+        elif operation == 'update':
+            return self.do_update(token, request_dict, response)
+        elif operation == 'delete':
+            return self.do_delete(token.userID, request_dict, response)
+        else:
+            return response.json(404)
+
+    def do_add(self, token, request_dict, response):
+
+        own_permission = ModelService.check_perm(userID=token.userID, permID=120)
+        if own_permission is not True:
+            return response.json(404)
+
+        title = request_dict.get('title', None)
+        content = request_dict.get('content', None)
+
+        if title and content:
+            try:
+                # 对content中的图片路径进行修改
+                content = str(content)
+                content = content.replace('faq/image/static/FAQImages/tmp', 'faq/image/static/FAQImages')
+
+                # 取出redis中保存的此次上传的图片信息
+                redisObject = RedisObject()
+                images = redisObject.get_data(key=token.token)
+                if images is not False:
+                    images = json.loads(images)
+
+                    # 把图片从临时文件移动到FAQ资源文件夹下
+                    for k, v in images.items():
+                        start_index1 = v.find('tmp/')
+                        start_index2 = start_index1 + 4
+                        new_path = v[0:start_index1] + v[start_index2:]
+                        shutil.move(v, new_path)
+                now_time = int(time.time())
+                FAQModel.objects.create(**{
+                    'title': title,
+                    'content': content,
+                    'add_time': now_time,
+                    'update_time': now_time
+
+                })
+
+                # 删除redis中token对应的信息
+                redisObject.del_data(key=token.token)
+            except Exception as e:
+                print(e)
+                return response.json(174)
+
+            return response.json(0)
+        else:
+            return response.json(444)
+
+    def do_query(self, userID, request_dict, response):
+
+        page = request_dict.get('page', None)
+        line = request_dict.get('line', None)
+        search_key = request_dict.get('search_key', None)
+        if page and line:
+            if search_key:
+                own_permission = ModelService.check_perm(userID=userID, permID=110)
+                if own_permission is not True:
+                    return response.json(404)
+                faq_qs = FAQModel.objects.filter(title__contains=search_key).order_by('-add_time')
+            else:
+                own_permission = ModelService.check_perm(userID=userID, permID=100)
+                if own_permission is not True:
+                    return response.json(404)
+
+                faq_qs = FAQModel.objects.filter().order_by('-add_time')
+
+            if not faq_qs.exists():
+                return response.json(0, {'count': 0, 'data': []})
+            count = faq_qs.count()
+            page = int(page)
+            line = int(line)
+            start = (page - 1) * line
+            end = start + line
+            faq_qs = faq_qs.values()[start:end]
+
+            return response.json(0, {'count': count, 'data': list(faq_qs)})
+        else:
+            return response.json(444)
+
+    def do_update(self, token, request_dict, response):
+        own_permission = ModelService.check_perm(userID=token.userID, permID=130)
+        if own_permission is not True:
+            return response.json(404)
+
+        id = request_dict.get('id', None)
+        title = request_dict.get('title', None)
+        content = request_dict.get('content', None)
+
+        if id:
+            now_time = int(time.time())
+            data = {
+                'update_time': now_time
+            }
+
+            if title:
+                data['title'] = title
+
+            if content:
+                content = str(content)
+                content = content.replace('faq/image/static/FAQImages/tmp', 'faq/image/static/FAQImages')
+
+                # 取出redis中保存的此次上传的图片信息
+                redisObject = RedisObject()
+                images = redisObject.get_data(key=token.token)
+                if images is not False:
+                    images = json.loads(images)
+
+                    # 把图片从临时文件移动到FAQ资源文件夹下
+                    for k, v in images.items():
+                        start_index1 = v.find('tmp/')
+                        start_index2 = start_index1 + 4
+                        new_path = v[0:start_index1] + v[start_index2:]
+                        shutil.move(v, new_path)
+                # 删除redis中token对应的信息
+                redisObject.del_data(key=token.token)
+
+                data['content'] = content
+
+            FAQModel.objects.filter(id=id).update(**data)
+
+            return response.json(0)
+        else:
+            return response.json(444)
+
+    def do_delete(self, userID, request_dict, response):
+
+        own_permission = ModelService.check_perm(userID=userID, permID=140)
+        if own_permission is not True:
+            return response.json(404)
+
+        id = request_dict.get('id', None)
+        if id:
+            try:
+                faq_qs = FAQModel.objects.filter(id=id)
+                faq_qs.delete()
+            except Exception as e:
+                print(e)
+                return response.json(173)
+            else:
+                return response.json(0)
+        else:
+            return response.json(444)

+ 149 - 1
Controller/OrderContrller.py

@@ -12,9 +12,14 @@
 @Contact: chanjunkai@163.com
 """
 import time
+
+import paypalrestsdk
 from django.utils.decorators import method_decorator
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import View
+
+from Ansjer.config_test import PAYPAL_CRD
+from Object.AliPayObject import AliPayObject
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Model.models import Order_Model, Device_Info
@@ -50,7 +55,7 @@ class OrderView(View):
         token = request_dict.get('token', None)
         # 设备主键uid
         tko = TokenObject(token)
-        response.lang = tko.lang
+        response.lang = request_dict.get('language', 'en')
         if tko.code != 0:
             return response.json(tko.code)
         userID = tko.userID
@@ -62,6 +67,14 @@ class OrderView(View):
             return self.do_admin_query(request_dict, userID, response)
         elif operation == 'detail':
             return self.do_detail(request_dict, userID, response)
+        elif operation == 'queryByStatus':
+            return self.do_query_order_by_status(request_dict, userID, response)
+        elif operation == 'orderDetail':
+            return self.do_query_order_detail(request_dict, userID, response)
+        elif operation == 'cancel':
+            return self.do_cancel_order(request_dict, userID, response)
+        elif operation == 'delete':
+            return self.do_delete_order(request_dict, userID, response)
         else:
             return response.json(444, 'error path')
 
@@ -157,3 +170,138 @@ class OrderView(View):
 
         else:
             return response.json(404)
+
+    def do_query_order_by_status(self, request_dict, userID, response):
+        status = request_dict.get('status', None)
+        page = request_dict.get('page', None)
+        line = request_dict.get('line', None)
+
+        if status and page and line:
+            order_qs = None
+            status = int(status)
+            if status == -1: # 获取所有订单
+                order_qs = Order_Model.objects.filter(userID__userID=userID)
+            elif status == 0: # 获取【代付款】订单
+                order_qs = Order_Model.objects.filter(userID__userID=userID, status=0)
+            elif status == 1:
+                order_qs = Order_Model.objects.filter(userID__userID=userID, status=1)
+
+            if order_qs is None or not order_qs.exists():
+                return response.json(0, {'data': [], 'count': 0})
+
+            page = int(page)
+            line = int(line)
+            start = (page - 1) * line
+            end = status + line
+            count = order_qs.count()
+            order_qs = order_qs[start:end].values("orderID", "UID", "channel", "desc", "price",
+                                                  "currency", "addTime", "payType", "rank__day", "rank__price",
+                                                  "status", 'channel', "rank__title", "currency")
+            return response.json(0, {'data': list(order_qs), 'count': count})
+        else:
+            return response.json(444)
+
+    def do_query_order_detail(self, request_dict, userID, response):
+        orderID = request_dict.get('orderID', None)
+
+        if orderID:
+            order_qs = Order_Model.objects.filter(orderID=orderID, userID__userID=userID)
+            if order_qs.exists():
+                print(order_qs)
+                order = order_qs.values("orderID", "UID", "channel", "desc", "price",
+                                        "currency", "addTime", "endTime", "payType",
+                                        "rank__day", "rank__price", "status", 'channel', "rank__title", "currency")[0]
+
+                return response.json(0, {'data': order})
+            else:
+                return response.json(173)
+        else:
+            return response.json(444)
+
+    def do_cancel_order(self, request_dict, userID, response):
+        orderID = request_dict.get('orderID', None)
+
+        if orderID is None:
+            return response.json(444)
+
+        order_qs = Order_Model.objects.filter(orderID=orderID)
+        if not order_qs.exists():
+            return response.json(800)
+
+        order = order_qs[0]
+        if order.status != 0:
+            return response.json(802)
+
+        if order.payType == 1: # 支付宝支付的订单
+            return self.do_cancel_alipay_order(order, response)
+        else:
+            return self.do_cancel_paypal_order(order, response)
+
+    def do_delete_order(self, request_dict, userID, response):
+        orderID = request_dict.get('orderID', None)
+
+        if orderID:
+            Order_Model.objects.filter(orderID=orderID, userID__userID=userID).delete()
+            return response.json(0)
+        else:
+            return response.json(444)
+
+    def do_cancel_alipay_order(self, order, response):
+        # 交易状态:
+        # WAIT_BUYER_PAY(交易创建,等待买家付款)
+        # TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)
+        # TRADE_SUCCESS(交易支付成功)
+        # TRADE_FINISHED(交易结束,不可退款)
+
+        try:
+            aliPayObj = AliPayObject()
+            alipay = aliPayObj.conf()
+            result = alipay.api_alipay_trade_query(out_trade_no=order.orderID)
+            print(result)
+
+            if result['code'] == '100000':
+                trade_status = result['trade_status']
+                if trade_status == 'TRADE_CLOSED' or trade_status == 'WAIT_BUYER_PAY':
+                    order.status = 2
+                    order.updTime = int(time.time())
+                    order.save()
+                    return response.json(0)
+                elif trade_status == 'TRADE_SUCCESS':
+                    order.status = 1
+                    order.updTime = int(time.time())
+                    order.save()
+                    return response.json(802)
+            elif result['code'] == '40004':
+                order.status = 2
+                order.updTime = int(time.time())
+                order.save()
+                return response.json(0)
+            else:
+                return response.json(10, result['sub_msg'])
+
+        except Exception as e:
+            print(repr(e))
+            return response.json(10, repr(e))
+
+    def do_cancel_paypal_order(self, order, response):
+        paypalrestsdk.configure(PAYPAL_CRD)
+        payment = paypalrestsdk.Payment.find(order.trade_no)
+        transactions = payment['transactions']
+        transaction = transactions[0]
+        related_resources = transaction['related_resources']
+        if len(related_resources) > 0:
+            related_resource = related_resources[0]
+            sale = related_resource['sale']
+            if sale['state'] == 'completed':
+                order.status = 1
+            elif sale['state'] == 'refunded':
+                order.status = 3
+
+            order.updTime = int(time.time())
+            order.save()
+            return response.json(802)
+
+        order.status = 2
+        order.updTime = int(time.time())
+        order.save()
+        return response.json(0)

+ 258 - 0
Controller/StatisticsController.py

@@ -0,0 +1,258 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+import json
+import time
+
+from django.db.models import Count
+from django.views.decorators.csrf import csrf_exempt
+
+from Model.models import UserAppFrequencyModel, AppFrequencyStatisticsModel, Device_User, \
+    AppFrequencyYearStatisticsModel, Equipment_Info, EquipmentInfoExStatisticsModel
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+
+
+@csrf_exempt
+def statistcsAppFrequency(request):
+    request.encoding = 'utf-8'
+    response = ResponseObject()
+    if request.method == 'POST':
+        request_dict = request.POST
+    elif request.method == 'GET':
+        request_dict = request.GET
+    else:
+        return response.json(444)
+
+    token = TokenObject(request_dict.get('token', None))
+    if token.code != 0:
+        return response.json(token.code)
+
+    target_year = request_dict.get('year', None)
+    target_month = request_dict.get('month', None)
+
+    localtime = time.localtime()
+    current_month = localtime.tm_mon
+    current_year = localtime.tm_year
+
+    if target_year and target_month:
+        current_year = int(target_year)
+        current_month = int(target_month)
+
+    time_struct = [current_year, 1, 1, 0, 0, 0, 0, 0, 0]
+
+    distance_time = 8 * 60 * 60
+
+    # 该月的开始时间
+    time_struct[1] = current_month
+    start_time = time.mktime(tuple(time_struct))
+    start_time = start_time - time.timezone - distance_time
+
+    # 该月的结束时间
+    time_struct[1] = current_month + 1
+    end_time = time.mktime(tuple(time_struct))
+    end_time = end_time - time.timezone - distance_time
+
+    # 统计该月的数据
+    uaf_qs = UserAppFrequencyModel.objects.filter(data_time__gte=start_time, data_time__lt=end_time) \
+        .values('type').annotate(quantity=Count('id')).order_by()
+
+    afs_qs = AppFrequencyStatisticsModel.objects.filter(year=current_year, month=current_month)
+
+    if afs_qs.exists():
+        afs_qs.update(data=json.dumps(uaf_qs))
+    else:
+        data = {
+            'data': json.dumps(list(uaf_qs)),
+            'month': current_month,
+            'year': current_year
+        }
+        AppFrequencyStatisticsModel.objects.create(**data)
+    return response.json(0)
+
+
+@csrf_exempt
+def statistcsAppFrequencyYear(request):
+    request.encoding = 'utf-8'
+    response = ResponseObject()
+    if request.method == 'POST':
+        request_dict = request.POST
+    elif request.method == 'GET':
+        request_dict = request.GET
+    else:
+        return response.json(444)
+
+    token = TokenObject(request_dict.get('token', None))
+    if token.code != 0:
+        return response.json(token.code)
+
+    year = request_dict.get('year', None)
+
+    localtime = time.localtime()
+
+    current_year = localtime.tm_year
+    if year:
+        current_year = int(year)
+
+    afs_qs = AppFrequencyStatisticsModel.objects.filter(year=current_year).values('data', 'month')
+    # num = Device_User.objects.count()
+    num = 300000
+
+    res = []
+    result = {
+        0: 0,
+        1: 0,
+        2: 0,
+        3: 0,
+        4: 0,
+        5: 0,
+        6: 0
+    }
+    quantity = 0
+    for afs in afs_qs:
+        data = json.loads(afs['data'])
+        for item in data:
+            result[item['type']] += item['quantity']
+            quantity += item['quantity']
+
+    tmps = []
+    for k, v in result.items():
+        tmp = {
+            'type': k,
+            'value': round(v / 12 / num, 3)
+        }
+        tmps.append(tmp)
+    res.append({
+        'year': current_year,
+        'data': tmps
+    })
+    print(res)
+
+    afys_qs = AppFrequencyYearStatisticsModel.objects.filter(year=current_year)
+    #
+    if afys_qs.exists():
+        afys_qs.update(data=json.dumps(res))
+    else:
+        data = {
+            'data': json.dumps(res),
+            'year': current_year,
+            'num': num
+        }
+        AppFrequencyYearStatisticsModel.objects.create(**data)
+    return response.json(0)
+
+
+@csrf_exempt
+def statistcsPushDay(request):
+    request.encoding = 'utf-8'
+    response = ResponseObject()
+    if request.method == 'POST':
+        request_dict = request.POST
+    elif request.method == 'GET':
+        request_dict = request.GET
+    else:
+        return response.json(444)
+
+    token = TokenObject(request_dict.get('token', None))
+    if token.code != 0:
+        return response.json(token.code)
+
+    current_time = int(time.time())
+    count = int((current_time + 8 * 3600) / (24 * 3600))
+    end_time = count * 24 * 3600 - 8 * 3600
+    start_time = end_time - 24 * 3600
+    print(start_time)
+    print(end_time)
+
+    eq_qs = Equipment_Info.objects.filter(addTime__gte=start_time, addTime__lte=end_time)
+    print(eq_qs.values())
+    # 0:APNS推送,1:谷歌推送,2:极光推送
+    now_time = int(time.time())
+    jpush = EquipmentInfoExStatisticsModel(push_type=2, statistics_date=start_time, add_time=now_time, date_type=0)
+    apns = EquipmentInfoExStatisticsModel(push_type=0, statistics_date=start_time, add_time=now_time, date_type=0)
+    gcm = EquipmentInfoExStatisticsModel(push_type=1, statistics_date=start_time, add_time=now_time, date_type=0)
+    total = EquipmentInfoExStatisticsModel(push_type=-1, statistics_date=start_time, add_time=now_time, date_type=0)
+    for eq in eq_qs:
+        if eq.push_type == 0:
+            do_sum(eq, apns)
+        elif eq.push_type == 1:
+            do_sum(eq, gcm)
+        elif eq.push_type == 2:
+            do_sum(eq, jpush)
+        do_sum(eq, total)
+    datas = []
+    datas.append(apns)
+    datas.append(gcm)
+    datas.append(jpush)
+    datas.append(total)
+
+    EquipmentInfoExStatisticsModel.objects.bulk_create(datas)
+    return response.json(0)
+
+
+@csrf_exempt
+def statistcsPushMonth(request):
+    request.encoding = 'utf-8'
+    response = ResponseObject()
+    if request.method == 'POST':
+        request_dict = request.POST
+    elif request.method == 'GET':
+        request_dict = request.GET
+    else:
+        return response.json(444)
+
+    token = TokenObject(request_dict.get('token', None))
+    if token.code != 0:
+        return response.json(token.code)
+
+    gmtime = time.gmtime(int(time.time()) + 28800)
+    current_month = gmtime.tm_mon - 1
+    # print(current_month)
+
+    time_struct = [gmtime.tm_year, current_month, 1, 0, 0, 0, 0, 0, gmtime.tm_isdst]
+    start_time = int(time.mktime(tuple(time_struct))) - 28800
+    # print(start_time)
+
+    time_struct[1] = current_month + 1
+    end_time = int(time.mktime(tuple(time_struct))) - 28800
+    # print(end_time)
+
+    eq_qs = EquipmentInfoExStatisticsModel.objects.filter(statistics_date__gte=start_time, statistics_date__lte=end_time, date_type=0)
+    # 0:APNS推送,1:谷歌推送,2:极光推送
+    now_time = int(time.time())
+    jpush = EquipmentInfoExStatisticsModel(push_type=2, statistics_date=start_time, add_time=now_time, date_type=1)
+    apns = EquipmentInfoExStatisticsModel(push_type=0, statistics_date=start_time, add_time=now_time, date_type=1)
+    gcm = EquipmentInfoExStatisticsModel(push_type=1, statistics_date=start_time, add_time=now_time, date_type=1)
+    total = EquipmentInfoExStatisticsModel(push_type=-1, statistics_date=start_time, add_time=now_time, date_type=1)
+    for eq in eq_qs:
+        if eq.push_type == 0:
+            do_sum_two(eq, apns)
+        elif eq.push_type == 1:
+            do_sum_two(eq, gcm)
+        elif eq.push_type == 2:
+            do_sum_two(eq, jpush)
+        elif eq.push_type == -1:
+            do_sum_two(eq, total)
+    datas = []
+    datas.append(apns)
+    datas.append(gcm)
+    datas.append(jpush)
+    datas.append(total)
+
+    EquipmentInfoExStatisticsModel.objects.bulk_create(datas)
+    return response.json(0)
+
+
+def do_sum(eq: Equipment_Info, target: EquipmentInfoExStatisticsModel):
+    if eq.push_server_status == 200:
+        target.number_of_successes += 1
+    else:
+        target.number_of_failures += 1
+
+    if eq.push_device_status == 1:
+        target.number_of_arrival += 1
+
+
+def do_sum_two(eq: EquipmentInfoExStatisticsModel, target: EquipmentInfoExStatisticsModel):
+    target.number_of_successes += eq.number_of_successes
+    target.number_of_failures += eq.number_of_failures
+    target.number_of_arrival += eq.number_of_arrival

+ 6 - 3
Controller/TestApi.py

@@ -35,6 +35,7 @@ from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 from django.utils.decorators import method_decorator
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic.base import View
+from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
 
 from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, OSS_ROLE_ARN, SERVER_DOMAIN, PAYPAL_CRD, \
     SERVER_DOMAIN_SSL
@@ -76,8 +77,8 @@ class testView(View):
         if operation is None:
             return response.json(444, 'error path')
         elif operation == 'tests':
-            userID  = '158943594633713800138000'
-            return self.do_filter_playlist(request_dict, userID, response)
+             res = make_password(123456)
+             return JsonResponse(status=200, data=res,safe=False)
         elif operation == 'cbu':
             return self.createBucket()
         elif operation == 'vodList':
@@ -92,12 +93,14 @@ class testView(View):
         elif operation == 'eqi_query':
             userID = '158943594633713800138000'
             return self.queryInterface(request_dict, userID, response)
+        elif operation == 'getAlexa':
+            userID = '158943594633713800138000'
+            return self.queryInterface(request_dict, userID, response)
         else:
             return 12344444
 
     def createBucket(self):
 
-
         #查看桶列表
         # url = "https://azvod1.s3-ap-northeast-1.amazonaws.com"
         # session = Session(ACCESS_KEY, SECRET_KEY)

+ 4 - 4
Controller/UIDPreview.py

@@ -79,8 +79,8 @@ class UIDPreview(View):
             bucket = oss2.Bucket(auth, 'oss-cn-hongkong.aliyuncs.com', 'statres')
 
             dvqs = Device_Info.objects.filter(UID=uid, userID_id=userID)
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_'+userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_'+userID)
             upqs = UID_Preview.objects.filter(uid=uid, channel=channel)
             if dvqs.exists():
                 if upqs.exists():
@@ -147,8 +147,8 @@ class UIDPreview(View):
         own_perm = ModelService.check_perm(userID, 20)
         if own_perm is True:
             id = request_dict.get('id')
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
             UID_Preview.objects.filter(id=id).delete()
             return response.json(0)
         else:

+ 85 - 19
Controller/UidSetController.py

@@ -13,6 +13,9 @@
 """
 import time
 import traceback
+
+from django.db.models import Count
+
 from Object.RedisObject import RedisObject
 import simplejson as json
 from django.utils.decorators import method_decorator
@@ -20,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
+    VodHlsModel, Order_Model, OssCrdModel, UidUserModel, UidChannelSetModel, User_Brand
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
@@ -81,9 +84,11 @@ class UidSetView(View):
         elif operation == 'update':
             return self.do_update(request_dict, response)
         elif operation == 'updateSet':
-            return self.do_update_set(request_dict, response)
+            return self.do_update_set(request, request_dict, response)
         elif operation == 'updateChannel':
             return self.do_update_channel_set(request_dict, response)
+        # elif operation == 'test':
+        #     return self.do_test(response)
         else:
             return response.json(444, 'error path')
 
@@ -117,8 +122,8 @@ class UidSetView(View):
         if own_perm is True:
             uid = request_dict.getlist('uid', None)
             id_list = request_dict.get('id_list', None)
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
             # 删除回滚
             with transaction.atomic():  # 上下文格式,可以在python代码的任何位置使用
                 val = 1
@@ -194,16 +199,16 @@ class UidSetView(View):
                     else:
                         val = val + 1
                         print('UidUserModel表没有数据')
-                #有后台管理 设备配置表UidSetModel ---uid --本身,
-                #有后台管理 设备关联用户推送表Equipment_Info --devUid --独立没有儿子的,
-                #有后台管理             设备预览图表UID_Preview ---uid---孤立,
-                #有后台管理 设备关联套餐表UID_Bucket ---uid---孤立,
-                #有后台管理            云存回放信息表VodHlsModel ---uid---孤立,
-                #有后台管理 订单信息表Order_Model --UID----独立没有儿子的,
-                #有后台管理 用户设备信息表(最多信息量的表)Device_Info ---UID---孤立,
+                # 有后台管理 设备配置表UidSetModel ---uid --本身,
+                # 有后台管理 设备关联用户推送表Equipment_Info --devUid --独立没有儿子的,
+                # 有后台管理             设备预览图表UID_Preview ---uid---孤立,
+                # 有后台管理 设备关联套餐表UID_Bucket ---uid---孤立,
+                # 有后台管理            云存回放信息表VodHlsModel ---uid---孤立,
+                # 有后台管理 订单信息表Order_Model --UID----独立没有儿子的,
+                # 有后台管理 用户设备信息表(最多信息量的表)Device_Info ---UID---孤立,
                 #           设备证书OssCrdModel ---uid---孤立
                 # 有后台管理 设备ap表 UidUserModel
-                #设备绑定UidPushModel---关联表---设备配置表UidSetModel---配置表的详情有显示
+                # 设备绑定UidPushModel---关联表---设备配置表UidSetModel---配置表的详情有显示
 
                 # raise DatabaseError     #测试用,检测是否能捕捉错误
                 if val == 9:
@@ -317,11 +322,11 @@ class UidSetView(View):
             errorInfo = traceback.format_exc()
             return response.json(500, {'details': errorInfo})
 
-    def do_update_set(self, request_dict, response):
+    def do_update_set(self, request, request_dict, response):
         uid = request_dict.get('uid', None)
         deviceContent = request_dict.get('content', None)
         token = request_dict.get('token', None)
-        print(deviceContent)
+        # print(deviceContent)
         if not deviceContent or not uid:
             return response.json(444, 'content,uid')
         tko = TokenObject(token)
@@ -332,11 +337,32 @@ class UidSetView(View):
         if userID is None:
             return response.json(309)
         try:
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
             deviceData = json.loads(deviceContent)
             uid_set_qs = UidSetModel.objects.filter(uid=uid)
-            uid_set_qs.update(**deviceData)
+            if not uid_set_qs.exists():
+                # 由于uid_set表和device_info表设备数量不一致,所以添加以下逻辑把device_info表中的相关信息保存到uid_set表
+                di_qs = Device_Info.objects.filter(UID=uid, userID=userID)
+                if di_qs.exists():
+                    di = di_qs[0]
+                    nowTime = int(time.time())
+                    uid_set_create_dict = {
+                        'uid': di.UID,
+                        'addTime': nowTime,
+                        'updTime': nowTime,
+                        'ip': CommonService.get_ip_address(request),
+                        'channel': di.ChannelIndex,
+                        'nickname': di.NickName,
+                    }
+                    for k, v in deviceData.items():
+                        uid_set_create_dict[k] = v
+                    UidSetModel.objects.create(**uid_set_create_dict)
+                else:
+                    return response.json(177)
+            else:
+                uid_set_qs.update(**deviceData)
+            print('update success')
         except Exception as e:
             return response.json(177, repr(e))
         else:
@@ -362,8 +388,8 @@ class UidSetView(View):
         if channel < 1:
             return response.json(444, 'channel')
         try:
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
             deviceData = json.loads(channelContent)
             uid_channel_set_qs = UidChannelSetModel.objects.filter(uid__uid=uid, channel=channel)
             if not uid_channel_set_qs.exists():
@@ -383,3 +409,43 @@ class UidSetView(View):
             return response.json(177, 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()
+    #     for di in di_qs:
+    #         print(di)
+    #
+    #     # 设备总数量
+    #     count = Device_Info.objects.values('UID').distinct().count()
+    #     print('设备总数量:' + str(count))
+    #
+    #     # 设备型号统计
+    #     print('设备型号统计:')
+    #     us_qs = UidSetModel.objects.values('deviceModel').annotate(c=Count('id')).order_by()
+    #     for us in us_qs:
+    #         print(us)
+    #
+    #     # 手机品牌类型统计
+    #     print('手机品牌类型统计:')
+    #     ub_qs = User_Brand.objects.values('deviceSupplier').annotate(c=Count('id')).order_by()
+    #     for ub in ub_qs:
+    #         print(ub)
+    #
+    #     # 手机型号统计
+    #     print('手机型号统计:')
+    #     ub_qs = User_Brand.objects.values('deviceSupplier', 'deviceModel').annotate(c=Count('id')).order_by()
+    #     for ub in ub_qs:
+    #         print(ub)
+    #
+    #     # 区域统计
+    #     print('区域统计:')
+    #     di_qs = Device_Info.objects.values('area').annotate(c=Count('UID', distinct=True)).order_by()
+    #     for di in di_qs:
+    #         print(di)
+    #
+    #     # 区域设备类型统计
+    #     print('区域设备类型统计:')
+    #     di_qs = Device_Info.objects.values('area', 'Type').annotate(c=Count('UID', distinct=True)).order_by()
+    #     for di in di_qs:
+    #         print(di)
+    #     return response.json(0)

+ 6 - 6
Controller/UidUser.py

@@ -133,8 +133,8 @@ def queryInterface(request):
 
     if tko.code == 0:
         userID = tko.userID
-        redisObj = RedisObject(db=8)
-        redisObj.del_data(key='uid_qs_' + userID)
+        # redisObj = RedisObject(db=8)
+        # redisObj.del_data(key='uid_qs_' + userID)
         uid_user_qs = UidUserModel.objects.filter(userID_id=userID)
         if is_ap:
             is_ap = int(is_ap)
@@ -258,8 +258,8 @@ def deleteInterface(request):
         response.lang = tko.lang
         if tko.code == 0:
             userID = tko.userID
-            redisObj = RedisObject(db=8)
-            redisObj.del_data(key='uid_qs_' + userID)
+            # redisObj = RedisObject(db=8)
+            # redisObj.del_data(key='uid_qs_' + userID)
             uid_user_qs = UidUserModel.objects.filter(userID_id=userID, id=id)
             if uid_user_qs.exists():
                 uid_user_qs.delete()
@@ -481,8 +481,8 @@ def v3queryInterface(request):
         return response.json(0)
     if tko.code == 0:
         userID = tko.userID
-        redisObj = RedisObject(db=8)
-        redisObj.del_data(key='uid_qs_' + userID)
+        # redisObj = RedisObject(db=8)
+        # redisObj.del_data(key='uid_qs_' + userID)
         uid_user_qs = UidUserModel.objects.filter(userID_id=userID)
         if is_ap:
             is_ap = int(is_ap)

+ 88 - 0
Controller/UserBrandControllerV2.py

@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+from django.utils.decorators import method_decorator
+from django.views.decorators.csrf import csrf_exempt
+from django.views.generic.base import View
+
+from Model.models import User_Brand, Device_User
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+
+
+class UserBrandV2(View):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(UserBrandV2, self).dispatch(*args, **kwargs)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        request_dict = request.GET
+        return self.validate(request_dict, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        request_dict = request.POST
+        return self.validate(request_dict, operation)
+
+    def validate(self, request_dict, operation):
+        token = request_dict.get('token', None)
+
+        response = ResponseObject()
+        token = TokenObject(token)
+
+        if token.code != 0:
+            return response.json(token.code)
+
+        if operation == 'add':
+            return self.do_add(token.userID, request_dict, response)
+        elif operation == 'query':
+            return self.do_query(token.userID, request_dict, response)
+        else:
+            return response.json(404)
+
+    def do_add(self, userID, request_dict, response):
+        deviceSupplier = request_dict.get('deviceSupplier', None)
+        deviceModel = request_dict.get('deviceModel', None)
+        osType = request_dict.get('osType', None)
+        osVersion = request_dict.get('osVersion', None)
+
+        if userID and deviceSupplier and deviceModel and osType and osVersion:
+            ub_qs = User_Brand.objects.filter(userID=userID)
+            if ub_qs.exists():
+                update = {
+                    'deviceSupplier': deviceSupplier,
+                    'deviceModel': deviceModel,
+                    'osType': osType,
+                    'osVersion': osVersion
+                }
+                ub_qs.update(**update)
+                return response.json(0)
+            else:
+                user = Device_User.objects.filter(userID=userID)
+                if not user.exists():
+                    return response.json(104)
+                data = {
+                    'userID': user[0],
+                    'deviceSupplier': deviceSupplier,
+                    'deviceModel': deviceModel,
+                    'osType': osType,
+                    'osVersion': osVersion
+                }
+                User_Brand.objects.create(**data)
+                return response.json(0)
+        else:
+            return response.json(444)
+
+    def do_query(self, userID, request_dict, response):
+
+        if not userID:
+            return response.json(444)
+        else:
+            ub_qs = User_Brand.objects.filter(userID=userID)
+            data = None
+            if ub_qs.exists():
+                data = ub_qs.values('id', 'deviceSupplier', 'deviceModel', 'osType', 'osVersion')[0]
+
+            return response.json(0, {'data': data})

+ 556 - 38
Controller/UserController.py

@@ -14,6 +14,9 @@
 import datetime
 import traceback
 import time
+
+import jwt
+import simplejson
 import simplejson as json
 import requests
 from django.contrib.auth.hashers import make_password, check_password  # 对密码加密模块
@@ -23,11 +26,13 @@ from django.utils.decorators import method_decorator
 from django.utils.timezone import utc
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
+from jwt.algorithms import RSAAlgorithm
 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
+from Model.models import Device_User, Role, UidPushModel, UserOauth2Model, UserExModel, Device_Info, UidSetModel, \
+    UserAppFrequencyModel
 from Object.AWS.SesClassObject import SesClassObject
 from Object.AliSmsObject import AliSmsObject
 from Object.RedisObject import RedisObject
@@ -50,7 +55,7 @@ class authCodeView(TemplateView):
 
     @method_decorator(csrf_exempt)
     def dispatch(self, *args, **kwargs):
-		# testtest11111111111111
+        # testtest11111111111111
         return super(authCodeView, self).dispatch(*args, **kwargs)
 
     @ratelimit(key='ip', rate='2/m')
@@ -440,7 +445,6 @@ class v3ChangePwdView(TemplateView):
             return response.json(177)
 
 
-
 class ForgetPwdView(TemplateView):
     '''
     忘记密码
@@ -972,7 +976,6 @@ class v2registerView(TemplateView):
             return self.do_login(email_qs, response)
 
 
-
 # 验证码注册v3
 class v3registerView(TemplateView):
     @method_decorator(csrf_exempt)
@@ -1148,7 +1151,6 @@ class v3registerView(TemplateView):
             return self.do_login(email_qs, response)
 
 
-
 # 重置密码
 # 忘记密码获取验证码v2
 class v2forgetPwdCodeView(TemplateView):
@@ -1414,7 +1416,6 @@ class v2resetPwdByCodeView(TemplateView):
         return response.json(0, res)
 
 
-
 # 忘记密码v3
 class v3resetPwdByCodeView(TemplateView):
     @method_decorator(csrf_exempt)
@@ -1572,7 +1573,6 @@ class v3resetPwdByCodeView(TemplateView):
         return response.json(0, res)
 
 
-
 # 登录
 class v2LoginView(TemplateView):
     @method_decorator(csrf_exempt)  # @csrf_exempt
@@ -1672,7 +1672,7 @@ class v2LoginView(TemplateView):
 class v3LoginView(TemplateView):
     @method_decorator(csrf_exempt)  # @csrf_exempt
     def dispatch(self, *args, **kwargs):
-        #chong 
+        # chong
         return super(v3LoginView, self).dispatch(*args, **kwargs)
 
     @ratelimit(key='ip', rate='5/m')
@@ -1714,13 +1714,13 @@ class v3LoginView(TemplateView):
                     password = password.decode('utf-8')
                     # 截去第一位,最后一位
                     password = password[1:-1]
-                if i==2:
+                if i == 2:
                     # 第2次先解密
                     password = base64.b64decode(password)
                     password = password.decode('utf-8')
                     # 去前2位,后2位
                     password = password[2:-2]
-                if i==3:
+                if i == 3:
                     # 第3次先解密
                     password = base64.b64decode(password)
                     password = password.decode('utf-8')
@@ -1758,13 +1758,18 @@ class v3LoginView(TemplateView):
         # users = user_qs.values('role__rid', 'role__roleName', 'userID', 'role', 'NickName', 'username', 'userEmail',
         #                        'phone', 'password', 'userIconPath', 'user_isValid', 'is_active')[0]
         users = user_qs.values('role__rid', 'role__roleName', 'userID', 'NickName', 'username', 'userEmail',
-                               'phone', 'password', 'userIconPath')[0]
+                               'phone', 'password', 'userIconPath', 'fingerprint_enable', 'fingerprint_key')[0]
         if not check_password(password, users['password']):
             return response.json(111)
         userID = users['userID']
         tko = TokenObject()
         res = tko.generate(
             data={'userID': userID, 'lang': response.lang, 'user': users['username'], 'm_code': '123413243214'})
+        oauth_qs = UserOauth2Model.objects.filter(userID__userID=userID)
+        auth_type = 0
+        if oauth_qs.exists():
+            auth_type = oauth_qs[0].authType
+
         if tko.code == 0:
             now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
             user_qs.update(last_login=now_time, language=response.lang)
@@ -1783,6 +1788,9 @@ class v3LoginView(TemplateView):
             res['username'] = users['username'] if users['username'] is not None else ''
             res['userEmail'] = users['userEmail'] if users['userEmail'] is not None else ''
             res['phone'] = users['phone'] if users['phone'] is not None else ''
+            # res['fingerprint_enable'] = users['fingerprint_enable']
+            # res['fingerprint_key'] = CommonService.encode_data(content=users['fingerprint_key'], start=2)
+            res['authType'] = auth_type
             return response.json(0, res)
         else:
             return response.json(tko.code)
@@ -1819,7 +1827,7 @@ class InitInfoView(View):
         tz = request_dict.get('tz', '0')
         lang = request_dict.get('lang', '')  # 语言区域
         now_time = int(time.time())
-        if all([token_val, push_type, appBundleId,userID]):
+        if all([token_val, push_type, appBundleId, userID]):
             push_type = int(push_type)
             if push_type == 0:
                 if appBundleId not in APNS_CONFIG.keys():
@@ -1926,7 +1934,7 @@ class verifyAuthcode(TemplateView):
         return response.json(0)
 
 
-# 获取验证码
+# 微信登录
 class wxAuthSignView(TemplateView):
 
     def post(self, request, *args, **kwargs):
@@ -1958,6 +1966,7 @@ class wxAuthSignView(TemplateView):
                 'com.ansjer.loocamccloud': {'appid': 'wx9f6d6ce63f85b367',
                                             'secret': 'fe495884cd24637f1ae516c7f53d1b97', },
                 'com.ansjer.zccloud': {'appid': 'wx2a9f5ef9baf2760f', 'secret': '5d38c7079676463149ffea593c58f2ed'},
+                'com.ansjer.customizede': {'appid': 'wx2a9f5ef9baf2760f', 'secret': '5d38c7079676463149ffea593c58f2ed'},
                 # ios
                 'com.ansjer.zccloud_ab': {'appid': 'wx2a9f5ef9baf2760f', 'secret': '5d38c7079676463149ffea593c58f2ed'},
                 # android
@@ -2031,6 +2040,12 @@ class wxAuthSignView(TemplateView):
         res['userEmail'] = user_list[0]["userEmail"] if user_list[0]["userEmail"] is not None else ''
         res['phone'] = user_list[0]["phone"] if user_list[0]["phone"] is not None else ''
         print(res)
+        # 添加用户登录类型
+        oauth_qs = UserOauth2Model.objects.filter(userID__userID=userID)
+        auth_type = 0
+        if oauth_qs.exists():
+            auth_type = oauth_qs[0].authType
+        res['authType'] = auth_type
         user_qs.update(last_login=now_time, online=True)
         return response.json(0, res)
 
@@ -2100,9 +2115,11 @@ class wxPerfectView(TemplateView):
                     'com.ansjer.loocamccloud': {'appid': 'wx9f6d6ce63f85b367',
                                                 'secret': 'fe495884cd24637f1ae516c7f53d1b97', },
                     'com.ansjer.zccloud': {'appid': 'wx2a9f5ef9baf2760f', 'secret': '5d38c7079676463149ffea593c58f2ed'},
+                    'com.ansjer.customizede': {'appid':'wx2a9f5ef9baf2760f', 'secret': '5d38c7079676463149ffea593c58f2ed'},
                     # android
                     'com.ansjer.zccloud_ab': {'appid': 'wx2a9f5ef9baf2760f',
                                               'secret': '5d38c7079676463149ffea593c58f2ed'},
+
                 }
                 if appBundleID in app_config.keys():
                     appid = app_config[appBundleID]['appid']
@@ -2410,13 +2427,17 @@ class OauthPerfectView(TemplateView):
         password = request_dict.get('password', None)
         authcode = request_dict.get('authcode', None)
         token = request_dict.get('token', None)
-        print(token)
         token = request_dict.get('token')
         tko = TokenObject(token)
         if password is None or authcode is None:
             return response.json(444, 'password,authcode')
-        authcode = authcode.strip()
-        password = password.strip()
+        authcode = CommonService.decode_data(authcode.strip())
+        if authcode is None:
+            return response.json(444, 'password,authcode')
+
+        password = CommonService.decode_data(password.strip())
+        if password is None:
+            return response.json(444, 'password,authcode')
         if phone is not None:
             phone = phone.strip()
             return self.do_phone(tko, phone, authcode, password, response)
@@ -2580,11 +2601,12 @@ class alexaAuthView(TemplateView):
         #     uid_arr.append({'uid': uid_q['UID'], 'nick': uid_q['NickName'], 'password': uid_q['View_Password']})
         res = {
             'userID': userID,
-        #     'uid_arr': uid_arr
+            #     'uid_arr': uid_arr
         }
-        return response.json(0,res)
+        return response.json(0, res)
         # return response.json(0, res)
 
+
 class alexaUidView(TemplateView):
     def post(self, request, *args, **kwargs):
         request.encoding = 'utf-8'
@@ -2609,11 +2631,11 @@ class alexaUidView(TemplateView):
             uid_list = []
             for uid_q in uid_qs:
                 uid_list.append(uid_q['UID'])
-                uid_arr.append({'uid': uid_q['UID'], 'nick': uid_q['NickName'], 'password': uid_q['View_Password'],})
+                uid_arr.append({'uid': uid_q['UID'], 'nick': uid_q['NickName'], 'password': uid_q['View_Password'], })
             res = {
                 'uid_arr': uid_arr
             }
-            return response.json(0,res)
+            return response.json(0, res)
         else:
             return response.json(107)
 
@@ -2626,16 +2648,16 @@ class alexaUidView(TemplateView):
             uid_dict = {}
             uid_list = []
             for uid_q in uid_qs:
-                #追加
+                # 追加
                 uid_list.append(uid_q['UID'])
-                #给uid_q['UID']赋值
+                # 给uid_q['UID']赋值
                 uid_dict[uid_q['UID']] = {'nick': uid_q['NickName'], 'password': uid_q['View_Password']}
             us_qs = UidSetModel.objects.filter(uid__in=uid_list, is_alexa=2).values('uid', 'region_alexa')
             # uid,password,region的列表
             uid_arr = []
             for us in us_qs:
                 uid = us['uid']
-                #设备alexa区域
+                # 设备alexa区域
                 region_alexa = us['region_alexa']
                 if region_alexa == '':
                     region_alexa = "en"
@@ -2650,6 +2672,7 @@ class alexaUidView(TemplateView):
         else:
             return response.json(107)
 
+
 # 登出
 class V2LogoutView(TemplateView):
     @method_decorator(csrf_exempt)
@@ -2811,14 +2834,14 @@ class Image_Code_RegisterView(TemplateView):
         request_dict = request.GET
         return self.validates(request_dict)
 
-    #检测验证码,并注册
-    def validates(self,request_dict):
+    # 检测验证码,并注册
+    def validates(self, request_dict):
         print("__________request_dict:%s" % request_dict)
-        userEmail = request_dict.get('userEmail',None)
-        password = request_dict.get('userPwd',None)
-        lang = request_dict.get('lang',None)
-        #前端传进来的uuid
-        imageCodeId = request_dict.get('imageCodeId',None)
+        userEmail = request_dict.get('userEmail', None)
+        password = request_dict.get('userPwd', None)
+        lang = request_dict.get('lang', None)
+        # 前端传进来的uuid
+        imageCodeId = request_dict.get('imageCodeId', None)
         # 页面输入的验证码
         response = ResponseObject(lang)
         valid_code = request_dict.get('id_v_code', None)
@@ -2839,7 +2862,7 @@ class Image_Code_RegisterView(TemplateView):
                     password = base64.b64decode(password)
                     password = password.decode('utf-8')
                     password = password[3:-3]
-            print("password%s"%password)
+            print("password%s" % password)
         except Exception as e:
             return response.json(111)
         try:
@@ -2856,7 +2879,7 @@ class Image_Code_RegisterView(TemplateView):
                     valid_code = base64.b64decode(valid_code)
                     valid_code = valid_code.decode('utf-8')
                     valid_code = valid_code[3:-3]
-            print("valid_code:%s"%valid_code)
+            print("valid_code:%s" % valid_code)
         except Exception as e:
             return response.json(121)
         if not userEmail:
@@ -2870,16 +2893,16 @@ class Image_Code_RegisterView(TemplateView):
             emailValid = Device_User.objects.filter(userEmail=userEmail)
             if emailValid:
                 return response.json(103)
-        #根据uuid拼接的key
-        image_code_key = "image_code_%s" %imageCodeId
-        #判断验证码是否过期
+        # 根据uuid拼接的key
+        image_code_key = "image_code_%s" % imageCodeId
+        # 判断验证码是否过期
         if image_code_key is None:
             return response.json(120)
         redisObj = RedisObject(db=6)
-        #redis里面的验证码
+        # redis里面的验证码
         redis_image_code = redisObj.get_data(key=image_code_key)
-        #验证用户输入的验证码和redis中的验证码
-        if valid_code.lower()!=redis_image_code.lower():
+        # 验证用户输入的验证码和redis中的验证码
+        if redis_image_code is False or valid_code.lower() != redis_image_code.lower():
             return response.json(121)
         # 删除redis中的图片验证码,防止用户使用同一个图片验证码验证多次
         redisObj.del_data(key=image_code_key)
@@ -2930,8 +2953,503 @@ class Image_Code_RegisterView(TemplateView):
         return response.json(0, res)
 
 
+class UserAppFrequencyView(TemplateView):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(UserAppFrequencyView, self).dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        operation = kwargs.get('operation')
+        return self.validates(request_dict, operation)
 
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        operation = kwargs.get('operation')
+        return self.validates(request_dict, operation)
 
+    def validates(self, request_dict, operation):
+        token = request_dict.get('token', None)
+        response = ResponseObject()
 
+        token = TokenObject(token)
+        if token.code != 0:
+            return response.json(token.code)
 
+        if operation == 'refresh':
+            return self.do_refresh(request_dict, token.userID, response)
+        else:
+            return response.json(404)
+
+    def do_refresh(self, request_dict, userID, response):
+        type = request_dict.get('type', None)
+        month = request_dict.get('month', None)
+        if not type or not month:
+            return response.json(444, 'type')
+        else:
+            type = int(type)
+            now_time = int(time.time())
+            month = int(month)
+            uaf_qs = UserAppFrequencyModel.objects.filter(user__userID=userID)
+
+            if not uaf_qs.exists():
+                user = Device_User.objects.filter(userID=userID)[0]
+                data = {
+                    'user': user,
+                    'type': type,
+                    'data_time': month,
+                    'add_time': now_time,
+                    'update_time': now_time,
+                }
+                UserAppFrequencyModel.objects.create(**data)
+                return response.json(0)
+            else:
+                updateMonth = time.strftime('%m', time.localtime(month))
+                uaf = uaf_qs.values('id', 'type', 'data_time')[0]
+                dbMonth = time.strftime('%m', time.localtime(int(uaf['data_time'])))
+                print('update month is ' + updateMonth)
+                print('db month is ' + dbMonth)
+                if updateMonth == dbMonth:
+                    UserAppFrequencyModel.objects.filter(id=uaf['id']).update(type=type)
+                    return response.json(0)
+                elif updateMonth > dbMonth:
+                    user = Device_User.objects.filter(userID=userID)[0]
+                    data = {
+                        'user': user,
+                        'type': type,
+                        'data_time': month,
+                        'add_time': now_time,
+                        'update_time': now_time,
+                    }
+                    UserAppFrequencyModel.objects.create(**data)
+                    return response.json(0)
+                else:
+                    return response.json(444, 'month')
+
+
+class loginCodeView(View):
+    @method_decorator(csrf_exempt)  # @csrf_exempt
+    def dispatch(self, *args, **kwargs):
+        return super(loginCodeView, self).dispatch(*args, **kwargs)
+
+    @ratelimit(key='ip', rate='2/m')
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.POST.get('lang', None)
+        if not lang:
+            lang = request.POST.get('language', None)
+        response = ResponseObject(lang)
+        request_dict = request.POST
+        phone = request_dict.get('phone', None)
+        if phone is not None:
+            was_limited = getattr(request, 'limited', False)
+            if was_limited is True:
+                return response.json(5)
+        return self.validate(request_dict, response)
+
+    @ratelimit(key='ip', rate='2/m')
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.GET.get('lang', None)
+        if not lang:
+            lang = request.GET.get('language', None)
+        response = ResponseObject(lang)
+        was_limited = getattr(request, 'limited', False)
+        if was_limited is True:
+            return response.json(5)
+        request_dict = request.GET
+        return self.validate(request_dict, response)
 
+    def validate(self, request_dict, response):
+        phone = request_dict.get('phone', None)
+        country_code = request_dict.get('country_code', None)
+        sign_name = request_dict.get('sign_name', None)
+
+        if phone and sign_name:
+            du_qs = Device_User.objects.filter(Q(phone=phone) | Q(username=phone))
+            if not du_qs.exists():
+                return response.json(104)
+            else:
+                redisObject = RedisObject()
+                login_code_key = '{phone}_login_code'.format(phone=phone)
+                login_code = redisObject.get_data(key=login_code_key)
+                login_code_ttl = redisObject.get_ttl(key=login_code_key)
+                if login_code_ttl > 240 and login_code:
+                    return response.json(90)
+                login_code = RandomStr(6, True)
+                aliSms = AliSmsObject()
+                if sign_name == 'zosi':
+                    sign_sms = '周视'
+                else:
+                    sign_sms = 'Ansjer'
+
+                res = aliSms.send_code_sms(phone=phone, code=login_code, sign_name=sign_sms, temp_msg='SMS_151675022')
+
+                if res['Code'] == 'OK':
+                    if redisObject.set_data(key=login_code_key, val=login_code, expire=300) is not True:
+                        return response.json(48)
+                    return response.json(0)
+                else:
+                    return response.json(10, res['Message'])
+        else:
+            return response.json(444)
+
+
+class v3LoginByCodeView(View):
+    @method_decorator(csrf_exempt)  # @csrf_exempt
+    def dispatch(self, *args, **kwargs):
+        return super(v3LoginByCodeView, self).dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.POST.get('lang', None)
+        if not lang:
+            lang = request.POST.get('language', None)
+        response = ResponseObject(lang)
+        request_dict = request.POST
+        phone = request_dict.get('phone', None)
+        if phone is not None:
+            was_limited = getattr(request, 'limited', False)
+            if was_limited is True:
+                return response.json(5)
+        return self.validate(request_dict, response)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.GET.get('lang', None)
+        if not lang:
+            lang = request.GET.get('language', None)
+        response = ResponseObject(lang)
+        was_limited = getattr(request, 'limited', False)
+        if was_limited is True:
+            return response.json(5)
+        request_dict = request.GET
+        return self.validate(request_dict, response)
+
+    def validate(self, request_dict, response):
+        phone = request_dict.get('phone', None)
+        code = request_dict.get('code', None)
+
+        if phone and code:
+            redisObject = RedisObject()
+            login_code_key = '{phone}_login_code'.format(phone=phone)
+            login_code = redisObject.get_data(key=login_code_key)
+
+            if login_code is not False:
+                print(code)
+                code = CommonService.decode_data(code)
+                print(code)
+                if login_code == code:
+                    if response.lang is None:
+                        response.lang = 'en'
+                    return self.do_phone_login(phone, response)
+                else:
+                    return response.json(121)
+            else:
+                return response.json(120)
+
+    def do_phone_login(self, phone, response):
+        user_qs = Device_User.objects.filter(Q(phone=phone) | Q(username=phone), is_active=True,
+                                             user_isValid=True)
+        return self.valid_login(user_qs, response)
+
+    def valid_login(self, user_qs, response):
+        if not user_qs.exists():
+            return response.json(104)
+        # users = user_qs.values('role__rid', 'role__roleName', 'userID', 'role', 'NickName', 'username', 'userEmail',
+        #                        'phone', 'password', 'userIconPath', 'user_isValid', 'is_active')[0]
+        users = user_qs.values('role__rid', 'role__roleName', 'userID', 'NickName', 'username', 'userEmail',
+                               'phone', 'password', 'userIconPath')[0]
+
+        userID = users['userID']
+        tko = TokenObject()
+        res = tko.generate(
+            data={'userID': userID, 'lang': response.lang, 'user': users['username'],
+                  'm_code': '123413243214'})
+        # 添加用户登录类型
+        oauth_qs = UserOauth2Model.objects.filter(userID__userID=userID)
+        auth_type = 0
+        if oauth_qs.exists():
+            auth_type = oauth_qs[0].authType
+
+        if tko.code == 0:
+            now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
+            user_qs.update(last_login=now_time, language=response.lang)
+            res['rid'] = users['role__rid']
+            res['roleName'] = users['role__roleName']
+            res['permList'] = ModelService.own_permission(userID)
+            res['userID'] = userID
+            # 昵称,邮箱,电话,刷新,头像
+            userIconPath = str(users['userIconPath'])
+            if userIconPath and userIconPath.find('static/') != -1:
+                userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
+                res['userIconUrl'] = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
+            else:
+                res['userIconUrl'] = ''
+            res['NickName'] = users['NickName'] if users['NickName'] is not None else ''
+            res['username'] = users['username'] if users['username'] is not None else ''
+            res['userEmail'] = users['userEmail'] if users['userEmail'] is not None else ''
+            res['phone'] = users['phone'] if users['phone'] is not None else ''
+            res['authType'] = auth_type
+            return response.json(0, res)
+        else:
+            return response.json(tko.code)
+
+
+class v3LoginByFingerprintView(View):
+    @method_decorator(csrf_exempt)  # @csrf_exempt
+    def dispatch(self, *args, **kwargs):
+        return super(v3LoginByFingerprintView, self).dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.POST.get('lang', None)
+        if not lang:
+            lang = request.POST.get('language', None)
+        response = ResponseObject(lang)
+        request_dict = request.POST
+
+        was_limited = getattr(request, 'limited', False)
+        if was_limited is True:
+            return response.json(5)
+        return self.validate(request_dict, response)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        lang = request.GET.get('lang', None)
+        if not lang:
+            lang = request.GET.get('language', None)
+        response = ResponseObject(lang)
+        was_limited = getattr(request, 'limited', False)
+        if was_limited is True:
+            return response.json(5)
+        request_dict = request.GET
+        return self.validate(request_dict, response)
+
+    def validate(self, request_dict, response):
+        password = request_dict.get("password", None)
+
+        if password:
+            password = CommonService.decode_data(password)
+            if password is None:
+                return response.json(444)
+            else:
+                user_qs = Device_User.objects.filter(username=password, is_active=True, user_isValid=True)
+                if not user_qs.exists():
+                    return response.json(104)
+                else:
+                    users = user_qs.values('role__rid', 'role__roleName', 'userID', 'NickName', 'username', 'userEmail',
+                               'phone', 'password', 'userIconPath', 'fingerprint_enable', 'fingerprint_key')[0]
+                    if users['fingerprint_enable'] == 0:
+                        return response.json(112)
+                    else:
+                        userID = users['userID']
+                        tko = TokenObject()
+                        res = tko.generate(
+                            data={'userID': userID, 'lang': response.lang, 'user': users['username'],
+                                  'm_code': '123413243214'})
+                        if tko.code == 0:
+                            now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
+                            user_qs.update(last_login=now_time, language=response.lang)
+                            res['rid'] = users['role__rid']
+                            res['roleName'] = users['role__roleName']
+                            res['permList'] = ModelService.own_permission(userID)
+                            res['userID'] = userID
+                            # 昵称,邮箱,电话,刷新,头像
+                            userIconPath = str(users['userIconPath'])
+                            if userIconPath and userIconPath.find('static/') != -1:
+                                userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
+                                res['userIconUrl'] = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
+                            else:
+                                res['userIconUrl'] = ''
+                            res['NickName'] = users['NickName'] if users['NickName'] is not None else ''
+                            res['username'] = users['username'] if users['username'] is not None else ''
+                            res['userEmail'] = users['userEmail'] if users['userEmail'] is not None else ''
+                            res['phone'] = users['phone'] if users['phone'] is not None else ''
+                            res['fingerprint_enable'] = users['fingerprint_enable']
+                            res['fingerprint_key'] = CommonService.encode_data(content=users['fingerprint_key'], start=2)
+                            return response.json(0, res)
+                        else:
+                            return response.json(tko.code)
+        else:
+            return response.json(444)
+
+
+class v3SetFingerprintView(View):
+    @method_decorator(csrf_exempt)
+    def dispatch(self, *args, **kwargs):
+        return super(v3SetFingerprintView, self).dispatch(*args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        return self.validate(request_dict)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        return self.validate(request_dict)
+
+    def validate(self, request_dict):
+        lang = request_dict.get('lang', None)
+        token = request_dict.get('token', None)
+        fingerprint_enable = request_dict.get('fingerprint_enable', None)
+        fingerprint_key = request_dict.get('fingerprint_key', None)
+
+        response = ResponseObject()
+
+        token = TokenObject(token)
+        if token.code != 0:
+            return response.json(token.code)
+
+        if not lang:
+            return response.json(444, 'lang')
+
+        response.lang = lang
+
+        data = {}
+
+        if fingerprint_enable:
+            data['fingerprint_enable'] = int(fingerprint_enable)
+
+        if fingerprint_key:
+            data['fingerprint_key'] = CommonService.decode_data(fingerprint_key, end=3)
+
+        if len(data) > 0:
+            Device_User.objects.filter(userID=token.userID).update(**data)
+        return response.json(0)
+
+
+class AppleAuthLogin(View):
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.POST
+        return self.validate(request_dict)
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        request_dict = request.GET
+        return self.validate(request_dict)
+
+    def validate(self, request_dict):
+        lang = request_dict.get('lang', None)
+        identity_token = request_dict.get('identity_token', None)
+        app_bundle_id = request_dict.get('app_bundle_id', None)  # 包名
+
+        response = ResponseObject(lang)
+        identity_token = CommonService.decode_data(identity_token)
+        # print(identity_token)
+        if identity_token:
+            key_url = 'https://appleid.apple.com/auth/keys'
+            key_response = requests.get(key_url).json()
+            # print(key_response)
+            head = jwt.get_unverified_header(identity_token)
+            # print(head)
+            token_key = head['kid']
+            key_object = None
+            alg = None
+            for pub_key in key_response['keys']:
+                if pub_key['kid'] == token_key:
+                    key_object = simplejson.dumps(pub_key)
+                    key_object = RSAAlgorithm.from_jwk(key_object)
+                    alg = pub_key['alg']
+                    break
+
+            if key_object:
+                try:
+                    claims = jwt.decode(identity_token, key=key_object, verify=True, algorithms=[alg], audience=app_bundle_id)
+                    unionID = claims['sub']
+                    print(claims)
+                    user_extend_qs = UserOauth2Model.objects.filter(unionID=unionID, authType=2)
+                    if user_extend_qs.exists():
+                        # 如果用户绑定过则直接登录
+                        userID = user_extend_qs[0].userID_id
+                        print(userID)
+                        user_qs = Device_User.objects.filter(userID=userID)
+                        return self.do_login(user_qs, response)
+                    else:
+                        # 如果用户为绑定过则创建用户并进行登录返回token
+                        userID = CommonService.getUserID(getUser=False)
+                        if claims.__contains__('email'):
+                            nickname = claims['email']
+                        else:
+                            nickname = 'apple_{num}'.format(num=CommonService.RandomStr(6, False))
+                        return self.do_register(userID, nickname, response, app_bundle_id, unionID)
+
+                except Exception as e:
+                    print(e)
+                    return response.json(717)
+            else:
+                return response.json(444)
+        else:
+            return response.json(444)
+
+    # 登录
+    def do_login(self, user_qs, response):
+        now_time = datetime.datetime.utcnow().replace(tzinfo=utc).astimezone(utc)
+        userID = user_qs[0].userID
+        print('userID' + userID)
+        tko = TokenObject()
+        user_list = user_qs.values("NickName", "userIconUrl", "userIconPath", "username", "userEmail", "phone")
+        res = tko.generate(data={'userID': userID, 'lang': response.lang, 'user': user_list[0]["username"]})
+        # 增加角色
+        user_qs[0].role.add(Role.objects.get(rid=1))
+        role_dict = ModelService.own_role(userID=userID)
+        res['rid'] = role_dict['rid']
+        res['roleName'] = role_dict['roleName']
+        res['permList'] = ModelService.own_permission(userID)
+        res['userID'] = userID
+        # 昵称,邮箱,电话,刷新,头像
+        userIconPath = str(user_list[0]["userIconPath"])
+        if userIconPath and userIconPath.find('static/') != -1:
+            userIconPath = userIconPath.replace('static/', '').replace('\\', '/')
+            res['userIconUrl'] = SERVER_DOMAIN + 'account/getAvatar/' + userIconPath
+        else:
+            res['userIconUrl'] = ''
+        res['NickName'] = user_list[0]["NickName"] if user_list[0]["NickName"] is not None else ''
+        res['username'] = user_list[0]["username"] if user_list[0]["username"] is not None else ''
+        res['userEmail'] = user_list[0]["userEmail"] if user_list[0]["userEmail"] is not None else ''
+        res['phone'] = user_list[0]["phone"] if user_list[0]["phone"] is not None else ''
+        print(res)
+        # 添加用户登录类型
+        oauth_qs = UserOauth2Model.objects.filter(userID__userID=userID)
+        auth_type = 0
+        if oauth_qs.exists():
+            auth_type = oauth_qs[0].authType
+        res['authType'] = auth_type
+        user_qs.update(last_login=now_time, online=True)
+        return response.json(0, res)
+
+    def do_register(self, userID, nickname, response, appBundleId, unionID):
+        data_valid = DataValid()
+        if data_valid.name_validate(userID) is not True:
+            return response.json(105)
+        try:
+            users = Device_User.objects.create(
+                username=userID,
+                NickName=nickname,
+                password=make_password('123456'),
+                userID=userID,
+                is_active=True,
+                user_isValid=True,
+            )
+
+            nowTime = int(time.time())
+            UserOauth2Model.objects.create(
+                addTime=nowTime,
+                updTime=nowTime,
+                userID_id=users.userID,
+                authType=2,
+                unionID=unionID
+            )
+        except Exception as e:
+            errorInfo = traceback.format_exc()
+            print(errorInfo)
+            return response.json(424, repr(e))
+        else:
+            user_qs = Device_User.objects.filter(Q(userID=userID))
+            print('---')
+            print(user_qs)
+            return self.do_login(user_qs, response)

+ 2 - 0
Controller/shareUserPermission.py

@@ -260,6 +260,8 @@ class shareUserEquipmentView(View):
                             res = {'error_UID': UID, 'Sharing': len(querysetList)}
                         else:
                             res = {'Sharing': len(querysetList)}
+                # redisObj = RedisObject(db=8)
+                # redisObj.del_data(key='uid_qs_' + GuestID)
                 return response.json(0, res)
 
 

+ 2 - 0
Model/models.py

@@ -147,6 +147,8 @@ class Device_User(AbstractBaseUser):
     language = models.CharField(blank=True, max_length=16, default='en', verbose_name=u'语言地区')
     # 手机注册增加字段
     phone = models.CharField(max_length=16, verbose_name=u'手机号', default='', blank=True)
+    fingerprint_enable = models.SmallIntegerField(default=0, verbose_name=u'是否开启了指纹登录') # 0:未开启,1:已开启
+    fingerprint_key = models.CharField(max_length=128, default='', verbose_name=u'客户端用于解码的密钥等信息')
     objects = UserManager()
 
     USERNAME_FIELD = 'userID'  # 必须有一个唯一标识

+ 10 - 0
Object/ResponseObject.py

@@ -31,6 +31,7 @@ class ResponseObject(object):
             109: 'The password not conform to the rules!',
             110: 'user doesn\'t activated',
             111: 'Error password',
+            112: 'Fingerprint login is not turned on',
             119: 'The qr code has expired',
             120: 'The code has expired',
             121: 'The verification code is wrong!',
@@ -55,6 +56,10 @@ class ResponseObject(object):
             712: 'Area needs to be consistent',
             713: 'Storage rules cannot be changed during the validity period',
             717: 'Authorization expires',
+            800: 'Order does not exist',
+            801: 'The refund amount cannot be greater than the order price',
+            802: 'The order has been completed and cannot be cancelled',
+            804: 'Refund, please do not repeat the operation',
             900: 'There is no information about this version!',
             901: 'Getting URL failure!',
             902: 'No update!',
@@ -93,6 +98,7 @@ class ResponseObject(object):
             109: '密码格式不符合!',
             110: '用户未激活!',
             111: '密码不正确!',
+            112: '未开通指纹登录',
             119: '二维码过期',
             120: '验证码过期',
             121: '验证码错了!',
@@ -117,6 +123,10 @@ class ResponseObject(object):
             712: '区域不一致',
             713: '有效期内不可更改存储规则',
             717: '授权过期',
+            800: '订单不存在',
+            801: '退款金额不能大于订单价格',
+            802: '订单已完成,不能撤销',
+            804: '订单已退款,请勿重复操作',
             900: '版本信息不存在',
             901: '获取链接失败',
             902: '无更新!',

+ 41 - 1
Service/CommonService.py

@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+import base64
 import datetime
 import time
 from pathlib import Path
@@ -12,6 +13,9 @@ from Ansjer.config import BASE_DIR, UNICODE_ASCII_CHARACTER_SET
 
 
 # 复用性且公用较高封装代码在这
+from Controller.CheckUserData import RandomStr
+
+
 class CommonService:
     # 添加模糊搜索
     @staticmethod
@@ -221,4 +225,40 @@ class CommonService:
         random = Random()
         for index in range(randomlength):
             str += characterSet[random.randint(0, length)]
-        return str
+        return str
+
+    @staticmethod
+    def decode_data(content, start=1, end=4):
+        try:
+            for i in range(start, end):
+                if i == 1:
+                    content = base64.b64decode(content)
+                    content = content.decode('utf-8')
+                    content = content[1:-1]
+                if i == 2:
+                    content = base64.b64decode(content)
+                    content = content.decode('utf-8')
+                    content = content[2:-2]
+                if i == 3:
+                    content = base64.b64decode(content)
+                    content = content.decode('utf-8')
+                    content = content[3:-3]
+
+            return content
+        except Exception as e:
+            print(e)
+            return None
+
+    @staticmethod
+    def encode_data(content, start=1, end=4):
+        for i in range(start, end):
+            if i == 1:
+                content = RandomStr(3, False)+content+RandomStr(3, False)
+                content = base64.b64encode(str(content).encode("utf-8")).decode('utf8')
+            if i == 2:
+                content = RandomStr(2, False)+str(content)+RandomStr(2, False)
+                content = base64.b64encode(str(content).encode("utf-8")).decode('utf8')
+            if i == 3:
+                content = RandomStr(1, False)+str(content)+RandomStr(1, False)
+                content = base64.b64encode(str(content).encode("utf-8")).decode('utf8')
+        return content

+ 28 - 0
Service/ModelService.py

@@ -1,3 +1,5 @@
+import requests
+
 from Model.models import *
 from Service.CommonService import CommonService
 import json
@@ -138,6 +140,7 @@ class ModelService:
 
     @staticmethod
     def del_eq_info(userID, uid):
+        notify_alexa_delete(userID, uid)
         ei_qs = Equipment_Info.objects.filter(userID_id=userID, devUid=uid)
         ei_qs.delete()
         # ei_count = ei_qs.count()
@@ -151,3 +154,28 @@ class ModelService:
     def get_uid_list(userID):
         uid_list = Device_Info.objects.filter(userID_id=userID).values_list('UID', flat=True)
         return list(uid_list)
+
+    @staticmethod
+    def notify_alexa_add(uid, userID, nickname):
+        url = 'https://www.zositech.xyz/deviceStatus/addOrupdate'
+        data = {
+            'UID': uid,
+            'userID': userID,
+            'uid_nick': nickname
+        }
+        try:
+            requests.post(url, data=data, timeout=5)
+        except Exception as e:
+            print(repr(e))
+
+
+def notify_alexa_delete(userID, UID):
+    url = 'https://www.zositech.xyz/deviceStatus/delete'
+    data = {
+        'userID': userID,
+        'UID': UID
+    }
+    try:
+        requests.post(url=url, data=data, timeout=5)
+    except Exception as e:
+        print(repr(e))

+ 1 - 0
Service/TemplateService.py

@@ -78,6 +78,7 @@ class TemplateService:
             'v3/account/register',
             'v3/account/changePwd',
             'v3/account/resetPwdByCode',
+            'account/appFrequency',
         ]
         return apiList