ソースを参照

更新自动续费没有抵扣优惠券问题

lang 3 年 前
コミット
0c701134cc
2 ファイル変更218 行追加85 行削除
  1. 7 6
      Controller/CloudStorage.py
  2. 211 79
      Controller/PaymentCycle.py

+ 7 - 6
Controller/CloudStorage.py

@@ -1128,14 +1128,14 @@ class CloudStorageView(View):
         dv_qs = Device_Info.objects.filter(userID_id=userID, UID=uid, isShare=False, isExist=1).values(
             'vodPrimaryUserID',
             'vodPrimaryMaster')
-        # if not dv_qs.exists():
-        #     return response.json(12)
+        if not dv_qs.exists():
+            return response.json(12)
 
         dvq = Device_Info.objects.filter(UID=uid)
         dvq = dvq.filter(~Q(vodPrimaryUserID='')).values('vodPrimaryUserID')
-        # if dvq.exists():
-        #     if dvq[0]['vodPrimaryUserID'] != userID:
-        #         return response.json(10033)
+        if dvq.exists():
+            if dvq[0]['vodPrimaryUserID'] != userID:
+                return response.json(10033)
 
         nowTime = int(time.time())
 
@@ -1196,7 +1196,8 @@ class CloudStorageView(View):
             # return HttpResponse(price)
             # 订阅周期扣款
             if(smqs[0]['cycle_config_id']):
-                subInfo = Paypal.subscriptions(store_info=smqs[0],lang=lang,orderID=orderID)
+                subInfo = Paypal.subscriptions(store_info=smqs[0],lang=lang,orderID=orderID,price=price)
+                #通过plan_id和agrement_id查询,是否活跃状态,活跃状态定制订阅
                 if not subInfo:
                     return response.json(10048)
                 Order_Model.objects.create(orderID=orderID, UID=uid, channel=channel, userID_id=userID,

+ 211 - 79
Controller/PaymentCycle.py

@@ -14,11 +14,12 @@ from django.db.models import Q, F, Count
 from paypalrestsdk.notifications import WebhookEvent
 import logging
 import json
+from paypalrestsdk import BillingPlan
 
 
 #周期扣款相关
 class Paypal:
-    def subscriptions(store_info,lang,orderID):
+    def subscriptions(store_info,lang,orderID,price):
         cycle_config = PayCycleConfigModel.objects.filter(id=store_info['cycle_config_id']).values()
         if not cycle_config:
             return False
@@ -40,7 +41,7 @@ class Paypal:
                 # "notify_url": "http://www.notify.com",  #通知客户协议已创建的 URL。只读并保留供将来使用。
                 "setup_fee": {
                     "currency": store_info['currency'],
-                    "value": store_info['price'],
+                    "value": price,
                 }
             },
             "name": store_info['lang__content'],
@@ -257,76 +258,194 @@ class PaypalCycleNotify(View):
 
     def do_paypal_webhook_notify(self, request_dict, request, response):
         logger = logging.getLogger('info')
-        json_str = request.body.decode("utf-8")
-        logger.info('json_str----------------')
-        logger.info(json_str)
-
+        json_agreement_str = request.body.decode("utf-8")
+        json_obj = json.loads(json_agreement_str)
         header = request.META
