PAYATHON 2026

Ruby on Rails 与 jBilling 有哪些现成集成方案?

支付阿杰

结论

jBilling 通常没有成熟、通用的 Ruby/Rails 专用客户端,无法直接完成全部数据读写。实际集成主要有两种方式:

  1. 在 Rails 中使用 SOAP 客户端,根据 jBilling 提供的 WSDL 调用 API。对于 MRI Ruby,这是最直接、耦合较低的方案。
  2. 如果应用已经运行在 JRuby 上,可以直接调用 jbilling_api.jar。Java 依赖应交给 Maven 或 Gradle 管理,不要把一批 JAR 文件随意复制到 Rails 项目中。

Java RMI 依赖 JVM,客户端与服务端的耦合较深。Burlap 在 Ruby 生态中的支持也比较有限。如果没有现成且稳定的内部基础设施,不适合优先用于 Rails 集成。

方案一:通过 SOAP 集成

Ruby 可以使用 savon 读取 WSDL 并发送 SOAP 请求。

# Gemfile
gem "savon"

可以在 Rails 中封装一个客户端:

# app/services/jbilling_client.rb
class JbillingClient
  def initialize
    @client = Savon.client(
      wsdl: ENV.fetch("JBILLING_WSDL_URL"),
      open_timeout: 5,
      read_timeout: 30,
      log: Rails.env.development?
    )
  end

  def operations
    @client.operations
  end

  def call(operation, message:)
    @client.call(operation, message: message).body
  rescue Savon::SOAPFault, Savon::HTTPError => e
    Rails.logger.error("jBilling request failed: #{e.class}: #{e.message}")
    raise
  end
end

首先查看当前 WSDL 暴露了哪些操作:

client = JbillingClient.new
puts client.operations

再按照 WSDL 定义的操作名和参数发起调用:

result = client.call(
  :operation_name,
  message: {
    someParameter: "value"
  }
)

示例没有写死 getUser、updateOrder 等方法名,因为不同 jBilling 版本和部署方式可能使用不同的接口、命名空间及认证参数。具体调用应以目标环境的 WSDL 为准。

如果认证信息需要写入 SOAP Header,可以在客户端配置中加入:

@client = Savon.client(
  wsdl: ENV.fetch("JBILLING_WSDL_URL"),
  soap_header: {
    "Authentication" => {
      "username" => ENV.fetch("JBILLING_USERNAME"),
      "password" => ENV.fetch("JBILLING_PASSWORD")
    }
  }
)

这里的 Header 名称和字段仅用于展示结构,实际配置必须根据 WSDL 或 jBilling 的部署设置调整。

方案二:在 JRuby 中直接调用 Java API

JRuby 可以加载 JAR,并通过 java_import 使用其中的 Java 类:

require "java"

Dir[Rails.root.join("vendor/jbilling/*.jar")].each do |jar|
  require jar
end

java_import "com.example.jbilling.SomeApiClass"

需要把 SomeApiClass 替换为当前版本 jbilling_api.jar 中的真实类名,具体调用方式也应以该版本的 Java API 文档为准。

这样可以直接使用 jBilling 的 Java DTO、异常类型和 remoting 实现,省去部分 SOAP 数据结构转换。不过,它也会带来一些限制:

  • Rails 应用只能运行在 JRuby 上。
  • Spring、CXF、日志组件等依赖可能与应用中的现有版本冲突。
  • 升级 jBilling 时,Java API 和传输层依赖可能同时发生变化。
  • 测试、部署以及 classpath 问题的排查会比普通 Rails 应用复杂。

引入大量 JAR 是否合理

依赖数量多不一定说明做法有问题。Spring、CXF 和日志组件等通常就是 Java 客户端的传递依赖。更需要关注的是依赖管理方式。

不要手工复制来源或版本不明的 JAR。更稳妥的处理方式包括:

  • 使用 Maven 或 Gradle 固定依赖版本。
  • 保留依赖锁定信息,保证开发、测试和生产环境使用相同版本。
  • 检查 Log4j、Commons Logging、Spring 等组件是否与应用已有依赖冲突。
  • 避免同时引入同一个库的多个版本。
  • 使用与生产环境相同的 JRuby 和 jBilling 版本运行集成测试。

如果这些 JAR 只能从 jBilling 发行包中取得,也应把它们作为一个具有明确版本的完整依赖集合管理,不要零散地加入 classpath。

更推荐的架构

如果 Rails 应用没有使用 JRuby,或者团队不想让 Rails 直接承担 Java 依赖,可以在 jBilling 前增加一个轻量的适配服务:

Rails application
        |
     HTTP/JSON
        |
jBilling adapter service
        |
Java API / SOAP
        |
     jBilling

适配服务处理认证、Java DTO 转换、错误映射和版本兼容,Rails 只需要调用稳定的 HTTP/JSON 接口。虽然系统中会多出一个服务,但 jBilling 的 Java 依赖可以与 Rails 隔离,升级时也更容易控制影响范围。

如果当前使用的 jBilling 版本提供可用的 REST API,也可以直接使用 REST。采用前需要核对该版本的官方文档,不能默认早期版本也有相同能力。

选择建议

  • MRI Rails:优先选择 SOAP 和 savon。
  • 已经使用 JRuby,并且需要完整的 Java API 能力:直接集成 jbilling_api.jar,同时使用标准 Java 构建工具管理依赖。
  • 系统规模较大,或者 Rails 与 jBilling 需要分别升级:增加独立的适配服务。
  • 如果只是为了调用 jBilling,不建议把现有的 MRI Rails 应用迁移到 JRuby,除非系统还有其他明确的 JVM 集成需求。

无论采用哪种方式,都要配置连接超时、读取超时和脱敏日志。重试只能用于查询操作,或者明确具有幂等保证的操作。创建账单、付款、订单等写操作不能直接无条件重试,否则可能产生重复数据。

备注:内容仅供参考。