Parcourir la source

记录钩子行为
添加paypal钩子记录表

lang il y a 3 ans
Parent
commit
75f6b80580
2 fichiers modifiés avec 283 ajouts et 228 suppressions
  1. 264 228
      Controller/PaymentCycle.py
  2. 19 0
      Model/models.py

+ 264 - 228
Controller/PaymentCycle.py

@@ -1,5 +1,6 @@
 from Ansjer.config import PAYPAL_CRD,SERVER_DOMAIN,SERVER_DOMAIN_SSL,PAYPAL_WEB_HOOK_ID, PAYPAL_WEB_HOOK_ID_TWO
-from Model.models import PayCycleConfigModel,Order_Model, Store_Meal, UID_Bucket, PromotionRuleModel, Unused_Uid_Meal,Device_Info, CouponModel, Order_Model
+from Model.models import PayCycleConfigModel,Order_Model, Store_Meal, UID_Bucket, PromotionRuleModel,\
+    Unused_Uid_Meal,Device_Info, CouponModel, Order_Model, PaypalWebHookEvent
 from Service.CommonService import CommonService
 from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 import requests
@@ -35,8 +36,11 @@ class Paypal:
         return True
 
     def subscriptions(store_info,lang,orderID,price):
+        logger = logging.getLogger('pay')
         cycle_config = PayCycleConfigModel.objects.filter(id=store_info['cycle_config_id']).values()
         if not cycle_config:
+            logger.info('----创建订阅失败----')
+            logger.info('订阅配置失败')
             return False
         cal_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
         if lang != 'cn':
@@ -91,7 +95,8 @@ class Paypal:
             billing_plan.activate()  # 激活
             plan_id = billing_plan.id
         else:
-            print(billing_plan.error)
+            logger.info('----创建计划失败----')
+            logger.info(billing_plan.error)
             return False
 
         now_time = int(time.time())
@@ -120,7 +125,8 @@ class Paypal:
                 if link.rel == "approval_url":
                     return {"plan_id": plan_id, "url": link.href}
         else:
-            print(billing_agreement.error)
+            logger.info('----创建订阅失败----')
+            logger.info(billing_agreement.error)
             return False
 
 class PaypalCycleNotify(View):
@@ -142,22 +148,21 @@ class PaypalCycleNotify(View):
             return self.do_paypal_cycle_return(request_dict, response)
         elif operation == 'paypalCycleNotify':  # paypal 周期付款回调
             return self.do_paypal_webhook_notify(request_dict,request, response)
-        elif operation == 'subscriptionNotify':               # paypal 订阅相关回调
-            return self.do_subscription_notify(request_dict,request, response)
+        elif operation == 'subscriptionBreakNotify':               # paypal 订阅相关回调
+            return self.do_subscription_break_notify(request_dict,request, response)
     def do_paypal_cycle_return(self, request_dict, response):
         lang = request_dict.get('lang', 'en')
         token = request_dict.get('token',None)
 
         logger = logging.getLogger('pay')
-        logger.info('---------进入paypay自动续费异步回调')
+        logger.info('--------进入paypay首次订阅付款回调--------')
         logger.info(request_dict)
-
-
         paypalrestsdk.configure(PAYPAL_CRD)
         billing_agreement = paypalrestsdk.BillingAgreement()
         billing_agreement_response = billing_agreement.execute(token)
         if billing_agreement_response.error:
-            print(billing_agreement_response.error)
+            logger.info('----付款失败----')
+            logger.info(billing_agreement_response.error)
             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)
@@ -165,7 +170,7 @@ class PaypalCycleNotify(View):
 
         orderID = billing_agreement_response.description
 
-        logger.info('------------billing_agreement_response------')
+        logger.info('----订阅详情----')
         logger.info(billing_agreement_response)
 
         agreement_id = billing_agreement_response.id
@@ -175,7 +180,7 @@ class PaypalCycleNotify(View):
                                      "userID__userID",
                                      "userID__username", 'coupon_id')
         if not orderID:
