Browse Source

更新优惠券功能

lang 3 years ago
parent
commit
bebce45885
4 changed files with 213 additions and 13 deletions
  1. 45 8
      Controller/CloudStorage.py
  2. 146 5
      Controller/PaymentCycle.py
  3. 20 0
      Model/models.py
  4. 2 0
      Object/ResponseObject.py

+ 45 - 8
Controller/CloudStorage.py

@@ -41,7 +41,7 @@ from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, OSS_ROLE_AR
 from Controller.CheckUserData import DataValid
 from Controller.CheckUserData import DataValid
 from Model.models import Device_Info, Order_Model, Store_Meal, VodHlsModel, OssCrdModel, UID_Bucket, StsCrdModel, \
 from Model.models import Device_Info, Order_Model, Store_Meal, VodHlsModel, OssCrdModel, UID_Bucket, StsCrdModel, \
     ExperienceContextModel, Pay_Type, CDKcontextModel, Device_User, SysMassModel, SysMsgModel, UidPushModel, \
     ExperienceContextModel, Pay_Type, CDKcontextModel, Device_User, SysMassModel, SysMsgModel, UidPushModel, \
-    Unused_Uid_Meal, UIDMainUser, UserModel, PromotionRuleModel, VideoPlaybackTimeModel, CloudLogModel
+    Unused_Uid_Meal, UIDMainUser, UserModel, PromotionRuleModel, VideoPlaybackTimeModel, CloudLogModel, CouponModel
 from Object.AWS.S3Email import S3Email
 from Object.AWS.S3Email import S3Email
 from Object.AliPayObject import AliPayObject
 from Object.AliPayObject import AliPayObject
 from Object.AliSmsObject import AliSmsObject
 from Object.AliSmsObject import AliSmsObject
@@ -54,6 +54,7 @@ from Object.m3u8generate import PlaylistGenerator
 from Object.WechatPayObject import WechatPayObject
 from Object.WechatPayObject import WechatPayObject
 from django.db.models import Q, F, Count
 from django.db.models import Q, F, Count
 from Controller.PaymentCycle import Paypal
 from Controller.PaymentCycle import Paypal
+from decimal import Decimal
 from Ansjer.config import SERVER_TYPE
 from Ansjer.config import SERVER_TYPE
 from Service.ModelService import ModelService
 from Service.ModelService import ModelService
 
 
@@ -193,7 +194,7 @@ class CloudStorageView(View):
         mold = request_dict.get('mold', None)
         mold = request_dict.get('mold', None)
         uid = request_dict.get('uid', None)
         uid = request_dict.get('uid', None)
         lang = request_dict.get('lang', 'en')
         lang = request_dict.get('lang', 'en')
-
+        nowTime = int(time.time())
         # DVR/NVR设备暂不返回云存套餐列表
         # DVR/NVR设备暂不返回云存套餐列表
         device_info_qs = Device_Info.objects.filter(Q(UID=uid), Q(Type__lte=4) | Q(Type=10001))
         device_info_qs = Device_Info.objects.filter(Q(UID=uid), Q(Type__lte=4) | Q(Type=10001))
         if device_info_qs.exists():
         if device_info_qs.exists():
@@ -238,7 +239,6 @@ class CloudStorageView(View):
                 res_c = {'area': area, 'items': items_list}
                 res_c = {'area': area, 'items': items_list}
                 res.append(res_c)
                 res.append(res_c)
             #是否促销
             #是否促销
-            nowTime = int(time.time())
             promotion = PromotionRuleModel.objects.filter(status=1, startTime__lte=nowTime,
             promotion = PromotionRuleModel.objects.filter(status=1, startTime__lte=nowTime,
                                                           endTime__gte=nowTime).values('id','ruleConfig','ruleName',
                                                           endTime__gte=nowTime).values('id','ruleConfig','ruleName',
                                                                                        'startTime','endTime','ruleDesc')
                                                                                        'startTime','endTime','ruleDesc')
@@ -255,6 +255,11 @@ class CloudStorageView(View):
                 promotion = {
                 promotion = {
                     'is_promotion': 0
                     'is_promotion': 0
                 }
                 }
+
+            #优惠券
+            couponObj = CouponModel.objects.filter(userID_id=userID,use_status=0,distributeTime__lte=nowTime,
+                                                   valid_time__gt=nowTime).annotate(coupon_id=F('id')).values(
+                                                   "coupon_id","type","coupon_discount")
             result = {
             result = {
                 'meals': res,
                 'meals': res,
                 'extra':
                 'extra':
@@ -262,7 +267,8 @@ class CloudStorageView(View):
                         'cloud_banner': SERVER_DOMAIN+'web/images/cloud_cn_banner.png',
                         'cloud_banner': SERVER_DOMAIN+'web/images/cloud_cn_banner.png',
                         'cloud_en_baner': SERVER_DOMAIN_SSL+'web/images/cloud_en_banner.png'
                         'cloud_en_baner': SERVER_DOMAIN_SSL+'web/images/cloud_en_banner.png'
                     },
                     },
