趣看小说对接支付宝支付

序言:

使用语言:python3

框架:flask

支付宝环境:沙箱环境

支付宝电脑网站支付文档:https://docs.open.alipay.com/270

对接的主要步骤:

1、在支付宝申请开发pc网页支付功能的应用,配置公匙和私匙(此步骤是实际生产环境所需要的)。

2、配置沙箱环境

3、客户端向服务器发起支付请求,请求包含参数:支付方式(支付宝、微信、等)、支付总金额

4、服务器接收客户端发送的带参数请求,生成订单编号,向数据库写入订单信息(订单编号,用户ID,支付总金额,订单创建时间,支付状态,支付方式)

5、调用支付宝接口并填写相关参数,生成包含支付宝支付二维码的链接,return redirect到此链接

6、买家扫码支付

7、同步接收支付宝的状态通知,校验是否success,向客户端返回支付成功或支付失败的页面

8、异步接收支付宝的状态通知,校验是否success,并校验订单编号和支付总金额与数据库里保存的订单信息是否相同,如果都校验成功,把之前写入数据库的订单信息补全(支付编号,支付时间,修改支付状态)

1、在支付宝申请应用

支付宝开放平台:https://open.alipay.com/platform/home.htm

在这里插入图片描述

  • 开发者中心→网页&移动应用→创建应用→支付接入

  • 填写应用名称、图标等相关信息并创建应用

  • 在功能列表中选择需要的功能,例如:电脑网站支付(可以点击添加功能按钮后进行搜索)

  • 根据需要设置:应用网关、授权回调地址、加签方式(私匙和公匙)

    • 生成应用的私钥和公钥(使用openssl生成或支付宝密匙生成器生成)

      openssl
      OpenSSL> genrsa -out app_private_key.pem 2048  # 私钥RSA2
      OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
      
      OpenSSL> exit
      
    • 保存私匙文件

      • 在payment应用中新建keys目录,用来保存秘钥文件。
      • 将应用私钥文件app_private_key.pem复制到payment/keys目录下。
    • 查看公钥

      • 将公钥内容复制给支付宝

        cat app_publict_key.pem
        

      在这里插入图片描述

    • 保存支付宝公钥

      • 在payment/keys目录下新建alipay_public_key.pem文件,用于保存支付宝的公钥文件。

        将支付宝的公钥内容复制到alipay_public_key.pem文件中

      在这里插入图片描述

      • 注意,还需要在公钥文件中补充开始与结束标志

        -----BEGIN PUBLIC KEY-----
        此处是公钥内容
        -----END PUBLIC KEY-----
        
2、配置沙箱环境

在这里插入图片描述

  • 与上步一样配置授权回调地址、公匙、私匙等信息

在这里插入图片描述

  • 下载支付宝沙箱钱包(安卓手机)

在这里插入图片描述

  • 点击沙箱账号,查看买家账号密码和卖家账号密码,可在支付宝沙箱钱包登录,方便后期测试。
3、配置客户端

在这里插入图片描述

  • 修改模板,最终效果:点击确认支付时,向服务器发送请求并携带参数:支付方式(支付宝、微信、等)、支付总金额
4、服务器接收请求
# alipay的APPID
ALIPAY_APPID = "2016092300580301"

# 是否开启沙箱环境
ALIPAY_DEBUG = True
ALIPAY_URL = "https://openapi.alipaydev.com/gateway.do"
  • 生成订单编号,向数据库写入订单信息(订单编号,用户ID,支付总金额,订单创建时间,支付状态,支付方式)【见步骤5的代码】

####5、调用支付宝接口并填写相关参数,生成包含支付宝支付二维码的链接alipay_url,return redirect到此链接

@payment_blue.route('/pay', methods=['get'])
@user_login_data
def pay():
    """充值页面"""
    user = g.user
    total_amount = request.args.get("docVlGender", None)
    pay_method = request.args.get("radio1", None)
    try:
        userid = user.id
    except:  # 用户没登录
        return redirect(url_for('users.login_html'))
    if total_amount == None or pay_method == None:
        data = {
            "user": user
        }
        return render_template('pay.html', data=data)
    else:
        # 生成订单编号
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + "{:0>8}".format(str(userid))
        print("订单编号:%s" % order_id)
        # 保存订单
        create_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        sql_str = "insert into tb_order_paid(order_id,user_id,total_amount,create_time,paid_status,paid_method) values ('%s',%d,'%s','%s',0,'alipay')" % (order_id, userid, total_amount, create_time)
        ret = executesql(sql_str)
        if ret:
            if pay_method == "wechatpay":
                # TODO 开发微信支付接口
                data = {
                    "user": user
                }
                return render_template('pay.html', data=data)
            if pay_method == "alipay":
                # 初始化alipay
                alipay_client = AliPay(
                    appid=config.ALIPAY_APPID,
                    app_notify_url=None,  # 默认回调url
                    app_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                                      "keys/rsa_private_key.pem"),
                    # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
                    alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                                        "keys/alipay_public_key.pem"),
                    sign_type="RSA2",  # RSA 或者 RSA2
                    debug=config.ALIPAY_DEBUG  # 默认False 沙箱环境为True
                )
                # 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string
                order_string = alipay_client.api_alipay_trade_page_pay(
                    out_trade_no=order_id,
                    total_amount=str(total_amount),
                    subject="趣看小说%s" % order_id,
                    return_url="http://www.qukanxs.site:6001/pay_success",
                    notify_url="http://www.qukanxs.site:6001/status"  # 支付宝支付成功异步通知地址
                )
                alipay_url = config.ALIPAY_URL + "?" + order_string
                return redirect(alipay_url)
        else:
            data = {
                "user": user
            }
            return render_template('pay.html', data=data)
