0.支付流程
1. 重点总结
1)用户进入“我的订单”页面,点击“去支付”;
触发后端js中的函数,发出ajsx异步请求,调用后端相应接口order_pay(order_id),目的是构建让用户跳转的支付连接地址,并推送给用户进行付款操作;因为请求方式是PUT,因此需要在参数中加入X-CSRFToken;
2)在后端进行逻辑处理,构建出跳转的支付链接地址pay_url(并指出用户完成支付后返回的地址return_url)。
支付链接地址经过js回调函数处理,将此pay_url返回给前端页面,此时自动打开手机支付宝app,用户对相应的订单进行支付操作,
支付完成后,跳转return_url相对应的前端页面paycomplete.html,如下图所示。
3)用户在支付完成后,需要修改数据库中订单的相关信息,比如说订单的状态status,以及支付宝的交易号trade_no,此时前端页面中的js向后端发送ajsx异步请求,向后端相应接口save_order_payment_result()发出逻辑处理。
js中alipayData = document.location.search.substr(1),切割URL中的参数信息,并以form格式将参数信息推送给后端接口,后端接收数据;
为安全起见,借助工具校验参数的合法性,确定参数是支付宝真实发出的;
最后修改数据库的订单状态信息。
此时,点击前文中支付成功界面中的“回到我的订单”,会发现订单状态已经从“去支付”变为“发表评论”。
2.后端代码
pay.py详细代码如下:
# coding:utf-8
from . import api
from ihome.utils.commons import login_required
from ihome.models import Order
from flask import g, current_app, jsonify, request
from ihome.utils.response_code import RET
from alipay import AliPay
from ihome import constants, db
import os
@api.route("/orders/<int:order_id>/payment", methods=["POST"])
@login_required
def order_pay(order_id):
"""发起支付宝支付"""
user_id = g.user_id
# 判断订单状态
try:
order = Order.query.filter(Order.id == order_id, Order.user_id == user_id, Order.status == "WAIT_PAYMENT").first()
except Exception as e:
current_app.logger.error(e)
return jsonify(errno=RET.DBERR, errmsg="数据库异常")
if order is None:
return jsonify(errno=RET.NODATA, errmsg="订单数据有误")
# 创建支付宝sdk的工具对象
alipay_client = AliPay(
appid="2016081600258081",
app_notify_url=None, # 默认回调url
app_private_key_path=os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem"), # 私钥
alipay_public_key_path=os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem"), # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
sign_type="RSA2", # RSA 或者 RSA2
debug=True # 默认False
)
# 手机网站支付,需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string
order_string = alipay_client.api_alipay_trade_wap_pay(
out_trade_no=order.id, # 订单编号
total_amount=str(order.amount/100.0), # 总金额
subject=u"爱家租房 %s" % order.id,