-                'promotion':promotion
+                'promotion':promotion,
+                'couponList':list(couponObj),
             }
             }
             return response.json(0, result)
             return response.json(0, result)
         else:
         else:
@@ -835,6 +841,10 @@ class CloudStorageView(View):
                     #     }
                     #     }
                     #     UIDMainUser.objects.create(**uid_main_dict)
                     #     UIDMainUser.objects.create(**uid_main_dict)
 
 
+                    # 核销coupon
+                    if order_list[0]['coupon_id']:
+                        CouponModel.objects.filter(id=order_list[0]['coupon_id']).update(use_status=1)
+
                     order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, promotion_rule_id=promotion_rule_id)
                     order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, promotion_rule_id=promotion_rule_id)
                     datetime = time.strftime("%Y-%m-%d", time.localtime())
                     datetime = time.strftime("%Y-%m-%d", time.localtime())
                     sys_msg_text_list = ['温馨提示:尊敬的客户,您的'+UID+'设备在'+datetime+'已成功购买云存套餐', 'Dear customer,you already subscribed the cloud storage package successfully for device ' + UID + ' on '+ time.strftime("%b %dth,%Y", time.localtime())]
                     sys_msg_text_list = ['温馨提示:尊敬的客户,您的'+UID+'设备在'+datetime+'已成功购买云存套餐', 'Dear customer,you already subscribed the cloud storage package successfully for device ' + UID + ' on '+ time.strftime("%b %dth,%Y", time.localtime())]
@@ -892,7 +902,7 @@ class CloudStorageView(View):
             nowTime = int(time.time())
             nowTime = int(time.time())
             order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
             order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
                                          "userID__userID",
                                          "userID__userID",
-                                         "userID__username")
+                                         "userID__username","coupon_id")
             userid = order_list[0]['userID__userID']
             userid = order_list[0]['userID__userID']
             username = order_list[0]['userID__username']
             username = order_list[0]['userID__username']
             UID = order_list[0]['UID']
             UID = order_list[0]['UID']
@@ -961,6 +971,10 @@ class CloudStorageView(View):
                 #     }
                 #     }
                 #     UIDMainUser.objects.create(**uid_main_dict)
                 #     UIDMainUser.objects.create(**uid_main_dict)
 
 
+                # 核销coupon
+                if order_list[0]['coupon_id']:
+                    CouponModel.objects.filter(id=order_list[0]['coupon_id']).update(use_status=1)
+
                 order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, promotion_rule_id=promotion_rule_id)
                 order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, promotion_rule_id=promotion_rule_id)
                 datetime = time.strftime("%Y-%m-%d", time.localtime())
                 datetime = time.strftime("%Y-%m-%d", time.localtime())
                 sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + UID + '设备在' + datetime + '已成功购买云存套餐',
                 sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + UID + '设备在' + datetime + '已成功购买云存套餐',
@@ -1083,6 +1097,10 @@ class CloudStorageView(View):
                     #     }
                     #     }
                     #     UIDMainUser.objects.create(**uid_main_dict)
                     #     UIDMainUser.objects.create(**uid_main_dict)
 
 
+                    # 核销coupon
+                    if order_list[0]['coupon_id']:
+                        CouponModel.objects.filter(id=order_list[0]['coupon_id']).update(use_status=1)
+
                     order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, promotion_rule_id=promotion_rule_id)
                     order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, promotion_rule_id=promotion_rule_id)
                     datetime = time.strftime("%Y-%m-%d", time.localtime())
                     datetime = time.strftime("%Y-%m-%d", time.localtime())
                     sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + UID + '设备在' + datetime + '已成功购买云存套餐',
                     sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + UID + '设备在' + datetime + '已成功购买云存套餐',
@@ -1109,6 +1127,7 @@ class CloudStorageView(View):
         pay_type = int(request_dict.get('pay_type', None))
         pay_type = int(request_dict.get('pay_type', None))
         rank = request_dict.get('rank', None)
         rank = request_dict.get('rank', None)
         is_select_discount = request_dict.get('is_select_discount', 0)
         is_select_discount = request_dict.get('is_select_discount', 0)
+        coupon_id = request_dict.get('coupon_id', 0)
         lang = request_dict.get('lang', 'en')
         lang = request_dict.get('lang', 'en')
         if not uid or not channel or not pay_type or not rank:
         if not uid or not channel or not pay_type or not rank:
             return response.json(444)
             return response.json(444)
