Browse Source

修复paypal订阅付款时取消问题

lang 3 years ago
parent
commit
ead1b865c4
1 changed files with 71 additions and 68 deletions
  1. 71 68
      Controller/PaymentCycle.py

+ 71 - 68
Controller/PaymentCycle.py

@@ -1,6 +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, PaypalWebHookEvent
+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, PaypalWebHookEvent
 from Service.CommonService import CommonService
 from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
 import requests
@@ -21,12 +21,12 @@ import json
 from paypalrestsdk import BillingPlan
 
 
-#周期扣款相关
+# 周期扣款相关
 class Paypal:
-    #检查是否有重复订阅
-    def checkSubscriptions(userID,uid,rank):
-        hasOrder = Order_Model.objects.filter(UID=uid,rank=rank)
-        hasOrder = hasOrder.filter(~Q(agreement_id='')).values('agreement_id','orderID').order_by('-addTime')[0:1]
+    # 检查是否有重复订阅
+    def checkSubscriptions(userID, uid, rank):
+        hasOrder = Order_Model.objects.filter(UID=uid, rank=rank)
+        hasOrder = hasOrder.filter(~Q(agreement_id='')).values('agreement_id', 'orderID').order_by('-addTime')[0:1]
         if not hasOrder.exists():
             return True
         paypalrestsdk.configure(PAYPAL_CRD)
@@ -35,7 +35,7 @@ class Paypal:
             return False
         return True
 
-    def subscriptions(store_info,lang,orderID,price):
+    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:
@@ -104,9 +104,9 @@ class Paypal:
             start_date_timestamp = now_time + 86400 - 3600  # 下次扣款为明天,提前1个小时扣款
             start_date_str = CommonService.timestamp_to_str(start_date_timestamp, "%Y-%m-%dT%H:%M:%SZ")
         elif cycle_config[0]['frequency'] == "MONTH":
-            start_date_timestamp = CommonService.calcMonthLater(1, now_time) - (5 * 86400) #下次扣款为下个月提前5天扣款
+            start_date_timestamp = CommonService.calcMonthLater(1, now_time) - (5 * 86400)  # 下次扣款为下个月提前5天扣款
             start_date_str = CommonService.timestamp_to_str(start_date_timestamp, "%Y-%m-%dT%H:%M:%SZ")
-        #订阅
+        # 订阅
         billingAgreement = {
             "name": store_info['lang__content'],
             "description": orderID,
@@ -129,6 +129,7 @@ class Paypal:
             logger.info(billing_agreement.error)
             return False
 
+
 class PaypalCycleNotify(View):
     def get(self, request, *args, **kwargs):
         request.encoding = 'utf-8'
@@ -147,12 +148,13 @@ class PaypalCycleNotify(View):
         elif operation == 'paypalCycleReturn':  # paypal成功订阅回调
             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 == 'subscriptionBreakNotify':               # paypal 订阅相关回调
-            return self.do_subscription_break_notify(request_dict,request, response)
+            return self.do_paypal_webhook_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)
+        token = request_dict.get('token', None)
 
         logger = logging.getLogger('pay')
         logger.info('--------进入paypay首次订阅付款回调--------')
@@ -169,12 +171,12 @@ class PaypalCycleNotify(View):
             return HttpResponseRedirect(red_url)
 
         orderID = billing_agreement_response.description
-
+        state = billing_agreement_response.state
+        nowTime = int(time.time())
+        promotion_rule_id = ''
         logger.info('----订阅详情----')
         logger.info(billing_agreement_response)
-
         agreement_id = billing_agreement_response.id
-        promotion_rule_id = ''
         order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
         order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
                                      "userID__userID",
@@ -186,6 +188,15 @@ class PaypalCycleNotify(View):
                 red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
             return HttpResponseRedirect(red_url)
         UID = order_list[0]['UID']
+        if state != 'Active':
+            order_qs.update(status=2, promotion_rule_id=promotion_rule_id)
+            logger.info('----UID:{UID},用户名:{last_time} {first_time}首次订阅付款失败----'.format
+                        (UID=UID,
+                         last_time=billing_agreement_response.payer.payer_info.last_name,
+                         first_time=billing_agreement_response.payer.payer_info.first_time,
+                         ))
+            logger.info('billing_agreement_state')
+            logger.info(state)
         try:
             userid = order_list[0]['userID__userID']
             username = order_list[0]['userID__username']
@@ -208,21 +219,20 @@ class PaypalCycleNotify(View):
             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')
+                                                          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:  #套餐使用中并且相同套餐叠加过期时间
+                    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:     #已过期或者不相同的套餐加入未使用的关联套餐表
+                    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():
@@ -230,15 +240,15 @@ class PaypalCycleNotify(View):
                         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)
+                            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)
+                         updateTime=nowTime, use_status=1)
                     uid_bucket_id = ub_cqs.id
 
                 dvq = Device_Info.objects.filter(UID=UID, vodPrimaryUserID='', vodPrimaryMaster='')
@@ -262,14 +272,15 @@ class PaypalCycleNotify(View):
                     CouponModel.objects.filter(id=order_list[0]['coupon_id']).update(use_status=2)
 
                 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)
                 # 如果存在序列号,消息提示用序列号
                 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())]
