Bonum Gateway APIs

1. Орчны Тохиргоо

Үндсэн URL & Хувьсагчид

Хувьсагч Тест Орчин Продакшн Орчин
API_BASE_URL https://testapi.bonum.mn https://apis.bonum.mn
APP_SECRET Мерчант бүртгэлийн үед өгөгдсөн Bonum-тай холбогдоно уу
DEFAULT_TERMINAL_ID Мерчант Порталд үүсгэсэн Bonum-тай холбогдоно уу

Хэлний Дэмжлэг

Accept-Language толгой ашиглан хариуг хүссэн хэлээрээ хүлээн авна:

Толгой Утга Тайлбар
Accept-Language mn Монгол хэлээр хариу
Accept-Language en Англи хэлээр хариу

2. Нэвтрэлт

GET Токен Авах

/bonum-gateway/ecommerce/auth/create

API нэвтрэлтийн access token болон refresh token авна. APP_SECRET-г мерчант порталд үүсгэнэ. Мерчант порталд терминал үүсгэж, түүний terminalId утгыг ашиглана.

Анхааруулга: Энэ endpoint нь хязгаарлалттай. Хэт олон удаа хүсэлт илгээвэл TOO_MANY_REQUESTS алдаа гарна.

Хүсэлтийн Толгой

Толгой Утга Тайлбар
Authorization AppSecret {APP_SECRET} Таны аппликейшны нууц түлхүүр
X-TERMINAL-ID {DEFAULT_TERMINAL_ID} Таны терминалын ID

Хариу 200 OK

{
    "tokenType": "Bearer",
    "accessToken": "eyJhbGciOiJIUzI1...",
    "expiresIn": 1800,
    "refreshToken": "eyJhbGciOiJIUzI1...",
    "refreshExpiresIn": 2000,
    "unit": "SECONDS"
}

Алдааны Хариу 429 Too Many Requests

{
    "traceId": "695cbcbce9d3faa6...",
    "errorCode": null,
    "error": null,
    "message": "Rate-Limit: Use previous token. Do not get token too frequently.",
    "data": null,
    "detail": null,
    "duration": 452,
    "status": 429
}

GET Токен Шинэчлэх

/bonum-gateway/ecommerce/auth/refresh

Хугацаа дууссан access token-г refresh token ашиглан шинэчилнэ.

Хүсэлтийн Толгой

Толгой Утга Тайлбар
Authorization Bearer {refreshToken} Таны refresh token

Хариу 200 OK

Токен Авах хариутай ижил бүтэцтэй шинэ access token буцаана.

3. Вэб Төлбөр / Нэгдсэн

GET 3.1 Төлбөрийн Провайдерууд

/bonum-gateway/ecommerce/invoices/payment-providers

Таны хэрэглэгчдэд боломжтой идэвхтэй төлбөрийн сонголтуудыг буцаана. Энэ жагсаалтыг өөрчлөх боломжтой.

Боломжтой Провайдерууд

Провайдер Тайлбар
QPAY QR суурьтай төлбөр. Бүх банк болон fintech апп-ууд QPAY дэмждэг
E_COMMERCE Онлайн картын төлбөр
WE_CHAT Хятад хэрэглэгчдэд зориулсан WeChat хэтэвчний төлбөр
SONO_SHOP SonoShop зээлээр одоо авч дараа төлөх

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}

Хариу 200 OK

[
    {
        "provider": "QPAY",
        "enabled": true
    },
    {
        "provider": "E_COMMERCE",
        "enabled": true
    },
    {
        "provider": "SONO_SHOP",
        "enabled": true
    }
]

POST 3.2 Нэхэмжлэл Үүсгэх

/bonum-gateway/ecommerce/invoices

Нэхэмжлэл үүсгэж, дагах линк буцаана. Хөтөч эсвэл клиент нь хэрэглэгчийг төлбөр хийхийн тулд дагах линк рүү чиглүүлэх ёстой.

Төлбөр дууссан эсвэл цуцлагдсан тохиолдолд callback (webhook) URL руу мэдэгдэл илгээгдэнэ. Callback нь Bonum-д урьдчилан тохируулсан HTTP(S) endpoint байх ёстой.

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}
Accept-Language mn or en
Content-Type application/json

Хүсэлтийн Бие

{
    "amount": 1,
    "callback": "https://your-domain.com/payment-callback?txn=c22765536",
    "transactionId": "aa22765536",
    "expiresIn": 23000,            // seconds
    "providers": ["QPAY"],         // optional, see "Get Payment Providers"
    "items": [                     // optional
        {
            "image": "https://example.com/product.png",
            "title": "Product Name",
            "remark": "Product Description",
            "amount": 1,
            "count": 1
        }
    ],
    "extras": [                    // optional
        {
            "placeholder": "Enter details",
            "type": "TEXT",        // NUMBER, PHONE, EMAIL, TEXT, ALL
            "required": true
        }
    ]
}

Хүсэлтийн Талбарууд

Талбар Төрөл Шаардлагатай Тайлбар
amount Number Тийм Нийт төлбөрийн дүн
callback String Тийм Төлбөрийн дараа чиглүүлэх URL
transactionId String Тийм Таны давтагдашгүй гүйлгээний тодорхойлогч
expiresIn Number Үгүй Дуусах хугацаа секундээр
providers Array Үгүй Төлбөрийн провайдеруудыг шүүх
items Array Үгүй Нэхэмжлэлийн бараа зүйлс
extras Array Үгүй Хэрэглэгчийн нэмэлт оруулах талбарууд

Хариу 200 OK

{
    "invoiceId": "8cf2c49d200f049f2b384f0adf42b981...",
    "followUpLink": "https://ecommerce.bonum.mn/ecommerce?invoiceId=c511ea63..."
}