-        logger.info('json_str----------------')
-        logger.info(header)
-        # json_str = '{"id":"WH-9K090101YP819052B-3LD205733F387905X","event_version":"1.0","create_time":"2022-01-05T08:17:36.937Z","resource_type":"plan","event_type":"BILLING.PLAN.CREATED","summary":"A billing plan was created","resource":{"merchant_preferences":{"setup_fee":{"currency":"USD","value":"0.02"},"return_url":"http://127.0.0.1:8000/payCycle/paypalCycleReturn?lang=en","cancel_url":"http://127.0.0.1:8000/web/paid2/en_fail.html","auto_bill_amount":"YES","initial_fail_amount_action":"CANCEL","max_fail_attempts":"1"},"update_time":"2022-01-05T08:17:15.829Z","create_time":"2022-01-05T08:17:15.129Z","name":"One year package","description":"20220105161712830917","links":[{"href":"https://api.sandbox.paypal.com/v1/payments/billing-plans/P-4RE38399B6473962EFFIEW6I","rel":"self","method":"GET"}],"payment_definitions":[{"id":"PD-8DC78035HJ0448121FFIEW6I","name":"Video save for 7 day","type":"REGULAR","frequency":"Day","amount":{"currency":"USD","value":"0.02"},"cycles":"0","frequency_interval":"1"}],"id":"P-4RE38399B6473962EFFIEW6I","state":"ACTIVE","type":"INFINITE"},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9K090101YP819052B-3LD205733F387905X","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9K090101YP819052B-3LD205733F387905X/resend","rel":"resend","method":"POST"}]}'
-        json_obj = json.loads(json_str)
-        transmission_id = header.get('paypal-transmission-id',None)
-        transmission_time = header.get('paypal-transmission-id',None)
-        webhook_id = '9RW011891A1707801'
-        cert_url = header.get('paypal-cert-url',None)
-        transmission_sig = header.get('paypal-transmission-sig',None)
-        auth_algo = header.get('paypal-auth-algo',None)
-        resource_type = json_obj.get('resource_type')
+        paypal_body = json_obj.get('resource')
+
+        billing_agreement_id = paypal_body.get('billing_agreement_id')
+        amount = paypal_body.get('amount')
+        if not billing_agreement_id:
+            return HttpResponse('success')
 
-        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'}"
+        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')
 
-        if resource_type == 'plan':
+        # self.get_plan_desc('P-4CG284532S612303METMEINY')
+        if resource_type == 'sale' and paypal_body.get('state') == 'completed':
             paypalrestsdk.configure(PAYPAL_CRD)
             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_agreement_str, cert_url, transmission_sig, auth_algo)
+            logger.info('-----------------------verify')
+            logger.info(response)
+            if response:
+                try:
+                    agreement_id = paypal_body.get('billing_agreement_id')
+                    order_qs = Order_Model.objects.filter(agreement_id=agreement_id, status=1)
+                    if not order_qs:
+                        return HttpResponse('failss')
+                    order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
+                                                 "userID__userID","uid_bucket_id",
+                                                 "userID__username",'plan_id','addTime','desc','payType','currency','commodity_type')
+                    plan_id = order_list[0]['plan_id']
+                    # plan_cycle = self.get_plan_desc(plan_id)
+                    # 订阅续费订单(如果查到的本地订单已经付过了且包中的完成周期数`不是0, 则说明是续费订单, 本地可以新建一个订单标记是续费的)
+                    nowTime = int(time.time())
+                    if(order_list[0]['addTime']+600 > nowTime):
+                        return HttpResponse('success')
 
+                    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():
+                        return HttpResponse('fail')
+                    # ##
+                    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 = 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
 