-                CloudStorage.CloudStorageView().do_vod_msg_Notice(UID, channel, userid, lang, sys_msg_text_list, 'SMS_219738485')
+                CloudStorage.CloudStorageView().do_vod_msg_Notice(UID, channel, userid, lang, sys_msg_text_list,
+                                                                  'SMS_219738485')
 
                 # return response.json(0)
                 red_url = "{SERVER_DOMAIN_SSL}web/paid2/success.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
@@ -290,7 +301,6 @@ class PaypalCycleNotify(View):
                 red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
             return HttpResponseRedirect(red_url)
 
-
     def do_paypal_webhook_notify(self, request_dict, request, response):
         logger = logging.getLogger('pay')
         logger.info('--------进入周期扣款钩子--------')
@@ -363,7 +373,7 @@ class PaypalCycleNotify(View):
                 logger.info('----订阅详情----')
                 logger.info(billing_agreement)
                 logger.info('订阅续费订单完成周期数==0,结束')
-                #更新order表,paypal的商家交易号
+                # 更新order表,paypal的商家交易号
                 Order_Model.objects.filter(orderID=billing_agreement.description).update(
                     updTime=int(time.time()),
                     trade_no=paypal_transaction_id
@@ -374,10 +384,11 @@ class PaypalCycleNotify(View):
             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')
+                                         "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:  #避免续费订单重复支付
+            if order_list[0]['addTime'] + 9200 > nowTime:  # 避免续费订单重复支付
                 logger.info('----paypal重复异步回调----')
                 return HttpResponse('success')
 
@@ -452,12 +463,17 @@ class PaypalCycleNotify(View):
                 #     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)
+                                           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())
@@ -470,11 +486,11 @@ class PaypalCycleNotify(View):
                 else:
                     lang = 'cn'
                 CloudStorage.CloudStorageView().do_vod_msg_Notice(UID, channel, userid, lang,
-                                                                sys_msg_text_list, 'SMS_219738485')
+                                                                  sys_msg_text_list, 'SMS_219738485')
                 logger.info('----周期扣款结果----')
                 logger.info('success')
 
-                #更新agreement
+                # 更新agreement
                 billing_agreement_update_attributes = [
                     {
                         "op": "replace",
@@ -495,7 +511,6 @@ class PaypalCycleNotify(View):
             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('--------进入订阅失败,付款失败,暂停--------')
@@ -579,9 +594,7 @@ class PaypalCycleNotify(View):
             logger.info(repr(e))
             return HttpResponse('fail', status=500)
 
-
-
-    def get_plan_desc(self,plan_id):
+    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))
@@ -611,24 +624,26 @@ class payCycle(View):
         if operation is None:
             return response.json(444, 'error path')
         elif operation == 'queryPayCycle':  # paypal成功订阅回调
-            return self.do_query_pay_cycle(request_dict,userID, response)
+            return self.do_query_pay_cycle(request_dict, userID, response)
         elif operation == 'cancelPayCycle':  # 取消自动续费
-            return self.do_cancel_pay_cycle(request_dict,userID, response)
+            return self.do_cancel_pay_cycle(request_dict, userID, response)
+
     def do_query_pay_cycle(self, request_dict, userID, response):
         lang = request_dict.get('lang', 'en')
-        uid = request_dict.get('uid',None)
-        orderObject = Order_Model.objects.filter(userID=userID,status=1,rank__lang__lang=lang).annotate(rank__title=F('rank__lang__title'), rank__content=F('rank__lang__content'))
+        uid = request_dict.get('uid', None)
+        orderObject = Order_Model.objects.filter(userID=userID, status=1, rank__lang__lang=lang).annotate(
+            rank__title=F('rank__lang__title'), rank__content=F('rank__lang__content'))
         if uid:
             orderObject = orderObject.filter(UID=uid)
-        orderObject = orderObject.filter(~Q(agreement_id = ''))
+        orderObject = orderObject.filter(~Q(agreement_id=''))
         if not orderObject.exists():
-            return response.json(0, {'data':[], 'count': 0})
+            return response.json(0, {'data': [], 'count': 0})
         orderQuery = orderObject.values("orderID", "UID", "channel", "desc", "price", "currency",
-                "addTime",
-                "updTime", "paypal", "rank__day", "payType",
-                "rank__price", "status",
-                "rank__lang__content", "rank__lang__title", "rank__currency",
-                "rank_id", "rank__expire","agreement_id").order_by('addTime')
+                                        "addTime",
+                                        "updTime", "paypal", "rank__day", "payType",
+                                        "rank__price", "status",
+                                        "rank__lang__content", "rank__lang__title", "rank__currency",
+                                        "rank_id", "rank__expire", "agreement_id").order_by('addTime')
         new_data = []
         values = []
         for d in orderQuery:
@@ -641,7 +656,7 @@ class payCycle(View):
     def do_cancel_pay_cycle(self, request_dict, userID, response):
         orderID = request_dict.get('orderID', 'None')
         orderObject = Order_Model.objects.filter(orderID=orderID)
-        orderObject = orderObject.filter(~Q(agreement_id = '')).values("agreement_id")
+        orderObject = orderObject.filter(~Q(agreement_id='')).values("agreement_id")
         if not orderObject.exists():
             return response.json(800)
 
@@ -660,15 +675,3 @@ class payCycle(View):
                 return response.json(10052)
         except Exception as e:
             return response.json(10052)
-
-
-
-
-
-
-
-
-
-
-
-