ソースを参照

Merge branch 'dev' of http://192.168.136.99:3000/servers/ASJServer into dev

 Conflicts:
	Ansjer/urls.py
	Controller/CloudStorage.py
	Controller/DeviceConfirmRegion.py
	Controller/PcInfo.py
	Controller/PctestController.py
	Controller/ShadowController.py
	Controller/TestApi.py
	Model/models.py
lang 4 年 前
コミット
a6b185c313

+ 23 - 0
Ansjer/file/wechatpay/apiclient_cert.pem

@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID7DCCAtSgAwIBAgIUfF0ljlOH7y//Ggpp9FV3bvBumSwwDQYJKoZIhvcNAQEL
+BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
+FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
+Q0EwHhcNMjEwNzMwMDc1ODU5WhcNMjYwNzI5MDc1ODU5WjB+MRMwEQYDVQQDDAox
+NTA4MjA5NzQxMRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xKjAoBgNVBAsM
+IeePoOa1t+WuieWjq+S9s+eUteWtkOaciemZkOWFrOWPuDELMAkGA1UEBgwCQ04x
+ETAPBgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAy/yNuCQI8pg92b9ptotcNyrHun37o7pJN7dzxVzGXwf2DdDJfrAHsen34m6c
+dNF8foEr8k2gCAdPuHsOU7iPtmyblRXpGJj1MC1kFton4X0zd/+TykcEtfK6o9u3
+KZY1yttt6QEAlFVI+5AzsUHK5Cz0LbH/61udDQyywxqbV0bEHGoxVDq4PmsbL83v
+Y/KE+40tONGRrMvP3DzBhT1afJe8hYFTdCYGGF9hZgQHDn6pmvroicT+32BBqqYz
+tjPIU73SLs+kHB+Fj7D+GhloSJRLfASVsrAfuAsbFQHc+JVmF0RhSjZRoo4oyMmw
+FuWz6adBAGXOgNh8BX5bhkQN9QIDAQABo4GBMH8wCQYDVR0TBAIwADALBgNVHQ8E
+BAMCBPAwZQYDVR0fBF4wXDBaoFigVoZUaHR0cDovL2V2Y2EuaXRydXMuY29tLmNu
+L3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0
+NkMwMUMzRThFQkQyMA0GCSqGSIb3DQEBCwUAA4IBAQCKOhM/GTDLL6pkAmrRdwW0
+gPQAih237SHN8UaXVF/shMLcnC4TQtb74b7T7q93ZANjvJJpkCwBRFvYdTPZZLPG
+Y2+KmwIaekAMNyjE8EXU9Y+IQhAdGyLhWiZk+hYK7qwfhjVfqNa/vgu6GAf+mgad
+gaGdxJHY7F2u2tycwetOPd+fD0PTUWqLvZyL04HFrmtHmuZOxYnGvF8scNDRpDAN
+cgRzZ0oFDa/J1QdZTpY/7HAtp3i+gjlqwypVYujI/oLbpYBzB1Zwf5WX6Qt6Ok66
+m1dJWhCkgB0mAyAys6atlCcLTxAksRIFGuIjoBOqOABsi3X5xFau99PH8bshybKU
+-----END CERTIFICATE-----

+ 28 - 0
Ansjer/file/wechatpay/apiclient_key.pem

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDL/I24JAjymD3Z
+v2m2i1w3Kse6ffujukk3t3PFXMZfB/YN0Ml+sAex6ffibpx00Xx+gSvyTaAIB0+4
+ew5TuI+2bJuVFekYmPUwLWQW2ifhfTN3/5PKRwS18rqj27cpljXK223pAQCUVUj7
+kDOxQcrkLPQtsf/rW50NDLLDGptXRsQcajFUOrg+axsvze9j8oT7jS040ZGsy8/c
+PMGFPVp8l7yFgVN0JgYYX2FmBAcOfqma+uiJxP7fYEGqpjO2M8hTvdIuz6QcH4WP
+sP4aGWhIlEt8BJWysB+4CxsVAdz4lWYXRGFKNlGijijIybAW5bPpp0EAZc6A2HwF
+fluGRA31AgMBAAECggEAN2/8yAWrFNtBO/NkdILtXeTXgRyKDhYrnePSp9mt49fT
+DDApArAudzDB+JzdEnZ4Yh0S53gnPOdXyChRXXl0PTzJD7xzrAat5BkB8Z/6ZLLV
+ERC5hqjEY/qCtNOatMeo+OenuEJYePewrQWkttDNpjN9bQnKJpmwVgKUdqe9ffs2
+MK15/ZeXUMPXb4U8IER7qr8muVABydxUzefx9F0OBTogbMSQ6q9UZw1cunD91T2H
+lJaQ4erSdLqEj0WEhf6FJ/rWJjfKA7MYYxTKM0YpODr4hf4R2Qds3iHJDIp9Y3Rp
+AlskQaWXEzoJVfYNCglMmTkrlGDSQlr3juaidkjphQKBgQDuY3swj5aUA5ui5S+y
+aFqwDu4OxZC9cVotFii5FuVGQIoylGRvkswPjYYXqZAHKpW+l2muiOJOZ9t8v7D8
+uZKjei5WT6DapnbXOqGbikNEsmnX56jiwB2oAnD41SHzK7jiXEP3rSK2OsXrEQjL
+NqeXAGHYetO7Xip0Tyu9WMUKSwKBgQDbDnG3lEC5TYWh1soq6JVCh9NJY/bOT/eO
+IWimTRlOV1S754auVjOV5FMwlgJN2MtP2qxxSjxjAInEVN9XgYIumh4XofuZ0esk
+IcnfWTpMXzbuT/KpkyjIjN+jwt0cjXbgHClwZpcYtoufGIlija2uuB5JlTeZ3eL/
+E2ovQuggvwKBgDzgarUb9fgWc8hFfsiwnXgYV/KtwSifqceZwQyDLEmkcaY4/uz/
+L91I5tVkF8O8vEDPqc1IZ4JeQ064JRpkyW215d9ktk8f83lDH8H4rPT+Gsln/1jo
+dqpQ9UiWJPVUVQJ5TWISdKrUl3ZQA07hxippjpMZyrguc+j/zsurv6XBAoGBAKYb
+rd+na+0X+91dIrCm7YgltvJP+zc3LGF6tABnNmlRj89tIZPRigx/txWAqv6dBo7n
+IxxFTsVEAzP9p96TNkRgWbFSA5gAtm4PsSTMZIjFKsJLnZc5IBPzvyJPAZxFKX+H
+22SAZtM2mWlrEcLJ7Iow08a4gBENULRb5IkyExPBAoGAQ1BwOxsg4XeKt8aXPLnB
+3Crw4XZAj3rGDSHxXFWXFe4+gwycQ9mGCls4MZyKLoGoiADKNau+DaJ4CGETkpBn
+F8hZ8l4F76RQpH2X+Qhn2hEL0dreeWcpAzC2NLHuthV5bR0EhGNgXwd8NjDC0CXU
+VaSntDOpcfQSRgvp/kjPE64=
+-----END PRIVATE KEY-----