-            print("not orderID")
+            logger.info('----订阅订单号失效----')
             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)
@@ -190,7 +195,7 @@ class PaypalCycleNotify(View):
                 values("day", "bucket_id", "bucket__storeDay", "expire")
             bucketId = smqs[0]['bucket_id']
             if not smqs.exists():
-                print("not smqs")
+                logger.info('----订阅套餐失效----')
                 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)
@@ -288,243 +293,274 @@ class PaypalCycleNotify(View):
 
     def do_paypal_webhook_notify(self, request_dict, request, response):
         logger = logging.getLogger('pay')
-        logger.info('---into---webhook_notify-------')
-        logger.info('---request_dict-------')
-        logger.info(request_dict)
+        logger.info('--------进入周期扣款钩子--------')
         json_agreement_str = request.body.decode("utf-8")
         json_obj = json.loads(json_agreement_str)
         header = request.META
         paypal_body = json_obj.get('resource')
-        logger.info('-----paypal_body------')
-        logger.info(paypal_body)
-        logger.info('-----paypal_header------')
+        logger.info('----主体信息----')
+        logger.info(json_agreement_str)
+        logger.info('----周期扣款头部信息----')
         logger.info(header)
+        try:
+            transmission_id = header.get('HTTP_PAYPAL_TRANSMISSION_ID', None)
+            transmission_time = header.get('HTTP_PAYPAL_TRANSMISSION_TIME', None)
+            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)
+            event_type = json_obj.get('event_type')
+            summary = json_obj.get('summary')
+            resource_type = json_obj.get('resource_type')
+            billing_agreement_id = paypal_body.get('billing_agreement_id')
+            paypal_transaction_id = paypal_body.get('id')
+            amount = paypal_body.get('amount')
+
+            if event_type != 'PAYMENT.SALE.COMPLETED':
+                logger.info('----钩子异常----')
+
+            # 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, PAYPAL_WEB_HOOK_ID, json_agreement_str, cert_url,
+                    transmission_sig, auth_algo)
+                logger.info('----验证签名----')
+                logger.info(response)
+                if not response:
+                    return HttpResponse('Fail', status=500)
 