GET 3.3 Нэхэмжлэлийн Төлөв (Зөвхөн Тест)

/bonum-gateway/ecommerce/invoices/{invoiceId}

АНХААРУУЛГА: ЭНЭ СЕРВИСИЙГ ПРОДАКШН ОРЧИНД АШИГЛАХГҮЙ.

"Нэхэмжлэл Үүсгэх"-ээр үүсгэсэн нэхэмжлэлийн төлбөрийн төлөвийг буцаана. Продакшн орчинд өөрийн локал өгөгдөл болон webhook мессежийг ашиглана: нэхэмжлэлийн бүртгэлийг өөрийн талд хадгалж, webhook хүлээн авсны дараа шинэчилнэ.

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}
Accept application/json

3.4 Нэхэмжлэлийн Webhook

Хэрэглэгч төлбөрөө дуусгасны дараа мерчантын бүртгүүлсэн webhook URL руу POST хүсэлтээр webhook мессеж илгээгдэнэ.

Амжилттай Төлбөрийн Webhook

{
    "type": "PAYMENT",
    "status": "SUCCESS",
    "message": "",
    "body": {
        "amount": 10000.00,
        "currency": "MNT",
        "completedAt": "2026-01-29 11:20:33",
        "terminalId": "17171994",
        "invoiceId": "8eff7d69001c03f486f64410f9daa82c",
        "paymentVendor": "QPAY",
        "initType": "ECOMMERCE",
        "status": "PAID",
        "respCode": "",
        "transactionId": "N998921",
        "extras-inputs": [],
        "extras": []
    }
}

Амжилтгүй Төлбөрийн Webhook

{
    "type": "PAYMENT",
    "status": "FAILED",
    "message": "",
    "body": {
        "transactionId": "B347699",
        "amount": 15000.00,
        "currency": "MNT",
        "updatedAt": 1769657291559,
        "terminalId": "17171994",
        "invoiceStatus": "EXPIRED"
    }
}

4. Картын Токенжуулалт

Хүсэлтийн Толгойн Тэмдэглэл: X-CARD-TOKEN-г хүсэлтийн толгойд хавсаргах ёстой. Түүний утга нь кредит картын токен амжилттай үүссэний дараа мерчантын webhook endpoint руу илгээгдэнэ.

POST 4.1 Картын Токен Үүсгэх

/mpay-service/merchant/cards/tokenize/request

Кредит картын токенжуулалтын хүсэлт үүсгэж, дагах линк буцаана. Линк нь хэрэглэгчийг шаардлагатай алхмуудаар дамжуулна. Дууссаны дараа мерчантын бүртгүүлсэн URL руу webhook мэдэгдэл илгээгдэнэ.

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}
Accept-Language mn or en
Content-Type application/json

Хүсэлтийн Бие

{
    "callback": "https://merchant-web/card-token-callback?id=20250512180511001",
    "transactionId": "15za20250512180511006",
    "payment": {
        "amount": 100.00
    },
    "subscription": {              // optional
        "planId": 1,
        "cycleValue": "5",
        "cycles": 5,
        "payNow": false,
        "custEmail": "customer@example.com"
    },
    "items": [                     // optional
        {
            "image": "https://example.com/item.png",
            "title": "Item title",
            "remark": "Item description",
            "amount": 1,
            "count": 10
        }
    ]
}

Хүсэлтийн Талбарууд

Талбар Төрөл Шаардлагатай Тайлбар
callback String Тийм Токенжуулалтын дараа хэрэглэгчийг чиглүүлэх URL
transactionId String Тийм Энэ токенжуулалтын хүсэлтийн давтагдашгүй ID
payment.amount Number Үгүй Төлбөрийн дүн (токенжуулалтын үед төлбөр хийх бол)
subscription.planId Number Үгүй Төлбөрийн төлөвлөгөөний ID (Төлбөрийн Төлөвлөгөөний Жагсаалт харна уу)
subscription.cycleValue String Үгүй Төлбөрийн өдөр: 1-7 (долоо хоног), 1-31 (сар), 1-366 (жил)
subscription.cycles Number Үгүй Төлбөрийн мөчлөгийн тоо. Null бол цуцлах хүртэл идэвхтэй
subscription.payNow Boolean Үгүй True бол одоогийн огноо эхний төлбөрийн огноо болно
subscription.custEmail String Үгүй Захиалгын мэдэгдэл авах хэрэглэгчийн имэйл

Хариу 200 OK

{
    "followUpLink": "https://ecommerce.bonum.mn/tokenize?id=73c642ec1df9ca...",
    "id": "73c642ec1df9ca..."
}

Картын Токен Webhook Мессеж

Токен амжилттай үүссэний дараа мерчантын бүртгүүлсэн URL руу webhook мессеж илгээгдэнэ:

{
    "type": "CARD-TOKEN",
    "status": "SUCCESS",
    "message": "",
    "body": {
        "token": "1fc53f9389f489ff6e04617bd6338a71...",
        "mask": "5150 23** **** 4778",
        "expiry": "2026/11",
        "bank": {
            "id": 19,
            "code": "150000",
            "name": "Golomt Bank",
            "icon": "https://bonum-prod-resource.s3.us-east-2.amazonaws.com/golomt.png"
        },
        "transactionId": "6ab20250512180511006",
        "completedAt": "2026-01-26 12:58:03",
        "amounts": [
            { "amount": 5.00, "currency": "MNT" }
        ],
        "subscriptions": [
            {
                "subscriptionId": 1,
                "planId": 1,
                "nextBillingDate": "2026-02-02 00:00:00"
            }
        ]
    }
}

Webhook Толгой

Толгой Тайлбар
X-CARD-TOKEN Үүсгэгдсэн картын токены утга

POST 4.2 Худалдан авалт (Картын Токеноор Төлөх)

