Flask 之 支付功能实现(支付宝)

功能逻辑分析

安装第三方提供的SDK

  • pip install python-alipay-sdk

生成与设置密钥文件

  • Mac,Ubuntu, Linux 中自带 openssl,win 自行百度
  • 在终端输入:openssl
openssl
OpenSSL> genrsa -out app_private_key.pem   2048  # 私钥
OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
OpenSSL> exit  # 退出

-----BEGIN PUBLIC KEY----------END PUBLIC KEY-----

写flask支付接口

导入SDK
from alipay import AliPay

from . import api
from ih import db, constants
from ih.utils.commons import login
from ih.models import Order
from flask import current_app, jsonify, g, request
from ihome.utils.response_code import RET
from alipay import AliPay
import os

# 请求方式:POST
# 请求参数:order_id
# 参数格式:json
# url:/orders/<int:order_id>/pay
@api.route("/orders/<int:order_id>/pay", methods=["POST"])
@login
def order_pay(order_id):
    """订单支付"""
    user_id = g.get("user_id")
    # 检验订单
    try:
        order = Order.query.filter(Order.id == order_id, Order.status == "WAIT_PAYMENT").first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库异常")

    if not order or order.user_id != user_id:
        return jsonify(errno=RET.ROLEERR, errmsg="操作失败")

    # 业务逻辑处理:调用支付宝接口

    # 创建支付宝sdk的工具对象
    # 私钥                                      当前目录(__file__ 代表当前目录路径)
    app_private_key_path = open(os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem")).read()  # 私钥
    alipay_public_key_path = open(os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem")).read()  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,


    alipay = AliPay(
        appid=constants.ALIPAY_APP_ID,
        app_notify_url=None, # 默认回调url
        app_private_key_string=app_private_key_path, # 私钥
        # 支付宝公钥,验证支付宝回传消息使用,不是你自己的公钥
        alipay_public_key_string=alipay_public_key_path,

        sign_type="RSA2",  # RSA 或者 RSA2
        debug=True  # 默认false, true是沙箱环境
    )

    # 手机网站支付,需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string
    order_string = alipay.api_alipay_trade_wap_pay(
        out_trade_no=order_id,  # 订单编号
        total_amount=order.amount/100.0,  # 支付金额
        subject="爱租房 %s " % order_id,  # 订单标题
        return_url="http://127.0.0.1:5000/orders.html",  # 返回链接地址
        notify_url=None  # 可选, 不填则使用默认notify url
    )

    pay_url = "https://openapi.alipaydev.com/gateway.do?" + order_string

    return jsonify(errno=RET.OK, errmsg="OK", data={"pay_url":pay_url})

"""
支付宝会把参数传递给return_url 返回
http://127.0.0.1:5000/orders.html?
charset=utf-8&   编码
out_trade_no=3&   订单id
method=alipay.trade.wap.pay.return&
total_amount=0.01&   金额
sign=AUOC5QZuyZVwQvPVjocUXyR8h9NkINDy8DEtUti%2BWg8Cd1JYitwJZ%2BMeN2Jo6GfBKnmCCjOTSVJSSnfO%2FKbySmy0tHHLB2T%2FBTLKO1x8w0NeN%2Bvk8U6WPktfOgKgV%2B%2FnEMcQ7LmIvudTAF3mBPggufJ00gZM0y1aFbyvDCu2FTMQxOYaJflFmNRC0i6NIbzTzjYEH3dW5b2qB9r%2Fcqb%2F7AxmVAA%2B61s8w%2FeKS%2BO83JGAiQ8epoPY3daPwYeSaAfe7hYryjip3eoIQQAdM3KxihgRGDH%2BvMUTVz69R6iTSjMcAapia4czBAhPbIZXdbwhT3fbNLf1SKkQxVqxNj37dQ%3D%3D&
trade_no=2020052222001458430500991696&  # 支付宝交易流水号
auth_app_id=2016101700711668&
version=1.0&  
app_id=2016101700711668&
sign_type=RSA2&
seller_id=2088102180059499&
timestamp=2020-05-22+13%3A22%3A28
"""
@api.route("/order/payment", methods=["PUT"])
@login
def save_order_payment():
    """保存订单支付结果"""
    alipay_dict = request.form.to_dict()

    # 对支付宝的数据进行分离  提取出支付宝的签名参数sign 和剩下的其他数据
    alipay_sign = alipay_dict.pop("sign")

    # 创建支付宝sdk的工具对象
    # 私钥                                      当前目录(__file__ 代表当前目录路径)
    app_private_key_path = open(os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem")).read()  # 私钥
    alipay_public_key_path = open(
        os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem")).read()  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,

    alipay = AliPay(
        appid=constants.ALIPAY_APP_ID,
        app_notify_url=None,  # 默认回调url
        app_private_key_string=app_private_key_path,  # 私钥
        # 支付宝公钥,验证支付宝回传消息使用,不是你自己的公钥
        alipay_public_key_string=alipay_public_key_path,
        sign_type="RSA2",  # RSA 或者 RSA2
        debug=True  # 默认false, true是沙箱环境
    )

    # 验证参数是否是支付宝传的,是,则返回True
    # verify 根据支付宝传来的参数,使用RSA2 加密,与支付宝传来的sign 是否一致
    result = alipay.verify(alipay_dict, alipay_sign)

    if result:
        # 修改订单信息
        order_id = alipay_dict.get("out_trade_no")
        trade_no = alipay_dict.get("trade_no")
        try:
            Order.query.filter_by(id=order_id).update({"status":"WAIT_COMMENT", "trade_no":trade_no})
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据库异常")

    return jsonify(errno=RET.OK, errmsg="OK")

更多的支付方式参考:https://github.com/fzlee/alipay/blob/master/README.zh-hans.md#alipay.trade.precreate


版权声明:本文为qq_29499041原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。