@@ -1161,6 +1180,24 @@ class CloudStorageView(View):
             return response.json(10041)
             return response.json(10041)
 
 
         orderID = CommonService.createOrderID()
         orderID = CommonService.createOrderID()
+
+        #优惠券
+        if coupon_id:
+            couponObj = CouponModel.objects.filter(id=coupon_id, use_status=0, distributeTime__lte=nowTime,
+                                                   valid_time__gt=nowTime)
+            couponQuery = couponObj.values("id", "type", "coupon_discount")
+            if not couponQuery.exists():
+                return response.json(10049)
+            price = Decimal(price)
+            coupon_discount = Decimal(couponQuery[0]['coupon_discount'])
+            if couponQuery[0]['type'] == 1:  #折扣
+                price = coupon_discount/10 * price
+            elif couponQuery[0]['type'] == 2:  #抵扣
+                price = price - couponQuery[0]['coupon_discount']
+            if price < 0:
+                return response.json(10049)
+            couponObj.update(use_status=1)
+
         if pay_type == 1:
         if pay_type == 1:
             # 订阅周期扣款
             # 订阅周期扣款
             if(smqs[0]['cycle_config_id']):
             if(smqs[0]['cycle_config_id']):
@@ -1172,7 +1209,7 @@ class CloudStorageView(View):
                                            price=price, currency=currency, addTime=nowTime, updTime=nowTime,
                                            price=price, currency=currency, addTime=nowTime, updTime=nowTime,
                                            pay_url=subInfo['url'], isSelectDiscounts=is_select_discount,
                                            pay_url=subInfo['url'], isSelectDiscounts=is_select_discount,
                                            commodity_code=commodity_code, commodity_type=commodity_type,
                                            commodity_code=commodity_code, commodity_type=commodity_type,
-                                           rank_id=rank, plan_id=subInfo['plan_id'])
+                                           rank_id=rank, plan_id=subInfo['plan_id'],coupon_id=coupon_id)
                 return response.json(0, {"redirectUrl": subInfo['url'], "orderID": orderID})
                 return response.json(0, {"redirectUrl": subInfo['url'], "orderID": orderID})
 
 
             #正常扣款
             #正常扣款
@@ -1210,7 +1247,7 @@ class CloudStorageView(View):
                                                price=price, currency=currency, addTime=nowTime, updTime=nowTime,
                                                price=price, currency=currency, addTime=nowTime, updTime=nowTime,
                                                pay_url=approval_url, isSelectDiscounts=is_select_discount,
                                                pay_url=approval_url, isSelectDiscounts=is_select_discount,
                                                commodity_code=commodity_code, commodity_type=commodity_type,
                                                commodity_code=commodity_code, commodity_type=commodity_type,
-                                               rank_id=rank, paymentID=paymentID)
+                                               rank_id=rank, paymentID=paymentID,coupon_id=coupon_id)
                     return response.json(0, {"redirectUrl": approval_url, "orderID": orderID})
                     return response.json(0, {"redirectUrl": approval_url, "orderID": orderID})
             return response.json(10, 'generate_order_false')
             return response.json(10, 'generate_order_false')
         elif pay_type == 2:
         elif pay_type == 2:
@@ -1253,7 +1290,7 @@ class CloudStorageView(View):
                                                price=price, currency=currency, addTime=nowTime, updTime=nowTime,
                                                price=price, currency=currency, addTime=nowTime, updTime=nowTime,
                                                pay_url=redirectUrl, isSelectDiscounts=is_select_discount,
                                                pay_url=redirectUrl, isSelectDiscounts=is_select_discount,
                                                commodity_code=commodity_code, commodity_type=commodity_type,
                                                commodity_code=commodity_code, commodity_type=commodity_type,
