Dart / Flutter SDK
A Dart/Flutter client library for the QPay V2 API with automatic token management, strong typing, and comprehensive error handling. Works with both server-side Dart CLI apps and Flutter mobile/web apps.
Installation
Dart
dart pub add qpayFlutter
flutter pub add qpayOr add it manually to your pubspec.yaml:
dependencies:
qpay: ^1.0.0Configuration
Direct Configuration
import 'package:qpay/qpay.dart';
const config = QPayConfig(
baseUrl: 'https://merchant.qpay.mn',
username: 'YOUR_USERNAME',
password: 'YOUR_PASSWORD',
invoiceCode: 'YOUR_INVOICE_CODE',
callbackUrl: 'https://yourapp.com/callback',
);From Environment Variables
For server-side Dart applications:
final config = QPayConfig.fromEnvironment();| Variable | Description |
|---|---|
QPAY_BASE_URL | QPay API base URL |
QPAY_USERNAME | QPay merchant username |
QPAY_PASSWORD | QPay merchant password |
QPAY_INVOICE_CODE | Default invoice code |
QPAY_CALLBACK_URL | Payment callback URL |
Custom HTTP Client
import 'package:http/http.dart' as http;
final httpClient = http.Client();
final client = QPayClient(config, httpClient: httpClient);Quick Start
import 'package:qpay/qpay.dart';
void main() async {
final client = QPayClient(QPayConfig(
baseUrl: 'https://merchant.qpay.mn',
username: 'YOUR_USERNAME',
password: 'YOUR_PASSWORD',
invoiceCode: 'YOUR_INVOICE_CODE',
callbackUrl: 'https://yourapp.com/callback',
));
try {
final invoice = await client.createSimpleInvoice(CreateSimpleInvoiceRequest(
invoiceCode: 'YOUR_INVOICE_CODE',
senderInvoiceNo: 'INV-001',
invoiceReceiverCode: 'terminal',
invoiceDescription: 'Order #001',
amount: 10000,
callbackUrl: 'https://yourapp.com/callback',
));
print('Invoice ID: ${invoice.invoiceId}');
print('QR Image: ${invoice.qrImage}');
print('Short URL: ${invoice.qPayShortUrl}');
for (final url in invoice.urls) {
print(' ${url.name}: ${url.link}');
}
} on QPayException catch (e) {
print('QPay error: ${e.code} - ${e.message}');
} finally {
client.close();
}
}Create Invoice
final invoice = await client.createSimpleInvoice(CreateSimpleInvoiceRequest(
invoiceCode: 'YOUR_INVOICE_CODE',
senderInvoiceNo: 'INV-002',
invoiceReceiverCode: 'terminal',
invoiceDescription: 'Coffee x2',
amount: 12000,
callbackUrl: 'https://yourapp.com/callback',
));
print('Invoice ID: ${invoice.invoiceId}');Cancel an invoice:
await client.cancelInvoice('invoice-id-here');Check Payment
final result = await client.checkPayment(PaymentCheckRequest(
objectType: 'INVOICE',
objectId: invoice.invoiceId,
));
if (result.count > 0) {
print('Payment received! Paid: ${result.paidAmount} MNT');
for (final row in result.rows) {
print(' ${row.paymentId}: ${row.paymentStatus} (${row.paymentAmount} ${row.paymentCurrency})');
}
} else {
print('No payment yet');
}List Payments
final payments = await client.listPayments(PaymentListRequest(
objectType: 'INVOICE',
objectId: invoice.invoiceId,
startDate: '2024-01-01',
endDate: '2024-12-31',
offset: Offset(pageNumber: 1, pageLimit: 20),
));
print('Total: ${payments.count}');
for (final item in payments.rows) {
print('${item.paymentId}: ${item.paymentAmount} ${item.paymentCurrency}');
}Get details for a single payment:
final detail = await client.getPayment('payment-id-here');
print('Payment ${detail.paymentId}: ${detail.paymentStatus}');Webhook Handling
QPay sends a POST request to your callbackUrl when a payment completes. In a Dart server (e.g., using shelf):
import 'dart:convert';
import 'package:shelf/shelf.dart';
import 'package:qpay/qpay.dart';
final config = QPayConfig.fromEnvironment();
final qpayClient = QPayClient(config);
Future<Response> callbackHandler(Request request) async {
final body = jsonDecode(await request.readAsString());
final paymentId = body['payment_id'] as String;
final result = await qpayClient.checkPayment(PaymentCheckRequest(
objectType: 'INVOICE',
objectId: paymentId,
));
if (result.count > 0) {
// Payment verified -- update your order status
print('Payment confirmed: $paymentId (${result.paidAmount} MNT)');
}
return Response.ok(jsonEncode({'status': 'ok'}));
}Error Handling
try {
await client.cancelInvoice('nonexistent-id');
} on QPayException catch (e) {
print('Status: ${e.statusCode}'); // e.g., 404
print('Code: ${e.code}'); // e.g., "INVOICE_NOTFOUND"
print('Message: ${e.message}');
print('Body: ${e.rawBody}');
if (e.code == QPayException.invoiceNotFound) {
print('Invoice does not exist');
} else if (e.code == QPayException.invoicePaid) {
print('Invoice has already been paid');
} else if (e.code == QPayException.authenticationFailed) {
print('Authentication failed');
}
}Flutter Integration
Display QR Code
import 'dart:convert';
import 'package:flutter/material.dart';
Widget buildQrImage(InvoiceResponse invoice) {
final bytes = base64Decode(invoice.qrImage);
return Image.memory(bytes);
}Open Bank App Deep Links
import 'package:url_launcher/url_launcher.dart';
Future<void> openBankApp(Deeplink deeplink) async {
final uri = Uri.parse(deeplink.link);
if (await canLaunchUrl(uri)) {
await launchUrl(uri);
}
}Payment Polling
Future<bool> waitForPayment(QPayClient client, String invoiceId) async {
for (var i = 0; i < 60; i++) {
await Future.delayed(const Duration(seconds: 5));
final result = await client.checkPayment(PaymentCheckRequest(
objectType: 'INVOICE',
objectId: invoiceId,
));
if (result.count > 0) {
return true; // Payment received
}
}
return false; // Timeout after 5 minutes
}API Reference
| Method | Description | Returns |
|---|---|---|
getToken() | Authenticate and get a new token pair | Future<TokenResponse> |
refreshToken() | Refresh the current access token | Future<TokenResponse> |
createInvoice(request) | Create a full invoice with all options | Future<InvoiceResponse> |
createSimpleInvoice(request) | Create a simple invoice | Future<InvoiceResponse> |
createEbarimtInvoice(request) | Create an invoice with ebarimt | Future<InvoiceResponse> |
cancelInvoice(invoiceId) | Cancel an existing invoice | Future<void> |
getPayment(paymentId) | Get payment details by ID | Future<PaymentDetail> |
checkPayment(request) | Check if a payment has been made | Future<PaymentCheckResponse> |
listPayments(request) | List payments with filters | Future<PaymentListResponse> |
cancelPayment(paymentId, request) | Cancel a card payment | Future<void> |
refundPayment(paymentId, request) | Refund a card payment | Future<void> |
createEbarimt(request) | Create an electronic tax receipt | Future<EbarimtResponse> |
cancelEbarimt(paymentId) | Cancel an electronic tax receipt | Future<EbarimtResponse> |
close() | Close the underlying HTTP client | void |
Links
- pub.dev: pub.dev/packages/qpayÂ
- GitHub: github.com/qpay-sdk/qpay-dartÂ
Last updated on