+ 0 - 2
Ansjer/urls.py

@@ -336,6 +336,4 @@ urlpatterns = [
 
     re_path('(?P<path>.*)', LogManager.errorPath),
 
-
-
 ]

+ 50 - 6
Controller/CloudStorage.py

@@ -108,6 +108,8 @@ class CloudStorageView(View):
             return self.do_vod_msg_end(request_dict)
         elif operation == 'vodMsgNotice':  # 云存操作系统消息
             return self.do_vod_msg_Notice(request_dict)
+        elif operation == 'doRefund':  # 退款
+            return self.do_refund(request_dict, response)
 
         else:
             token = request_dict.get('token', None)
@@ -533,7 +535,7 @@ class CloudStorageView(View):
     <meta http-equiv="content-type" content="text/html;charset=utf-8">
     <!-- viewport的<meta>标签,这个标签可以修改在大部分的移动设备上面的显示,为了确保适当的绘制和触屏缩放。-->
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <link rel="shortcut icon" href="https://test.dvema.com/web/images/favicon.ico" type="image/x-icon"  charset="utf-8"/>  
+    <link rel="shortcut icon" href="https://test.zositechc.cn/web/images/favicon.ico" type="image/x-icon"  charset="utf-8"/>  
     <title>Trading particulars</title>
     <style>
     	.title_head{
@@ -576,7 +578,7 @@ class CloudStorageView(View):
 	<div class="title_head">Trading particulars</div>
     <div class="content">
     	<p >
-    		<img src="https://test.dvema.com/web/images/failed.jpg" class="content_img">
+    		<img src="https://test.zositechc.cn/web/images/failed.jpg" class="content_img">
     		<br />
     		Payment failure
     	</p>
@@ -632,7 +634,7 @@ class CloudStorageView(View):
     <meta http-equiv="content-type" content="text/html;charset=utf-8">
     <!-- viewport的<meta>标签,这个标签可以修改在大部分的移动设备上面的显示,为了确保适当的绘制和触屏缩放。-->
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <link rel="shortcut icon" href="https://test.dvema.com/web/images/favicon.ico" type="image/x-icon" charset="utf-8">  
+    <link rel="shortcut icon" href="https://test.zositechc.cn/web/images/favicon.ico" type="image/x-icon" charset="utf-8">  
     <title>''' + showtitle + '''</title>
     <style>
             .title_head{
@@ -678,7 +680,7 @@ class CloudStorageView(View):
         
     <div class="content">
             <p>
-					<img src="https://test.dvema.com/web/images/success.png" class="content_img">
+					<img src="https://test.zositechc.cn/web/images/success.png" class="content_img">
                     <br>
                     ''' + showtitle + '''
             </p>
@@ -1492,8 +1494,8 @@ class CloudStorageView(View):
         response = ResponseObject()
         now_time = int(time.time())
         # 过期前第365天提示一次,测试用
-        list = UID_Bucket.objects.filter(Q(endTime__gt=now_time + 3600 * 8736) & Q(endTime__lte=(now_time + 3600 * 8760))).values('id','uid','bucket__area','channel','endTime')
-        self.do_vod_msg(now_time,list)
+        # list = UID_Bucket.objects.filter(Q(endTime__gt=now_time + 3600 * 8736) & Q(endTime__lte=(now_time + 3600 * 8760))).values('id','uid','bucket__area','channel','endTime')
+        # self.do_vod_msg(now_time,list)
 
         # 过期前第7天提示一次
         list = UID_Bucket.objects.filter(Q(endTime__gt=now_time + 3600 * 144) & Q(endTime__lte=(now_time + 3600 * 168))).values('id','uid','bucket__area','channel','endTime')
@@ -1671,6 +1673,48 @@ class CloudStorageView(View):
             res = aliSms.send_code_sms_cloud(phone=phone, params = params, sign_name=sign_ms,
                                        temp_msg=temp_msg)
 
+    def do_refund(self, request_dict, response):
+        orderID = request_dict.get('orderID', None)    # 商户订单号
+        if not orderID:
+            return response.json(444)
+        try:
+            order_qs = Order_Model.objects.filter(orderID=orderID).values('status', 'payType', 'price')
+            if not order_qs.exists():
+                return response.json(173)
+
+            # 支付状态不为支付成功和退款失败
+            status = order_qs[0]['status']
+            if status != 1 and status != 4:
+                return response.json(805)
+
+            now_time = int(time.time())
+            payType = order_qs[0]['payType']
+            refund_amount = order_qs[0]['price']    # 退款金额
+            out_request_no = str(time.strftime('%Y%m%d%H%M%S', time.localtime(now_time)))    # 退款请求号
+            # 根据支付类型处理退款
+            if payType == 1:    # PayPal
+                pass
+            elif payType == 2:  # 支付宝
+                aliPayObj = AliPayObject()
+                alipay = aliPayObj.conf()
+                refund_response = alipay.api_alipay_trade_refund(refund_amount=refund_amount, out_trade_no=orderID,
+                                                                 out_request_no=out_request_no)
+                # 退款成功,修改订单支付状态为'退款成功',否则改为'退款失败'
+                status = 5 if refund_response['code'] == '10000' else 4
+                order_qs.update(status=status, updTime=now_time)
+            elif payType == 3:  # 微信
+                wechatPayObj = WechatPayObject()
+                refund_amount = int(float(refund_amount) * 100)  # 退款金额,单位为分,只能为整数
+                refund_success = wechatPayObj.refund(out_trade_no=orderID, out_refund_no=out_request_no,
+                                                     total_fee=refund_amount, refund_fee=refund_amount)
+                status = 5 if refund_success else 4
+                order_qs.update(status=status, updTime=now_time)
+            else:   # 不支持退款的支付类型
+                return response.json(805)
+            return response.json(0)
+        except Exception as e:
+            print(e)
+            return response.json(500, repr(e))
 
 
 # 删除过期云存播放列表

+ 28 - 13
Controller/DeviceConfirmRegion.py

@@ -107,24 +107,39 @@ class StatisticsIpRegion(TemplateView):
         response = ResponseObject()
         ip = request_dict.get('ip', None)
         uid = request_dict.get('uid', None)
+        # 0 or 1
+        is_p2p = int(request_dict.get('is_p2p', 0))
+        is_relay = int(request_dict.get('is_relay', 0))
 
-        if not all([ip, uid]):
+        if not all([ip, uid]) or (not is_p2p and not is_relay):
             return response.json(444)
 
         try:
-            # 判断uid是否已记录过ip信息
-            p2p_ip_qs = P2PIpModel.objects.filter(uid=uid)
+            now_time = int(time.time())
+            p2p_ip_qs = P2PIpModel.objects.filter(uid=uid).values('p2p_request_times', 'relay_request_times')
             if p2p_ip_qs.exists():
-                return response.json(174)
-
-            # 根据ip确定位置信息
-            ip_info = CommonService.getIpIpInfo(ip, 'CN')
-            # 获取国家,地区,城市
-            country_name = ip_info['country_name']
-            region_name = ip_info['region_name']
-            city_name = ip_info['city_name']
-            P2PIpModel.objects.create(uid=uid, ip=ip, country_name=country_name, region_name=region_name,
-                                      city_name=city_name, add_time=int(time.time()))
+                # 已存在数据,更新p2p请求次数或relay请求次数
+                if is_p2p:
+                    p2p_request_times = p2p_ip_qs[0]['p2p_request_times'] + 1
+                    p2p_ip_qs.update(p2p_request_times=p2p_request_times, update_time=now_time)
+                else:
+                    relay_request_times = p2p_ip_qs[0]['relay_request_times'] + 1
+                    p2p_ip_qs.update(relay_request_times=relay_request_times, update_time=now_time)
+            else:
+                # 根据ip确定位置信息
+                ip_info = CommonService.getIpIpInfo(ip, 'CN')
+                # 获取大洲,国家,地区,城市
+                continent_code = ip_info['continent_code']
+                country_name = ip_info['country_name']
+                if continent_code == 'AP' and country_name != 'CN':
+                    # 如果大洲代码为'AP',国家不为'CN',为亚洲
+                    continent_code = 'AS'
+                continent_name = RegionModel.objects.filter(continent_code=continent_code).values('name')[0]['name']
+                region_name = ip_info['region_name']
+                city_name = ip_info['city_name']
+                P2PIpModel.objects.create(uid=uid, ip=ip, continent_name=continent_name, country_name=country_name,
+                                          region_name=region_name, city_name=city_name, p2p_request_times=is_p2p,
+                                          relay_request_times=is_relay, add_time=now_time, update_time=now_time)
             return response.json(0)
         except Exception as e:
             print(e)

+ 3 - 0
Controller/EquipmentManager.py

@@ -1227,6 +1227,7 @@ def update_device_shadow(request):
         push_status = request_dict.get('push_status', None)
         pwd = request_dict.get('pwd', None)
         resetTime = request_dict.get('resetTime', None)
+        is_ptz = request_dict.get('is_ptz', None)
         is_alexa = request_dict.get('is_alexa', None)
 
         us_qs = UidSetModel.objects.filter(uid=uid)
@@ -1258,6 +1259,8 @@ def update_device_shadow(request):
             qs_dict['detect_status'] = push_status
         if pwd:
             qs_dict['pwd'] = pwd
+        if is_ptz:
+            qs_dict['is_ptz'] = is_ptz
         if is_alexa:
             qs_dict['is_alexa'] = is_alexa
         if us_qs.exists():

+ 88 - 1
Controller/PcInfo.py

@@ -11,7 +11,7 @@ from django.http import HttpResponse
 
 from django.views.generic.base import View
 
-from Model.models import Pc_Info
+from Model.models import Pc_Info, PctestlogModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
@@ -48,8 +48,12 @@ class PcInfo(View):
                 return self.query(request_dict, response)
             elif operation == 's3addandupload':
                 return self.s3addandupload(request_dict, response, request)
+            elif operation == 's3addanduploadlog': #上传日志文件
+                return self.s3addanduploadlog(request_dict, response, request)
             elif operation == 's3download':
                 return self.s3download(request_dict, response)
+            elif operation == 's3downloadlog': #下载日志文件
+                return self.s3downloadlog(request_dict, response)
             elif operation == 's3delete':
                 return self.s3delete(request_dict, response)
             elif operation == 'edit':
@@ -294,6 +298,63 @@ class PcInfo(View):
                 else:
                     return response.json(500)
 
+    def s3addanduploadlog(self, request_dict, response, request):
+        logger = logging.getLogger('info')
+        logger.info('s3方式上传参数:')
+        logger.info(request_dict)
+        token = request_dict.get('token', None)
+        tko = TokenObject(token)
+        response.lang = tko.lang
+        if tko.code != 0:
+            return response.json(tko.code)
+        userID = tko.userID
+        if not userID:
+            return response.json(104)
+        pc_name = request_dict.get('pc_name', None)
+        bundle_version = request_dict.get('bundle_version', None)
+        pc_version = request_dict.get('pc_version', None)
+        pc_test = request_dict.get('pc_test', None)
+        lang = request_dict.get('lang', None)
+        file_name = request_dict.get('file_name', None)
+        file_type = request_dict.get('file_type', None)
+        package = request_dict.get('package', None)
+        explain = request_dict.get('explain', '')
+        is_update = request_dict.get('is_update', None)
+        is_open = request_dict.get('is_open', None)
+        pathtype = request_dict.get('pathtype', None)
+        # logger.info('文件名字:')
+        # logger.info(file_name)
+        param_flag = CommonService.get_param_flag(
+            data=[pc_name, bundle_version, pc_version, pc_test, lang, file_name, file_type, package, is_update,
+                  is_open])
+        if param_flag is not True:
+            return response.json(444)
+
+        logger.info('开始上传')
+        # 把安装包上传到s3
+        aws_s3_guonei = boto3.client(
+            's3',
+            aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+            config=botocore.client.Config(signature_version='s3v4'),
+            region_name='cn-northwest-1'
+        )
+        download_link = '{pc_name}/{pathtype}/{pc_version}_{bundle_version}_{pc_test}_{file_name}'.format(
+            pc_name=pc_name, pathtype=pathtype, pc_version=pc_version, bundle_version=bundle_version,
+            pc_test=pc_test, file_name=file_name)
+        response_url = aws_s3_guonei.generate_presigned_url(
+            ClientMethod='put_object',
+            Params={
+                'Bucket': 'pc-package',
+                'Key': download_link
+            },
+            ExpiresIn=3600
+        )
+        add_time = time.time()
+        PctestlogModel.objects.create(user_id=userID, content=download_link, addtime=add_time)
+        return response.json(0, {'upload_url': response_url})
+
+
     def s3download(self, request_dict, response):
         pc_name = request_dict.get('pc_name', None)
         bundle_version = request_dict.get('bundle_version', None)
@@ -328,6 +389,32 @@ class PcInfo(View):
                }
         return response.json(0, res)
 
+    def s3downloadlog(self, request_dict, response):
+        id = request_dict.get('id', None)
+        path = PctestlogModel.objects.filter(id=id)
+        if not path:
+            return response.json(173)
+        path = path[0]['content']
+        aws_s3_guonei = boto3.client(
+            's3',
+            aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+            config=botocore.client.Config(signature_version='s3v4'),
+            region_name='cn-northwest-1'
+        )
+        response_url = aws_s3_guonei.generate_presigned_url(
+            ClientMethod='get_object',
+            Params={
+                'Bucket': 'pc-package',
+                'Key': path
+            },
+            ExpiresIn=3600
+        )
+        res = {'path': path,
+               'response_url': response_url
+               }
+        return response.json(0, res)
+
     def edit(self, request_dict, response):
         id = request_dict.get('id', None)
         explain = request_dict.get('explain', None)

+ 237 - 77
Controller/PctestController.py

@@ -51,50 +51,56 @@ class PcTest(View):
                 # 获取访问者的id和岗位
                 userID = tko.id
                 jobID = tko.job
-                if jobID == 1:
-                    # 管理员可访问的接口
-                    if operation == 'job/add':
-                        return self.jobadd(request_dict, userID, response)
-                    elif operation == 'job/query':
-                        return self.jobquery(request_dict, userID, response)
-                    elif operation == 'device/add':
-                        return self.deviceadd(request_dict, userID, response)
-                    elif operation == 'device/query':
-                        return self.devicequery(request_dict, userID, response)
-                    elif operation == 'function/add':
-                        return self.functionadd(request_dict, userID, response)
-                    elif operation == 'function/query':
-                        return self.functionquery(request_dict, userID, response)
-                    elif operation == 'job/device/add':
-                        return self.jobdeviceadd(request_dict, userID, response)
-                    elif operation == 'job/device/query':
-                        return self.jobdevicequery(request_dict, jobID, response)
-                    elif operation == 'device/function/add':
-                        return self.devicefunctionadd(request_dict, userID, response)
-                    elif operation == 'device/function/query':
-                        return self.devicefunctionquery(request_dict, jobID, response)
-                    elif operation == 'staff/add':
-                        return self.staffadd(request_dict, userID, response)
-                    elif operation == 'staff/query':
-                        return self.staffquery(request_dict, userID, response)
-                    elif operation == 'staff/delete':
-                        return self.staffdelete(request_dict, userID, response)
-                    elif operation == 'log/query':
-                        return self.logquery(request_dict, userID, response)
-                    else:
-                        return response.json(404)
+                # if jobID == 1:
+                #     # 管理员可访问的接口
+                if operation == 'job/add':
+                    return self.jobadd(request_dict, userID, response)
+                elif operation == 'job/query':
+                    return self.jobquery(request_dict, userID, response)
+                elif operation == 'job/delete':
+                    return self.jobdelete(request_dict, userID, response)
+                elif operation == 'device/add':
+                    return self.deviceadd(request_dict, userID, response)
+                elif operation == 'device/query':
+                    return self.devicequery(request_dict, userID, response)
+                elif operation == 'device/delete':
+                    return self.devicedelete(request_dict, userID, response)
+                elif operation == 'function/add':
+                    return self.functionadd(request_dict, userID, response)
+                elif operation == 'function/query':
+                    return self.functionquery(request_dict, userID, response)
+                elif operation == 'function/delete':
+                    return self.functiondelete(request_dict, userID, response)
+                elif operation == 'job/device/add':
+                    return self.jobdeviceadd(request_dict, userID, response)
+                elif operation == 'device/function/add':
+                    return self.devicefunctionadd(request_dict, userID, response)
+                elif operation == 'staff/add':
+                    return self.staffadd(request_dict, userID, response)
+                elif operation == 'staff/query':
+                    return self.staffquery(request_dict, userID, response)
+                elif operation == 'staff/delete':
+                    return self.staffdelete(request_dict, userID, response)
+
+
+                # 公共访问的接口
+                if operation == 'job/device/query':
+                    return self.jobdevicequery(request_dict, jobID, response)
+                elif operation == 'device/function/query':
+                    return self.devicefunctionquery(request_dict, jobID, response)
+                elif operation == 'log/add':
+                    return self.logadd(request_dict, userID, response)
+                elif operation == 'log/query':
+                    return self.logquery(request_dict, userID, response)
+                elif operation == 'token/fullInfo':
+                    return self.fullInfo(request_dict, userID, response)
+                elif operation == 'staff/initPass':
+                    return self.initPass(request_dict, userID, response)
+                elif operation == 'staff/updatePass':
+                    return self.updatePass(request_dict, userID, response)
                 else:
-                    # 普通员工访问的接口
-                    if operation == 'job/device/query':
-                        return self.jobdevicequery(request_dict, jobID, response)
-                    elif operation == 'device/function/query':
-                        return self.devicefunctionquery(request_dict, jobID, response)
-                    elif operation == 'log/add':
-                        return self.logadd(request_dict, userID, response)
-                    elif operation == 'log/query':
-                        return self.logquery(request_dict, userID, response)
-                    else:
-                        return response.json(404)
+                    return response.json(404)
+
 
     def login(self, request_dict, response):
         username = request_dict.get('username', None)
@@ -105,20 +111,27 @@ class PcTest(View):
             return response.json(444)
         user_qs = PctestuserModel.objects.filter(username=username, password=password)
         if not user_qs.exists():
-            return response.json(104)
-        users = user_qs.values('id', 'username', 'password', 'job')[0]
+            if not PctestuserModel.objects.filter(username=username).exists():
+                return response.json(104)
+            return response.json(111)
+
+        users = user_qs.values('id', 'username', 'password', 'job__id', 'job__jobcode')[0]
         tko = TokenObject()
         # 加密
         res = tko.generate(
-            data={'id': users['id'], 'username': users['username'], 'password': users['password'], 'job': users['job']})
+            data={'id': users['id'], 'username': users['username'], 'password': users['password'], 'jobid': users['job__id'], 'job': users['job__jobcode']})
         res_qs = {
             'res': res,
-            'job': users['job']
+            'id': users['id'],
+            'username': users['username'],
+            'job': users['job__jobcode'],
+            'jobid': users['job__id']
         }
         return response.json(0, res_qs)
 
     def jobadd(self, request_dict, userID, response):
         jobname = request_dict.get('jobname', None)
