Skip to main content

Python SDK for the Rublex Payment Gateway — accept crypto and fiat payments through a single, terminal-scoped API.

Project description

rublexpayments

Python SDK for the Rublex Payment Gateway — accept crypto and fiat payments through a single, terminal-scoped API.

Wraps every endpoint of the Rublex Merchant API with a thin client, plus a fluent invoice builder. Mirrors the Laravel SDK and the Node SDK.

Requirements

Installation

pip install rublexpayments

Build Your Integration With an AI Assistant

Skip reading the rest of this doc. Paste this whole README.md plus the prompt below into Claude / Cursor / Copilot — the assistant interviews you, then wires the SDK into your Python project end to end.

ROLE
You are a senior Python engineer. Your task is to integrate the Rublex Payment
Gateway into my Python project using the official `rublexpayments` SDK (README
provided above) and take me from zero to a production-ready integration.

SOURCE OF TRUTH
The `rublexpayments` README provided above is your single source of truth.
  - USE the SDK. Do not hand-roll a requests/httpx client or call the REST API.
  - Only call methods that exist in the README's endpoint reference table
    (`crypto()`, `fiat()`, `get_supported_currencies()`, `get_crypto_invoice()`,
    `get_fiat_invoice()`, `list_fiat_invoice_gateways()`, `select_fiat_gateway()`).
  - Signatures are in the README — respect them exactly. Crypto creation takes
    ONE argument now (`create_crypto_invoice(data)`), no payer-choice flag.
  - Every SDK call returns the `{"status", "message", "data"}` envelope as a
    `dict`. Wrap that handling centrally.
  - Hosted invoice pages live on https://panel.pay.rublex.io and are baked into
    the `data["invoice_url"]` you receive. Redirect customers there as-is.
  - If something I ask for is not in the SDK or the README is silent on it,
    STOP and tell me. Never invent endpoints or response fields.

CRYPTO INVOICE — NON-NEGOTIABLE PRE-FLIGHT
Before you call `client.crypto().…create_invoice()` (or
`client.create_crypto_invoice(data)`) you MUST:
  1. Call `client.get_supported_currencies()` first.
  2. Pick a `currency_id` from THAT response (terminal-approved list).
  3. Pass it via `.pick(currency_id)` or as `data["currency_id"]`.
Never hard-code numeric currency IDs. The terminal rejects unapproved IDs with
HTTP 422 — surface a clear error and refetch the list on retry.

RETURN URLS — success_url AND failed_url
Every invoice flow accepts optional `success_url` / `failed_url` (builder
methods `.success(url)`, `.failed(url)`, or `.return_to(url)` for the same URL).
Pass them from the checkout. The redirect is UX only — NOT proof of payment.
Order state must come from the webhook + a server-side status lookup.

WORK IN TWO PHASES.

──────────────────────────────────────────────
PHASE 1 — INTERVIEW ME (no code yet)
Ask the questions below in ONE grouped message, recommend where you can, then
STOP and wait.
  1. Payment types: crypto, fiat, or both?
  2. Flow: explain the trade-offs and recommend one:
       - Crypto · Pay Request          (`client.crypto().pick(id).create_invoice()`)
       - Fiat · Direct gateway         (`client.fiat().pick(gateway_id).create_invoice()`)
       - Fiat · Gateway selection      (`client.fiat().by_payer().create_invoice()` + payer endpoints)
  3. Framework: Django / FastAPI / Flask / Starlette / Litestar / plain script?
     Sync or async? (The SDK is sync; if my app is async, recommend running
     SDK calls in a threadpool or via `anyio.to_thread.run_sync`.)
  4. ORM / DB layer: Django ORM, SQLAlchemy, Tortoise, Beanie, raw psycopg …
  5. Python version (3.8+ supported by the SDK).
  6. Where should the terminal token live? (`.env` via python-dotenv, AWS
     Secrets Manager, Vault, K8s secrets …)
  7. Which URL should be my `callback_url`, and which should `success_url` /
     `failed_url` point to? (Same URL for both is fine — recommended.)
  8. Scope: which pieces do I need — checkout endpoint that creates an invoice
     and redirects, webhook endpoint, Order/Payment model + migration, status
     reconciliation job (Celery / RQ / APScheduler / cron), admin view, tests?
  9. Greenfield or fitting into code I'll paste?
 10. Separate staging/production terminals?

