Python支付网关与Rapyd集成
#python #flask #fintech #paymentsapi

由Nicholas Babu

无论您的业务是在线还是本地人,在收取付款方式方面都可以灵活地有助于您的收入和声誉。当您的客户有良好的购买经验时,您可以赢得他们的信任和忠诚度,这鼓励他们一次又一次地返回您的商业。”

Rapyd是一个金融科技平台,提供各种服务,包括发行卡,处理订阅和经常性账单,并为个人或企业使用提供灵活的付款方式。使用Rapyd,您可以从全球各种ATM和非处方现金访问点存入或撤回现金,或将电子商务商店与其收集API集成。

在本文中,您将学习如何在Python应用程序中集成Rapyd Collect的Checkout Workflow。

Rapyd收集API

Rapyd Collect API允许您接受来自世界任何地方的付款。为了帮助您增加覆盖范围和销售,它适用于以下类别下的一千多种付款方式类型:

  • 银行重定向
  • 银行转移
  • ewallet
  • Cash

Rapyd收集还允许您处理订阅,开票和付款修改,例如发行退款或取消交易。

Rapyd被认证为1级服务提供商,并获得了英国标准机构(BSI)信息安全证书。遵守这些行业安全标准可确保Rapyd平台是very safe用于处理敏感信息。

为了使开始在您的应用程序中收取付款,Rapyd为WooCommerce和Shopify等一些最受欢迎的电子商务平台提供了现成的插件。如果那些无法满足您的应用程序设置需求,则与API进行自定义集成也很简单。

Rapyd Collect提供两个结帐选项:托管和嵌入。对于托管结帐,用户被重定向到Rapyd的网站,以完成结帐过程,然后再将其重定向回到“成功” URL,假设一切都没有任何问题。嵌入式结帐使您的客户可以在您的应用程序中从您的应用程序中进行securely check out,而无需离开您的网站。在本教程中,您将实现托管的结帐工作流:

Rough architecture diagram for hosted checkout workflow

此工作流通常包括以下内容:

  • 您的应用程序向/v1/checkout端点提出了付款详细信息的请求,包括重定向URL。
  • 在呼叫该端点成功后,用户然后将用户重定向到Rapyd的托管结帐页面,该页面与上图中的步骤1中使用的付款详细信息有关。
  • 从结帐页面中,根据用户的操作,用户要么将用户重定向到complete_checkout_urlcancel_checkout_url,如上面的付款详细信息所定义的。

在使用Rapyd的Python应用程序中实施付款

在开始之前,以下是必须完成的一些先决条件才能与教程一起进行:

  • 在您的机器上下载并安装Python 3
  • 创建一个Rapyd account并按照提示完成激活过程。有关更多详细信息,请参阅注册客户门户帐户的指南。然后继续下面的步骤完成设置。

从您的Rapyd仪表板中,切换到沙盒模式,选择左窗格上的开发人员图标,然后单击凭据详细信息选项卡。请注意访问密钥和秘密键,因为这些需要对Rapyd的端点进行API调用。当您完成开发/测试应用程序并准备从客户那里收取真实现金时,您还需要更新这些密钥。您会发现,从沙盒模式(沙盒凭据)切换到生产模式(生产凭据)时,有两组访问和秘密键。

Steps to follow to access your app's credentials

在仪表板上,您可以通过更改徽标和颜色,编辑接受的付款方式和卡类型,添加和邀请用户/角色,添加Webhook端点等来自定义组织的结帐页面。

要添加一些基本的自定义,请单击左下方的设置齿轮,然后选择品牌以揭示可以自定义结帐页面的接口。在这里,您可以添加品牌的徽标,更改付款操作按钮的颜色或文本,调整可接受的付款方式等。在您看到合适的情况下,请务必在此页面上进行编辑,然后单击保存在继续创建Python应用之前。

Brand customization dashboard

Python应用程序设置

在本教程中,您将使用Flask framework创建Python Web应用程序。该应用将包含三个文件:

  • app.py:包含应用程序路由实现
  • utilities.py:包含可重复使用的make_request方法,您可以从应用程序中的任何地方调用,传递正确的参数
  • requirements.txt:包含应用依赖项

要开始,创建一个名为events的新文件夹,该文件夹将用作您的项目文件夹。在其中,创建文件 unigess.txt 并添加以下内容:

flask==2.2.2

接下来,创建文件 app.py 并粘贴以下代码:

from flask import Flask, request, redirect
import utilities

app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def app_home():
    # payment form submissions (payment-form name) in html below.
    if request.method == 'POST' and request.form['amount']:
        amount = int(request.form['amount'])
        body = {
            'amount': amount,
            'complete_checkout_url': 'http://example.com/complete',
            'country': 'US',
            'currency': 'USD',
            'cancel_checkout_url': 'http://example.com/cancel',
            'language': 'en',
        }

        try:
            # Generate checkout with this payment object
            req = utilities.make_request('post', '/v1/checkout', body)
            print('++++++ payment created +++++')
            print(req['data']['redirect_url'])
            print('++++++ payment created +++++')

            # Redirect to checkout.
            return redirect(req['data']['redirect_url'])

        except Exception as ex:
            print(ex)

    # Checkout html
    checkout_markup = "<div> <h1>Welcome to my Website!</h1> <hr>" \
                    "<h1> Checkout my upcoming event</h1> " \
                    "<section><h3>Consuming 3rd party apis (online)</h3> " \
                    "<p>Introduction to Postman Collections and api examples</p>" \
                    "<bold>$100</bold> <p></p>" \
                    "<form name=payment-form method=POST> " \
                    "<input type=hidden name=amount value=100>" \
                    " <input type=submit value=\"Reserve your slot \" name=submit>" \
                    "</form>" \
                    "</section><hr>" \
                    "</div>"
    return checkout_markup


@app.route('/rapyd-webhooks', methods=['POST'])
def rapyd_webhooks():
    print("Data received from Rapyd Webhook event is : ", request.json)
    return "Data received"

app.run(debug=True)

上面的 app.py 文件定义了应用程序的主页,该页面将包含带有名为“金额”的输入字段的付款表格,并将显式值设置为100。在现实世界中,这个数字将来自产品的总价格计算。

提交表单时,发生以下事情:

  • 表格发布到同一URL,从邮政请求中,您获得了表格中定义的金额值。
  • 此金额用于创建一个字典,其中包含有关付款项目的详细信息,以生成结帐表格,包括货币和重定向URL。
  • 然后,该应用程序使用UTITIORITION make_request方法向/v1/checkout端点提出请求,以传递上面的详细信息。关于成功,它将您重定向到具有您之前设置的自定义的hosted checkout page

最后,创建 utilities.py 文件。为了向Rapyd的API端点提出请求,要求正确格式化请求对象,包括所需的headers and signatures。 Rapyd可以帮助您使用utilities有效地进行此操作。您只需在Python选项卡下复制代码并将其粘贴到utilities.py文件中,然后将access_keysecret_key变量的值设置为在您的应用程序tab下的rapyd dashboard上的“开发人员”选项卡下的那些。

(注意:稍后,当您从沙盒切换到生产时,不要忘记相应地更新相同的值。您还需要将基本URL更新到生产中,以避免遇到问题。)

import json
import random
import string
import hmac
import base64
import hashlib
import time
import requests

"""
Replace base_url, access_key and secret key
accordingly (sandbox vs production)
"""
base_url = 'https://sandboxapi.rapyd.net'
secret_key = '<secret key>'
access_key = '<access key>'

"""
Generates and returns a unique random salt.
"""


def generate_salt(length=12):
    return ''.join(random.sample(string.ascii_letters + string.digits, length))


"""
Returns the current time in seconds.
"""


def get_unix_time(days=0, hours=0, minutes=0, seconds=0):
    return int(time.time())


"""
Generates a signature in relation to, the random salt, current time, http
method, path, the request body and the app keys.
"""


def update_timestamp_salt_sig(http_method, path, body):
    if path.startswith('http'):
        path = path[path.find(f'/v1'):]
    salt = generate_salt()
    timestamp = get_unix_time()
    to_sign = (http_method, path, salt, str(timestamp), access_key, secret_key, body)

    h = hmac.new(secret_key.encode('utf-8'), ''.join(to_sign).encode('utf-8'), hashlib.sha256)
    signature = base64.urlsafe_b64encode(str.encode(h.hexdigest()))
    return salt, timestamp, signature


"""
The current header signature dictionary.
"""


def current_sig_headers(salt, timestamp, signature):
    sig_headers = {'access_key': access_key,
                'salt': salt,
                'timestamp': str(timestamp),
                'signature': signature,
                'idempotency': str(get_unix_time()) + salt}
    return sig_headers


