前面章节完成了阿里支付的工具类的编写。现在将此工具类应用至view中:
首先看支付宝文档发现。return_url是采用get方法发起的请求。而notify_url这是post请求的。所以我们可以做到同一个view中
而无论是哪个请求 他们的内部执行方法是一样的。都是创建1个支付宝的工具类然后传递参数。然后将支付宝发送过来的参数将除sign参数之外的其他参数进行排序加密然后跟sign参数的值进行比对。
如果比对成功则修改订单状态。
代码示例
# trade/views
from rest_framework.views import APIView
from utils.alipay import AliPay
from MxShop.settings import private_key_path, public_key_path
from datetime import datetime
from rest_framework.response import Response
class AliPayViewset(APIView):
def get(self, request):
"""
处理支付宝的return_url返回
:param request:
:return:
"""
# 将支付宝传递过来的参数分开 分成sign和非sign参数
processed_dict = {}
for key, value in request.POST.items():
processed_dict[key] = value
sign = processed_dict.pop("sign", None)
# 建立支付工具对象
alipay = AliPay(
appid="2016101100661810",
app_notify_url="http://127.0.0.1:8000/alipay/return/",
app_private_key_path=private_key_path,
alipay_public_key_path=public_key_path,
debug=True,
return_url="http://127.0.0.1:8000/alipay/return/"
)
# 校验sign是否正确
verify_re = alipay.verify(processed_dict, sign)
# 正确的话就修改订单状态
if verify_re is True:
order_sn = processed_dict.get('out_trade_no', None)
trade_no = processed_dict.get('trade_no', None)
trade_status = processed_dict.get('trade_status', None)
existed_orders = OrderInfo.objects.filter(order_sn=order_sn)
for existed_order in existed_orders:
existed_order.pay_status = trade_status
existed_order.trade_no = trade_no
existed_order.pay_time = datetime.now()
existed_order.save()
return Response("success")
#跟上面一模一样
def post(self, request):
"""
处理支付宝的notify_url
:param request:
:return:
"""
processed_dict = {}
for key, value in request.POST.items():
processed_dict[key] = value
sign = processed_dict.pop("sign", None)
alipay = AliPay(
appid="2016101100661810",
app_notify_url="http://127.0.0.1:8000/alipay/return/",
app_private_key_path= private_key_path,
alipay_public_key_path= public_key_path,
debug=True,
return_url = "http://127.0.0.1:8000/alipay/return/"
)
verify_re = alipay.verify(processed_dict, sign)
if verify_re is True:
order_sn = processed_dict.get('out_trade_no',None)
trade_no = processed_dict.get('trade_no', None)
trade_status = processed_dict.get('trade_status', None)
existed_orders = OrderInfo.objects.filter(order_sn=order_sn)
for existed_order in existed_orders:
existed_order.pay_status = trade_status
existed_order.trade_no = trade_no
existed_order.pay_time = datetime.now()
existed_order.save()
return Response("success")
urls:
path('alipay/return/', AliPayViewset.as_view(), name='alipay'),
settings.py中设置下公钥和私钥的路径 省的因为路径出问题
#支付宝相关配置
private_key_path = os.path.join(BASE_DIR, 'apps/trade/keys/private_2048.txt')
public_key_path = os.path.join(BASE_DIR, 'apps/trade/keys/alipay_key_2048.txt')
订单接口这样就OK了
但是还有地方需要订单url 比如订单列表页和订单详情页。但是我们数据库中又没有存储订单url的相关字段,咋办。这就需要serializer动态生成的字段了.使用serializerMethod字段。
官方文档;
https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
具体的代码就是我们在OrderSerializer和OrderDetailSerializer两个类中进行添加字段和函数:
# 两个类都是添加此字段(此方法必须设置read_only=True)
alipay_url = serializers.SerializerMethodField(read_only=True)
# 通过此函数(格式:get_ + 字段名)rest会自动寻找对应的字段
# 生成url地址返回给前端页面
def get_alipay_url(self, obj):
alipay = AliPay(
appid="2016101100661810",
app_notify_url="http://127.0.0.1:8000/alipay/return/",
app_private_key_path=private_key_path,
alipay_public_key_path=public_key_path,
debug=True,
return_url = "http://127.0.0.1:8000/alipay/return/"
)
url = alipay.direct_pay(
subject=obj.order_sn,
out_trade_no=obj.order_sn,
total_amount=obj.order_mount
)
re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url)
return re_url
教程中后来有说到根据前端页面跳转到支付宝之后 支付宝请求数据返回给后端。而后端没办法直接发送数据给vue前端进行跳转(vue毕竟不是服务器)所以给出了1个方案是将vue丢到django中。当做模板来用。 我靠 这样性能得多差,还不好调试
果断不理他。 然后教程也给出了第二种方法 获取支付宝的支付图片。然后vue展示图片并且发心跳请求,来确认订单状态是否是已支付。然而。没教程 = = 就给了接口文档 好吧。等项目中真的用到的时候在写吧 先把文档给出来吧
https://docs.open.alipay.com/api_1/alipay.trade.page.pay/
第十章内容完结。 内容有些多。改天找时间捋一捋流程