-                                               rank_id=rank)
+                                               rank_id=rank,coupon_id=coupon_id)
 
 
                     return JsonResponse(status=200, data={'result_code': 0, 'reason': 'success',
                     return JsonResponse(status=200, data={'result_code': 0, 'reason': 'success',
                                                           'result': {"redirectUrl": redirectUrl, "orderID": orderID},
                                                           'result': {"redirectUrl": redirectUrl, "orderID": orderID},

+ 146 - 5
Controller/PaymentCycle.py

@@ -1,5 +1,5 @@
 from Ansjer.config import PAYPAL_CRD,SERVER_DOMAIN,SERVER_DOMAIN_SSL
 from Ansjer.config import PAYPAL_CRD,SERVER_DOMAIN,SERVER_DOMAIN_SSL
-from Model.models import PayCycleConfigModel,Order_Model, Store_Meal, UID_Bucket, PromotionRuleModel, Unused_Uid_Meal,Device_Info
+from Model.models import PayCycleConfigModel,Order_Model, Store_Meal, UID_Bucket, PromotionRuleModel, Unused_Uid_Meal,Device_Info, CouponModel
 from Service.CommonService import CommonService
 from Service.CommonService import CommonService
 from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 import requests
 import requests
@@ -125,6 +125,8 @@ class PaypalCycleNotify(View):
             return self.do_paypal_cycle_return(request_dict, response)
             return self.do_paypal_cycle_return(request_dict, response)
         elif operation == 'paypalCycleNotify':  # paypal 周期付款回调
         elif operation == 'paypalCycleNotify':  # paypal 周期付款回调
             return self.do_paypal_webhook_notify(request_dict,request, response)
             return self.do_paypal_webhook_notify(request_dict,request, response)
+        elif operation == 'test':  # paypal 周期付款回调
+            return self.do_test(request_dict,request, response)
     def do_paypal_cycle_return(self, request_dict, response):
     def do_paypal_cycle_return(self, request_dict, response):
         lang = request_dict.get('lang', 'en')
         lang = request_dict.get('lang', 'en')
         token = request_dict.get('token',None)
         token = request_dict.get('token',None)
@@ -153,7 +155,7 @@ class PaypalCycleNotify(View):
 
 
             order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
             order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
                                          "userID__userID",
                                          "userID__userID",
-                                         "userID__username")
+                                         "userID__username",'coupon_id')
             userid = order_list[0]['userID__userID']
             userid = order_list[0]['userID__userID']
             username = order_list[0]['userID__username']
             username = order_list[0]['userID__username']
             UID = order_list[0]['UID']
             UID = order_list[0]['UID']
@@ -225,6 +227,10 @@ class PaypalCycleNotify(View):
                 #     }
                 #     }
                 #     UIDMainUser.objects.create(**uid_main_dict)
                 #     UIDMainUser.objects.create(**uid_main_dict)
 
 
+                # 核销coupon
+                if order_list[0]['coupon_id']:
+                    CouponModel.objects.filter(id=order_list[0]['coupon_id']).update(use_status=1)
+
                 order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id,
                 order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id,
                                 promotion_rule_id=promotion_rule_id,agreement_id=agreement_id)
                                 promotion_rule_id=promotion_rule_id,agreement_id=agreement_id)
                 datetime = time.strftime("%Y-%m-%d", time.localtime())
                 datetime = time.strftime("%Y-%m-%d", time.localtime())
@@ -267,12 +273,147 @@ class PaypalCycleNotify(View):
         transmission_sig = header.get('paypal-transmission-sig',None)
         transmission_sig = header.get('paypal-transmission-sig',None)
         auth_algo = header.get('paypal-auth-algo',None)
         auth_algo = header.get('paypal-auth-algo',None)
         resource_type = json_obj.get('resource_type')
         resource_type = json_obj.get('resource_type')