6、客户端会自动跳转到支付宝的扫码支付页面,买家扫码支付

####7、同步接收支付宝的状态通知,校验是否success,向客户端返回支付成功或支付失败的页面

@payment_blue.route('/pay_success', methods=['get'])
@user_login_data
def alipay_pay_success():
    """支付宝保存支付成功的返回信息"""
    user = g.user
    data = request.args.to_dict()
    print("data=%s" % data)
    signature = data.pop("sign")
    print("signature=%s" % signature)
    print("data=%s" % data)
    # 初始化alipay
    alipay_client = AliPay(
        appid=config.ALIPAY_APPID,
        app_notify_url="http://www.qukanxs.site:6001/status",  # 默认回调url
        app_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                          "keys/rsa_private_key.pem"),
        # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
        alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                            "keys/alipay_public_key.pem"),
        sign_type="RSA2",  # RSA 或者 RSA2
        debug=config.ALIPAY_DEBUG  # 默认False 沙箱环境为True
    )
    success = alipay_client.verify(data, signature)
    if success:
        order_id = data["out_trade_no"]
    else:
        trade_id = None
    data = {
        "trade_id": trade_id,
        "user": user
    }
    return render_template('pay_success.html', data=data)
  • pay_success.html页面
{% extends 'base.html' %}

{% block title_block %}
支付完成
{% endblock %}

{% block detail_block %}
    <div class="common_list_con clearfix">
        <div class="order_success">
            {% if data.trade_id %}
            <p><b>订单支付成功</b></p>
            <p>您的订单已成功支付,支付交易号:{{ data.trade_id }}</p>
            {% else %}
            <p><b>订单支付失败</b></p>
            <p>请返回支付页面重新支付</p>
            {% endif %}
        </div>
    </div>
{% endblock %}

{% block foot_block %}
    <div class="footer">

        <hr>

        <p>本站所有小说为转载作品,所有章节均由网友上传,转载至本站只是为了宣传本书让更多读者欣赏。</p>

        <p>Copyright &#169; 趣看小说 All Rights Reserved. </p>

        <script>tj();</script>

    </div>

    </body>

    </html>
{% endblock %}

####8、异步接收支付宝的状态通知,校验是否success,并校验订单编号和支付总金额与数据库里保存的订单信息是否相同,如果都校验成功,把之前写入数据库的订单信息补全(支付编号,支付时间,修改支付状态)

@payment_blue.route('/status', methods=['post'])
@user_login_data
def alipay_pay_status():
    print("haha")
    data = request.form.to_dict()
    print("data=%s" % data)
    signature = data.pop("sign")
    print("signature=%s" % signature)
    print("data=%s" % data)
    # 初始化alipay
    alipay_client = AliPay(
        appid=config.ALIPAY_APPID,
        app_notify_url=None,  # 默认回调url
        app_private_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                          "keys/rsa_private_key.pem"),
        # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
        alipay_public_key_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                            "keys/alipay_public_key.pem"),
        sign_type="RSA2",  # RSA 或者 RSA2
        debug=config.ALIPAY_DEBUG  # 默认False 沙箱环境为True
    )
    success = alipay_client.verify(data, signature)
    if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED" ):
        order_id = data["out_trade_no"]
        trade_id = data["trade_no"]
        total_amount = data["total_amount"]
        paid_time = data["timestamp"]
        # 判断订单编号,支付金额是否相同
        sql_str = "select user_id from tb_order_paid where order_id='%s' and total_amount='%s'" % (order_id, total_amount)
        user_id = selectsql(sql_str)[0] if selectsql(sql_str) else None
        if user_id:
            # 增加用户金币数量
            sql_str = "update tb_users set golds=(%d+golds) where id=%d;" % (float(total_amount) * 100, user_id)
            executesql(sql_str)
            sql_str = "update tb_order_paid set trade_id=%s,paid_time='%s',paid_status=1 where order_id='%s'" % (trade_id, paid_time, order_id)
            executesql(sql_str)
            return "success"
    return False
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值