-        billing_agreement_id = paypal_body.get('billing_agreement_id')
-        paypal_transaction_id = paypal_body.get('id')
-        amount = paypal_body.get('amount')
-        if not billing_agreement_id:
-            #普通支付,更新paypal交易id
-            paymentID = paypal_body.get('parent_payment')
-            if paymentID and paypal_transaction_id:
-                Order_Model.objects.filter(paymentID=paymentID).update(
+            else:
+                logger.info('----付款状态有误----')
+                logger.info(resource_type)
+                logger.info(paypal_body.get('state'))
+                return HttpResponse('Fail', status=500)
+
+            #记录钩子日志
+            PaypalWebHookEvent.objects.create(
+                webhook_event_id=json_obj.get('id'),
+                resource_type=json_obj.get('resource_type'),
+                event_type=1,
+                summary=summary,
+                agreement_id=billing_agreement_id,
+                trade_no=paypal_transaction_id,
+                resource=json_agreement_str,
+                created_time=int(time.time()),
+            )
+            if not billing_agreement_id:
+                #普通支付,更新paypal交易id
+                paymentID = paypal_body.get('parent_payment')
+                if paymentID and paypal_transaction_id:
+                    Order_Model.objects.filter(paymentID=paymentID).update(
+                        updTime=int(time.time()),
+                        trade_no=paypal_transaction_id
+                    )
+                return HttpResponse('success')
+
+            agreement_id = paypal_body.get('billing_agreement_id')
+            billing_agreement = paypalrestsdk.BillingAgreement.find(agreement_id)
+
+            # 订阅续费订单(如果完成周期数`==0,则是自动续费第一次扣款。否则说明是续费订单)
+            if billing_agreement.agreement_details.cycles_completed == '0':
+                logger.info('----订阅详情----')
+                logger.info(billing_agreement)
+                logger.info('订阅续费订单完成周期数==0,结束')
+                #更新order表,paypal的商家交易号
+                Order_Model.objects.filter(orderID=billing_agreement.description).update(
                     updTime=int(time.time()),
                     trade_no=paypal_transaction_id
                 )
-            return HttpResponse('success')
+                return HttpResponse('success')
+            oldOrderID = billing_agreement.description
+            order_qs = Order_Model.objects.filter(orderID=oldOrderID, status=1)
+            if not order_qs:
+                return HttpResponse('fail', status=500)
+            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','updTime')
+            nowTime = int(time.time())
+            if order_list[0]['addTime'] + 9200 > nowTime:  #避免续费订单重复支付
+                logger.info('----paypal重复异步回调----')
+                return HttpResponse('success')
 
-        transmission_id = header.get('HTTP_PAYPAL_TRANSMISSION_ID',None)
-        transmission_time = header.get('HTTP_PAYPAL_TRANSMISSION_TIME',None)
-        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')
+            logger.info('----走入订阅过程----')
 
-        # 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, PAYPAL_WEB_HOOK_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')
-                    billing_agreement = paypalrestsdk.BillingAgreement.find(agreement_id)
-
-                    # 订阅续费订单(如果完成周期数`==0,则是自动续费第一次扣款。否则说明是续费订单)
-                    if billing_agreement.agreement_details.cycles_completed == '0':
-                        logger.info('----billing_agreement----')
-                        logger.info(billing_agreement)
-                        logger.info('订阅续费订单完成周期数==0,结束')
-                        #更新order表,paypal的商家交易号
-                        Order_Model.objects.filter(orderID=billing_agreement.description).update(
-                            updTime=int(time.time()),
-                            trade_no=paypal_transaction_id
-                        )
-                        return HttpResponse('success')
-                    oldOrderID = billing_agreement.description
-                    order_qs = Order_Model.objects.filter(orderID=oldOrderID, status=1)
-                    if not order_qs:
-                        return HttpResponse('fail', status=500)
-                    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','updTime')
-                    nowTime = int(time.time())
-                    if order_list[0]['addTime'] + 9200 > nowTime:  #避免续费订单重复支付
-                        logger.info('-----------------------paypal重复异步回调')
-                        return HttpResponse('success')
-
-                    logger.info('-----走入订阅过程-------------')
-
-                    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', status=500)
-                    # ##
-                    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
-
-                        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'], ai_rank_id=1, trade_no=paypal_transaction_id)
-                        # 如果存在序列号,消息提示用序列号
-                        device_name = CommonService.query_serial_with_uid(uid=UID)
-                        datetime = time.strftime("%Y-%m-%d", time.localtime())
-                        sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + device_name + '设备在' + datetime + '已成功续订云存套餐',
-                                             'Dear customer,you already subscribed the cloud storage package successfully for device ' + device_name + ' on ' + time.strftime(
-                                                 "%b %dth,%Y", time.localtime())]
-
-                        if order_list[0]['payType'] == 1:
-                            lang = 'en'
+            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', status=500)
+            # ##
+            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:
-                            lang = 'cn'
-                        CloudStorage.CloudStorageView().do_vod_msg_Notice(UID, channel, userid, lang,
-                                                                        sys_msg_text_list, 'SMS_219738485')
-                        logger.info('-----------------------result')
-                        logger.info('success')
-
-                        #更新agreement
-                        billing_agreement_update_attributes = [
-                            {
-                                "op": "replace",
-                                "path": "/",
-                                "value": {
-                                    "description": orderID,
-                                }
-                            }
-                        ]
-                        billing_agreement.replace(billing_agreement_update_attributes)
-                        logger.info('{UID}成功续费paypal:----'.format(UID=UID))
-                        return HttpResponse('success')
-                except Exception as e:
-                    print(e)
-                    logger.info('-----------------------paypal异步回调失败')
-                    logger.info(e)
-                    logger.info('do_paypal_webhook_notify支付失败:----')
-                    logger.info("错误行数:{errLine}".format(errLine=e.__traceback__.tb_lineno))
-                    logger.info(repr(e))
-                    return HttpResponse('fail', status=500)
-        return HttpResponse('fail')
-
-
-    def do_subscription_notify(self, request_dict, request, response):
+                            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)
+                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'], ai_rank_id=1, trade_no=paypal_transaction_id)
+                # 如果存在序列号,消息提示用序列号
+                device_name = CommonService.query_serial_with_uid(uid=UID)
+                datetime = time.strftime("%Y-%m-%d", time.localtime())
+                sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + device_name + '设备在' + datetime + '已成功续订云存套餐',
+                                     'Dear customer,you already subscribed the cloud storage package successfully for device ' + device_name + ' 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(UID, channel, userid, lang,
+                                                                sys_msg_text_list, 'SMS_219738485')
+                logger.info('----周期扣款结果----')
+                logger.info('success')
+
+                #更新agreement
+                billing_agreement_update_attributes = [
+                    {
+                        "op": "replace",
+                        "path": "/",
+                        "value": {
+                            "description": orderID,
+                        }
+                    }
+                ]
+                billing_agreement.replace(billing_agreement_update_attributes)
+                logger.info('{UID}成功续费paypal:----'.format(UID=UID))
+                return HttpResponse('success')
+        except Exception as e:
+            print(e)
+            logger.info('----周期扣款钩子失败----')
+            logger.info('do_paypal_webhook_notify支付失败:----')
+            logger.info("错误行数:{errLine}".format(errLine=e.__traceback__.tb_lineno))
+            logger.info(repr(e))
+            return HttpResponse('fail', status=500)
+
+
+    def do_subscription_break_notify(self, request_dict, request, response):
         logger = logging.getLogger('pay')
