支付成功回调接口

正常情况下我们只需要一个post回调给支付宝用(不需要登录认证,因为支付宝验证签名后===>校验成功,我们才会进行改订单状态)
同时这里咱们写了一个get回调,用于给前端做数据校验,做双重验证,更加稳妥


如果我们的notify_url是本地调试,外网无法访问,就会使支付宝无法回调而失败,所以我们可以利用内网穿透:
内网穿透:https://zhuanlan.zhihu.com/p/370483324

支付成功回调接口

order/views.py

方案一:

# 后端支付跳转接口 这里不需要大量用到数据库交互 所以选择用APIView更方便
class SuccessView(APIView):
    # 支付宝get回调前端页面 前端页面get请求后端校验数据
    def get(self,request,*args,**kwargs):
        # 从请求参数中获取订单号
        out_trade_no = request.query_params.get('out_trade_no')
        order_obj = models.Order.objects.filter(out_trade_no=out_trade_no).first()
        # 判断订单支付状态 返回True/False 前端自行处理
        if order_obj.order_status == 1:
            return Response(True)
        else:
            return Response(False)

    # 支付宝回调接口
    def post(self,request,*args,**kwargs):
        from luffyapi.libs.alipay_zf import alipay
        from luffyapi.utils.logger import log
        # 继承APIView post请求来的时候 获取前端传过来的数据
        # 这里是QueryDict对象 不允许通过pop删除数据 所以我们转成dict类型
        data = request.data.dict()
        print(type(data))
        # 获取订单号 key参考alipay的API参数
        out_trade_no = data.get('out_trade_no',None)
        # 获取支付时间 key参考alipay的API参数
        gmt_payment = data.get('gmt_payment',None)
        # 获取签名
        signature = data.pop("sign")
        # 验证签名 只有签名正确 才能修改订单状态 防止有人恶意发送post请求给我们
        success = alipay.verify(data, signature)
        # 判断订单状态 交易完成/支付成功
        if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
            # 更新订单支付状态以及付款时间
            models.Order.objects.filter(out_trade_no=out_trade_no
                                        ).update(order_status=1,pay_time=gmt_payment)
            # 记录日志
            log.info('%s订单支付成功'%out_trade_no)
            return Response('success')  # 这里固定返回值 否则支付宝会8次异步回调
        else:
            log.info('%s订单支付异常'%out_trade_no)
            return Response('error')

方案二:

from rest_framework.views import APIView
from .models import Order
class PaySuccessView(APIView):
    def get(self,request): # 自己用的
        try:
            out_trade_no=request.query_params.get('out_trade_no')
            # 根据订单号,查订单的状态
            Order.objects.get(out_trade_no=out_trade_no,order_status=1)
        except Exception as e:
            raise e
        return APIResponse()

    # 给支付宝用---》回调回来数据格式
    def post(self,request):
        # django :requset.POST  request.GET --->QueryDict的对象--》不允许删除数据
        try:
            result_data = request.data.dict()  # request.data 是post的数据,复制了一份数据
            out_trade_no = result_data.get('out_trade_no') # 订单号
            signature = result_data.pop('sign') # 签名
            from libs import apay
            # 验证签名,只有这个正确,才能修改订单状态--》防止恶意发送post请求给我们
            result = apay.pay.verify(result_data, signature)
            if result and result_data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
                # 完成订单修改:订单状态、流水号、支付时间
                models.Order.objects.filter(out_trade_no=out_trade_no).update(order_status=1)
                # 完成日志记录
                logger.warning('%s订单支付成功' % out_trade_no)
                return Response('success') # 固定的
            else:
                logger.error('%s订单支付失败' % out_trade_no)
        except:
            pass
        return Response('failed')
View Code

order/urls.py

from django.urls import path, re_path, include
from . import views
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('pay',views.PayView,'pay')




urlpatterns = [
    path('', include(router.urls)),
    path('success/',views.SuccessView.as_view(),'success')
]

settings/dev.py

LUFFY_URL = "http://127.0.0.1:8080"  # 前台基URL
BASE_URL = "http://127.0.0.1:8000"  # 后台基URL
RETURN_URL= LUFFY_URL + "/pay/success"  # 支付宝get回调,前台地址 尾部没有/
NOTIFY_URL= BASE_URL + "/order/success/"  # 支付宝post异步回调,后台地址

 

posted @ 2022-06-20 14:19  _yessir  阅读(1032)  评论(0编辑  收藏  举报