+        jobcode = request_dict.get('jobcode', None)
         param_flag = CommonService.get_param_flag(
             data=[jobname])
         if param_flag is not True:
@@ -127,50 +140,121 @@ class PcTest(View):
         if job_qs.exists():
             return response.json(174)
         else:
-            PctestjobModel.objects.create(jobname=jobname)
+            PctestjobModel.objects.create(jobname=jobname,jobcode=jobcode)
             return response.json(0)
 
     def jobquery(self, request_dict, userID, response):
-        job_list = PctestjobModel.objects.filter(id__gt=1)
-        count = job_list.count()
-        res = job_list
-        send_json = CommonService.qs_to_dict(res)
-        send_json['count'] = count
-        return response.json(0, send_json)
+        # user_qs = PctestuserModel.objects.filter(id=userID).values('job')
+        # job_qs = PctestjobModel.objects.filter(id=user_qs[0]['job'])
+        #
+        # if job_qs[0].id == 1:
+        #     job_qs = PctestjobModel.objects.filter()
+        job_qs = PctestjobModel.objects.filter()
+        device_qs = PctestjobdeviceModel.objects.filter(job__in=job_qs).values('device')
+
+        data = CommonService.qs_to_list(job_qs.values('id', 'jobname', 'jobcode'))
+
+        i = 0
+        for jobs in job_qs:
+            data[i]['devices'] = CommonService.qs_to_list(device_qs.filter(job__id=jobs.id).values('device__id', 'device__devicename'))
+            i = i + 1
+        count = device_qs.count()
+        return response.json(0, {'datas': data, 'count': count})
+
+    def jobdelete(self, request_dict, userID, response):
+        id = request_dict.get('id', None)
+        job_qs = PctestjobModel.objects.filter(id=id)
+        if job_qs.exists:
+            job_qs.delete()
+            PctestjobdeviceModel.objects.filter(job__in=job_qs).delete()
+        return response.json(0)
 
     def deviceadd(self, request_dict, userID, response):
