PAYATHON 2026

其他语言中有哪些类似 ActiveMerchant 的支付处理框架?

支付阿杰

结论

在 PHP 生态中,最接近 ActiveMerchant 的方案是 Omnipay 和 Payum。Python 项目可以考虑 django-payments;如果只使用 Stripe,也可以选择 dj-stripe。不过,Python 生态目前没有一个在覆盖范围和行业认知度上都能完全对应 ActiveMerchant 的通用框架。

实际项目一般按需求选择:

  • 如果需要在多个支付网关之间切换,可以使用 Omnipay、Payum 或 django-payments 这类统一抽象层。
  • 如果已经确定使用 Stripe、PayPal、Adyen 等供应商,直接采用官方 SDK 通常更容易及时获得新 API、Webhook 和安全更新。

PHP

Omnipay

Omnipay 为支付网关提供统一接口,其设计思路与 ActiveMerchant 很接近。不同支付平台的支持通常通过独立的 gateway package 安装。

典型调用方式如下,具体类名和参数取决于安装的网关适配器:

<?php

use Omnipay\Omnipay;

$gateway = Omnipay::create('Stripe');

$gateway->setApiKey($_ENV['STRIPE_SECRET_KEY']);

$response = $gateway->purchase([
    'amount'   => '10.00',
    'currency' => 'USD',
    'token'    => $paymentToken,
])->send();

if ($response->isSuccessful()) {
    $transactionId = $response->getTransactionReference();
} elseif ($response->isRedirect()) {
    $response->redirect();
} else {
    throw new RuntimeException($response->getMessage());
}

Omnipay 适合这些场景:

  • 应用需要支持多个支付网关。
  • 希望业务代码不直接依赖某家供应商的 SDK。
  • 主要处理授权、扣款、退款和跳转支付等常见流程。

各网关提供的能力并不完全一致。统一接口通常只能覆盖它们共有的部分,订阅、分账、争议处理和特定风控功能仍可能需要直接调用供应商 API。

Payum

Payum 也提供支付抽象,并支持请求、状态、存储和通知处理。与单纯的网关封装相比,它更侧重完整的支付工作流,也可以与 Symfony 等框架集成。

通常先创建支付对象,再执行 capture:

<?php

$payment = $registry->getGateway('stripe');

$model = new ArrayObject([
    'amount'      => 1000,
    'currency'    => 'USD',
    'description' => 'Order #1001',
]);

$payment->execute(new Capture($model));

金额单位、模型字段和网关配置会随适配器而变化,不能假设所有网关都采用相同格式。接入时应查阅当前版本及对应 gateway 的文档。

Python

django-payments

对于 Django 项目,django-payments 提供统一的支付模型和 provider 抽象,可以用来封装不同的支付服务商。

常见做法是先创建支付记录:

from decimal import Decimal
from payments import get_payment_model

Payment = get_payment_model()

payment = Payment.objects.create(
    variant="default",
    description="Order #1001",
    total=Decimal("10.00"),
    currency="USD",
    billing_first_name="Ada",
    billing_last_name="Lovelace",
    billing_email="ada@example.com",
)

之后再通过 provider 对应的表单、跳转页面或回调流程完成支付。对于已经使用 Django ORM,并希望统一保存支付状态和交易记录的项目,这种方式比较合适。

不同 provider 要求的字段和支持的操作可能不同。退款、重复扣款和异步支付状态更新等功能需要逐项确认。

dj-stripe

dj-stripe 不是多网关框架,而是 Stripe 与 Django 的深度集成层。它可以把 Stripe 的部分对象和 Webhook 事件同步到 Django 数据库。

如果业务确定只使用 Stripe,dj-stripe 往往比通用抽象层更实用。如果以后可能更换支付供应商,它无法提供 ActiveMerchant 那种可替换的网关接口。

官方 Python SDK

对于非 Django 项目,或者需要使用供应商全部功能的项目,通常直接采用官方 SDK。例如 Stripe 的 Python SDK:

import os
import stripe

stripe.api_key = os.environ["STRIPE_SECRET_KEY"]

payment_intent = stripe.PaymentIntent.create(
    amount=1000,
    currency="usd",
    automatic_payment_methods={"enabled": True},
)

print(payment_intent.id)

示例中的 amount=1000 通常表示最小货币单位。以 USD 为例,1000 cents 就是 10.00 USD。零小数货币等情况有所不同,必须按照支付平台的货币规则处理。

其他语言和平台

其他生态也有相近的选择,但它们未必属于”多网关统一接口”:

  • JavaScript/TypeScript:通常直接使用 Stripe、PayPal、Adyen 等平台的官方 Node.js SDK。
  • Java/.NET:通常也以支付供应商的官方 SDK 为主。涉及复杂的订阅、账单和支付编排时,可以考虑独立计费平台。
  • Kill Bill:基于 JVM 的开源订阅、计费和支付平台,更接近完整的 billing system,不是轻量级的 ActiveMerchant 替代品。
  • jPOS:主要用于 ISO 8583 和金融交易消息处理,不是普通网站支付网关的直接替代方案。

选择方法

选型前,可以先列出业务实际需要的能力:

  1. 确认支付模式,包括一次性支付、预授权、订阅、退款、分账或线下支付。
  2. 确认是否确实需要支持多个网关。
  3. 检查框架是否支持目标网关所需的具体功能,不能只看支持列表。
  4. 验证 Webhook 签名、幂等键、退款和异步状态更新机制。
  5. 分开建模订单状态与支付状态,避免支付回调直接修改订单却没有审计记录。
  6. 如果统一框架缺少必要功能,应保留调用供应商官方 SDK 的扩展接口。

如果只接入一个支付平台,官方 SDK 通常更稳妥。如果明确需要切换多个网关,PHP 项目可以优先评估 Omnipay 或 Payum,Django 项目可以评估 django-payments。框架的维护状态和网关支持会随时间变化,选型前还应检查目标包当前的发布记录、兼容版本和安全维护情况。

注意事项

  • 不要在服务器日志或数据库中保存完整银行卡号、CVC 等敏感信息。
  • 优先采用支付平台托管页面、Hosted Fields 或 tokenization,以缩小 PCI DSS 合规范围。
  • Webhook 必须验证签名,并能处理重复投递。不能只根据浏览器跳转结果判断支付是否成功。
  • 创建支付、退款和确认订单时,应使用幂等机制。
  • 金额应使用整数形式的最小货币单位或 Decimal,不应使用二进制浮点数计算。
  • ActiveMerchant 这类抽象只能统一常见操作,无法消除不同支付平台在状态模型、错误码和结算规则上的差异。

备注:内容仅供参考。