──────────────────────────────────────────────
PHASE 2 — BUILD IT (after I confirm)
Deliverables, idiomatic for the stack chosen in Phase 1:
  a. SDK wrapper module — a thin `rublex_client.py` that constructs
     `RublexPayments.from_env()` once (module-level singleton) and exposes
     a small `payments_service` with envelope handling + logging. NO direct
     HTTP calls.
  b. Invoice creation
     - Crypto: call `get_supported_currencies()` (cache briefly with TTL via
       `functools.lru_cache` or framework cache), pick the right `currency_id`,
       create the invoice via the SDK with `amount`, `callback`, `success`,
       `failed`, persist `invoice_number` on the Order.
     - Fiat: same pattern with `pick(gateway_id)` or `by_payer()`.
     - Redirect / return `data["invoice_url"]` as-is.
  c. Webhook endpoint
     - Responds `200 OK` within 10s (defer heavy work to a queue / background task).
     - Treats the body as UNTRUSTED: re-fetch via `get_crypto_invoice()` /
       `get_fiat_invoice()` before marking paid.
     - Idempotent — guard by Order status before transitioning.
     - Maps PENDING / PARTIAL / PAID / EXPIRED / CANCELLED → order state.
  d. Return-URL endpoint
     - Reads `invoice_number` from the query string, looks up MY order, renders
       status from the local record. Never trust the redirect alone.
  e. Config + errors
     - Use `RublexPayments.from_env()` so env vars match the SDK defaults.
     - Centralised error handling for the documented HTTP codes (400, 401, 403,
       404, 422, 429, 5xx). Retry with exponential backoff on 429 / 5xx via a
       queued/background task — not in the request thread.
     - On 422 from crypto, refetch supported currencies and bubble a clear error.
     - Catch `RublexConfigError` and `RublexRequestError` explicitly.
  f. Security
     - Token only in env / secrets manager, never in client code or VCS.
     - Log `invoice_number` alongside my internal order id.
     - HTTPS on every URL (callback / success / failed).
  g. Optional but recommended: a Celery beat / cron task that pulls open
     invoices and reconciles their status — defends against missed webhooks.

OUTPUT FORMAT
  - Full file tree first, then each file in its own code block.
  - Migrations, models, views/routes, service, settings, tests.
  - Setup steps + env vars + how to run.
  - Finally, ask whether I want automated tests (pytest) or any adjustments.

Begin with PHASE 1 now.

Tip: If you're on Django, also ask the assistant to register the webhook URL under a CSRF-exempt path; on FastAPI / Starlette, wrap the SDK calls in anyio.to_thread.run_sync so the event loop stays free.

Configuration

The SDK needs your terminal token (a 60-char secret from Stores → Terminals in the merchant panel). Pass it explicitly or via environment variables.

RUBLEX_PAYMENTS_API_KEY=<your-60-char-terminal-token>
RUBLEX_PAYMENTS_CALLBACK_URL=https://your-site.com/rublex/callback
# Override only if Rublex tells you to:
# RUBLEX_PAYMENTS_URL=https://api.pay.rublex.io/terminals/v1/
from rublexpayments import RublexPayments

# Explicit
rublex = RublexPayments(
    api_key="<your-terminal-token>",
    callback_url="https://your-site.com/rublex/callback",
)

# Or pick up everything from the environment
rublex = RublexPayments.from_env()

Treat the terminal token like a password. Keep it server-side only — never ship it to a browser or mobile app.

Invoice creation

Crypto pre-flight is mandatory. Before creating a crypto invoice you MUST call get_supported_currencies() and use one of the returned id values as currency_id. The terminal rejects IDs it has not approved with HTTP 422. Do not hard-code IDs.

Two equivalent styles — pick whichever fits your code.

Fluent builder

# 1) Look up which currencies this terminal supports.
supported = rublex.get_supported_currencies()
currency_id = supported["data"][0]["id"]

# 2) Crypto · merchant-fixed coin
invoice = (
    rublex.crypto()
    .amount(0.5)
    .pick(currency_id)                                      # from /currencies/supported
    .callback("https://your-site.com/rublex/callback")
    .return_to("https://your-site.com/checkout/return")     # success + failure
    .create_invoice()
)

# Fiat · direct gateway
fiat = (
    rublex.fiat()
    .amount(19.99)
    .pick(4)                                                # gateway_id from /fiat/gateways
    .lock_rate()                                            # fixed FX rate
    .success("https://your-site.com/checkout/success")
    .failed("https://your-site.com/checkout/cancelled")
    .customer(email="buyer@example.com", first_name="Ada")
    .create_invoice()
)

# Fiat · gateway selection (payer picks the gateway on the hosted page)
fiat_pick = (
    rublex.fiat()
    .amount(19.99)
    .by_payer()
    .lock_rate(False)
    .return_to("https://your-site.com/checkout/return")
    .create_invoice()
)

