Эх сурвалжийг харах

ai支付创建订单和支付回调接口(PayPal)

locky 3 жил өмнө
parent
commit
0b541577cc

+ 110 - 38
Controller/AiController.py

@@ -88,6 +88,8 @@ class AiView(View):
             return response.json(444, 'error path')
         elif operation == 'identification':  # ai识别
             return self.do_ai_identification(request.POST, response)
+        elif operation == 'doPayPalCallBack':  # paypal支付回调
+            return self.do_pay_by_paypal_callback(request_dict, response)
         else:
             token = request_dict.get('token', None)
             # 设备主键uid
@@ -97,8 +99,7 @@ class AiView(View):
                 return response.json(tko.code)
             userID = tko.userID
             if operation == 'createpayorder':  # 创建支付订单
-                ip = CommonService.get_ip_address(request)
-                return self.do_create_pay_order(request_dict, userID, ip, response)
+                return self.do_create_pay_order(request_dict, userID, response)
             elif operation == 'changeaistatus':  # 修改AI开关状态
                 return self.do_change_ai_status(userID, request_dict, response)
             elif operation == 'getAiStatus':  # 获取AI开关状态
@@ -404,7 +405,7 @@ class AiView(View):
             # d['rank__lang__content'] = '月' if lang == 'cn' else 'month'
         return response.json(0, {'data': data, 'count': count})
 
-    def do_create_pay_order(self, request_dict, userID, ip, response):
+    def do_create_pay_order(self, request_dict, userID, response):
         uid = request_dict.get('uid', None)
         channel = request_dict.get('channel', None)
         pay_type = int(request_dict.get('pay_type', 1))
@@ -412,6 +413,8 @@ class AiView(View):
         lang = request_dict.get('lang', 'en')
         if not uid or not channel or not pay_type or not ai_meal_id:
             return response.json(444)
+
+        # 判断是否为主用户
         # dv_qs = Device_Info.objects.filter(userID_id=userID, UID=uid, isShare=False, isExist=1).values(
         #     'vodPrimaryUserID',
         #     'vodPrimaryMaster')
@@ -424,46 +427,115 @@ class AiView(View):
         #     if dvq[0]['vodPrimaryUserID'] != userID:
         #         return response.json(10033)
 
-        nowTime = int(time.time())
-        smqs = AiStoreMeal.objects.filter(id=ai_meal_id, pay_type=pay_type, is_show=1). \
+        # 获取ai套餐数据
+        ai_sm_qs = AiStoreMeal.objects.filter(id=ai_meal_id, pay_type=pay_type, is_show=1). \
             values('currency', 'price', 'content', 'effective_day', 'title')
-        if not smqs.exists():
+        if not ai_sm_qs.exists():
             return response.json(173)
-        currency = smqs[0]['currency']
-        price = smqs[0]['price']
-        content = smqs[0]['content']
-        day = smqs[0]['effective_day']
+        currency = ai_sm_qs[0]['currency']
+        price = ai_sm_qs[0]['price']
+        content = ai_sm_qs[0]['content']
+        day = ai_sm_qs[0]['effective_day']
 
         orderID = CommonService.createOrderID()
-        price = float(price)
-        price = round(price, 2)
+        price = round(float(price), 2)
         if pay_type == 1:
