Skip to Content
SDKsPython

Python SDK

Python client library for the QPay V2 API. Provides both synchronous (QPayClient) and asynchronous (AsyncQPayClient) clients with automatic token management, typed request/response dataclasses, and comprehensive error handling. Built on httpx.

PyPI GitHub

Installation

pip install qpay-py

Requires Python 3.9+.

Configuration

From Environment Variables

from qpay import QPayConfig config = QPayConfig.from_env()
VariableDescription
QPAY_BASE_URLQPay API base URL (e.g., https://merchant.qpay.mn)
QPAY_USERNAMEQPay merchant username
QPAY_PASSWORDQPay merchant password
QPAY_INVOICE_CODEDefault invoice code
QPAY_CALLBACK_URLPayment callback URL

Manual Configuration

from qpay import QPayConfig config = QPayConfig( base_url="https://merchant.qpay.mn", username="your_username", password="your_password", invoice_code="YOUR_INVOICE_CODE", callback_url="https://yoursite.com/callback", )

Custom HTTP Client

import httpx from qpay import QPayClient, QPayConfig http_client = httpx.Client(timeout=60.0) client = QPayClient(config, http_client=http_client)

Quick Start

Synchronous

from qpay import QPayClient, QPayConfig, CreateSimpleInvoiceRequest config = QPayConfig.from_env() with QPayClient(config) as client: invoice = client.create_simple_invoice( CreateSimpleInvoiceRequest( invoice_code=config.invoice_code, sender_invoice_no="ORDER-001", invoice_receiver_code="terminal", invoice_description="Payment for Order #001", amount=50000.0, callback_url=config.callback_url, ) ) print(f"Invoice ID: {invoice.invoice_id}") print(f"QR Image: {invoice.qr_image}") print(f"Short URL: {invoice.qpay_short_url}")

Asynchronous

import asyncio from qpay import AsyncQPayClient, QPayConfig, CreateSimpleInvoiceRequest config = QPayConfig.from_env() async def main(): async with AsyncQPayClient(config) as client: invoice = await client.create_simple_invoice( CreateSimpleInvoiceRequest( invoice_code=config.invoice_code, sender_invoice_no="ORDER-001", invoice_receiver_code="terminal", invoice_description="Payment for Order #001", amount=50000.0, callback_url=config.callback_url, ) ) print(f"Invoice ID: {invoice.invoice_id}") asyncio.run(main())

Create Invoice

from qpay import CreateSimpleInvoiceRequest invoice = client.create_simple_invoice( CreateSimpleInvoiceRequest( invoice_code="YOUR_CODE", sender_invoice_no="INV-101", invoice_receiver_code="terminal", invoice_description="Simple invoice", amount=10000.0, callback_url="https://yoursite.com/callback", ) ) print(f"Invoice ID: {invoice.invoice_id}") print(f"QR Text: {invoice.qr_text}") print(f"Short URL: {invoice.qpay_short_url}") for url in invoice.urls: print(f" {url['name']}: {url['link']}")

Cancel an invoice:

client.cancel_invoice("invoice-id-here")

Check Payment

from qpay import PaymentCheckRequest, Offset result = client.check_payment( PaymentCheckRequest( object_type="INVOICE", object_id="invoice-id-here", offset=Offset(page_number=1, page_limit=10), ) ) if result.count > 0: print(f"Payment received! Paid: {result.paid_amount}") for row in result.rows: print(f" {row.payment_id}: {row.payment_status} ({row.payment_amount} {row.payment_currency})") else: print("No payment yet")

List Payments

from qpay import PaymentListRequest, Offset result = client.list_payments( PaymentListRequest( object_type="INVOICE", object_id="invoice-id-here", start_date="2024-01-01", end_date="2024-12-31", offset=Offset(page_number=1, page_limit=20), ) ) print(f"Total: {result.count}") for item in result.rows: print(f" {item.payment_id} | {item.payment_amount} {item.payment_currency} | {item.payment_status}")

Get details for a single payment:

detail = client.get_payment("payment-id-here") print(f"Payment {detail.payment_id}: {detail.payment_status} ({detail.payment_amount} {detail.payment_currency})")

Webhook Handling

QPay sends a POST request to your callback_url when a payment completes.

FastAPI

from fastapi import FastAPI, HTTPException, Request from qpay import AsyncQPayClient, QPayConfig, QPayError, PaymentCheckRequest app = FastAPI() config = QPayConfig.from_env() qpay = AsyncQPayClient(config) @app.on_event("shutdown") async def shutdown(): await qpay.close() @app.post("/api/qpay/callback") async def qpay_callback(request: Request): body = await request.json() payment_id = body.get("payment_id") try: result = await qpay.check_payment( PaymentCheckRequest( object_type="INVOICE", object_id=payment_id, ) ) if result.count > 0: # Payment verified -- update your order status print(f"Payment confirmed: {payment_id} ({result.paid_amount} MNT)") except QPayError as e: raise HTTPException(status_code=e.status_code, detail=e.message) return {"status": "ok"}

Django

import json from django.http import JsonResponse, HttpResponseBadRequest from django.views.decorators.csrf import csrf_exempt from qpay import QPayClient, QPayConfig, PaymentCheckRequest config = QPayConfig.from_env() @csrf_exempt def qpay_callback(request): if request.method != "POST": return HttpResponseBadRequest("Method not allowed") body = json.loads(request.body) payment_id = body.get("payment_id") with QPayClient(config) as client: result = client.check_payment( PaymentCheckRequest( object_type="INVOICE", object_id=payment_id, ) ) if result.count > 0: # Payment verified -- update your order status pass return JsonResponse({"status": "ok"})

Error Handling

from qpay import QPayError try: client.cancel_invoice("nonexistent-id") except QPayError as e: print(f"Status: {e.status_code}") # e.g., 404 print(f"Code: {e.code}") # e.g., "INVOICE_NOTFOUND" print(f"Msg: {e.message}") # e.g., "Invoice not found" print(f"Raw: {e.raw_body}") # full response body

Error Code Constants

from qpay import ( ERR_AUTHENTICATION_FAILED, ERR_INVOICE_NOT_FOUND, ERR_INVOICE_PAID, ERR_INVOICE_ALREADY_CANCELED, ERR_INVALID_AMOUNT, ERR_PAYMENT_NOT_FOUND, ERR_PAYMENT_ALREADY_CANCELED, ERR_PERMISSION_DENIED, QPayError, ) try: client.cancel_invoice("some-id") except QPayError as e: if e.code == ERR_INVOICE_NOT_FOUND: print("Invoice does not exist") elif e.code == ERR_INVOICE_PAID: print("Invoice has already been paid") elif e.code == ERR_INVOICE_ALREADY_CANCELED: print("Already canceled") else: raise

API Reference

MethodReturnsDescription
get_token()TokenResponseAuthenticate and get a new token pair
refresh_token()TokenResponseRefresh the current access token
create_invoice(req)InvoiceResponseCreate a detailed invoice
create_simple_invoice(req)InvoiceResponseCreate a simple invoice
create_ebarimt_invoice(req)InvoiceResponseCreate an invoice with ebarimt
cancel_invoice(id)NoneCancel an invoice
get_payment(id)PaymentDetailGet payment details
check_payment(req)PaymentCheckResponseCheck payment status
list_payments(req)PaymentListResponseList payments
cancel_payment(id, req)NoneCancel a payment
refund_payment(id, req)NoneRefund a payment
create_ebarimt(req)EbarimtResponseCreate an ebarimt receipt
cancel_ebarimt(id)EbarimtResponseCancel an ebarimt receipt
close()NoneClose the underlying HTTP client

The AsyncQPayClient has the same methods, all returning coroutines (async/await).

Last updated on