"""
Formats the request body and returns it, and the unique salt, signature and current timestamp.
"""


def pre_call(http_method, path, body=None):
    str_body = json.dumps(body, separators=(',', ':'), ensure_ascii=False) if body else ''
    salt, timestamp, signature = update_timestamp_salt_sig(http_method=http_method, path=path, body=str_body)
    return str_body.encode('utf-8'), salt, timestamp, signature


"""
Creates the body and headers with the right signature according to the current request contexts,
for use in the make_request method.
"""


def create_headers(http_method, url, body=None):
    body, salt, timestamp, signature = pre_call(http_method=http_method, path=url, body=body)
    return body, current_sig_headers(salt, timestamp, signature)


"""
Reusable utility method.
Use this from anywhere in your application.
"""


def make_request(method, path, body=''):
    body, headers = create_headers(method, base_url + path, body)

    if method == 'get':
        response = requests.get(base_url + path, headers=headers)
    elif method == 'put':
        response = requests.put(base_url + path, data=body, headers=headers)
    elif method == 'delete':
        response = requests.delete(base_url + path, data=body, headers=headers)
    else:
        response = requests.post(base_url + path, data=body, headers=headers)

    if response.status_code != 200:
        raise TypeError(response, method, base_url + path)
    return json.loads(response.content)

测试应用程序

所有三个文件都到位后,请使用您的CLI工具从应用程序文件夹的根来运行pip install -r requirements.txt来安装Python应用程序依赖的依赖项。

然后运行python app.pypython3 app.pyhttp://127.0.0.1:5000/启动应用程序,并从您喜欢的浏览器访问相同的URL。

Server and Python app running in the browser

从这里,您可以单击保留您的插槽按钮以提交付款表并启动付款创建请求,该请求将成功地将您重定向到您之前设计的托管结帐页面。

根据用户从那里采取的操作,它们将被重定向到您在创建付款对象时定义的complete_checkout_urlcancel_checkout_url。还在此结帐页面上,用户可以根据您以前的设置/允许的选项选择其首选付款选项。

Testing/simulating a successful checkout process

要模拟在沙箱环境中成功的交易,请使用卡号41111111111111,任何值的CVV代码和持卡人名称以及到期日期的任何未来日期。要测试客户在付款期间可能会得到的所有边缘案例/响应,请在test credit and debit card numbers上查看此帖子。

超越基本知识

从此工作流程中,当客户在结帐页面上的操作后重定向时,没有付款ID可以与付款相关联。同样,如果以后的付款完成(例如在经常性订阅中),则不需要您的客户遵循工作流程。解决这些问题的一种灵活解决方案是使用Webhooks。

webhooks是一种很好的方式,可以让您的应用程序知道外部发生的事情。与API端点不同,您不会称呼webhooks。他们“回电给您”。 Rapyd还包括此功能/功能。您可以从应用程序发送相关事件的应用程序中提供一个URL,然后可以使用这些详细信息来添加以前的工作流程中的丢失的部分,例如更新完成/退款的付款,以与您的付款表格实现创建的付款对象有关。

您已经在 app.py 文件中定义了一个webhook端点。要开始测试并进一步进行操作,您需要包括ngrok,并通过在另一个终端运行ngrok http 5000来揭示Python应用程序。然后,您可以让Rapyd知道您有一个Webhook URL准备使用Rapyd仪表板的开发人员部分下的Webhooks选项卡:

Webhook configuration dashboard

下图显示了在终端上打印的传入Webhook事件的有效载荷您的Python应用程序正在运行:

Webhook events payloads

这是一个GIF,显示了在行动中工作的网络钩:

Webhook events vs. user actions

结论

在本教程中,您探讨了如何将RAPYD收集API集成到Python应用程序中的基础知识,以允许客户使用其首选的付款选项从世界任何地方退房。如果您想要为用户提供不同的结帐体验,也可以考虑Rapyd的嵌入式结帐选项,用户可以在不离开网站的情况下安全地退房。

Rapyd还允许您创建与您和您的伴侣的eligible,在API之上提供的相同服务。 Rapyd处理所有敏感信息,使您只能访问应用程序所需的元数据。然后,您可以将您的服务以Rapyd API构建的服务转售给其他消费者以获利。

今天要了解有关Rapyd,explore the docssign up for a free account的更多信息。

您可以在this GitHub repo中找到本教程的完整代码。