-            #正常扣款
-            cal_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
-            if lang != 'cn':
-                cal_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
-            call_sub_url = "{SERVER_DOMAIN_SSL}cloudstorage/dopaypalcallback?orderID={orderID}&lang={lang}". \
-                format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL, orderID=orderID, lang=lang)
-            # call_sub_url = "http://binbin.uicp.vip/cloudstorage/dopaypalcallback?orderID={orderID}".format(
-            # SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL, orderID=orderID)
-            Order_Model.objects.create(orderID=orderID, UID=uid, channel=channel, userID_id=userID,
-                                       desc=content, payType=pay_type, payTime=nowTime,
-                                       price=price, currency=currency, addTime=nowTime, updTime=nowTime,
-                                       pay_url='', commodity_code='', commodity_type=1,
-                                       ai_rank_id=ai_meal_id, rank_id=1, order_type=1, status=1)
-            has = AiService.objects.filter(uid=uid, channel=channel, use_status=1)
-            if has.exists():
-                use_status = 0
-                endTime = 0
-            else:
-                use_status = 1
-                endTime = nowTime+(day*86400)
-            # return response.json(0)
-            AiService.objects.create(orders_id=orderID, uid=uid, channel=channel, detect_status=1,
-                                       endTime=endTime, addTime=nowTime, updTime=nowTime,
-                                     use_status=use_status, detect_group='1')
-            return response.json(0, {"orderID": orderID})
-        return response.json(10, 'generate_order_false')
+            # 创建PayPal支付
+            cancel_url = CommonService.get_payment_status_url(lang, 'fail')
+            call_sub_url = "{}AiService/doPayPalCallBack?orderID={}&lang={}".format(SERVER_DOMAIN_SSL, orderID, lang)
+
+            paypalrestsdk.configure(PAYPAL_CRD)
+            payment = paypalrestsdk.Payment({
+                "intent": "sale",
+                "payer": {"payment_method": "paypal"},
+                "redirect_urls": {"return_url": call_sub_url, "cancel_url": cancel_url},
+                "transactions": [{
+                    "item_list": {"items": [
+                        {"name": "Cloud video", "sku": "1", "price": price, "currency": "USD", "quantity": 1}]},
+                    "amount": {"total": price, "currency": currency},
+                    "description": content}]})
+            if not payment.create():        # 创建失败
+                return response.json(10, payment.error)
+            paymentID = payment['id']       # 获取paymentID
+            nowTime = int(time.time())
+            for link in payment.links:
+                if link.rel == "approval_url":
+                    pay_url = str(link.href)
+                    Order_Model.objects.create(orderID=orderID, UID=uid, channel=channel, userID_id=userID,
+                                               desc=content, payType=pay_type, payTime=nowTime, price=price,
+                                               currency=currency, addTime=nowTime, updTime=nowTime, pay_url=pay_url,
+                                               rank_id=ai_meal_id, paymentID=paymentID, ai_rank_id=1)
+                    return response.json(0, {"redirectUrl": pay_url, "orderID": orderID})
+            return response.json(10, 'create_ai_order_failed')
+
+    def do_pay_by_paypal_callback(self, request_dict, response):  # paypal支付回调
+        logger = logging.getLogger('info')
+        logger.info('---------进入paypal异步回调')
+        paymentId = request_dict.get('paymentId', None)
+        PayerID = request_dict.get('PayerID', None)
+        orderID = request_dict.get('orderID', None)
+        lang = request_dict.get('lang', 'en')
+
+        logger.info("paymentID={paymentId},payerID={PayerID}".format(paymentId=paymentId, PayerID=PayerID))
+
+        # redis加锁,防止订单重复
+        redisObj = RedisObject()
+        isLock = redisObj.CONN.setnx(orderID + 'do_notify', 1)
+        redisObj.CONN.expire(orderID + 'do_notify', 60)
+        if not isLock:
+            return response.json(5)
+        try:
+            order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
+            if not orderID:
+                pay_failed_url = CommonService.get_payment_status_url(lang, 'fail')
+                return HttpResponseRedirect(pay_failed_url)
+
+            paypalrestsdk.configure(PAYPAL_CRD)
+            payment = paypalrestsdk.Payment.find(paymentId)
+            logger.info("payment------")
+            logger.info(payment)
+
+            payres = payment.execute({"payer_id": PayerID})
+            logger.info(payres)
+            if not payres:
+                pay_failed_url = CommonService.get_payment_status_url(lang, 'fail')
+                redisObj.del_data(key=orderID + 'do_notify')
+                return HttpResponseRedirect(pay_failed_url)
+
+            nowTime = int(time.time())
+            order_list = order_qs.values("UID", "channel", "commodity_code", "ai_rank", "isSelectDiscounts",
+                                         "userID__userID", "userID__username", "coupon_id")
+            userid = order_list[0]['userID__userID']
+            username = order_list[0]['userID__username']
+            UID = order_list[0]['UID']
+            channel = order_list[0]['channel']
+            ai_rank = order_list[0]['ai_rank']
+
+            # 套餐时间
+            ai_sm_qs = AiStoreMeal.objects.filter(id=ai_rank).values('effective_day')
+            if not ai_sm_qs.exists():
+                return response.json(173)
+            with transaction.atomic():
+                # 更新设备主用户
+                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)
+
+                # 更新订单数据,返回支付成功url
+                order_qs.update(status=1, updTime=nowTime)
+                pay_success_url = CommonService.get_payment_status_url(lang, 'fail')
+                redisObj.del_data(key=orderID + 'do_notify')
+                return HttpResponseRedirect(pay_success_url)
+        except Exception as e:
+            if order_qs:
+                order_qs.update(status=10)
+            pay_failed_url = CommonService.get_payment_status_url(lang, 'fail')
+            redisObj.del_data(key=orderID + 'do_notify')
+            return HttpResponseRedirect(pay_failed_url)
 
     def update_jpush_time(self,userID, request_dict, response):
         logger = logging.getLogger('info')

+ 12 - 1
Service/CommonService.py

@@ -8,9 +8,10 @@ from random import Random
 import ipdb
 import simplejson as json
 from django.core import serializers
+from django.http import HttpResponseRedirect
 from django.utils import timezone
 from pyipip import IPIPDatabase
-from Ansjer.config import BASE_DIR, UNICODE_ASCII_CHARACTER_SET
+from Ansjer.config import BASE_DIR, UNICODE_ASCII_CHARACTER_SET, SERVER_DOMAIN_SSL
 import OpenSSL.crypto as ct
 from base64 import encodebytes
 from Controller.CheckUserData import RandomStr
@@ -492,3 +493,13 @@ GCqvlyw5dfxNA+EtxNE2wCW/LW7ENJlACgcfgPlBZtpLheWoZB/maw4=
         # print('signature:', signature)
         return signature
 
+    @staticmethod
+    def get_payment_status_url(lang, payment_status):
+        # 返回相应的支付状态url
+        if lang == 'cn':
+            file_name = 'success.html' if payment_status == 'success' else 'en_success.html'
+        else:
+            file_name = 'fail.html' if payment_status == 'fail' else 'en_fail.html'
+        pay_failed_url = "{}web/paid2/{}".format(SERVER_DOMAIN_SSL, file_name)
+        return pay_failed_url
+