+
+        json_str = '{"id":"WH-22P96595RY482870W-2B701244WV459014K","event_version":"1.0","create_time":"2022-01-06T05:56:33.126Z","resource_type":"sale","event_type":"PAYMENT.SALE.COMPLETED","summary":"Payment completed for $ 0.02 USD","resource":{"billing_agreement_id":"I-CR65R6YXS3VA","amount":{"total":"0.02","currency":"USD","details":{"subtotal":"0.02"}},"payment_mode":"INSTANT_TRANSFER","update_time":"2022-01-06T05:56:18Z","create_time":"2022-01-06T05:56:18Z","protection_eligibility_type":"ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE","transaction_fee":{"currency":"USD","value":"0.02"},"protection_eligibility":"ELIGIBLE","links":[{"method":"GET","rel":"self","href":"https://api.sandbox.paypal.com/v1/payments/sale/2FE30648Y2273061H"},{"method":"POST","rel":"refund","href":"https://api.sandbox.paypal.com/v1/payments/sale/2FE30648Y2273061H/refund"}],"id":"2FE30648Y2273061H","state":"completed","invoice_number":""},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-22P96595RY482870W-2B701244WV459014K","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-22P96595RY482870W-2B701244WV459014K/resend","rel":"resend","method":"POST"}]}'
+        header = "{'PATH_INFO': '/payCycle/paypalCycleNotify', 'wsgi.file_wrapper': <class 'gunicorn.http.wsgi.FileWrapper'>, 'CONTENT_LENGTH': '1226', 'wsgi.multiprocess': True, 'HTTP_PAYPAL_TRANSMISSION_TIME': '2022-01-06T05:56:36Z', 'wsgi.version': (1, 0), 'SERVER_NAME': '0.0.0.0', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.0', 'REMOTE_PORT': '42322', 'HTTP_HTTP_X_FORWARDED_FOR': '173.0.80.116', 'RAW_URI': '/payCycle/paypalCycleNotify', 'HTTP_X_REAL_IP': '173.0.80.116', 'HTTP_X_B3_SPANID': 'f37d2832010b10f2', 'REMOTE_ADDR': '127.0.0.1', 'wsgi.input': <gunicorn.http.body.Body object at 0x7ff31a5b92b0>, 'HTTP_PAYPAL_TRANSMISSION_SIG': 'JI+rFKqe9YqufExp/aJxkyRWG3II+4t6CSCWLHqNrjcd/FP729G0s8lFMPixnGpUemj4+WsJTbu29G4ZR3zxl+CwrlKhPQxe0fE0mUw+/AaBa6THpnoXEVwz9spI/kbH3dNmSXePfW0D5+HyVmWgkac23icxi4G92ZmmszPBzBdcNIc3BumXGSfJwX19cchta0VY7GnD5ePvW1FstPp9eC7NyhDH11xDpvM2qZZqhxH6hahIywVNA0gyNydkYbkbjnD+hGC+HrKKMx0Tpw8eGxUHReWJIEsiw7YCPLBwZIab5PV/+L4A/LscK/JicOeDealP+SKPJICZvinLHDzK0Q==', 'HTTP_PAYPAL_TRANSMISSION_ID': '688538e0-6eb5-11ec-a473-05e6d85b61e7', 'gunicorn.socket': <socket.socket fd=24, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8082), raddr=('127.0.0.1', 42322)>, 'HTTP_PAYPAL_AUTH_ALGO': 'SHA256withRSA', 'HTTP_PAYPAL_AUTH_VERSION': 'v2', 'wsgi.url_scheme': 'http', 'wsgi.errors': <gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7ff31a5b9a58>, 'QUERY_STRING': '', 'wsgi.multithread': False, 'HTTP_CORRELATION_ID': 'b696eaa58ea49', 'HTTP_ACCEPT': '*/*', 'HTTP_USER_AGENT': 'PayPal/AUHD-214.0-56138150', 'CONTENT_TYPE': 'application/json', 'HTTP_PAYPAL_CERT_URL': 'https://api.sandbox.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a594-7a8abba8', 'HTTP_CONNECTION': 'close', 'SERVER_PORT': '8082', 'HTTP_HOST': 'test.zositechc.cn:443', 'HTTP_X_FORWARDED_FOR': '173.0.80.116', 'SERVER_SOFTWARE': 'gunicorn/19.7.1', 'wsgi.run_once': False, 'REQUEST_METHOD': 'POST'}"
+
         if resource_type == 'plan':
         if resource_type == 'plan':
             paypalrestsdk.configure(PAYPAL_CRD)
             paypalrestsdk.configure(PAYPAL_CRD)
             response = paypalrestsdk.WebhookEvent.verify(
             response = paypalrestsdk.WebhookEvent.verify(
                 transmission_id, transmission_time, webhook_id, json_str, cert_url, transmission_sig, auth_algo)
                 transmission_id, transmission_time, webhook_id, json_str, cert_url, transmission_sig, auth_algo)
 
 
