PAYATHON 2026

如何在 WSO2 API Manager 中集成 payment gateway

支付阿杰

明确结论

这里的 callback URL 不是支付网关首页,也不是 Developer Portal 的普通页面地址。它是支付完成后接收支付结果的回调端点。

建议采用以下集成流程:

  1. 用户提交 subscription 后,WSO2 API Manager 创建一个待处理的 workflow,并生成 workflowReferenceId。
  2. 自定义 workflow executor 将用户重定向到支付网关,同时传递:
    • 支付回调地址 callback URL
    • workflowReferenceId
    • 订单号等业务参数
  3. 支付网关将支付结果通知支付回调服务。
  4. 回调服务先向支付网关核验支付结果。
  5. 确认支付成功后,回调服务调用 WSO2 API Manager 的 workflow callback API,将 workflow 标记为 APPROVED。
  6. API Manager 随后执行 workflow executor 的 complete(...),完成 subscription。

通常不应让支付网关或浏览器直接调用 Java complete(...) 方法。API Manager 会在处理 workflow callback 时从内部调用该方法。

callback URL 应该指向哪里

建议将它设置为由你控制的服务端地址,例如:

https://billing.example.com/payment/wso2/callback

这个地址负责接收支付网关发来的服务器通知,然后调用 API Manager。

不要把支付网关的浏览器跳转当作可信的支付成功通知。很多支付平台会同时提供两类回调:

  • return_url:支付完成后,将用户的浏览器跳转到指定页面。
  • notify_url 或 webhook:支付平台从服务端向商户系统发送通知。

是否完成 subscription,应以 webhook 通知或主动查询支付结果为准,不能只根据浏览器跳转参数判断支付是否成功。

如果当前 WSO2 版本的文档明确要求将 API Manager 的 workflow callback endpoint 用作 callback URL,还需要确认支付网关能否按照该接口的要求发送 HTTP 方法、JSON 数据和认证信息。多数支付网关无法直接满足这些要求,所以通常需要增加一个支付回调服务。

推荐的处理流程

1. 创建 subscription workflow

自定义 subscription workflow executor 在 execute(...) 阶段发起支付,并让 workflow 保持待处理状态。此时需要保存以下映射关系:

paymentOrderId -> workflowReferenceId

不要只依赖浏览器传递 workflowReferenceId。在服务端保存映射可以避免参数被篡改,也便于处理异步通知和重复回调。

支付请求的结构可以是:

{
  "orderId": "PAY-20260831-0001",
  "amount": "99.00",
  "currency": "CNY",
  "returnUrl": "https://portal.example.com/payment/result",
  "notifyUrl": "https://billing.example.com/payment/wso2/callback",
  "metadata": {
    "workflowReferenceId": "8de4b993-xxxx-xxxx-xxxx-87eaf9d2b491"
  }
}

具体字段名由支付网关决定。有些网关会使用 additional_parameters、metadata、custom 或 passback_params 等名称。

2. 接收并验证支付通知

回调服务收到通知后,至少要验证以下内容:

  • 支付网关签名是否正确;
  • 订单号是否存在;
  • 订单金额和币种是否匹配;
  • 支付状态是否为最终成功状态;
  • 该订单是否已经处理;
  • 必要时,通过支付网关的订单查询 API 再次确认。

示例逻辑:

@PostMapping("/payment/wso2/callback")
public ResponseEntity<String> handlePaymentCallback(
        @RequestBody String requestBody,
        @RequestHeader Map<String, String> headers) {

    PaymentNotification notification =
            paymentGateway.verifyAndParse(requestBody, headers);

    if (!notification.isPaymentSuccessful()) {
        return ResponseEntity.ok("ignored");
    }

    PaymentOrder order = paymentOrderRepository
            .findByOrderId(notification.getOrderId())
            .orElseThrow(() -> new IllegalArgumentException("Unknown order"));

    if (!order.matches(notification.getAmount(), notification.getCurrency())) {
        throw new IllegalStateException("Payment amount or currency mismatch");
    }

    if (!order.isWorkflowCompleted()) {
        wso2WorkflowClient.approve(order.getWorkflowReferenceId());
        order.markWorkflowCompleted();
        paymentOrderRepository.save(order);
    }

    return ResponseEntity.ok("success");
}

这段代码只展示整体结构。支付签名的验证方式、回调返回内容和重试规则,都应以实际使用的支付网关协议为准。

3. 调用 WSO2 workflow callback API

不同版本的 WSO2 API Manager 可能使用不同的 REST API 路径、版本号、认证方式和请求结构,不能把某个固定 URL 当作所有版本都适用的地址。应在当前部署版本的 REST API 文档或 API Console 中确认 workflow endpoint。

常见的调用形式如下:

curl --request POST \
  'https://apim.example.com:<port>/<workflow-callback-endpoint>' \
  --header 'Authorization: Bearer <access-token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "workflowReferenceId": "8de4b993-xxxx-xxxx-xxxx-87eaf9d2b491",
    "workflowStatus": "APPROVED",
    "description": "Payment verified"
  }'

主要参数是:

{
  "workflowReferenceId": "<创建 subscription 时生成的引用 ID>",
  "workflowStatus": "APPROVED"
}

有些版本可能使用 status,也可能将接口放在旧版 Store API、DevPortal API 或独立的 workflow callback service 中。具体实现必须以当前版本的 OpenAPI 定义为准,不能只替换示例中的版本号。

如果支付失败、订单关闭或超时,可以根据当前版本支持的状态提交 REJECTED。不要自行猜测状态名称,应先查看该版本允许的 workflow status 枚举。

complete(...) 是怎样被调用的

自定义 Java workflow executor 通常分为两个阶段:

public WorkflowResponse execute(Workflow workflow)

用户提交 subscription 时会执行 execute(...)。该方法用于创建支付订单,并让 workflow 保持待处理状态。

public WorkflowResponse complete(Workflow workflow)

workflow callback API 收到 APPROVED 或 REJECTED 状态后,API Manager 会根据 workflowReferenceId 找到原来的 workflow,再调用对应 executor 的 complete(...)。

正常的调用链如下:

支付成功
  -> 支付回调服务验证结果
  -> 调用 workflow callback API
  -> API Manager 查找 workflow
  -> API Manager 调用 complete(...)
  -> subscription 被批准

不建议在支付回调代码中直接实例化 executor 并调用:

executor.complete(workflow);

这种做法会绕过 API Manager 的 workflow 持久化、状态检查、事务处理和 executor 定位机制,可能导致 workflow 已经批准,但 subscription 没有正确更新。

complete(...) 的示意实现

自定义 executor 的结构大致如下:

public class PaymentSubscriptionWorkflowExecutor
        extends SubscriptionCreationWorkflowExecutor {

    @Override
    public WorkflowResponse execute(Workflow workflow)
            throws WorkflowException {

        SubscriptionWorkflowDTO subscriptionWorkflow =
                (SubscriptionWorkflowDTO) workflow;

        String workflowReferenceId =
                subscriptionWorkflow.getExternalWorkflowReference();

        String paymentUrl = createPaymentOrder(
                workflowReferenceId,
                subscriptionWorkflow
        );

        WorkflowResponse response = new GeneralWorkflowResponse();
        response.setWorkflowStatus(WorkflowStatus.CREATED);
        response.setRedirectUrl(paymentUrl);

        return response;
    }

    @Override
    public WorkflowResponse complete(Workflow workflow)
            throws WorkflowException {

        return super.complete(workflow);
    }
}

这段代码只说明职责如何划分。类名、DTO、状态常量、setRedirectUrl(...) 是否存在,以及父类的具体行为,都取决于所使用的 WSO2 API Manager 版本。实现时应参考目标版本提供的 workflow executor API 和示例代码。

通常应尽量复用 WSO2 自带的 subscription completion 逻辑,例如调用父类的 complete(...)。如果只修改 workflow 状态,可能会漏掉真正的 subscription 状态更新。

回调后跳转到 Developer Portal

workflow callback 是服务端的状态更新接口,不一定负责页面跳转。支付完成后,可以将浏览器跳转到自己的结果页:

https://portal.example.com/payment/result?orderId=PAY-20260831-0001

结果页再通过后端查询:

  • 支付订单状态;
  • workflow 状态;
  • subscription 是否已激活。

不要在 URL 中直接暴露访问令牌,也不要让前端使用高权限凭据调用 WSO2 workflow API。

注意事项

  • workflowReferenceId 必须是创建该 subscription workflow 时生成的值,不能用 subscription ID、application ID 或支付订单号代替。
  • callback API 通常需要认证。访问令牌和客户端密钥只能保存在服务端。
  • 支付网关可能重复发送通知,因此回调处理必须具备幂等性。
  • 必须先验证支付,再批准 subscription,否则可能出现用户未付款却可以调用 API 的时间窗口。
  • API Manager 无法访问支付回调服务时,应检查反向代理、TLS 证书、防火墙和主机名解析。
  • 如果 callback 返回成功,但 subscription 仍处于 ON_HOLD 或待审批状态,应检查 workflowReferenceId、executor 配置、workflow 状态值和 API Manager 日志。
  • 支付成功和 workflow 批准最好通过可重试的状态机处理。如果支付已经成功,但 API Manager 暂时不可用,应保存订单状态并重试 callback,不要要求用户再次付款。

备注:内容仅供参考。