PAYATHON 2026

WSO2 Business Activity Monitor 是否支持支付网关

支付阿杰

结论

WSO2 Business Activity Monitor(BAM)用于采集、聚合和分析 API 使用数据,不是计费或支付系统。它通常没有开箱即用的 payment gateway,也不处理信用卡扣款、退款、发票、税费和支付状态。

比较合理的做法是把流程分成三层:

  1. WSO2 API Manager 管理 API、识别身份并控制流量。
  2. BAM 记录和汇总 API 调用量。
  3. 独立的 Billing Service 根据用量计算费用,再调用 Stripe、PayPal、Adyen 或银行支付接口收款。

某些版本的 WSO2 API Manager 可能支持 monetization、订阅套餐或第三方计费扩展,但这不代表 BAM 内置了支付网关。具体功能要以当前版本的官方文档和产品包为准。

为什么不应让 BAM 直接处理付款

API 用量统计和支付处理属于不同的业务域。

BAM 可以回答:

  • 哪个订阅者调用了哪个 API;
  • 调用了多少次;
  • 请求是否成功;
  • 调用发生在哪个时间段;
  • 响应时间和流量是多少。

支付系统还要处理:

  • 套餐、阶梯价和免费额度;
  • 月结、预付费或余额扣减;
  • 发票和税费;
  • 支付授权、失败重试和退款;
  • 支付回调验签;
  • 对账和审计;
  • PCI DSS 等支付安全要求。

如果把这些逻辑写进 BAM 的统计任务,统计数据、价格规则和支付状态会耦合在一起。统计任务重新执行时,还可能造成重复扣款。

推荐的集成架构

Client
  │
  ▼
WSO2 API Manager
  │  usage events
  ▼
BAM / Analytics
  │  aggregated usage
  ▼
Billing Service
  ├── Pricing Engine
  ├── Invoice Service
  ├── Customer Mapping
  └── Payment Gateway Adapter
                         │
                         ▼
              Third-party Payment Gateway

BAM 输出”可计费用量”,Billing Service 把用量转换成账单,Payment Gateway 只处理实际支付。

实施步骤

1. 建立统一的客户和订阅标识

首先要把 API Manager 中的订阅关系映射到支付系统中的客户。建议至少保存以下字段:

{
  "tenantId": "tenant-001",
  "subscriberId": "user-123",
  "applicationId": "app-456",
  "apiId": "orders-api",
  "subscriptionId": "sub-789",
  "billingCustomerId": "cus_xxxxx"
}

不要把用户名作为唯一的计费主键。用户名、邮箱和显示名称都可能变化,稳定的 subscriptionId、applicationId 或租户标识更适合用作关联键。

2. 从 BAM 获取结算周期内的用量

具体的表名和查询方式取决于 BAM 版本及其数据存储配置,不能假设所有环境都使用相同的统计表。业务上需要得到类似下面的结果:

SELECT
    tenant_id,
    subscriber_id,
    application_id,
    api_id,
    COUNT(*) AS request_count
FROM api_usage_events
WHERE event_time >= :period_start
  AND event_time < :period_end
  AND billable = TRUE
GROUP BY
    tenant_id,
    subscriber_id,
    application_id,
    api_id;

结算周期应采用半开区间:

period_start <= event_time < period_end

这样可以避免相邻账期重复计算边界上的请求。

哪些请求可以计费也要事先确定,例如:

  • 只有成功响应才收费;
  • 所有到达网关的请求都收费;
  • 4xx 不收费,但需要确定 5xx 是否收费;
  • 重试请求是否单独计费;
  • 缓存命中的请求是否收费。

这些都是计费规则。不能因为 BAM 中有一条事件,就默认该请求需要收费。

3. 在独立服务中计算费用

下面的示例演示如何计算免费额度和超额费用:

from decimal import Decimal

def calculate_charge(request_count: int) -> Decimal:
    free_quota = 10_000
    unit_price = Decimal("0.0025")

    billable_count = max(0, request_count - free_quota)
    return (Decimal(billable_count) * unit_price).quantize(
        Decimal("0.01")
    )