+        deviceid = request_dict.get('deviceid', None)
         devicename = request_dict.get('devicename', None)
+        functions= request_dict.get('functions', None)
         param_flag = CommonService.get_param_flag(
             data=[devicename])
         if param_flag is not True:
             return response.json(444)
-        job_qs = PctestdeviceModel.objects.filter(devicename=devicename)
-        if job_qs.exists():
-            return response.json(174)
-        else:
+
+        if not deviceid:
+            device_qs = PctestdeviceModel.objects.filter(devicename=devicename)
+            if device_qs.exists():
+                return response.json(174)
             PctestdeviceModel.objects.create(devicename=devicename)
-            return response.json(0)
+
+        else:
+            device_qs = PctestdeviceModel.objects.filter(id=deviceid)
+            PctestdeviceModel.objects.filter(id=deviceid).update(devicename=devicename)
+
+
+        function_list = PctestfunctionModel.objects.filter(id__in=functions.split(','))
+        # 判断设备与此职能是否有关联,避免重复添加
+        PctestModel.objects.filter(device_id=device_qs[0].id, function__in=function_list).delete()
+        for fun in function_list:
+            PctestModel.objects.create(device_id=device_qs[0].id, function_id=fun.id)
+        return response.json(0)
+
+
+
 
     def devicequery(self, request_dict, userID, response):