-        logger.info('response----------------')
-        logger.info(response)
-        return HttpResponse(json_obj.get('id'))
 
 
+
+            logger.info('response----------------')
+            logger.info(response)
+            return HttpResponse(json_obj.get('id'))
+
+
+    def do_test(self, request_dict, request, response):
+
+        json_str = '{"id":"WH-22P96595RY482870W-2B701244WV459014K","event_version":"1.0","create_time":"2022-01-06T05:56:33.126Z","resource_type":"sale","event_type":"PAYMENT.SALE.COMPLETED","summary":"Payment completed for $ 0.02 USD","resource":{"billing_agreement_id":"I-CR65R6YXS3VA","amount":{"total":"0.02","currency":"USD","details":{"subtotal":"0.02"}},"payment_mode":"INSTANT_TRANSFER","update_time":"2022-01-06T05:56:18Z","create_time":"2022-01-06T05:56:18Z","protection_eligibility_type":"ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE","transaction_fee":{"currency":"USD","value":"0.02"},"protection_eligibility":"ELIGIBLE","links":[{"method":"GET","rel":"self","href":"https://api.sandbox.paypal.com/v1/payments/sale/2FE30648Y2273061H"},{"method":"POST","rel":"refund","href":"https://api.sandbox.paypal.com/v1/payments/sale/2FE30648Y2273061H/refund"}],"id":"2FE30648Y2273061H","state":"completed","invoice_number":""},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-22P96595RY482870W-2B701244WV459014K","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-22P96595RY482870W-2B701244WV459014K/resend","rel":"resend","method":"POST"}]}'
+        header = "{'PATH_INFO': '/payCycle/paypalCycleNotify', 'wsgi.file_wrapper': <class 'gunicorn.http.wsgi.FileWrapper'>, 'CONTENT_LENGTH': '1226', 'wsgi.multiprocess': True, 'HTTP_PAYPAL_TRANSMISSION_TIME': '2022-01-06T05:56:36Z', 'wsgi.version': (1, 0), 'SERVER_NAME': '0.0.0.0', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.0', 'REMOTE_PORT': '42322', 'HTTP_HTTP_X_FORWARDED_FOR': '173.0.80.116', 'RAW_URI': '/payCycle/paypalCycleNotify', 'HTTP_X_REAL_IP': '173.0.80.116', 'HTTP_X_B3_SPANID': 'f37d2832010b10f2', 'REMOTE_ADDR': '127.0.0.1', 'wsgi.input': <gunicorn.http.body.Body object at 0x7ff31a5b92b0>, 'HTTP_PAYPAL_TRANSMISSION_SIG': 'JI+rFKqe9YqufExp/aJxkyRWG3II+4t6CSCWLHqNrjcd/FP729G0s8lFMPixnGpUemj4+WsJTbu29G4ZR3zxl+CwrlKhPQxe0fE0mUw+/AaBa6THpnoXEVwz9spI/kbH3dNmSXePfW0D5+HyVmWgkac23icxi4G92ZmmszPBzBdcNIc3BumXGSfJwX19cchta0VY7GnD5ePvW1FstPp9eC7NyhDH11xDpvM2qZZqhxH6hahIywVNA0gyNydkYbkbjnD+hGC+HrKKMx0Tpw8eGxUHReWJIEsiw7YCPLBwZIab5PV/+L4A/LscK/JicOeDealP+SKPJICZvinLHDzK0Q==', 'HTTP_PAYPAL_TRANSMISSION_ID': '688538e0-6eb5-11ec-a473-05e6d85b61e7', 'gunicorn.socket': <socket.socket fd=24, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8082), raddr=('127.0.0.1', 42322)>, 'HTTP_PAYPAL_AUTH_ALGO': 'SHA256withRSA', 'HTTP_PAYPAL_AUTH_VERSION': 'v2', 'wsgi.url_scheme': 'http', 'wsgi.errors': <gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7ff31a5b9a58>, 'QUERY_STRING': '', 'wsgi.multithread': False, 'HTTP_CORRELATION_ID': 'b696eaa58ea49', 'HTTP_ACCEPT': '*/*', 'HTTP_USER_AGENT': 'PayPal/AUHD-214.0-56138150', 'CONTENT_TYPE': 'application/json', 'HTTP_PAYPAL_CERT_URL': 'https://api.sandbox.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a594-7a8abba8', 'HTTP_CONNECTION': 'close', 'SERVER_PORT': '8082', 'HTTP_HOST': 'test.zositechc.cn:443', 'HTTP_X_FORWARDED_FOR': '173.0.80.116', 'SERVER_SOFTWARE': 'gunicorn/19.7.1', 'wsgi.run_once': False, 'REQUEST_METHOD': 'POST'}"
+
+        json_obj = json.loads(json_str)
+
+        # transmission_id = header.get('HTTP_PAYPAL_TRANSMISSION_ID',None)
+        # transmission_time = header.get('HTTP_PAYPAL_TRANSMISSION_TIME',None)
+        # webhook_id = '6TS30758D98835230'
+        # cert_url = header.get('HTTP_PAYPAL_CERT_URL',None)
+        # transmission_sig = header.get('HTTP_PAYPAL_TRANSMISSION_SIG',None)
+        # auth_algo = header.get('HTTP_PAYPAL_AUTH_ALGO',None)
+        # resource_type = json_obj.get('resource_type')
+
+        transmission_id = '688538e0-6eb5-11ec-a473-05e6d85b61e7'
+        transmission_time = '2022-01-06T05:56:36Z'
+        webhook_id = '6TS30758D98835230'
+        cert_url = 'https://api.sandbox.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a594-7a8abba8'
+        transmission_sig = 'JI+rFKqe9YqufExp/aJxkyRWG3II+4t6CSCWLHqNrjcd/FP729G0s8lFMPixnGpUemj4+WsJTbu29G4ZR3zxl+CwrlKhPQxe0fE0mUw+/AaBa6THpnoXEVwz9spI/kbH3dNmSXePfW0D5+HyVmWgkac23icxi4G92ZmmszPBzBdcNIc3BumXGSfJwX19cchta0VY7GnD5ePvW1FstPp9eC7NyhDH11xDpvM2qZZqhxH6hahIywVNA0gyNydkYbkbjnD+hGC+HrKKMx0Tpw8eGxUHReWJIEsiw7YCPLBwZIab5PV/+L4A/LscK/JicOeDealP+SKPJICZvinLHDzK0Q=='
+        auth_algo = 'SHA256withRSA'
+        resource_type = json_obj.get('resource_type')
+
+        if resource_type == 'sale':
+            paypalrestsdk.configure(PAYPAL_CRD)
+            response = paypalrestsdk.WebhookEvent.verify(
+                transmission_id, transmission_time, webhook_id, json_str, cert_url, transmission_sig, auth_algo)
+            if response:
+                try:
+                    agreement_id = json_obj.get('resource')['billing_agreement_id']
+                    order_qs = Order_Model.objects.filter(agreement_id=agreement_id, status=0)
+
+                    if not order_qs:
+                        return False
+                    order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
+                                                 "userID__userID",
+                                                 "userID__username")
+                    return HttpResponse(order_list)
+
+                    userid = order_list[0]['userID__userID']
+                    username = order_list[0]['userID__username']
+                    UID = order_list[0]['UID']
+                    channel = order_list[0]['channel']
+                    rank = order_list[0]['rank']
+                    smqs = Store_Meal.objects.filter(id=rank). \
+                        values("day", "bucket_id", "bucket__storeDay", "expire")
+                    bucketId = smqs[0]['bucket_id']
+                    if not smqs.exists():
+                        print("not smqs")
+                        red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                        if lang != 'cn':
+                            red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(
+                                SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
+                        return HttpResponseRedirect(red_url)
+                    # ##
+                    ubqs = UID_Bucket.objects.filter(uid=UID).values("id", "bucket_id", "bucket__storeDay",
+                                                                     "bucket__region",
+                                                                     "endTime", "use_status")
+                    expire = smqs[0]['expire']
+
+                    if order_list[0]['isSelectDiscounts'] == 1:
+                        expire = smqs[0]['expire'] * 2
+                    # 是否有促销
+                    nowTime = int(time.time())
+                    promotion = PromotionRuleModel.objects.filter(status=1, startTime__lte=nowTime,
+                                                                  endTime__gte=nowTime).values('id', 'ruleConfig')
+                    if promotion.exists():
+                        promotion_rule_id = promotion[0]['id']
+                        expire = expire * 2
+                    with transaction.atomic():
+                        if ubqs.exists():
+                            ubq = ubqs[0]
+                            if ubq['use_status'] == 1 and ubq['bucket_id'] == bucketId:  # 套餐使用中并且相同套餐叠加过期时间
+                                endTime = CommonService.calcMonthLater(expire, ubq['endTime'])
+                                UID_Bucket.objects.filter(id=ubq['id']).update \
+                                    (uid=UID, channel=channel, bucket_id=bucketId,
+                                     endTime=endTime, updateTime=nowTime)
+                            else:  # 已过期或者不相同的套餐加入未使用的关联套餐表
+                                has_unused = Unused_Uid_Meal.objects.filter(uid=UID, bucket_id=bucketId).values("id")
+                                nums = 2 if order_list[0]['isSelectDiscounts'] == 1 else 1
+                                if promotion.exists():
+                                    nums = nums + 1
+                                if has_unused.exists():
+                                    Unused_Uid_Meal.objects.filter(id=has_unused[0]['id']).update(num=F('num') + nums)
+                                else:
+                                    Unused_Uid_Meal.objects.create(uid=UID, channel=channel, addTime=nowTime, num=nums,
+                                                                   expire=smqs[0]['expire'], bucket_id=bucketId)
+                                UID_Bucket.objects.filter(id=ubq['id']).update(has_unused=1)
+                            uid_bucket_id = ubq['id']
+                        else:
+                            endTime = CommonService.calcMonthLater(expire)
+                            ub_cqs = UID_Bucket.objects.create \
+                                (uid=UID, channel=channel, bucket_id=bucketId, endTime=endTime, addTime=nowTime,
+                                 updateTime=nowTime, use_status=1)
+                            uid_bucket_id = ub_cqs.id
+
+                        dvq = Device_Info.objects.filter(UID=UID, vodPrimaryUserID='', vodPrimaryMaster='')
+                        if dvq.exists():
+                            dvq_set_update_dict = {
+                                'vodPrimaryUserID': userid,
+                                'vodPrimaryMaster': username
+                            }
+                            dvq.update(**dvq_set_update_dict)
+
+                        # uid_main_exist = UIDMainUser.objects.filter(UID=UID)
+                        # if not uid_main_exist.exists():
+                        #     uid_main_dict = {
+                        #         'UID': UID,
+                        #         'user_id': userid
+                        #     }
+                        #     UIDMainUser.objects.create(**uid_main_dict)
+
+                        order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id,
+                                        promotion_rule_id=promotion_rule_id, agreement_id=agreement_id)
+                        datetime = time.strftime("%Y-%m-%d", time.localtime())
+                        sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + UID + '设备在' + datetime + '已成功订阅云存套餐',
+                                             'Dear customer,you already subscribed the cloud storage package successfully for device ' + UID + ' on ' + time.strftime(
+                                                 "%b %dth,%Y", time.localtime())]
+
+                        CloudStorage.CloudStorageView.do_vod_msg_Notice(self, UID, channel, userid, lang,
+                                                                        sys_msg_text_list, 'SMS_219738485')
+                        return True
+                except Exception as e:
+                    print(repr(e))
+                    if order_qs:
+                        order_qs.update(status=10, promotion_rule_id=promotion_rule_id)
+                    return False
+        return False

