Skip to Content
FrameworksSpring Boot

Spring Boot

QPay V2 payment starter for Spring Boot 3.2+. Built on top of qpay-java , this package provides auto-configuration, a QPayTemplate helper, webhook controller with Spring events, and Thymeleaf fragments.


Installation

Maven

<dependency> <groupId>io.github.qpay-sdk</groupId> <artifactId>qpay-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency>

Gradle

implementation 'io.github.qpay-sdk:qpay-spring-boot-starter:1.0.0'

The starter automatically configures a QPayClient bean and QPayTemplate bean when the application starts.


Configuration

application.properties

qpay.base-url=https://merchant.qpay.mn qpay.username=your_username qpay.password=your_password qpay.invoice-code=your_invoice_code qpay.callback-url=https://yoursite.com/qpay/webhook qpay.webhook-path=/qpay/webhook

application.yml

qpay: base-url: https://merchant.qpay.mn username: your_username password: your_password invoice-code: your_invoice_code callback-url: https://yoursite.com/qpay/webhook webhook-path: /qpay/webhook

Configuration Properties

PropertyDefaultDescription
qpay.base-urlhttps://merchant.qpay.mnQPay API base URL
qpay.usernameMerchant username
qpay.passwordMerchant password
qpay.invoice-codeDefault invoice code
qpay.callback-urlPayment callback URL
qpay.webhook-path/qpay/webhookWebhook endpoint path

Quick Start

import mn.qpay.spring.QPayTemplate; import mn.qpay.sdk.models.InvoiceResponse; import org.springframework.web.bind.annotation.*; @RestController public class PaymentController { private final QPayTemplate qpay; public PaymentController(QPayTemplate qpay) { this.qpay = qpay; } @PostMapping("/pay") public InvoiceResponse createPayment(@RequestParam String orderId, @RequestParam double amount) { return qpay.createSimpleInvoice(orderId, amount); } }

Create Invoice

Simple Invoice (via QPayTemplate)

QPayTemplate provides convenient methods that automatically use the configured invoiceCode and callbackUrl:

@Autowired private QPayTemplate qpay; // Uses configured invoice-code and callback-url automatically InvoiceResponse invoice = qpay.createSimpleInvoice("ORDER-001", 10000); // Access response fields String invoiceId = invoice.getInvoiceId(); String qrImage = invoice.getQrImage(); // Base64 QR code String qrText = invoice.getQrText(); // QR code text String shortUrl = invoice.getQPayShortUrl(); // Short payment URL List<PaymentUrl> urls = invoice.getUrls(); // Bank deep links

Full Invoice (via QPayClient)

For advanced use cases, access the underlying QPayClient directly:

import mn.qpay.sdk.QPayClient; import mn.qpay.sdk.models.*; QPayClient client = qpay.getClient(); CreateInvoiceRequest request = new CreateInvoiceRequest(); request.setInvoiceCode("YOUR_CODE"); request.setSenderInvoiceNo("ORDER-001"); request.setInvoiceReceiverCode("receiver_001"); request.setInvoiceDescription("Payment for Order #001"); request.setAmount(10000); request.setCallbackURL("https://yoursite.com/qpay/webhook"); InvoiceResponse invoice = client.createInvoice(request);

Check Payment

PaymentCheckResponse result = qpay.checkPayment("INVOICE_ID"); if (result.getRows() != null && !result.getRows().isEmpty()) { // Payment confirmed }

Webhook Handling

The starter includes a built-in QPayWebhookController that handles POST requests at the configured webhook path (default: /qpay/webhook).

When QPay sends a callback:

  1. The controller extracts invoice_id from the JSON body
  2. Calls checkPayment to verify the payment
  3. Publishes a QPayWebhookEvent via Spring’s ApplicationEventPublisher if payment is confirmed
  4. Returns a JSON response with the status

The webhook endpoint is automatically registered as:

@PostMapping("${qpay.webhook-path:/qpay/webhook}")

Events

QPayWebhookEvent

The starter uses Spring’s application event system. Listen for payment events with @EventListener:

import mn.qpay.spring.QPayWebhookEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; @Component public class PaymentEventListener { @EventListener public void onPayment(QPayWebhookEvent event) { String invoiceId = event.getInvoiceId(); PaymentCheckResponse result = event.getResult(); // Update order status, send notification, etc. orderService.markAsPaid(invoiceId); } }

Async Event Handling

Enable async processing with Spring’s @Async:

@Component public class AsyncPaymentListener { @Async @EventListener public void onPayment(QPayWebhookEvent event) { // Runs in a separate thread processPayment(event.getInvoiceId()); } }

Thymeleaf Fragments

The starter includes Thymeleaf template fragments for rendering QR codes and payment buttons.

QR Code

<div th:replace="~{fragments/qpay :: qr-code(${invoice.qrImage}, 256)}"></div>

Renders a centered QR code image. The second parameter is the size in pixels (defaults to 256).

Payment Buttons

<div th:replace="~{fragments/qpay :: payment-buttons(${invoice.urls})}"></div>

Renders a flex container with styled bank payment link buttons, each showing the bank logo and name.

Full Page Example

<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <body> <h1>Payment</h1> <div th:replace="~{fragments/qpay :: qr-code(${invoice.qrImage}, 256)}"></div> <h2>Pay with Bank App</h2> <div th:replace="~{fragments/qpay :: payment-buttons(${invoice.urls})}"></div> </body> </html>

Testing

Mocking QPayTemplate

import mn.qpay.spring.QPayTemplate; import mn.qpay.sdk.models.InvoiceResponse; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import static org.mockito.Mockito.*; @SpringBootTest class PaymentControllerTest { @MockBean private QPayTemplate qPayTemplate; @Test void testCreateInvoice() { InvoiceResponse mockInvoice = new InvoiceResponse(); mockInvoice.setInvoiceId("inv_123"); mockInvoice.setQrImage("base64data"); when(qPayTemplate.createSimpleInvoice("ORDER-001", 10000)) .thenReturn(mockInvoice); // Your test assertions } }

Testing Webhook Events

import mn.qpay.spring.QPayWebhookEvent; import org.springframework.test.context.event.ApplicationEvents; import org.springframework.test.context.event.RecordApplicationEvents; @SpringBootTest @RecordApplicationEvents class WebhookTest { @Autowired ApplicationEvents events; @Test void testWebhookFiresEvent() { // Trigger webhook... long count = events.stream(QPayWebhookEvent.class).count(); assertEquals(1, count); } }

API Reference

Auto-configured Beans

BeanTypeDescription
qPayClientmn.qpay.sdk.QPayClientCore QPay HTTP client
qPayTemplatemn.qpay.spring.QPayTemplateConvenience wrapper with defaults

QPayTemplate Methods

MethodReturn TypeDescription
createSimpleInvoice(String senderInvoiceNo, double amount)InvoiceResponseCreate invoice with configured defaults
checkPayment(String invoiceId)PaymentCheckResponseCheck payment status for an invoice
getClient()QPayClientAccess the underlying client

QPayProperties

PropertyTypeDescription
baseUrlStringQPay API base URL
usernameStringMerchant username
passwordStringMerchant password
invoiceCodeStringDefault invoice code
callbackUrlStringPayment callback URL
webhookPathStringWebhook endpoint path

QPayWebhookEvent

MethodReturn TypeDescription
getInvoiceId()StringQPay invoice ID
getResult()PaymentCheckResponseFull payment check response

Last updated on