生产环境还要保存当前账期的价格快照。不能只保存 plan_id,然后每次读取最新价格。否则套餐价格调整后,重新计算历史账单可能得到不同的金额。

一条计费明细可以采用以下结构:

{
  "billingPeriod": "2026-08",
  "subscriptionId": "sub-789",
  "apiId": "orders-api",
  "requestCount": 12500,
  "freeQuota": 10000,
  "billableCount": 2500,
  "unitPrice": "0.0025",
  "amount": "6.25",
  "currency": "USD",
  "pricingVersion": "orders-basic-v3"
}

计算金额时应使用定点数或 Decimal,不要使用二进制浮点数。

4. 生成账单后再调用支付网关

支付请求必须包含稳定的幂等键,以免任务重试造成重复扣款:

POST /payments
Authorization: Bearer <token>
Idempotency-Key: invoice-2026-08-sub-789
Content-Type: application/json

{
  "customerId": "cus_xxxxx",
  "invoiceId": "invoice-2026-08-sub-789",
  "amount": 625,
  "currency": "USD"
}

这里的 amount 使用最小货币单位,625 表示 6.25 USD。不同 payment gateway 的字段和接口并不相同,具体应以所选网关的实际 API 为准。

Billing Service 需要维护自己的支付状态,例如:

DRAFT → FINALIZED → PAYMENT_PENDING → PAID
                                  └──→ PAYMENT_FAILED

发起支付请求后,不要立即把账单标记为 PAID。最终状态通常要通过验签后的 payment webhook 或主动查询结果来确认。

5. 根据欠费状态控制 API 访问

出现欠费后,可以采用不同的处理策略:

  • 只发送提醒,不中断 API;
  • 降低订阅配额;
  • 暂停对应的 subscription;
  • 暂停整个 application;
  • 预付费余额不足时立即拒绝调用。

如果需要暂停访问,应由 Billing Service 调用 API Manager 的管理接口,或者执行受支持的订阅状态变更。不要直接修改 API Manager 或 BAM 的内部数据库。内部数据结构可能随版本变化,直接修改还可能绕过缓存和业务校验。

是否可以采用类似 StratosLive 的方式

可以借鉴 StratosLive 将用量采集、费用计算、账单生成和支付处理分开的思路,但不应把它的内部实现当作可以直接复用的 BAM payment gateway 插件。

除非目标 WSO2 版本明确提供公开且受支持的计费组件和扩展接口,否则更稳妥的方案是:

  • 把 BAM 作为 metering 数据源;
  • 自建或接入 billing platform;
  • 通过 adapter 封装不同的 payment gateway;
  • 通过 API Manager 的公开管理接口控制欠费账户。

这种结构便于更换支付服务商,也能避免价格规则依赖 BAM 的存储结构。

需要特别注意的问题

用量数据不能直接等同于账单

BAM 的统计数据可能存在延迟、重复事件或漏报。生成账单前,应检查数据完整性并进行去重。可以使用以下信息组合生成相对稳妥的唯一键:

gatewayNodeId + eventId

如果事件没有稳定的 eventId,就需要在采集链路中增加可用于去重的标识。

账单必须可以复现

建议保留:

  • 原始或归档后的用量记录;
  • 聚合结果;
  • 定价规则版本;
  • 免费额度;
  • 折扣和税费;
  • 调整记录;
  • payment gateway 的交易编号。

如果用量发生修正,不要直接覆盖已经出具的账单。通常应生成 credit note、debit adjustment,或者在下一账期加入调整项。

不要在实时请求链路中同步扣款

如果每次 API 调用都同步请求 payment gateway,会明显增加延迟,支付服务的故障也会传递到 API 调用链路。按量后付费通常按周期聚合用量;预付费场景则维护本地余额或配额,再通过异步流程充值。

注意支付数据安全

API Manager 和 BAM 不应保存完整银行卡号、CVV 等敏感支付信息。应优先使用 payment gateway 提供的托管支付页面或 tokenization,并验证所有支付回调的签名和时间戳,同时防范重放风险。

实际落地时,应把 BAM 当作用量计量组件,而不是收款组件。常见且便于维护的做法,是在 BAM 和第三方 payment gateway 之间增加独立的 Billing Service。

备注:内容仅供参考。