-        device_list = PctestdeviceModel.objects.all()
-        count = device_list.count()
-        res = device_list
-        send_json = CommonService.qs_to_dict(res)
-        send_json['count'] = count
-        return response.json(0, send_json)
+        # user_qs = PctestuserModel.objects.filter(id=userID).values('job')
+        # job_qs = PctestjobModel.objects.filter(id=user_qs[0]['job'])
+        #
+        # if job_qs[0].id == 1:
+        #     device_qs = PctestjobdeviceModel.objects.filter().values('device')
+        # else:
+        #     device_qs = PctestjobdeviceModel.objects.filter(job__in=job_qs).values('device')
+        device_qs = PctestdeviceModel.objects.filter()
+
+        function_qs = PctestModel.objects.filter(device__in=device_qs)
+
+        device_qs = device_qs.values('id', 'devicename')
+        data = CommonService.qs_to_list(device_qs)
+        i = 0
+        for devices in device_qs:
+            data[i]['functions'] = CommonService.qs_to_list(function_qs.filter(device__id=devices['id']).values('function__id','function__functionname','function__functioncode'))
+            i = i + 1
+        count = device_qs.count()
+        return response.json(0, {'datas': data, 'count': count})
+
+    def devicedelete(self, request_dict, userID, response):
+        id = request_dict.get('id', None)
+        device_qs = PctestdeviceModel.objects.filter(id=id)
+        if device_qs.exists:
+            device_qs.delete()
+            PctestModel.objects.filter(device__in=device_qs).delete()
+
+        return response.json(0)
 
     def functionadd(self, request_dict, userID, response):
         functionname = request_dict.get('functionname', None)
