WSO2 Business Activity Monitor 是否支持支付网关
结论
WSO2 Business Activity Monitor(BAM)用于采集、聚合和分析 API 使用数据,不是计费或支付系统。它通常没有开箱即用的 payment gateway,也不处理信用卡扣款、退款、发票、税费和支付状态。
比较合理的做法是把流程分成三层:
- WSO2 API Manager 管理 API、识别身份并控制流量。
- BAM 记录和汇总 API 调用量。
- 独立的 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。
备注:内容仅供参考。