-        logger.info('---into---do_subscription_notify-------')
+        logger.info('--------进入订阅失败,付款失败,暂停--------')
         json_agreement_str = request.body.decode("utf-8")
         json_obj = json.loads(json_agreement_str)
-        logger.info('---json_obj-------')
-        logger.info(json_agreement_str)
         header = request.META
         paypal_body = json_obj.get('resource')
-        logger.info('-----subscription_body------')
-        logger.info(paypal_body)
-        logger.info('-----subscription_header------')
+        logger.info('----主体信息----')
+        logger.info(json_agreement_str)
+        logger.info('----进入订阅失败头部信息----')
         logger.info(header)
-
-        billing_agreement_id = paypal_body.get('billing_agreement_id')
-        paypal_transaction_id = paypal_body.get('id')
-        amount = paypal_body.get('amount')
-        # if not billing_agreement_id:
-        #     #普通支付,更新paypal交易id
-        #     paymentID = paypal_body.get('parent_payment')
-        #     if paymentID and paypal_transaction_id:
-        #         Order_Model.objects.filter(paymentID=paymentID).update(
-        #             updTime=int(time.time()),
-        #             trade_no=paypal_transaction_id
-        #         )
-        #     return HttpResponse('success')
-
-        transmission_id = header.get('HTTP_PAYPAL_TRANSMISSION_ID',None)
-        transmission_time = header.get('HTTP_PAYPAL_TRANSMISSION_TIME',None)
-        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')
-
-        logger.info(resource_type)
-        logger.info(paypal_body.get('state'))
-
-        # self.get_plan_desc('P-4CG284532S612303METMEINY')
-        if resource_type == 'sale' and paypal_body.get('state') == 'completed':
+        try:
+            transmission_id = header.get('HTTP_PAYPAL_TRANSMISSION_ID', None)
+            transmission_time = header.get('HTTP_PAYPAL_TRANSMISSION_TIME', None)
+            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)
+            event_type = json_obj.get('event_type')
+            summary = json_obj.get('summary')
+            resource_type = json_obj.get('resource_type')
+            billing_agreement_id = paypal_body.get('billing_agreement_id')
+            paypal_transaction_id = paypal_body.get('id')
+            amount = paypal_body.get('amount')
+
+            # self.get_plan_desc('P-4CG284532S612303METMEINY')
             paypalrestsdk.configure(PAYPAL_CRD)
             response = paypalrestsdk.WebhookEvent.verify(
-                transmission_id, transmission_time, PAYPAL_WEB_HOOK_ID_TWO, json_agreement_str, cert_url, transmission_sig, auth_algo)
-            logger.info('-----------------------verify')
+                transmission_id, transmission_time, PAYPAL_WEB_HOOK_ID_TWO, json_agreement_str, cert_url,
+                transmission_sig, auth_algo)
+            logger.info('----验证签名----')
             logger.info(response)