/mpay-service/merchant/transaction/purchase

Өмнө үүсгэсэн картын токен ашиглан төлбөр хийнэ.

Тэмдэглэл: Ачаалал ихтэй үед төлбөрүүд дараалалд орж болно. Дараалалд орсон төлбөрүүд асинхрон байдлаар гүйцэтгэгдэж, үр дүнг webhook-ээр дамжуулна.

errorCode талбарыг ашиглах эсвэл харуулахгүй байна уу. Энэ нь зөвхөн дотоод хэрэглээнд зориулагдсан.

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}
X-CARD-TOKEN Картын токены утга
Accept-Language mn or en
Content-Type application/json

Хүсэлтийн Бие

{
    "amount": 15,
    "currency": "MNT",
    "transactionId": "your-unique-transaction-id"
}

Амжилттай Хариу 200 OK

{
    "traceId": "6965c23f4a88878d...",
    "errorCode": "${invalid.bonum.response.00}",
    "error": null,
    "message": "Payment successful (00)",
    "data": {
        "id": 172345,
        "completedAt": "2026-01-13 11:55:44",
        "status": "SUCCESS",
        "description": "",
        "cardStatus": "ACTIVE"
    },
    "detail": null,
    "duration": 759,
    "status": 200
}

Алдааны Хариу 400 Bad Request

{
    "traceId": "6965b3f57a560ad2...",
    "errorCode": "${invalid.bonum.response.56}",
    "error": null,
    "message": "Card payment not possible (56)",
    "data": {
        "id": 171044,
        "completedAt": "2026-01-13 10:54:46",
        "status": "FAILED",
        "description": "",
        "cardStatus": "INACTIVE"
    },
    "detail": null,
    "duration": 635,
    "status": 400
}

Дараалалд Орсон Хариу 201 Created

{
    "traceId": "697088018770d01b...",
    "errorCode": "QUEUED",
    "error": null,
    "message": "bonum.token.invoice.queued",
    "data": {
        "id": 662,
        "completedAt": "2026-01-21 16:02:10",
        "status": "QUEUED",
        "description": "",
        "cardStatus": null,
        "respCode": null
    },
    "detail": null,
    "duration": 1192,
    "status": 201
}

GET 4.3 Буцаалт

/mpay-service/merchant/transaction/rollback/{id}

Өмнө дууссан худалдан авалтын гүйлгээг буцаана.

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}
X-CARD-TOKEN Картын токены утга

Замын Параметрүүд

Параметр Тайлбар
id Буцаах гүйлгээний ID

5. Захиалгын Төлөвлөгөө

GET 5.1 Төлбөрийн Төлөвлөгөөний Жагсаалт

/mpay-service/merchant/values/payment-plans

Мерчантын төлбөрийн төлөвлөгөөнүүдийн (захиалгын төлөвлөгөө) жагсаалтыг буцаана. Төлбөрийн төлөвлөгөөг Мерчант Порталд үүсгэх, унших, засах, устгах боломжтой.

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}

Хариу 200 OK

{
    "traceId": "6960b2d3ec9f9d4a...",
    "data": [
        {
            "planId": 1,
            "name": "Test Weekly Plan 1",
            "remark": "Weekly payment plan",
            "createdAt": "2025-03-20 15:53:51",
            "recurringType": "WEEKLY",
            "amount": 5.00,
            "status": "ACTIVE",
            "cardCount": 0,
            "retryCount": 3
        },
        {
            "planId": 21,
            "name": "Monthly Plan",
            "remark": "Monthly payment plan",
            "createdAt": "2026-01-08 16:21:30",
            "recurringType": "MONTHLY",
            "amount": 9.00,
            "status": "ACTIVE",
            "cardCount": 0,
            "retryCount": 3
        }
    ],
    "status": 200
}

POST 5.2 Захиалга Хийх

/mpay-service/merchant/subscriptions/subscribe

Кредит картын токеныг төлбөрийн төлөвлөгөөнд захиалга хийнэ.

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}
X-CARD-TOKEN Картын токены утга
Content-Type application/json

Хүсэлтийн Бие

{
    "planId": 30,
    "cycleValue": 10,
    "cycles": 3,
    "payNow": false,
    "custEmail": "customer@example.com"
}

Хүсэлтийн Талбарууд

Талбар Төрөл Шаардлагатай Тайлбар
planId Number Тийм "Төлбөрийн Төлөвлөгөөний Жагсаалт"-аас авсан төлбөрийн төлөвлөгөөний ID
cycleValue Number Тийм Төлбөрийн өдөр: WEEKLY 1-7 (Дав-Ням), MONTHLY 1-31, YEARLY 1-366
cycles Number Үгүй Мөчлөгийн тоо. Null бол цуцлах хүртэл идэвхтэй
payNow Boolean Үгүй True бол cycleValue-г үл тоомсорлоно; эхний төлбөр шууд хийгдэнэ
custEmail String Үгүй Мэдэгдэл авах хэрэглэгчийн имэйл

Тэмдэглэл: Захиалгын огноо нь төлбөрийн төлөвлөгөөний cycleValue-тай таарвал, захиалга хийх үед төлбөр шууд хийгдэнэ.

Амжилттай Хариу 201 Created

{
    "traceId": "6976ca6cbdfca1fc...",
    "data": {
        "subscriptionId": 41,
        "subscribedAt": "2026-01-26 09:59:11",
        "cardMask": "9496 43** **** 2727",
        "plan": {
            "planId": 4,
            "name": "Monthly Plan",
            "recurringType": "MONTHLY",
            "amount": 3,
            "status": "ACTIVE",
            "retryCount": 3
        },
        "nextBillAt": "2026-01-27 00:00:00",
        "lastBilledAt": "2026-01-26 09:59:11",
        "status": "ACTIVE"
    },
    "status": 201
}

