Ruby SDK for the MONA Pay API: create checkout links and VietQR codes, manage virtual accounts, webhooks and email notifications, and verify signed webhooks.
Requires Ruby 2.6+. Standard library only, no gem dependencies.
The package is not on RubyGems yet. Until it is, install it from GitHub:
# Gemfile
gem "monapay", git: "https://github.com/mona-software/monapay-ruby"Once it is published on RubyGems:
# Gemfile
gem "monapay", "~> 0.4"require "monapay"
client = MonaPay::Client.from_env
checkout = client.checkouts.create({
amount: 250_000,
order_code: "DH10234",
return_url: "https://shop.example/payment/return"
})
puts checkout["checkout_url"]# From environment variables (see Configuration)
client = MonaPay::Client.from_env
# Or explicitly
client = MonaPay::Client.new(
client_id: ENV.fetch("MONAPAY_CLIENT_ID"),
client_secret: ENV.fetch("MONAPAY_CLIENT_SECRET"),
# optional: base_url:, open_timeout: (10), read_timeout: (30)
)
profile = client.me- Client credentials (
client_id+client_secret) are the recommended login.username:/password:is a legacy fallback and does not work for accounts with 2FA enabled. - The token is cached until 60 seconds before
expires_in. A request that fails with HTTP 401 triggers a new login and is retried once. X-Client-Secretis sent on non-GET requests. A new secret returned byclient.keys.generateis stored in the client.- Methods return the
datafield of the response. Errors are raised asMonaPay::APIErrorwithstatusandbody.
| Accessor | Methods |
|---|---|
keys |
generate, list, destroy, reveal, rotate |
bank_accounts |
list |
va |
register, verify, register_notification, verify_notification, list |
payment_profile |
get, set, rotate_return_secret, reveal_return_secret |
checkouts |
create, get, list, cancel |
qr |
generate, cancel |
transactions |
list, iterate, retry |
sandbox |
create_transaction |
webhooks |
list, create, update, remove, test |
webhook_logs |
list, stats |
email_configs |
list, create, get, update, remove, verify, resend_verification, test |
email_logs |
list, stats |
email_suppressions |
list, remove |
checkouts.create and checkouts.cancel send an Idempotency-Key header generated by the SDK; pass idempotency_key: to set your own. Fulfil orders from the CHECKOUT_PAID webhook or from checkouts.get, not from the browser redirect.
client.sandbox.create_transaction(virtual_account_number: "MONA123", amount: 10_000, description: "Sandbox test")qr = client.qr.generate(
ownerNumber: "0123456789", ownerType: "PER", merchantId: "MONA",
terminalId: "WEB", orderId: "ORDER-001", virtualAccountPrefix: "MONA",
beneficiaryName: "NGUYEN VAN A", amount: 250_000, description: "ORDER-001"
)client.transactions.iterate(virtual_account_number: "MONA123", limit: 100).each do |transaction|
puts transaction["transaction_code"]
enditerate also accepts since_id:; the enumerator stops before the item whose id or transaction_code matches. It is not sent to the API.
Pass the raw request body to the verifier. The signature is HMAC-SHA256 of "<timestamp>.<raw_body>", compared in constant time, with a default tolerance of 300 seconds.
result = MonaPay.verify_webhook(raw_body, timestamp, signature, ENV.fetch("MONAPAY_WEBHOOK_SECRET"))
raise "invalid webhook: #{result.reason}" unless result.ok?timestamp and signature come from the X-Mona-Timestamp and X-Mona-Signature headers. Use transaction_code as the idempotency key. A Rails controller is in examples/rails_webhook_controller.rb.
MonaPay::Client.from_env reads:
| Variable | Purpose |
|---|---|
MONAPAY_CLIENT_ID, MONAPAY_CLIENT_SECRET |
API key credentials (recommended) |
MONAPAY_USERNAME, MONAPAY_PASSWORD |
Legacy password login; does not work for accounts with 2FA enabled |
MONAPAY_BASE_URL |
API base URL, defaults to https://api.monapay.vn |
The webhook examples read MONAPAY_WEBHOOK_SECRET.
Documentation: https://monapay.vn/docs
ruby test/run.rbMIT
MONA Pay is part of MONA Cloud by The MONA Group.