-            if response:
-                try:
-                    agreement_id = paypal_body.get('billing_agreement_id')
-                    billing_agreement = paypalrestsdk.BillingAgreement.find(agreement_id)
-
-                    logger.info('-----------------------billing_agreement')
-                    logger.info(billing_agreement)
-                except:
-                    return HttpResponse('not billing_agreement')
+            if not response:
+                return HttpResponse('Fail', status=500)
+            event_type_code = 0
+            if event_type == 'PAYMENT.SALE.COMPLETED':
+                event_type_code = 1
+            elif event_type == 'PAYMENT.SALE.REVERSED':
+                event_type_code = 2
+            elif event_type == 'BILLING.SUBSCRIPTION.CANCELLED':
+                event_type_code = 3
+            elif event_type == 'BILLING.SUBSCRIPTION.SUSPENDED':
+                event_type_code = 4
+            elif event_type == 'Subscription payment failed':
+                event_type_code = 5
+
+            # 记录钩子日志
+            PaypalWebHookEvent.objects.create(
+                webhook_event_id=json_obj.get('id'),
+                resource_type=json_obj.get('resource_type'),
+                event_type=event_type_code,
+                summary=summary,
+                agreement_id=billing_agreement_id,
+                trade_no=paypal_transaction_id,
+                resource=json_agreement_str,
+                created_time=int(time.time()),
+            )
+            return HttpResponse('success')
+        except Exception as e:
+            print(e)
+            logger.info('----进入订阅失败----')
+            logger.info('do_paypal_webhook_notify支付失败:----')
+            logger.info("错误行数:{errLine}".format(errLine=e.__traceback__.tb_lineno))
+            logger.info(repr(e))
+            return HttpResponse('fail', status=500)
 
 
 

+ 19 - 0
Model/models.py

@@ -2275,4 +2275,23 @@ class DeviceOTAUpgradeRecord(models.Model):
         db_table = 'device_OTA_upgrade_record'
         verbose_name = '设备OTA升级记录'
         verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+class PaypalWebHookEvent(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    webhook_event_id = models.CharField(max_length=200, blank=True, verbose_name='webhook事件ID', default='')
+    resource_type = models.CharField(max_length=11, verbose_name='资源类型', blank=True, default='')
+    ## event_type: 1=PAYMENT.SALE.COMPLETED(付款,订阅成功后钩子),2=PAYMENT.SALE.REVERSED(付款撤销)
+    ## event_type: 3=BILLING.SUBSCRIPTION.CANCELLED(订阅取消),4=BILLING.SUBSCRIPTION.SUSPENDED(订阅暂停),5=Subscription payment failed(订阅付款失败)
+    event_type = models.SmallIntegerField(default=0, verbose_name='事件类型')
+    summary = models.CharField(max_length=500, verbose_name='事件概要', blank=True, default='')
+    agreement_id = models.CharField(max_length=22, db_index=True, verbose_name='订阅ID', blank=True, default='')
+    trade_no = models.CharField(max_length=22, db_index=True, verbose_name='交易ID', blank=True, default='')
+    resource = models.TextField(blank=True, default='', verbose_name=u'资源详情')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+
+    class Meta:
+        db_table = 'paypal_webhook_event'
+        verbose_name = 'paypal钩子事件记录表'
+        verbose_name_plural = verbose_name
         ordering = ('id',)