Skip to main content
Bonum is a payment service provider operating in Mongolia. The Droplinked integration creates invoices via the Bonum API, accepts Apple/Google Pay tokens through Bonum’s hosted PSP, and reconciles settlement back into Droplinked’s revenue-distribution saga.
Bonum settles off-platform: the saga records the revenue-split plan, then a downstream operator (typically MCredit) pays sub-merchants and reports back via the settlement API.

Architecture

  • Three Prisma models: BonumTransaction, MerchantPrefixRegistry, BonumConfig
  • NestJS module: dedicated bonum module on the backend
  • Payment strategy: BonumPaymentStrategy — registered in PaymentFactory under provider === 'BONUM'
  • Saga step: the revenue-distribution step forks for Bonum orders (records splits, no live transfer)
  • Webhook receiver: POST /bonum/webhook (IntegrationApiKeyGuard)
  • Settlement cron: two daily audit passes (SettlementReconciliationCron)

API surface

Configuration

Payment flow

1

Create payment intent

POST /orders/v2/create-payment-intent with provider=BONUM. The PaymentFactory routes to BonumPaymentStrategy.createPaymentIntent(), which upserts a BonumTransaction and returns an invoice ID prefixed with the shop’s merchant prefix.
2

Customer pays

The frontend uses the returned Apple/Google Pay token via the Bonum hosted page.
3

Confirm payment

POST /bonum/payment/confirm calls the integration service → Bonum PSP. The verify use case then confirms via /api/payment-log/read.
4

Run the confirmation saga

The standard ConfirmPaymentSaga runs; for Bonum the revenue-distribution step records splits rather than executing live transfers.
5

Receive settlement webhook

Bonum POSTs to /bonum/webhookHandleBonumWebhookUseCase sets settledAt.
6

Sub-merchant payout

MCredit (or the equivalent operator) reads the settlement API, pays sub-merchants, then calls PATCH /settlement/transactions/payout to mark the batch paid.

Testing

Sandbox setup

The Bonum sandbox at testpsp.bonum.mn issues real bank charges. Use minimum amounts (100 MNT) for every test.
  1. Set BONUM_API_BASE_URL=https://testpsp.bonum.mn
  2. Obtain a sandbox BONUM_MERCHANT_KEY from the MCredit team
  3. Confirm NODE_ENV is not production

Unit tests

Critical scenarios

Settlement API examples

Cron audit

The settlement-reconciliation cron runs two daily passes:
  • Pass 1 — warns on BonumTransaction rows that are verified but unsettled after 48h
  • Pass 2 — warns on rows that remain unverified after 24h

E2E against sandbox

Requires a sandbox BONUM_MERCHANT_KEY and an active MerchantPrefixRegistry entry.
1

Provision the shop

Create a shop with bonumEnabled=true and assign a merchant prefix.
2

Create the intent

POST /orders/v2/create-payment-intent with provider=BONUM → confirm the returned invoice ID starts with the shop’s prefix.
3

Pay via sandbox

Use a real Apple/Google Pay token from testpsp.bonum.mn, POST it with the invoice ID to the integration service’s /bonum/payment/process endpoint.
4

Verify

GET /bonum/payment-log/read?invoiceId=<id> should return success=true.