Ruby SDK
Ruby client library for the QPay V2 API. Idiomatic Ruby interface with Struct-based request/response objects, automatic token management with mutex synchronization, and Faraday HTTP under the hood.
Requirements: Ruby 3.0+, Faraday ~> 2.0
Installation
Add to your Gemfile:
gem "qpay-sdk"Then run:
bundle installOr install directly:
gem install qpay-sdkConfiguration
Environment Variables
| Variable | Description |
|---|---|
QPAY_BASE_URL | QPay API base URL (e.g., https://merchant.qpay.mn) |
QPAY_USERNAME | QPay merchant username |
QPAY_PASSWORD | QPay merchant password |
QPAY_INVOICE_CODE | Default invoice code |
QPAY_CALLBACK_URL | Payment callback URL |
config = QPay::Config.from_envManual Configuration
config = QPay::Config.new(
base_url: "https://merchant.qpay.mn",
username: "YOUR_USERNAME",
password: "YOUR_PASSWORD",
invoice_code: "YOUR_INVOICE_CODE",
callback_url: "https://yoursite.com/callback"
)Custom Faraday Connection
faraday = Faraday.new do |f|
f.options.timeout = 60
f.adapter Faraday.default_adapter
end
client = QPay::Client.new(config: config, faraday: faraday)Quick Start
require "qpay"
config = QPay::Config.from_env
client = QPay::Client.new(config: config)
invoice = client.create_simple_invoice(
QPay::CreateSimpleInvoiceRequest.new(
invoice_code: config.invoice_code,
sender_invoice_no: "ORDER-001",
invoice_receiver_code: "terminal",
invoice_description: "Payment for Order #001",
amount: 10_000,
callback_url: config.callback_url
)
)
puts "Invoice ID: #{invoice.invoice_id}"
puts "QR Image: #{invoice.qr_image}"
puts "Short URL: #{invoice.qpay_short_url}"
invoice.urls.each do |url|
puts " #{url['name']}: #{url['link']}"
endCreate Invoice
invoice = client.create_simple_invoice(
QPay::CreateSimpleInvoiceRequest.new(
invoice_code: "INV_CODE",
sender_invoice_no: "ORDER-002",
invoice_receiver_code: "terminal",
invoice_description: "Quick payment",
sender_branch_code: "BRANCH01", # optional
amount: 5_000,
callback_url: "https://yoursite.com/callback"
)
)Cancel an invoice:
client.cancel_invoice("invoice-id-here")Check Payment
result = client.check_payment(
QPay::PaymentCheckRequest.new(
object_type: "INVOICE",
obj_id: "INVOICE_ID",
offset: QPay::Offset.new(page_number: 1, page_limit: 10)
)
)
if result.count > 0
puts "Payment received! Paid: #{result.paid_amount}"
result.rows.each do |row|
puts " #{row.payment_id}: #{row.payment_status} (#{row.payment_amount} #{row.payment_currency})"
end
else
puts "No payment yet"
endList Payments
payments = client.list_payments(
QPay::PaymentListRequest.new(
object_type: "INVOICE",
obj_id: "INVOICE_ID",
start_date: "2024-01-01",
end_date: "2024-12-31",
offset: QPay::Offset.new(page_number: 1, page_limit: 20)
)
)
puts "Total: #{payments.count}"
payments.rows.each do |item|
puts " #{item.payment_id}: #{item.payment_amount} #{item.payment_currency} (#{item.payment_status})"
endGet details for a single payment:
detail = client.get_payment("payment-id-here")
puts "Payment #{detail.payment_id}: #{detail.payment_status}"Webhook Handling
QPay sends a POST request to your callback_url when a payment completes.
Rails
class QpayCallbacksController < ApplicationController
skip_before_action :verify_authenticity_token
def create
payment_id = params[:payment_id]
config = QPay::Config.from_env
client = QPay::Client.new(config: config)
result = client.check_payment(
QPay::PaymentCheckRequest.new(
object_type: "INVOICE",
obj_id: payment_id,
)
)
if result.count > 0
# Payment verified -- update your order status
Rails.logger.info("Payment confirmed: #{payment_id} (#{result.paid_amount} MNT)")
end
render json: { status: "ok" }
end
endSinatra
require "sinatra"
require "qpay"
post "/api/qpay/callback" do
body = JSON.parse(request.body.read)
payment_id = body["payment_id"]
config = QPay::Config.from_env
client = QPay::Client.new(config: config)
result = client.check_payment(
QPay::PaymentCheckRequest.new(
object_type: "INVOICE",
obj_id: payment_id,
)
)
if result.count > 0
# Payment verified
end
{ status: "ok" }.to_json
endError Handling
All API errors raise QPay::Error, which is a subclass of StandardError:
begin
client.create_simple_invoice(request)
rescue QPay::Error => e
puts e.message # "qpay: INVOICE_LINE_REQUIRED - ..."
puts e.status_code # 400
puts e.code # "INVOICE_LINE_REQUIRED"
puts e.raw_body # Raw JSON response body
endError Code Constants
rescue QPay::Error => e
case e.code
when QPay::AUTHENTICATION_FAILED
# Re-authenticate
when QPay::INVOICE_NOTFOUND
# Handle missing invoice
when QPay::INVOICE_PAID
# Invoice already paid
when QPay::PAYMENT_NOTFOUND
# Handle missing payment
when QPay::PAYMENT_ALREADY_CANCELED
# Payment was already canceled
when QPay::INVALID_AMOUNT
# Amount out of range
when QPay::PERMISSION_DENIED
# Access denied
end
endAPI Reference
| Method | Parameters | Returns | Description |
|---|---|---|---|
get_token | — | TokenResponse | Authenticate and get token pair |
refresh_token | — | TokenResponse | Refresh access token |
create_invoice | CreateInvoiceRequest | InvoiceResponse | Create full invoice |
create_simple_invoice | CreateSimpleInvoiceRequest | InvoiceResponse | Create simple invoice |
create_ebarimt_invoice | CreateEbarimtInvoiceRequest | InvoiceResponse | Create invoice with tax info |
cancel_invoice | invoice_id (String) | nil | Cancel an invoice |
get_payment | payment_id (String) | PaymentDetail | Get payment details |
check_payment | PaymentCheckRequest | PaymentCheckResponse | Check payment status |
list_payments | PaymentListRequest | PaymentListResponse | List payments |
cancel_payment | payment_id, request: (optional) | nil | Cancel a payment |
refund_payment | payment_id, request: (optional) | nil | Refund a payment |
create_ebarimt | CreateEbarimtRequest | EbarimtResponse | Create tax receipt |
cancel_ebarimt | payment_id (String) | EbarimtResponse | Cancel tax receipt |
Links
- RubyGems: rubygems.org/gems/qpay-sdk
- GitHub: github.com/qpay-sdk/qpay-ruby
Last updated on