+ 20 - 0
Model/models.py

@@ -624,6 +624,7 @@ class Order_Model(models.Model):
     promotion_rule_id = models.CharField(blank=True, max_length=64, default='', verbose_name='促销id')
     promotion_rule_id = models.CharField(blank=True, max_length=64, default='', verbose_name='促销id')
     plan_id = models.CharField(default='', blank=True, max_length=64, verbose_name=u'paypal计划id')
     plan_id = models.CharField(default='', blank=True, max_length=64, verbose_name=u'paypal计划id')
     agreement_id = models.CharField(default='', blank=True, max_length=64, verbose_name=u'paypal协议id')
     agreement_id = models.CharField(default='', blank=True, max_length=64, verbose_name=u'paypal协议id')
+    coupon_id = models.CharField(default='', blank=True, max_length=10, verbose_name=u'优惠券id')
 
 
     # 备用字段
     # 备用字段
     spare_4 = models.CharField(default='', blank=True, max_length=64, db_index=True, verbose_name=u'备用字段4')
     spare_4 = models.CharField(default='', blank=True, max_length=64, db_index=True, verbose_name=u'备用字段4')
@@ -638,6 +639,25 @@ class Order_Model(models.Model):
         verbose_name_plural = verbose_name
         verbose_name_plural = verbose_name
         ordering = ('-orderID',)
         ordering = ('-orderID',)
 
 