Алдаа: Давхар Захиалга 429 Too Many Requests

// If one subscription process is not finished and another is issued for the same card
{
    "traceId": "6960ba5dc45779dd...",
    "message": "subscription.process.waiting",
    "data": null,
    "status": 429
}

Алдаа: Картын Төлбөр Татгалзсан 400 Bad Request

// Card system denies the payment request
{
    "traceId": "6960bb4080c62f87...",
    "errorCode": "${invalid.bonum.response.89}",
    "message": "Payment not possible (89)",
    "data": null,
    "status": 400
}

5.3 Захиалга Удирдах

PUT Захиалгын Токен Солих (Шинэ Токен Үүсгэх)

/mpay-service/merchant/subscriptions/{subscriptionId}/change/create-new-token

Шинэ токен үүсгэн захиалгын картын токеныг солино.

{
    "callback": "https://merchant-web/card-token-callback?id=something",
    "transactionId": "123456000",
    "items": [                     // optional
        {
            "image": "https://example.com/item.png",
            "title": "Item title",
            "remark": "Item description",
            "amount": 1,
            "count": 10
        }
    ]
}

PUT Захиалгын Токен Солих (Одоо байгаа Токен)

/mpay-service/merchant/subscriptions/{subscriptionId}/change

Одоо байгаа токен ашиглан захиалгын картын токеныг солино.

Толгой Утга
X-CARD-TOKEN Шинэ картын токены утга

GET Захиалгууд Авах

/mpay-service/merchant/subscriptions

Картын токены захиалгуудыг буцаана.

Толгой Утга
X-CARD-TOKEN Картын токены утга

DELETE Захиалга Цуцлах

/mpay-service/merchant/subscriptions/{subscriptionId}

Картын токеныг төлбөрийн төлөвлөгөөнөөс захиалга цуцална. Дараагийн төлбөрийн мөчлөгийн төлбөр дараагийн төлбөрийн огноонд хийгдсээр байна.

Толгой Утга
X-CARD-TOKEN Картын токены утга

DELETE Захиалга Устгах

/mpay-service/merchant/subscriptions/{subscriptionId}/delete

Захиалгыг бүрмөсөн устгана. Дараагийн төлбөрийн мөчлөгт төлбөр үүсэхгүй.

Толгой Утга
X-CARD-TOKEN Картын токены утга

Захиалгын Автомат Төлбөрийн Webhook

Картын токен Төлбөрийн Төлөвлөгөөнд захиалга хийсний дараа, төлбөр нь төлбөрийн огноонд автоматаар хийгдэнэ. Мерчантын бүртгүүлсэн URL руу webhook мессеж илгээгдэнэ:

{
    "type": "SUBSCRIPTION-PAYMENT",
    "status": "SUCCESS",               // SUCCESS | FAILED
    "message": "",
    "body": {
        "subscriptionId": 41,
        "invoiceId": 786,
        "planId": 4,
        "transactionId": "20000007",
        "completedAt": "2026-01-27 02:00:08",
        "amount": 3,
        "currency": "MNT"
    }
}

6. QR Код / Deeplink Төлбөр

POST 6.1 QR Код Үүсгэх

/mpay-service/merchant/transaction/qr/create

QPAY-г дэмждэг банк болон fintech апп-уудаар төлбөр хийх QR код үүсгэнэ.

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}
Content-Type application/json

Хүсэлтийн Бие

{
    "amount": 10,
    "transactionId": "3ba1234567890a",
    "expiresIn": 600                   // 10 minutes, in seconds
}

Хариу 200 OK

{
    "traceId": "69b76ea35599c03c...",
    "status": 200,
    "data": {
        "invoiceId": "1234bacd123",
        "qrCode": "12345...abc",
        "qrImage": "[base64 encoded QR image]",
        "links": [
            {
                "name": "Khan bank",
                "description": "Khan bank",
                "logo": "https://qpay.mn/q/logo/khanbank.png",
                "link": "khanbank://q?qPay_QRcode=...",
                "appStoreId": "1555908766",
                "androidPackageName": "com.khanbank.retail"
            },
            {
                "name": "Social Pay",
                "description": "Golomt bank",
                "logo": "https://qpay.mn/q/logo/socialpay.png",
                "link": "socialpay-payment://q?qPay_QRcode=...",
                "appStoreId": "1152919460",
                "androidPackageName": "mn.egolomt.socialpay"
            },
            {
                "name": "Trade and Development bank",
                "description": "TDB online",
                "logo": "https://qpay.mn/q/logo/tdbbank.png",
                "link": "tdbbank://q?qPay_QRcode=...",
                "appStoreId": "1458831706",
                "androidPackageName": "mn.tdb.pay"
            }
        ]
    }
}

POST 6.2 QR Нэхэмжлэл

/mpay-service/merchant/transaction/qr

QR кодоор (QPAY QR Code) нэхэмжлэлийн мэдээлэл авна.

Хүсэлтийн Бие

{
    "qrCode": "0002010102121531279404962794049600..."
}

PUT Картын Токеноор Төлөх

/merchant/transaction/qr/pay

Картын токен ашиглан QR нэхэмжлэл төлнө.

Хүсэлтийн Толгой

Толгой Утга
Authorization Bearer {accessToken}
X-CARD-TOKEN Картын токены утга
Accept-Language mn or en

Хүсэлтийн Бие

{
    "qrCode": "0002010102121531279404962794049600...",
    "transactionId": "f123456789"
}

7. Webhook Дамжуулалт & Баталгаажуулалт

Webhook Хэрхэн Ажилладаг

Төлбөрийн Gateway нь гүйлгээ болон картын токены мэдээллийг мерчантын бүртгүүлсэн webhook URL руу HTTP POST-оор илгээдэг. Мессежийн баталгаажуулалтад x-checksum-v2 толгой хавсаргагдана.

