Unofficial Ruby SDK for Airwallex APIs.
This is an unofficial Ruby SDK for Airwallex. It is not maintained, sponsored, or endorsed by Airwallex.
Requires Ruby 3.1+.
- Configuration support
- Demo and production environments
- Authentication and token caching
- Faraday-based HTTP client
- Typed error handling
- PaymentIntents resource
- Refunds resource
- Idempotency key support
- Webhook signature verification
- Optional Rails initializer generator
- RSpec/WebMock test coverage
Add this line to your application's Gemfile:
gem "airwallex-ruby"Then run:
bundle installFor local development against a checkout of this repository:
gem "airwallex-ruby", path: "../airwallex-ruby"require "airwallex"
Airwallex.configure do |config|
config.client_id = ENV["AIRWALLEX_CLIENT_ID"]
config.api_key = ENV["AIRWALLEX_API_KEY"]
config.login_as = ENV["AIRWALLEX_LOGIN_AS"]
config.environment = :demo
config.timeout = 30
config.open_timeout = 10
end
client = Airwallex.clientYou can also construct a client directly without global configuration:
client = Airwallex::Client.new(
client_id: ENV["AIRWALLEX_CLIENT_ID"],
api_key: ENV["AIRWALLEX_API_KEY"],
login_as: ENV["AIRWALLEX_LOGIN_AS"],
environment: :demo
)| Environment | Base URL |
|---|---|
:demo |
https://api-demo.airwallex.com/api/v1 |
:production |
https://api.airwallex.com/api/v1 |
Set config.environment or pass environment: when creating a client.
Authentication is handled automatically. When an authenticated request is made, the client calls POST /authentication/login if no valid token is cached. The access token is stored in memory and reused until it expires. All authenticated requests include Authorization: Bearer <token>.
You can authenticate explicitly or check authentication state:
client.authenticate
client.authenticated?payment_intent = client.payment_intents.create(
{
amount: 1000,
currency: "PHP",
merchant_order_id: "ORDER-1001",
return_url: "https://example.com/return"
},
idempotency_key: "order-1001-create"
)
puts payment_intent["id"]
puts payment_intent["client_secret"]payment_intent = client.payment_intents.retrieve("int_123")payment_intent = client.payment_intents.update(
"int_123",
{
amount: 1500
},
idempotency_key: "order-1001-update"
)client.payment_intents.cancel(
"int_123",
idempotency_key: "order-1001-cancel"
)payment_intents = client.payment_intents.list(
currency: "PHP",
page_num: 0,
page_size: 20
)refund = client.refunds.create(
{
payment_intent_id: "int_123",
amount: 500,
reason: "requested_by_customer",
metadata: {
order_id: "ORDER-1001"
}
},
idempotency_key: "order-1001-refund-1"
)refund = client.refunds.retrieve("ref_123")refunds = client.refunds.list(
payment_intent_id: "int_123",
page_num: 0,
page_size: 20
)Use idempotency keys for payment creation, updates, cancellations, and refunds. The key should be unique per operation.
Good examples:
order-1001-createorder-1001-updateorder-1001-refund-1
Pass idempotency_key: to resource methods or lower-level client.post / client.patch calls. The SDK sends the key as the x-idempotency-key header.
Verify incoming webhook requests using the raw request body and Airwallex signature headers:
raw_body = request.body.read
event = Airwallex::Webhook.construct_event(
payload: raw_body,
signature: request.headers["x-signature"],
timestamp: request.headers["x-timestamp"],
secret: ENV.fetch("AIRWALLEX_WEBHOOK_SECRET")
)
case event["name"]
when "payment_intent.succeeded"
# handle payment success
when "refund.accepted"
# handle refund accepted
endImportant notes:
- Always use the raw request body.
- Verify the signature before parsing JSON (
construct_eventdoes this for you). - Old timestamps are rejected by default (300 second tolerance).
- Signature comparison is timing-safe.
Run the generator:
rails generate airwallex:installThis creates:
config/initializers/airwallex.rb
Credentials example:
airwallex:
client_id: your_client_id
api_key: your_api_key
login_as: optional_account_id
webhook_secret: your_webhook_secretRails webhook controller example:
class AirwallexWebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def create
event = Airwallex::Webhook.construct_event(
payload: request.body.read,
signature: request.headers["x-signature"],
timestamp: request.headers["x-timestamp"],
secret: Rails.application.credentials.dig(:airwallex, :webhook_secret) || ENV.fetch("AIRWALLEX_WEBHOOK_SECRET")
)
case event["name"]
when "payment_intent.succeeded"
# handle payment success
when "refund.accepted"
# handle refund accepted
end
head :ok
rescue Airwallex::WebhookSignatureError, Airwallex::InvalidResponseError
head :bad_request
end
endRoute:
post "/webhooks/airwallex", to: "airwallex_webhooks#create"See also examples/rails_webhook_controller.rb.
A lightweight Rails integration example is available in:
examples/rails_app
It demonstrates:
- Airwallex initializer configuration
- PaymentIntent creation
- Refund creation
- Webhook verification
- Example routes
See docs/examples.md for more usage notes.
The SDK raises typed errors for configuration, authentication, HTTP status codes, timeouts, invalid responses, and webhook verification failures.
| Error | Description |
|---|---|
Airwallex::Error |
Base error for all SDK errors |
Airwallex::ConfigurationError |
Missing or invalid configuration |
Airwallex::AuthenticationError |
Login or token handling failed |
Airwallex::ArgumentError |
Invalid method arguments |
Airwallex::HTTPError |
Base class for HTTP error responses |
Airwallex::BadRequestError |
HTTP 400 |
Airwallex::UnauthorizedError |
HTTP 401 |
Airwallex::ForbiddenError |
HTTP 403 |
Airwallex::NotFoundError |
HTTP 404 |
Airwallex::ConflictError |
HTTP 409 |
Airwallex::RateLimitError |
HTTP 429 |
Airwallex::ServerError |
HTTP 5xx |
Airwallex::TimeoutError |
Request timeout or connection failure |
Airwallex::InvalidResponseError |
Invalid JSON or webhook payload |
Airwallex::WebhookSignatureError |
Webhook signature or timestamp verification failed |
Example:
begin
client.payment_intents.retrieve("int_123")
rescue Airwallex::NotFoundError => e
puts e.status
puts e.code
puts e.message
rescue Airwallex::RateLimitError
# retry later
rescue Airwallex::Error => e
# generic Airwallex SDK error
endBuild the gem from a checkout:
gem build airwallex-ruby.gemspecOr use the Rake task (output goes to pkg/):
bundle exec rake buildInstall locally:
gem install ./airwallex-ruby-0.1.0.gem
# or, after rake build:
gem install ./pkg/airwallex-ruby-0.1.0.gemTest in IRB:
require "airwallex"
Airwallex::VERSION
# => "0.1.0"Do not publish until the release checklist is complete and changes have been reviewed.
After review, tag and push. GitHub Actions publishes to RubyGems and creates a GitHub Release:
git tag v0.1.0
git push origin main
git push origin v0.1.0Requires the RUBYGEMS_API_KEY repository secret. See docs/release.md.
gem push airwallex-ruby-0.1.0.gem
# or, after rake build:
gem push pkg/airwallex-ruby-0.1.0.gemSee docs/release.md for the full release checklist.
Manual sandbox verification scripts are available under:
scripts/sandbox
See:
Example:
cp .env.example .env
bundle exec rspec
ruby scripts/sandbox/authenticate.rb
ruby scripts/sandbox/create_payment_intent.rbThese scripts require Airwallex sandbox credentials and are not part of the automated unit test suite.
bundle install
bundle exec rspec
bundle exec rubocop
bundle exec rake buildSee docs/airwallex-research.md for API notes and planned resources.
- RSpec is used for the test suite.
- WebMock is used to stub Airwallex API requests.
- No real Airwallex credentials are required for unit tests.
- PaymentIntent confirm/capture support
- PaymentAttempts resource
- Customers resource
- PaymentConsents resource
- Transfers resource
- Balances resource
- Transactions resource
- File uploads
- More Rails generators
- Integration test mode
- Issues: use GitHub Issues for bugs and feature requests.
- Pull requests: contributions are welcome. See CONTRIBUTING.md.
- Security: do not report vulnerabilities in public issues. See SECURITY.md.
- CI: GitHub Actions runs specs, RuboCop, and gem build.
- Fork the repository
- Create a feature branch
- Add specs for your changes
- Run the test suite (
bundle exec rspec) and RuboCop (bundle exec rubocop) - Open a pull request
Runnable and copy-paste examples live in the examples/ directory:
- basic_configuration.rb
- payment_intent_create.rb
- refund_create.rb
- webhook_verification.rb
- rails_webhook_controller.rb
MIT — see LICENSE.txt.