+class CouponModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='主键')
+    userID_id = models.CharField(default='', db_index=True, blank=True, max_length=32, verbose_name=u'用户ID')
+    use_status = models.SmallIntegerField(default=0, verbose_name='使用状态') #0未使用;1冻结;2已使用
+    type = models.SmallIntegerField(default=0, verbose_name='优惠类型') #1打折; 2抵扣
+    coupon_discount = models.DecimalField( max_digits=19, decimal_places=2, verbose_name='折扣力度')
+    distributeTime = models.IntegerField(verbose_name='发放到用户账户时间', default=0)
+    valid_time = models.PositiveIntegerField(default=9999999999, verbose_name='有效期间')  #超过有效期不可在使用;0永久
+    # use_limit = models.CharField(default=0, max_length=100, verbose_name='使用限制')  #0:所有服务都可使用; 1:云存;2:ai;
+    addTime = models.IntegerField(verbose_name='添加时间', default=0)
+
+    def __str__(self):
+        return self.id
+
+    class Meta:
+        db_table = 'coupon'
+        verbose_name = u'优惠券'
+        verbose_name_plural = verbose_name
+
 class PayCycleConfigModel(models.Model):
 class PayCycleConfigModel(models.Model):
     id = models.AutoField(primary_key=True, verbose_name='主键')
     id = models.AutoField(primary_key=True, verbose_name='主键')
     # name = models.CharField(default='',max_length=200, verbose_name='计划名字')
     # name = models.CharField(default='',max_length=200, verbose_name='计划名字')

+ 2 - 0
Object/ResponseObject.py

@@ -105,6 +105,7 @@ class ResponseObject(object):
             10046: 'Sorry, users who have activated cloud storage packages do not support logout at the moment, please contact customer service',
             10046: 'Sorry, users who have activated cloud storage packages do not support logout at the moment, please contact customer service',
             10047: 'Please delete all devices under your account first',
             10047: 'Please delete all devices under your account first',
             10048: 'Subscribe to the failure',
             10048: 'Subscribe to the failure',
+            10049: 'The coupon is not available',
         }
         }
         data_cn = {
         data_cn = {
             0: '成功',
             0: '成功',
@@ -203,6 +204,7 @@ class ResponseObject(object):
             10046: '已开通云存的用户,暂不支持注销,请联系客服',
             10046: '已开通云存的用户,暂不支持注销,请联系客服',
             10047: '请先删除您当前帐户下的所有设备',
             10047: '请先删除您当前帐户下的所有设备',
             10048: '订阅失败',
             10048: '订阅失败',
+            10049: '该优惠券不可用',
         }
         }
         if self.lang == 'cn':
         if self.lang == 'cn':
             msg = data_cn
             msg = data_cn