-            logger.info('response----------------')
-            logger.info(response)
-            return HttpResponse(json_obj.get('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)
+                        orderID = CommonService.createOrderID()
+                        Order_Model.objects.create(orderID=orderID, UID=UID, channel=channel, userID_id=userid,
+                                                   desc=order_list[0]['desc'], payType=order_list[0]['payType'], payTime=nowTime,
+                                                   price=amount.get('total'), currency=order_list[0]['currency'], addTime=nowTime, updTime=nowTime,
+                                                   pay_url='', isSelectDiscounts=0,
+                                                   commodity_code=order_list[0]['commodity_code'], commodity_type=order_list[0]['commodity_type'],
+                                                   rank_id=rank, paymentID='', coupon_id='',uid_bucket_id=uid_bucket_id,status=1,agreement_id=agreement_id,plan_id=order_list[0]['plan_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())]
 
-    def do_test(self, request_dict, request, response):
+                        if order_list[0]['payType'] == 1:
+                            lang = 'en'
+                        else:
+                            lang = 'cn'
+                        CloudStorage.CloudStorageView.do_vod_msg_Notice(self, UID, channel, userid, lang,
+                                                                        sys_msg_text_list, 'SMS_219738485')
+                        logger.info('-----------------------result')
+                        logger.info('success')
+                        return HttpResponse('success')
+                except Exception as e:
+                    print(e)
+                    return HttpResponse('fail')
+        return HttpResponse('fail')
 
-        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)
+    def do_test(self, request_dict, request, response):
+        #normal_pay
+        # json_str = '{"id":"WH-8SU832847J141682K-0FF265943E8692615","event_version":"1.0","create_time":"2022-01-10T06:31:49.863Z","resource_type":"sale","event_type":"PAYMENT.SALE.COMPLETED","summary":"Payment completed for $ 0.02 USD","resource":{"amount":{"total":"0.02","currency":"USD","details":{"subtotal":"0.02"}},"payment_mode":"INSTANT_TRANSFER","create_time":"2022-01-10T06:31:45Z","transaction_fee":{"currency":"USD","value":"0.02"},"parent_payment":"PAYID-MHN5E5Y1RH70069CT417990V","update_time":"2022-01-10T06:31:45Z","protection_eligibility_type":"ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE","application_context":{"related_qualifiers":[{"id":"0FJ93448LU7282046","type":"CART"}]},"protection_eligibility":"ELIGIBLE","links":[{"method":"GET","rel":"self","href":"https://api.sandbox.paypal.com/v1/payments/sale/6N498138TH641260G"},{"method":"POST","rel":"refund","href":"https://api.sandbox.paypal.com/v1/payments/sale/6N498138TH641260G/refund"},{"method":"GET","rel":"parent_payment","href":"https://api.sandbox.paypal.com/v1/payments/payment/PAYID-MHN5E5Y1RH70069CT417990V"}],"id":"6N498138TH641260G","state":"completed","invoice_number":""},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-8SU832847J141682K-0FF265943E8692615","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-8SU832847J141682K-0FF265943E8692615/resend","rel":"resend","method":"POST"}]}'
+        json_agreement_str = '{"id":"WH-9BE23393R5338163R-48P08088YL173821A","event_version":"1.0","create_time":"2022-01-10T10:27:42.925Z","resource_type":"sale","event_type":"PAYMENT.SALE.COMPLETED","summary":"Payment completed for $ 0.02 USD","resource":{"billing_agreement_id":"I-K8PCK2NJC6N6","amount":{"total":"0.02","currency":"USD","details":{"subtotal":"0.02"}},"payment_mode":"INSTANT_TRANSFER","update_time":"2022-01-10T10:27:19Z","create_time":"2022-01-10T10:27:19Z","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/4H259512Y67055105"},{"method":"POST","rel":"refund","href":"https://api.sandbox.paypal.com/v1/payments/sale/4H259512Y67055105/refund"}],"id":"4H259512Y67055105","state":"completed","invoice_number":""},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9BE23393R5338163R-48P08088YL173821A","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9BE23393R5338163R-48P08088YL173821A/resend","rel":"resend","method":"POST"}]}'
+        header = {'wsgi.file_wrapper': '<class gunicorn.http.wsgi.FileWrapper>', 'wsgi.version': '(1, 0)', 'HTTP_CONNECTION': 'close', 'wsgi.url_scheme': 'http', 'HTTP_PAYPAL_CERT_URL': 'https://api.sandbox.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a594-7a8abba8', 'HTTP_PAYPAL_TRANSMISSION_ID': '022fbbc0-7139-11ec-afa1-0114a54fc1fc', 'SERVER_NAME': '0.0.0.0', 'HTTP_CORRELATION_ID': 'be4c80f0a6c05', 'REMOTE_ADDR': '127.0.0.1', 'HTTP_PAYPAL_TRANSMISSION_SIG': 'IM3Xwyjw5YUgBKPsgyjPdMAh6DSFTtqdwy8zbJBXBhFyB77B6mEqnRfhtEgwwBhag6HsStmKBGIScFhs5Nuraru7DbT4+7Tu5fNx3oQIHeHtR/FYZoQcv86bjZ9cq+Xo04HmhUfgBAsSetS+CuY5TsN60d1m8Hld1MTDjk1UuSbk8HA3dBLiMzWT7wUw3/SUau/C7TtLnWGmdJlkFne+b/5s0+HsuXn3wQQCDIHO0sBMBo72NdlyMlLIunSdoEJ61pKi2U1jQ6qqe/59IrY2q4ufx9D6JZ4bUB6z3NQZ+Gm7zrlKabT6HkVovLJbuBgRgRWWUoY02CuVXZ9w4AzVNQ==', 'REMOTE_PORT': '58060', 'HTTP_ACCEPT': '*/*', 'CONTENT_TYPE': 'application/json', 'HTTP_USER_AGENT': 'PayPal/AUHR-214.0-56015767', 'SCRIPT_NAME': '', 'HTTP_X_FORWARDED_FOR': '173.0.80.117', 'HTTP_HOST': 'test.zositechc.cn:443', 'wsgi.multiprocess': True, 'SERVER_PROTOCOL': 'HTTP/1.0', 'PATH_INFO': '/payCycle/paypalCycleNotify', 'SERVER_SOFTWARE': 'gunicorn/19.7.1', 'wsgi.input': '<gunicorn.http.body.Body object at 0x7fb966cddfd0>', 'REQUEST_METHOD': 'POST', 'wsgi.errors': '<gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7fb966cdda90>', 'CONTENT_LENGTH': '1226', 'wsgi.run_once': False, 'HTTP_X_B3_SPANID': 'e8ede80526720f95', 'HTTP_PAYPAL_AUTH_ALGO': 'SHA256withRSA', 'QUERY_STRING': '', 'HTTP_PAYPAL_TRANSMISSION_TIME': '2022-01-09T10:43:40Z', 'wsgi.multithread': False, 'HTTP_HTTP_X_FORWARDED_FOR': '173.0.80.117', 'HTTP_X_REAL_IP': '173.0.80.117', 'RAW_URI': '/payCycle/paypalCycleNotify', 'HTTP_PAYPAL_AUTH_VERSION': 'v2', 'gunicorn.socket': '<socket.socket fd=51, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=(127.0.0.1, 8082), raddr=(127.0.0.1, 58060)>', 'SERVER_PORT': '8082'}
+
+
+        json_obj = json.loads(json_agreement_str)
+        paypal_body = json_obj.get('resource')
+        billing_agreement_id = paypal_body.get('billing_agreement_id')
+        amount = paypal_body.get('amount')
+        if not billing_agreement_id:
+            return HttpResponse('success')
+
+        nowTime = int(time.time())
+        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')
+        # return HttpResponse(resource_type)
 
-        # 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'
+        transmission_id = 'f42509f0-71ff-11ec-a473-05e6d85b61e7'
+        transmission_time = '2022-01-10T10:27:46Z'
+        webhook_id = '3J888119TD851704M'
         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=='
+        transmission_sig = 'R6sBDhsoq5+FRQHWe+8tSeKJMlRDnt9F2SlWlWVVEfDu9mvQ0zKl74bwcN1zMbvH4o7fWVNbwkcPW70/t4O0YBsj9BcMwL8hDxcuWuHp20RBzaI2dlBpdPEke19wr/fhJKGZCDYuvptV2RJGCSePBn3gKs7hkY5ribELPDqHuajlgVxMmoXm/+CHrMmPo6gSGgTuEMzEn4/ENuj3uJoCkcYqsFx3tUHg6eakUvQ+vYAyflRx9hX7QXEQHp15PWLgGzHkm9zGmnX6YoG5keo5MbJEYh9LfHJjmHmHVErvOtHebJxfTEDZwGoqw+WHr3KqnP4L1gaUj7XIXsQzbiFTBg=='
         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)
+        resource_type = 'sale'
+        # self.get_plan_desc('P-4CG284532S612303METMEINY')
+        if resource_type == 'sale' and paypal_body.get('state') == 'completed':
+            # paypalrestsdk.configure(PAYPAL_CRD)
+            # response = paypalrestsdk.WebhookEvent.verify(
+            #     transmission_id, transmission_time, webhook_id, json_agreement_str, cert_url, transmission_sig, auth_algo)
+            response = True
             if response:
                 try:
-                    agreement_id = json_obj.get('resource')['billing_agreement_id']
-                    order_qs = Order_Model.objects.filter(agreement_id=agreement_id, status=0)
-
+                    agreement_id = paypal_body.get('billing_agreement_id')
+                    order_qs = Order_Model.objects.filter(agreement_id=agreement_id, status=1)
                     if not order_qs:
-                        return False
+                        return HttpResponse('failss')
                     order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
-                                                 "userID__userID",
-                                                 "userID__username")
-                    return HttpResponse(order_list)
+                                                 "userID__userID","uid_bucket_id",
+                                                 "userID__username",'plan_id','addTime','desc','payType','currency','commodity_type')
+                    plan_id = order_list[0]['plan_id']
+                    # plan_cycle = self.get_plan_desc(plan_id)
+                    # 订阅续费订单(如果查到的本地订单已经付过了且包中的完成周期数`不是0, 则说明是续费订单, 本地可以新建一个订单标记是续费的)
+                    nowTime = int(time.time())
+                    if(order_list[0]['addTime']+600 > nowTime):
+                        return HttpResponse('success')
 
                     userid = order_list[0]['userID__userID']
                     username = order_list[0]['userID__username']