Төлбөрийн Webhook Мессеж

{
    "type": "PAYMENT",
    "status": "SUCCESS",               // SUCCESS | FAILED
    "message": "Successful",
    "body": {
        "invoiceId": "abc....xyz....",
        "transactionId": "your-transaction-id"
    }
}

Картын Токен Webhook Мессеж

{
    "type": "CARD-TOKEN",
    "status": "SUCCESS",               // SUCCESS | FAILED
    "message": "Successful",
    "body": {
        "token": "abc....xyz....",
        "transactionId": "your-transaction-id"
    }
}

Checksum Баталгаажуулалт

Ирж буй webhook мессежийг x-checksum-v2 толгой ашиглан баталгаажуулна. MERCHANT_CHECKSUM_KEY-г Bonum аюулгүй байдлаар өгнө. Энэ түлхүүрийг найдвартай хадгална уу.

// Kotlin Example

fun checksumValidation(httpRequest: HttpRequest): Boolean {
    // This key will be provided by Bonum — keep it secure
    val MERCHANT_CHECKSUM_KEY = ""

    val raw = JSON.toJson(
        value = httpRequest.requestBody,
        prettyPrint = false     // no indentation
    )

    val checksumValue = checksum(raw, MERCHANT_CHECKSUM_KEY)
    val checksumHeaderValue = httpRequest.headers.get("x-checksum-v2")

    return Objects.equals(checksumValue, checksumHeaderValue)
}

fun checksum(value: String, key: String): String {
    val secretKey = SecretKeySpec(
        key.toByteArray(Charsets.UTF_8),
        "HmacSHA256"
    )
    val mac = Mac.getInstance("HmacSHA256")
    mac.init(secretKey)

    val hmacArray = mac.doFinal(
        value.toByteArray(Charsets.UTF_8)
    )

    return hex(hmacArray)
}

private fun hex(vl: ByteArray): String {
    val sb = StringBuilder(vl.size * 2)
    for (b in vl) {
        sb.append(String.format("%02x", b.toInt() and 0xff))
    }
    return sb.toString()
}

8. Дэмжлэг & Холбоо Барих

Лавлагаа:
Мерчант Портал - https://merchant.bonum.mn/
Postman Цуглуулга - Postman дээр харах


Нэмэлт тусламж хэрэгтэй бол манай багтай холбогдоно уу:
- Имэйл: info@bonum.mn
- Утас: +976 7200-5000

1. Environment Setup

Base URLs & Variables

Variable Testing Environment Production Environment
API_BASE_URL https://testapi.bonum.mn https://apis.bonum.mn
APP_SECRET Provided during merchant setup Contact Bonum
DEFAULT_TERMINAL_ID Created on Merchant Portal Contact Bonum

Language Support

Use the Accept-Language header to receive responses in your preferred language:

Header Value Description
Accept-Language mn Mongolian responses
Accept-Language en English responses

2. Authentication

GET Get Token

/bonum-gateway/ecommerce/auth/create

Obtain an access token and refresh token for API authentication. The APP_SECRET is created on the merchant portal. Create a terminal on the merchant portal and use its terminalId value.

Caution: This endpoint is protected by rate limiting. Excessive or too frequent requests will result in a TOO_MANY_REQUESTS error.

Request Headers

Header Value Description
Authorization AppSecret {APP_SECRET} Your application secret key
X-TERMINAL-ID {DEFAULT_TERMINAL_ID} Your terminal ID

Response 200 OK

{
    "tokenType": "Bearer",
    "accessToken": "eyJhbGciOiJIUzI1...",
    "expiresIn": 1800,
    "refreshToken": "eyJhbGciOiJIUzI1...",
    "refreshExpiresIn": 2000,
    "unit": "SECONDS"
}

Error Response 429 Too Many Requests

{
    "traceId": "695cbcbce9d3faa6...",
    "errorCode": null,
    "error": null,
    "message": "Rate-Limit: Use previous token. Do not get token too frequently.",
    "data": null,
    "detail": null,
    "duration": 452,
    "status": 429
}

GET Refresh Token

/bonum-gateway/ecommerce/auth/refresh

Refresh an expired access token using the refresh token.

Request Headers

Header Value Description
Authorization Bearer {refreshToken} Your refresh token

Response 200 OK

Returns a new access token with the same structure as the Get Token response.

3. Web Payment / All in One

GET 3.1 Get Payment Providers

/bonum-gateway/ecommerce/invoices/payment-providers

Returns the active payment options available for your customers. This list can be modified.

Available Providers

Provider Description
QPAY QR-based payment. All banks and fintech apps support QPAY
E_COMMERCE Online card payment
WE_CHAT WeChat wallet payment for Chinese customers
SONO_SHOP Buy Now, Pay Later via SonoShop loan

Request Headers

Header Value
Authorization Bearer {accessToken}

Response 200 OK

[
    {
        "provider": "QPAY",
        "enabled": true
    },
    {
        "provider": "E_COMMERCE",
        "enabled": true
    },
    {
        "provider": "SONO_SHOP",
        "enabled": true
    }
]

POST 3.2 Create Invoice

/bonum-gateway/ecommerce/invoices

Creates an invoice and returns a follow-up link. The browser or client must redirect to the follow-up link for the user to proceed with payment.

Once payment is completed or cancelled, a notification will be sent to the callback (webhook) URL. The callback must be an HTTP(S) endpoint pre-configured on the Bonum side.

Request Headers

Header Value
Authorization Bearer {accessToken}
Accept-Language mn or en
Content-Type application/json

Request Body

