Paypal集成到Flask应用程序

Paypal integration to Flask application

本文关键字:应用程序 Flask 集成 Paypal      更新时间:2023-09-26

阅读后,我对Paypal流量事件有点误解https://developer.paypal.com/docs/api/.我想把快速结账和信用卡支付集成到我的网站上。我使用的Flaskpaypalrestsdk没有任何Flask扩展。

以下是我的应用程序摘录:

@app.route('/', methods=['GET'])
def index():
    # Page with but form, price/quantity/name values
    # are stored in hidden fields, "Buy now" acts as submit
    return render_template('index.html')
@app.route('/payment/paypal', methods=['POST'])
def payment_paypal():
    # Here I am creating dict with required params
    payment_template = {
        'intent': 'sale',
        'payer': {'payment_method': 'paypal'},
        'redirect_urls': {
          'return_url': url_for('payment_paypal_execute'),
          'cancel_url': url_for('payment_paypal_error')
        },
        ......
    }
    payment = paypalrestsdk.Payment(payment)
    if payment.create():
        print('Payment "{}" created successfully'.format(payment.id))
        for link in payment.links:
            if link.method == "REDIRECT":
                redirect_url = str(link.href)
                print('Redirect for approval: {}'.format(redirect_url))
                return redirect(redirect_urls)
@app.route('/payment/paypal/execute', methods=['GET'])
def payment_paypal_execute():
    payer_id = request.args.get('payerId')
    payment_id = request.args.get('paymentId')
    token = request.args.get('token')
    pending_payment = PayPalPayment.query.filter_by(token=token).filter_by(state='created').first_or_404()
    try:
        payment = paypalrestsdk.Payment.find(pending_payment.payment_id)
    except paypalrestsdk.exceptions.ResourceNotFound as ex:
        print('Paypal resource not found: {}'.format(ex))
        abort(404)
    if payment.execute({"payer_id": payer_id}):
        pending_payment.state = payment.state
        pending_payment.updated_at = datetime.strptime(payment.update_time, "%Y-%m-%dT%H:%M:%SZ")
        db.session.commit()
        return render_template('payment/success.html', payment_id=payment.id, state=payment.state)
    return render_template('payment/error.html', payment_error=payment.error, step='Finallizing payment')

它工作正常,在点击成功创建的按钮payment(状态为created)后,用户重定向到审批页面。在那里他点击"确认"。。。当我指定return_url时,我从未返回到我的应用程序!也就是说,申请永远不会被告知买家批准付款,它应该在我自己的数据库中更新,新的许可证应该发送给那个人。

问题:

  1. 我找不到使用pyhtonrestsdk定义某些回调的方法。怎么做?

  2. 即使我在data-callback中添加了回调(我尝试使用纯Javascript按钮代码嵌入ExpressCheckout),我的应用程序也没有被调用。我怀疑是因为远程服务器无法调用http://127.0.0.1/payment/paypal/success

  3. 用户可以在点击"确认"后立即用PayPal确认关闭窗口,所以我不能相信浏览器重定向,它稍后会执行。

最后,我怀疑我不清楚PayPal的工作流程,但我无法在开发者门户网站上找到更多关于它事件的信息。

和往常一样,魔鬼隐藏在细节中。我的主要问题是:贝宝不会将我重定向到我的应用程序,但我发现它会将我重定向(在确认后)到URL,该URL看起来像https://sandbox.paypal.com/,查询字符串包含所需的参数。即redirect_urls按预期工作,只是将我重定向到错误的主机。

在那之后,我记得url_for生成相对链接。所以刚刚添加了关键字_external=True,我已经被重定向到我的应用程序,所有必需的参数和付款都已成功确认并执行。

即,正确的redirect_urls块将看起来像:

'redirect_urls': {
    'return_url': url_for('payment_paypal_execute', _external=True),
    'cancel_url': url_for('payment_paypal_error', _external=True)
}

最后我得到了以下工作流程:

  1. 打开了/index),它有按钮Pay with PayPal。它是表单中的图像按钮。在这个按钮表单旁边,包含金额、产品名称和数量的隐藏字段(实际上这不是一个好主意,因为我们不能信任用户,所以我只存储了product_license_type_id,它存储在DB中,包含了有关产品的所有必需信息)。

  2. 单击后,POST表单将变为"/payment/paypal"(paypal_create),其中创建对象Payment并填充所有字段。如果调用payment.create成功完成,它还会在我自己的数据库中用payment_idstate创建记录(这些字段与贝宝工作流有关,当然实际上我正在存储与我的应用程序有关的其他几个字段)。

  3. 一旦在PayPal端创建了付款,应用程序就会查看列表payment.links的响应。我们想要一个有rel == 'approval_url'method == 'REDIRECT'的,并返回flask.redirect(found_link)

  4. 在PayPal网站上,买家应点击"批准",查看发货地址,之后他将立即被重定向到redirect_urls.return_url,查询字符串中有以下参数:PayerIDpaymentIdtoken

  5. 重定向回来后,您应该从查询字符串中获取这些参数(请记住,这是区分大小写的!),使用PayPal API(payment = paypalrestsdk.Payment.find(payment_id))找到付款并最终确定(payment.execute({"payer_id": payer_id}):)。

  6. 完成付款后,状态更改为approved

  7. 。。。。

  8. 利润!

UPD:您在销售帐户首选项时不需要打开"自动重定向",这种方法适用于将一个帐户集成到多个网站。