@@ -337,27 +456,22 @@ class PaypalCycleNotify(View):
                         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)
+                        return HttpResponse('fail')
                     # ##
                     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
+                    # 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
+                    # 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]
@@ -368,9 +482,9 @@ class PaypalCycleNotify(View):
                                      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
+                                # nums = 2 if order_list[0]['isSelectDiscounts'] == 1 else 1
+                                # if promotion.exists():
+                                nums = 1
                                 if has_unused.exists():
                                     Unused_Uid_Meal.objects.filter(id=has_unused[0]['id']).update(num=F('num') + nums)
                                 else:
@@ -400,20 +514,38 @@ class PaypalCycleNotify(View):
                         #         '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)
+                        orderID = CommonService.createOrderID()
+                        Order_Model.objects.create(orderID=orderID, UID=UID, channel=channel, userID_id=userid,
+                                                   desc=order_list[0]['desc'], payType=order_list[0]['payType'], payTime=nowTime,
+                                                   price=amount.get('total'), currency=order_list[0]['currency'], addTime=nowTime, updTime=nowTime,
+                                                   pay_url='', isSelectDiscounts=0,
+                                                   commodity_code=order_list[0]['commodity_code'], commodity_type=order_list[0]['commodity_type'],
+                                                   rank_id=rank, paymentID='', coupon_id='',uid_bucket_id=uid_bucket_id,status=1,agreement_id=agreement_id,plan_id=order_list[0]['plan_id'])
                         datetime = time.strftime("%Y-%m-%d", time.localtime())
-                        sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + UID + '设备在' + datetime + '已成功订阅云存套餐',
+                        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())]
 
+                        if order_list[0]['payType'] == 1:
+                            lang = 'en'
+                        else:
+                            lang = 'cn'
                         CloudStorage.CloudStorageView.do_vod_msg_Notice(self, UID, channel, userid, lang,
                                                                         sys_msg_text_list, 'SMS_219738485')
-                        return True
+                        return HttpResponse('success')
                 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
+                    print(e)
+                    return HttpResponse('fail')
+        return HttpResponse('fail')
+
+
+    def get_plan_desc(self,plan_id):
+        paypalrestsdk.configure(PAYPAL_CRD)
+        billing_plan = paypalrestsdk.BillingPlan.find(plan_id)
+        print("Got Billing Plan Details for Billing Plan[%s]" % (billing_plan.id))
+        exit()
+
+
+
+
+