支付成功回调接口
正常情况下我们只需要一个post回调给支付宝用(不需要登录认证,因为支付宝验证签名后===>校验成功,我们才会进行改订单状态)
同时这里咱们写了一个get回调,用于给前端做数据校验,做双重验证,更加稳妥
如果我们的notify_url是本地调试,外网无法访问,就会使支付宝无法回调而失败,所以我们可以利用内网穿透:
内网穿透:https://zhuanlan.zhihu.com/p/370483324
# 后端支付跳转接口 这里不需要大量用到数据库交互 所以选择用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')
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异步回调,后台地址