{
    "amount": 1,
    "callback": "https://your-domain.com/payment-callback?txn=c22765536",
    "transactionId": "aa22765536",
    "expiresIn": 23000,            // seconds
    "providers": ["QPAY"],         // optional, see "Get Payment Providers"
    "items": [                     // optional
        {
            "image": "https://example.com/product.png",
            "title": "Product Name",
            "remark": "Product Description",
            "amount": 1,
            "count": 1
        }
    ],
    "extras": [                    // optional
        {
            "placeholder": "Enter details",
            "type": "TEXT",        // NUMBER, PHONE, EMAIL, TEXT, ALL
            "required": true
        }
    ]
}

Request Body Fields

Field Type Required Description
amount Number Yes Total payment amount
callback String Yes URL to redirect after payment
transactionId String Yes Your unique transaction identifier
expiresIn Number No Expiry time in seconds
providers Array No Filter payment providers
items Array No Line items for the invoice
extras Array No Extra input fields for customer

Response 200 OK

{
    "invoiceId": "8cf2c49d200f049f2b384f0adf42b981...",
    "followUpLink": "https://ecommerce.bonum.mn/ecommerce?invoiceId=c511ea63..."
}

GET 3.3 Get Invoice Status (Testing Only)

/bonum-gateway/ecommerce/invoices/{invoiceId}

CAUTION: DO NOT USE THIS SERVICE ON PRODUCTION.

Returns the payment status of an invoice created by "Create Invoice". For production, use your local data and webhook message delivery: store the invoice record on your side and update it once a webhook is received.

Request Headers

Header Value
Authorization Bearer {accessToken}
Accept application/json

3.4 Invoice Webhook Messages

After the user completes a payment, a webhook message is sent to the merchant's registered webhook URL via POST.

Successful Payment Webhook

{
    "type": "PAYMENT",
    "status": "SUCCESS",
    "message": "",
    "body": {
        "amount": 10000.00,
        "currency": "MNT",
        "completedAt": "2026-01-29 11:20:33",
        "terminalId": "17171994",
        "invoiceId": "8eff7d69001c03f486f64410f9daa82c",
        "paymentVendor": "QPAY",
        "initType": "ECOMMERCE",
        "status": "PAID",
        "respCode": "",
        "transactionId": "N998921",
        "extras-inputs": [],
        "extras": []
    }
}

Failed Payment Webhook

{
    "type": "PAYMENT",
    "status": "FAILED",
    "message": "",
    "body": {
        "transactionId": "B347699",
        "amount": 15000.00,
        "currency": "MNT",
        "updatedAt": 1769657291559,
        "terminalId": "17171994",
        "invoiceStatus": "EXPIRED"
    }
}

4. Card Tokenization

Request Header Note: X-CARD-TOKEN must be attached to request headers. Its value is sent to the merchant's webhook endpoint once the credit card token is generated successfully.

POST 4.1 Create Card Token

/mpay-service/merchant/cards/tokenize/request

Creates a credit card tokenization request and returns a follow-up link. The link takes the user through the necessary steps. Once done, a webhook notification will be sent to the merchant's registered URL.

Request Headers

Header Value
Authorization Bearer {accessToken}
Accept-Language mn or en
Content-Type application/json

Request Body

{
    "callback": "https://merchant-web/card-token-callback?id=20250512180511001",
    "transactionId": "15za20250512180511006",
    "payment": {
        "amount": 100.00
    },
    "subscription": {              // optional
        "planId": 1,
        "cycleValue": "5",
        "cycles": 5,
        "payNow": false,
        "custEmail": "customer@example.com"
    },
    "items": [                     // optional
        {
            "image": "https://example.com/item.png",
            "title": "Item title",
            "remark": "Item description",
            "amount": 1,
            "count": 10
        }
    ]
}

Request Body Fields

Field Type Required Description
callback String Yes URL to redirect user after tokenization
transactionId String Yes Your unique ID for this tokenization request
payment.amount Number No Payment amount (if making a payment during tokenization)
subscription.planId Number No Payment plan ID (see List of Payment Plans)
subscription.cycleValue String No Billing day: 1-7 (weekly), 1-31 (monthly), 1-366 (yearly)
subscription.cycles Number No Number of billing cycles. If null, active until cancelled
subscription.payNow Boolean No If true, current date becomes first billing date
subscription.custEmail String No Customer email for subscription notifications

Response 200 OK

{
    "followUpLink": "https://ecommerce.bonum.mn/tokenize?id=73c642ec1df9ca...",
    "id": "73c642ec1df9ca..."
}

Card Token Webhook Message

On successful token generation, a webhook message is sent to the merchant's registered URL:

{
    "type": "CARD-TOKEN",
    "status": "SUCCESS",
    "message": "",
    "body": {
        "token": "1fc53f9389f489ff6e04617bd6338a71...",
        "mask": "5150 23** **** 4778",
        "expiry": "2026/11",
        "bank": {
            "id": 19,
            "code": "150000",
            "name": "Golomt Bank",
            "icon": "https://bonum-prod-resource.s3.us-east-2.amazonaws.com/golomt.png"
        },
        "transactionId": "6ab20250512180511006",
        "completedAt": "2026-01-26 12:58:03",
        "amounts": [
            { "amount": 5.00, "currency": "MNT" }
        ],
        "subscriptions": [
            {
                "subscriptionId": 1,
                "planId": 1,
                "nextBillingDate": "2026-02-02 00:00:00"
            }
        ]
    }
}

Webhook Headers

Header Description
X-CARD-TOKEN The generated card token value

POST 4.2 Purchase (Pay with Card Token)

/mpay-service/merchant/transaction/purchase

Initiates a payment using a previously generated card token.

Note: During high traffic, payments may be queued. Queued payments are executed asynchronously and the result is delivered via webhook.

Do not rely on or expose the errorCode field. It is for internal use only.

Request Headers