+        functioncode = request_dict.get('functioncode', None)
+        id = request_dict.get('id', None)
         param_flag = CommonService.get_param_flag(
             data=[functionname])
         if param_flag is not True:
             return response.json(444)
-        job_qs = PctestfunctionModel.objects.filter(functionname=functionname)
-        if job_qs.exists():
-            return response.json(174)
+
+        if not id:
+            job_qs = PctestfunctionModel.objects.filter(functionname=functionname)
+            if job_qs.exists():
+                return response.json(174)
+            PctestfunctionModel.objects.create(functionname=functionname,functioncode=functioncode)
         else:
-            PctestfunctionModel.objects.create(functionname=functionname)
-            return response.json(0)
+            PctestfunctionModel.objects.filter(id=id).update(functionname=functionname, functioncode=functioncode)
+
+        return response.json(0)
+
+    def functiondelete(self, request_dict, userID, response):
+        id = request_dict.get('id', None)
+        function_qs = PctestfunctionModel.objects.filter(id=id)
+
+        if function_qs.exists:
+            function_qs.delete()
+        return response.json(0)
 
     def functionquery(self, request_dict, userID, response):
         function_list = PctestfunctionModel.objects.all()
@@ -252,22 +336,65 @@ class PcTest(View):
     def staffadd(self, request_dict, userID, response):
         username = request_dict.get('username', None)
         password = request_dict.get('password', None)
+        id = request_dict.get('id', None)
         job_id = request_dict.get('job_id', None)
         param_flag = CommonService.get_param_flag(
-            data=[username, password, job_id])
+            data=[username, job_id])
         if param_flag is not True:
             return response.json(444)
         # 判断员工与岗位是否存在,员工存在返回174
         user_list = PctestuserModel.objects.filter(username=username)
+
         job_list = PctestjobModel.objects.filter(id=job_id)
-        if not job_list.exists() or user_list.exists():
+        if not job_list.exists():
             return response.json(174)
-        else:
+
+        if not id:
+            if user_list.exists():
+                return response.json(174)
             PctestuserModel.objects.create(username=username, password=password, job_id=job_id)
-            return response.json(0)
+        else:
+            PctestuserModel.objects.filter(id=id).update(username=username, job_id=job_id)
+
+        return response.json(0)
+
+
+    def initPass(self, request_dict, userID, response):
+
+        id = request_dict.get('id', None)
+        param_flag = CommonService.get_param_flag(
+            data=[id])
+        if param_flag is not True:
+            return response.json(444)
+
+        # 判断员工与岗位是否存在,员工存在返回174
+        user_list = PctestuserModel.objects.filter(id=id)
+        if user_list.exists():
+            user_list.update(password='555')
+
+        return response.json(0)
+
+    def updatePass(self, request_dict, userID, response):
+
+        id = request_dict.get('id', None)
+        password = request_dict.get('password', None)
+        param_flag = CommonService.get_param_flag(
+            data=[id,password])
+        if param_flag is not True:
+            return response.json(444)
+
+        # 判断员工与岗位是否存在,员工存在返回174
+        user_list = PctestuserModel.objects.filter(id=id)
+        if user_list.exists():
+            user_list.update(password=password)
+
+        return response.json(0)
+
+
+
 
     def staffquery(self, request_dict, userID, response):
-        user_list = PctestuserModel.objects.filter(id__gt=1).values('id', 'username', 'job__jobname')
+        user_list = PctestuserModel.objects.filter(id__gt=1).values('id', 'username', 'job__id', 'job__jobname', 'job__jobcode')
         users_list = []
         for i in user_list:
             users_list.append(i)