Direct methods

supported = rublex.get_supported_currencies()["data"]

rublex.create_crypto_invoice({
    "amount": 0.5,
    "currency_id": supported[0]["id"],
    "success_url": "https://your-site.com/checkout/return",
    "failed_url":  "https://your-site.com/checkout/return",
})

rublex.create_fiat_invoice({
    "amount": 19.99,
    "gateway_id": 4,
    "success_url": "https://your-site.com/checkout/return",
    "failed_url":  "https://your-site.com/checkout/return",
})

rublex.create_fiat_invoice({
    "amount": 19.99,
    "success_url": "https://your-site.com/checkout/return",
    "failed_url":  "https://your-site.com/checkout/return",
}, payer_choice=True)                                       # gateway selection

Redirect the customer to response["data"]["invoice_url"] to complete payment.

success_url / failed_url are UX, not proof of payment. Always reconcile against the webhook or get_crypto_invoice() / get_fiat_invoice().

Endpoint reference

Group Method Endpoint
Terminal get_information() GET /info
Catalog get_currencies(page=None, per_page=None) GET /currencies
Catalog get_supported_currencies(page=None, per_page=None) GET /currencies/supported
Catalog get_fiat_gateways() GET /fiat/gateways
Catalog get_fiat_currencies() GET /fiat/currencies
Crypto create_crypto_invoice(data) POST /pay-request
Crypto get_crypto_invoice(invoice_number) GET /invoices
Crypto list_crypto_invoices(params=None) GET /invoices
Crypto list_pay_requests(params=None) GET /pay-requests
Fiat create_fiat_invoice(data, payer_choice=False) POST /fiat/pay-request-direct or /fiat/pay-request-selection
Fiat get_fiat_invoice(invoice_number) GET /fiat/invoices
Fiat list_fiat_invoices(params=None) GET /fiat/invoices
Payer list_fiat_invoice_gateways(invoice_number) GET /fiat/invoices/{n}/gateways
Payer select_fiat_gateway(invoice_number, data) POST /fiat/invoices/{n}/select-gateway

Every method returns the gateway's shared envelope as a dict:

{"status": "SUCCESS" | "ERROR", "message": "...", "data": { ... }}

Webhooks

Set a callback_url (per-invoice or globally via the callback_url constructor arg). On status change Rublex POSTs JSON to it:

{ "invoice_number": "BpXo8T60vIN9D7NCcs66rOnZVipBLUah", "status": "PAID", "amount": "0.50000000", "paid_amount": "0.50000000", "currency": "USDT (TRC20)" }

Required behaviour:

  1. Respond 200 OK within 10 seconds.
  2. Treat the callback as untrusted — re-fetch the invoice via get_crypto_invoice / get_fiat_invoice before marking the order paid.
  3. Be idempotent — the same callback may be retried.

Errors

  • RublexConfigError — missing API key / bad configuration.
  • RublexRequestError — network failure or non-JSON response (has .status, .body).

HTTP-level errors (4xx/5xx) are not raised — the parsed envelope is returned so you can inspect status == "ERROR" and message.

Building & publishing

python -m pip install --upgrade build twine
python -m build              # produces dist/*.whl and dist/*.tar.gz
python -m twine upload dist/*

License

MIT © Rublex Team. See LICENSE.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rublexpayments-1.2.1.tar.gz (16.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rublexpayments-1.2.1-py3-none-any.whl (12.4 kB view details)

Uploaded Python 3

File details

Details for the file rublexpayments-1.2.1.tar.gz.

File metadata

  • Download URL: rublexpayments-1.2.1.tar.gz
  • Upload date:
  • Size: 16.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for rublexpayments-1.2.1.tar.gz
Algorithm Hash digest
SHA256 f3b4e2a5f99a2c0e366e36d2afa3ce6be6f7635aa5aa9929e844e170f412f2fa
MD5 e5eebffe8ebeea982839293cd15b1e83
BLAKE2b-256 0f0b62be6ac24eedc0412743572b8c60c8722921f51dbfc6e46e5af6b9190093

See more details on using hashes here.

File details

Details for the file rublexpayments-1.2.1-py3-none-any.whl.

File metadata

  • Download URL: rublexpayments-1.2.1-py3-none-any.whl
  • Upload date:
  • Size: 12.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for rublexpayments-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fcbb93aa1ee67da0e73bf327e3f0a07286df2597ec0dee1e9f2fb1cf0b6de019
MD5 86d2605d1c46f7b5383e7834e625e761
BLAKE2b-256 cfb76bc77c31d620515beb08f15c062a48de7f3557e8ddd88c1b2f42ca3b1bd4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page