Header Value
Authorization Bearer {accessToken}
X-CARD-TOKEN Card token value
Accept-Language mn or en
Content-Type application/json

Request Body

{
    "amount": 15,
    "currency": "MNT",
    "transactionId": "your-unique-transaction-id"
}

Successful Response 200 OK

{
    "traceId": "6965c23f4a88878d...",
    "errorCode": "${invalid.bonum.response.00}",
    "error": null,
    "message": "Payment successful (00)",
    "data": {
        "id": 172345,
        "completedAt": "2026-01-13 11:55:44",
        "status": "SUCCESS",
        "description": "",
        "cardStatus": "ACTIVE"
    },
    "detail": null,
    "duration": 759,
    "status": 200
}

Failed Response 400 Bad Request

{
    "traceId": "6965b3f57a560ad2...",
    "errorCode": "${invalid.bonum.response.56}",
    "error": null,
    "message": "Card payment not possible (56)",
    "data": {
        "id": 171044,
        "completedAt": "2026-01-13 10:54:46",
        "status": "FAILED",
        "description": "",
        "cardStatus": "INACTIVE"
    },
    "detail": null,
    "duration": 635,
    "status": 400
}

Queued Response 201 Created

{
    "traceId": "697088018770d01b...",
    "errorCode": "QUEUED",
    "error": null,
    "message": "bonum.token.invoice.queued",
    "data": {
        "id": 662,
        "completedAt": "2026-01-21 16:02:10",
        "status": "QUEUED",
        "description": "",
        "cardStatus": null,
        "respCode": null
    },
    "detail": null,
    "duration": 1192,
    "status": 201
}

GET 4.3 Rollback Purchase

/mpay-service/merchant/transaction/rollback/{id}

Rolls back a previously completed purchase transaction.

Request Headers

Header Value
Authorization Bearer {accessToken}
X-CARD-TOKEN Card token value

Path Parameters

Parameter Description
id The transaction ID to rollback

5. Subscription Plans

GET 5.1 List of Payment Plans

/mpay-service/merchant/values/payment-plans

Returns the list of payment plans (subscription plans) of the merchant. Payment plans can be created, read, updated, and deleted on the Merchant Portal.

Request Headers

Header Value
Authorization Bearer {accessToken}

Response 200 OK

{
    "traceId": "6960b2d3ec9f9d4a...",
    "data": [
        {
            "planId": 1,
            "name": "Test Weekly Plan 1",
            "remark": "Weekly payment plan",
            "createdAt": "2025-03-20 15:53:51",
            "recurringType": "WEEKLY",
            "amount": 5.00,
            "status": "ACTIVE",
            "cardCount": 0,
            "retryCount": 3
        },
        {
            "planId": 21,
            "name": "Monthly Plan",
            "remark": "Monthly payment plan",
            "createdAt": "2026-01-08 16:21:30",
            "recurringType": "MONTHLY",
            "amount": 9.00,
            "status": "ACTIVE",
            "cardCount": 0,
            "retryCount": 3
        }
    ],
    "status": 200
}

POST 5.2 Subscribe

/mpay-service/merchant/subscriptions/subscribe

Subscribes a credit card token to a payment plan.

Request Headers

Header Value
Authorization Bearer {accessToken}
X-CARD-TOKEN Card token value
Content-Type application/json

Request Body

{
    "planId": 30,
    "cycleValue": 10,
    "cycles": 3,
    "payNow": false,
    "custEmail": "customer@example.com"
}

Request Body Fields

Field Type Required Description
planId Number Yes Payment plan ID from "List of Payment Plans"
cycleValue Number Yes Billing day: WEEKLY 1-7 (Mon-Sun), MONTHLY 1-31, YEARLY 1-366
cycles Number No Number of cycles. If null, active until cancelled
payNow Boolean No If true, ignores cycleValue; first payment is immediate
custEmail String No Customer email for notifications

Note: If the subscription date matches the payment plan's cycleValue, the payment is processed immediately during subscription.

Successful Response 201 Created

{
    "traceId": "6976ca6cbdfca1fc...",
    "data": {
        "subscriptionId": 41,
        "subscribedAt": "2026-01-26 09:59:11",
        "cardMask": "9496 43** **** 2727",
        "plan": {
            "planId": 4,
            "name": "Monthly Plan",
            "recurringType": "MONTHLY",
            "amount": 3,
            "status": "ACTIVE",
            "retryCount": 3
        },
        "nextBillAt": "2026-01-27 00:00:00",
        "lastBilledAt": "2026-01-26 09:59:11",
        "status": "ACTIVE"
    },
    "status": 201
}

Error: Multiple Subscription 429 Too Many Requests

// If one subscription process is not finished and another is issued for the same card
{
    "traceId": "6960ba5dc45779dd...",
    "message": "subscription.process.waiting",
    "data": null,
    "status": 429
}

Error: Card Payment Denied 400 Bad Request

// Card system denies the payment request
{
    "traceId": "6960bb4080c62f87...",
    "errorCode": "${invalid.bonum.response.89}",
    "message": "Payment not possible (89)",
    "data": null,
    "status": 400
}

5.3 Manage Subscriptions

PUT Change Subscription Token (Create New Token)

/mpay-service/merchant/subscriptions/{subscriptionId}/change/create-new-token

Changes the card token for a subscription by creating a new token.

{
    "callback": "https://merchant-web/card-token-callback?id=something",
    "transactionId": "123456000",
    "items": [                     // optional
        {
            "image": "https://example.com/item.png",
            "title": "Item title",
            "remark": "Item description",
            "amount": 1,
            "count": 10
        }
    ]
}

PUT Change Subscription Token (Existing Token)

/mpay-service/merchant/subscriptions/{subscriptionId}/change

Changes the card token for a subscription using an existing token.