@@ -296,14 +423,47 @@ class PcTest(View):
 
     def logquery(self, request_dict, userID, response):
         if userID == 1:
-            job_device_list = PctestlogModel.objects.values('user__username', 'content', 'addtime')
+            job_device_list = PctestlogModel.objects.values('id', 'user__id', 'user__username', 'content', 'addtime')
         else:
-            job_device_list = PctestlogModel.objects.filter(user_id=userID).values('content','addtime')
+            job_device_list = PctestlogModel.objects.filter(user_id=userID).values('id', 'user__id', 'user__username', 'content', 'addtime')
         device_list = []
         for i in job_device_list:
             device_list.append(i)
         return response.json(0, device_list)
 
+    def fullInfo(self, request_dict, userID, response):
+        user_qs = PctestuserModel.objects.filter(id=userID).values('job')
+        fullinfo = []
+        data = {}
+        if user_qs.exists():
+
+            job_qs = PctestjobModel.objects.filter(id=user_qs[0]['job'])
+            user_qs = user_qs.values('id', 'username')
+
+            # device_qs = PctestjobdeviceModel.objects.filter(job__in=job_qs).values('device')
+            #
+            # function_qs = PctestModel.objects.filter(device__in=device_qs)
+
+
+            data = user_qs[0]
+            data['jobs'] = CommonService.qs_to_list(job_qs.values('id', 'jobname', 'jobcode'))
+
+            # i = 0
+            # for jobs in data['jobs']:
+            #
+            #     data['jobs'][i]['devices'] = CommonService.qs_to_list(device_qs.filter(job__id=jobs['id']).values('device__id', 'device__devicename'))
+            #
+            #     j = 0
+            #     for devices in jobs['devices']:
+            #         data['jobs'][i]['devices'][j]['functions'] = CommonService.qs_to_list(function_qs.filter(device__id=devices['device__id']).values('function__id','function__functionname','function__functioncode'))
+            #         j = j+1
+            #
+            #     i = i+1
+
+
+            fullinfo.append(data)
+        return response.json(0, fullinfo)
+
 
 class TokenObject1:
 

+ 1 - 1
Controller/ShadowController.py

@@ -138,7 +138,7 @@ def update_device_shadow(request):
             qs_dict['is_custom_voice'] = is_custom_voice
         if double_wifi:
             qs_dict['double_wifi'] = double_wifi
-        if double_wifi:
+        if is_ptz:
             qs_dict['is_ptz'] = is_ptz
         if us_qs.exists():
             if is_alexa and us_qs[0].is_alexa == 0:

+ 23 - 6
Controller/TestApi.py