Header Value
X-CARD-TOKEN The new card token value

GET Get Subscriptions

/mpay-service/merchant/subscriptions

Returns the subscriptions of a card token.

Header Value
X-CARD-TOKEN Card token value

DELETE Unsubscribe

/mpay-service/merchant/subscriptions/{subscriptionId}

Unsubscribes a card token from a payment plan. The next billing cycle payment will still be executed at the next billing date.

Header Value
X-CARD-TOKEN Card token value

DELETE Delete Subscription

/mpay-service/merchant/subscriptions/{subscriptionId}/delete

Deletes a subscription entirely. No payment is created for the next billing cycle.

Header Value
X-CARD-TOKEN Card token value

Subscription Automatic Payment Webhook

Once a card token is subscribed to a Payment Plan, payments are processed automatically on billing dates. A webhook message is sent to the merchant's registered URL:

{
    "type": "SUBSCRIPTION-PAYMENT",
    "status": "SUCCESS",               // SUCCESS | FAILED
    "message": "",
    "body": {
        "subscriptionId": 41,
        "invoiceId": 786,
        "planId": 4,
        "transactionId": "20000007",
        "completedAt": "2026-01-27 02:00:08",
        "amount": 3,
        "currency": "MNT"
    }
}

6. QR Code / Deeplink Payment

POST 6.1 Create QR Code

/mpay-service/merchant/transaction/qr/create

Creates a QR code for payment via QPAY-supported bank and fintech apps.

Request Headers

Header Value
Authorization Bearer {accessToken}
Content-Type application/json

Request Body

{
    "amount": 10,
    "transactionId": "3ba1234567890a",
    "expiresIn": 600                   // 10 minutes, in seconds
}

Response 200 OK

{
    "traceId": "69b76ea35599c03c...",
    "status": 200,
    "data": {
        "invoiceId": "1234bacd123",
        "qrCode": "12345...abc",
        "qrImage": "[base64 encoded QR image]",
        "links": [
            {
                "name": "Khan bank",
                "description": "Khan bank",
                "logo": "https://qpay.mn/q/logo/khanbank.png",
                "link": "khanbank://q?qPay_QRcode=...",
                "appStoreId": "1555908766",
                "androidPackageName": "com.khanbank.retail"
            },
            {
                "name": "Social Pay",
                "description": "Golomt bank",
                "logo": "https://qpay.mn/q/logo/socialpay.png",
                "link": "socialpay-payment://q?qPay_QRcode=...",
                "appStoreId": "1152919460",
                "androidPackageName": "mn.egolomt.socialpay"
            },
            {
                "name": "Trade and Development bank",
                "description": "TDB online",
                "logo": "https://qpay.mn/q/logo/tdbbank.png",
                "link": "tdbbank://q?qPay_QRcode=...",
                "appStoreId": "1458831706",
                "androidPackageName": "mn.tdb.pay"
            }
        ]
    }
}

POST 6.2 Get Invoice by QR Code

/mpay-service/merchant/transaction/qr

Gets QR invoice information by qrCode (QPAY QR Code).

Request Body

{
    "qrCode": "0002010102121531279404962794049600..."
}

PUT Pay by Card Token

/merchant/transaction/qr/pay

Pays a QR invoice using a card token.

Request Headers

Header Value
Authorization Bearer {accessToken}
X-CARD-TOKEN Card token value
Accept-Language mn or en

Request Body

{
    "qrCode": "0002010102121531279404962794049600...",
    "transactionId": "f123456789"
}

7. Webhook Delivery & Validation

How Webhooks Work

The Payment Gateway sends transaction and card token information to the merchant's registered webhook URL via HTTP POST. A x-checksum-v2 header is included for message validation.

Payment Webhook Message

{
    "type": "PAYMENT",
    "status": "SUCCESS",               // SUCCESS | FAILED
    "message": "Successful",
    "body": {
        "invoiceId": "abc....xyz....",
        "transactionId": "your-transaction-id"
    }
}

Card Token Webhook Message

{
    "type": "CARD-TOKEN",
    "status": "SUCCESS",               // SUCCESS | FAILED
    "message": "Successful",
    "body": {
        "token": "abc....xyz....",
        "transactionId": "your-transaction-id"
    }
}

Checksum Validation

Validate incoming webhook messages using the x-checksum-v2 header. The MERCHANT_CHECKSUM_KEY will be provided by Bonum securely. Keep this key safe.

// Kotlin Example

fun checksumValidation(httpRequest: HttpRequest): Boolean {
    // This key will be provided by Bonum — keep it secure
    val MERCHANT_CHECKSUM_KEY = ""

    val raw = JSON.toJson(
        value = httpRequest.requestBody,
        prettyPrint = false     // no indentation
    )

    val checksumValue = checksum(raw, MERCHANT_CHECKSUM_KEY)
    val checksumHeaderValue = httpRequest.headers.get("x-checksum-v2")

    return Objects.equals(checksumValue, checksumHeaderValue)
}

fun checksum(value: String, key: String): String {
    val secretKey = SecretKeySpec(
        key.toByteArray(Charsets.UTF_8),
        "HmacSHA256"
    )
    val mac = Mac.getInstance("HmacSHA256")
    mac.init(secretKey)

    val hmacArray = mac.doFinal(
        value.toByteArray(Charsets.UTF_8)
    )

    return hex(hmacArray)
}

private fun hex(vl: ByteArray): String {
    val sb = StringBuilder(vl.size * 2)
    for (b in vl) {
        sb.append(String.format("%02x", b.toInt() and 0xff))
    }
    return sb.toString()
}

8. Support & Contact

References:
Merchant Portal - https://merchant.bonum.mn/
Postman Collection - View on Postman


If you need further assistance, please contact our team:
- Email: info@bonum.mn
- Phone: +976 7200-5000