@@ -12,6 +12,7 @@
 @Contact: chanjunkai@163.com
 """
 import botocore
+from django.db import transaction
 from django.views.generic.base import View
 import os
 
@@ -43,7 +44,8 @@ from Object.RedisObject import RedisObject
 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, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
-from Model.models import Device_Info, Order_Model, Store_Meal, VodHlsModel, OssCrdModel, UID_Bucket, CompanySerialModel, SerialNumberModel, CompanyModel, VPGModel
+from Model.models import Device_Info, Order_Model, Store_Meal, VodHlsModel, OssCrdModel, UID_Bucket, CompanySerialModel, \
+    SerialNumberModel, CompanyModel, VPGModel, Unused_Uid_Meal, StsCrdModel, ExperienceContextModel
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Object.UidTokenObject import UidTokenObject
@@ -759,13 +761,28 @@ class testView(View):
                             content_type="application/json,charset=utf-8")
 
     def delete_device(self, response):
-        # 每两周删除一次tech01@ansjer.com~tech10@ansjer.com账号下的设备
+        # 定时删除测试账号下的设备数据
         try:
-            userID_list = ['tech01@ansjer.com', 'tech02@ansjer.com', 'tech03@ansjer.com',
-                           'tech04@ansjer.com', 'tech05@ansjer.com', 'tech06@ansjer.com',
-                           'tech07@ansjer.com', 'tech08@ansjer.com', 'tech09@ansjer.com', 'tech10@ansjer.com']
+            userID_list = ['tech01@ansjer.com', 'tech02@ansjer.com', 'tech03@ansjer.com', 'tech04@ansjer.com',
+                           'tech05@ansjer.com', 'tech06@ansjer.com', 'tech07@ansjer.com', 'tech08@ansjer.com',
+                           'tech09@ansjer.com', 'tech10@ansjer.com', 'fix01@ansjer.com', 'fix02@ansjer.com',
+                           'fix03@ansjer.com', 'fix04@ansjer.com', 'fix05@ansjer.com']
             device_user = Device_User.objects.filter(username__in=userID_list)
-            Device_Info.objects.filter(userID__in=device_user).delete()
+            device_info_qs = Device_Info.objects.filter(userID__in=device_user).values('UID')
+            uid_list = []
+            for device_info in device_info_qs:
+                uid_list.append(device_info['UID'])
+            with transaction.atomic():
+                # 删除设备云存相关数据
+                UidSetModel.objects.filter(uid__in=uid_list).delete()
+                UID_Bucket.objects.filter(uid__in=uid_list).delete()
+                Unused_Uid_Meal.objects.filter(uid__in=uid_list).delete()
+                Order_Model.objects.filter(UID__in=uid_list).delete()
+                StsCrdModel.objects.filter(uid__in=uid_list).delete()
+                VodHlsModel.objects.filter(uid__in=uid_list).delete()
+                ExperienceContextModel.objects.filter(uid__in=uid_list).delete()
+                Device_Info.objects.filter(userID__in=device_user).delete()
+
             return response.json(0)
         except Exception as e:
             return response.json(500, repr(e))

+ 8 - 4
Model/models.py

@@ -581,7 +581,7 @@ class Order_Model(models.Model):
     updTime = models.IntegerField(verbose_name='更新时间', default=0)
     # endTime = models.IntegerField(verbose_name='结束时间', default=0)
     isSelectDiscounts = models.SmallIntegerField(default=0, verbose_name=u'用户是否选择了第二年优惠 [0=否,1是]')
-    status = models.SmallIntegerField(default=0, verbose_name='付款状态')  # 0:待支付,1:成功,2:取消,3:已退款, 9:处理中,10:付款失败
+    status = models.SmallIntegerField(default=0, verbose_name='付款状态')  # 0:待支付,1:成功,2:取消,3:已退款,4: 退款失败,5: 退款成功, 9:处理中,10:付款失败
     payType = models.SmallIntegerField(default=0, verbose_name='付款类型0:paypal,1:alipay')
     payTime = models.IntegerField(verbose_name='支付成功时间', default=0)
     rank = models.ForeignKey(Store_Meal, to_field='id', default='', on_delete=models.CASCADE, verbose_name='套餐类型')
@@ -1610,7 +1610,7 @@ class CloudLogModel(models.Model):
 class PctestjobModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
     jobname = models.CharField(blank=True, max_length=32, verbose_name=u'岗位名字')
-
+    jobcode = models.SmallIntegerField(default=3, verbose_name='岗位code 。1:管理员,3:普通人员')
     class Meta:
         db_table = 'pctest_job'
         verbose_name = u'pc岗位表'
@@ -1632,7 +1632,7 @@ class PctestdeviceModel(models.Model):
 class PctestfunctionModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
     functionname = models.CharField(blank=True, max_length=32, verbose_name=u'职能名字')
-
+    functioncode = models.SmallIntegerField(default=1, verbose_name='职能code 。PC端自己逻辑判断')
     class Meta:
         db_table = 'pctest_function'
         verbose_name = u'pc设备职能表'
@@ -1692,12 +1692,16 @@ class PctestModel(models.Model):
 
 class P2PIpModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
-    uid = models.CharField(max_length=20, default='', unique=True, verbose_name='设备uid')
+    uid = models.CharField(max_length=20, default='', unique=True, db_index=True, verbose_name='设备uid')
     ip = models.CharField(default='', max_length=32, verbose_name='ip')
+    p2p_request_times = models.IntegerField(default=0, verbose_name='p2p请求次数')
+    relay_request_times = models.IntegerField(default=0, verbose_name='relay请求次数')
+    continent_name = models.CharField(default='', max_length=10, verbose_name='大洲')
     country_name = models.CharField(default='', max_length=100, verbose_name='国家')
     region_name = models.CharField(default='', max_length=100, verbose_name='地区')
     city_name = models.CharField(default='', max_length=100, verbose_name='城市')
     add_time = models.IntegerField(default=0, verbose_name='添加时间')
+    update_time = models.IntegerField(default=0, verbose_name='更新时间')
 
     class Meta:
         db_table = 'p2p_ip'

+ 2 - 0
Object/ResponseObject.py

@@ -61,6 +61,7 @@ class ResponseObject(object):
             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',
+            805: 'No refund',
             900: 'There is no information about this version!',
             901: 'Getting URL failure!',
             902: 'No update!',
@@ -154,6 +155,7 @@ class ResponseObject(object):
             801: '退款金额不能大于订单价格',
             802: '订单已完成,不能撤销',
             804: '订单已退款,请勿重复操作',
+            805: '无法退款',
             900: '版本信息不存在',
             901: '获取链接失败',
             902: '无更新!',

+ 27 - 0
Object/WechatPayObject.py

@@ -5,6 +5,8 @@ from urllib.parse import quote
 import requests
 import xmltodict
 
+from Ansjer.config import BASE_DIR
+
 
 class WechatPayObject:
     """配置账号信息"""
@@ -20,6 +22,7 @@ class WechatPayObject:
         self.TRADE_TYPE = 'APP'
         self.APIKEY = 'ZHansjeransjeransjer680301000000'
         self.url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'  # 微信请求url
+        self.refund_url = 'https://api.mch.weixin.qq.com/secapi/pay/refund'   # 退款url
         self.error = None
         self.params = None
 
@@ -199,3 +202,27 @@ class WechatPayObject:
             xml += '<' + k + '>' + v + '</' + k + '>'
         xml += "</xml>"
         return xml
+
+    def refund(self, out_trade_no, out_refund_no, total_fee, refund_fee):
+        params = {
+            'appid': self.APPID,
+            'mch_id': self.MCHID,
+            'nonce_str': self.getNonceStr(),
+            'out_trade_no': out_trade_no,   # 商户订单号
+            'out_refund_no': out_refund_no,    # 商户退款单号
+            'total_fee': total_fee,     # 订单金额
+            'refund_fee': refund_fee    # 退款金额
+        }
+        # doc: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3
+        string_sign = "&".join([f"{k}={params[k]}" for k in sorted(params)] + [f"{'key'}={self.APIKEY}"])
+        params['sign'] = hashlib.md5(string_sign.encode('utf8')).hexdigest().upper()   # MD5签名
+        xml = "<xml>{}</xml>".format("".join([f"<{k}>{v}</{k}>" for k, v in params.items()]))   # 数据拼接成xml格式
+        cert = f"{BASE_DIR}/Ansjer/file/wechatpay/apiclient_cert.pem"
+        key = f"{BASE_DIR}/Ansjer/file/wechatpay/apiclient_key.pem"
+        r = requests.post(url=self.refund_url, headers={'Content-Type': 'text/xml'}, data=xml.encode('utf-8'),
+                          cert=(cert, key), verify=True)
+        response = xmltodict.parse(r.text)
+        if response['xml']['return_code'] == 'SUCCESS':
+            return True
+        else:
+            return False