Files
android/docs/dhiraaguapi/02-reload.md
T
2026-10-03 00:26:00 +05:00

6.4 KiB
Raw Blame History

Reload (Easy TopUp, paid by BML card)

Top up a Dhiraagu prepaid number through the dhiraagu.com.mv Easy TopUp page. Dhiraagu only builds the order: the money moves on a BML Merchant Services transaction that Dhiraagu creates for it, which is then paid exactly like any card-only BML merchant link (BML API → Merchant Card Payment).

Reconstructed from docs/dhiraaguapi/tmp/dhiraagu_reload_gateway.md (a Firefox HAR).


Flow overview

GET  /services/easy-topup                     → nonce #1
POST cart&act=recharge        (nonce #1)      → cartId
GET  /services/payment-v2?cartid=<cartId>     → nonce #2
POST merchant&act=form        (nonce #2)      → BML gateway's merchantId
POST payment&act=create       (nonce #2)      → paymentId, oid
POST bml&act=createV2         (nonce #2)      → BML transaction url  ──┐
                                                                       │
        ── from here: the BML card-only merchant flow ──               │
GET  transaction.merchants…/<id>/paynow  ←─────────────────────────────┘
… Pomelo tokenise, next-action, Wibmo 3-D Secure, MPGS …  → TRANSACTION_CONFIRMED
GET  transaction.merchants…/<id>?wait=1   → 302 dhiraagu-bml-response.aspx (tops up)
                                          → 302 /services/reload-receipt

After the payment the browser is sent transaction…/<id>?wait=1 → dhiraagu-bml-response.aspx?transactionId=<id>&state=CONFIRMED&signature=… → /services/reload-receipt?pyid=<paymentId>. This is what makes Dhiraagu top up the number — a payment that stopped at BML's TRANSACTION_CONFIRMED was charged but not delivered until that URL was opened. The card flow follows it for every merchant, see BML API → Return to the merchant.

Recovering a stuck reload: open https://transaction.merchants.bankofmaldives.com.mv/<id>?wait=1 in a browser. BML signs the callback, so the transaction id is all that's needed. (curl gets a Cloudflare 403 on the Dhiraagu hop; a browser works.)


Common

All API calls are POST https://www.dhiraagu.com.mv/api/sdk-dhr-webapi.ashx?website_id=CA2BB809-3A22-485B-A518-DA6B6DE653A5&sub=<sub>&act=<act> with a JSON body and these headers:

Header Value
User-Agent a browser UA (same as Number Lookup)
Content-Type application/json
X-Requested-With XMLHttpRequest
Origin https://www.dhiraagu.com.mv
nonce var nonce = "…" from the page that makes the call

Every response is {"respStatus":"OK","resp":…} on success.

Each page has its own nonce: the cart call uses the Easy TopUp page's, the rest use the payment page's.


1. Settings (optional)

GET …&sub=setting&act=reload — the page reads its limits from here. Thijooree hardcodes them.

{"gstRate":0.08,"dailyLimit":3000,
 "amountLimit":{"min":20,"max":1080,"message":"Enter a whole number amount between MVR 20 and 1000"},
 "reloadPerDay":{"easyTopUp":4,"myAccount":6}, …}
Rule Value
Amount whole MVR, 20 – 1000 (the message says 1000; max says 1080 — Thijooree uses 1000)
GST 8%, included in the amount
Per day MVR 3000, 4 Easy TopUps

GST, as the page works it out: gst = round2(amount × 0.08 / 1.08), credited amount − gst (MVR 20 → GST 1.48, credited 18.52).


2. Cart

sub=cart&act=recharge, nonce from GET /services/easy-topup.

{"formId":2,"serviceNumber":"7XXXXXX","amount":20,"amountGST":1.48,"amountRecharge":18.52,
 "gstRate":0.08,"memberId":"","memberName":"","memberNId":"","customerId":"","customerCode":"","version":2}
{"cartId":"002773ed-…","formId":2,"cartAmount":20.00,"cartExpiry":"…",
 "paymentUrl":"https://www.dhiraagu.com.mv/services/payment-v2?cartid=002773ed-…", …}

The page also calls sub=dhiraaguIO&act=infoSubscriberStatus ({"number"}) before this, to show the number's status and balance. Thijooree skips it — Number Lookup has already confirmed a prepaid number.


3. Payment gateway

sub=merchant&act=form, {"formId":2}, nonce from GET /services/payment-v2?cartid=<cartId>. Lists the gateways; gatewayId: 1 is Bank of Maldives (2 = MIB, 3 = DhiraaguPay).

[{"merchantId":"98de333c-…","merchantId2":"3f5cf6b7-…","formId":2,"gatewayId":1,
  "gatewayName":"Bank of Maldives", …}, …]

4. Payment

sub=payment&act=create

{"formId":2,"cartId":"<cartId>","gatewayId":1,"dhiraaguPayNumber":"","amount":"20.00",
 "paymentMerchantId":"<BML merchantId>","memberId":"","tokenize":"","paymentType":"",
 "recurringFrequency":"","bmlTokenId":""}
{"paymentId":"3ea4351b-…","oid":"ET20260006911381","gatewayId":1,"amount":20.00,"paymentStatus":0, …}

5. BML transaction

sub=bml&act=createV2, {"paymentId":"<paymentId>"}. Returns the BML Merchant Services transaction (amounts in cents):

{"state":"INITIATED","amount":2000,"currency":"MVR","localId":"ET20260006911381",
 "url":"https://transaction.merchants.bankofmaldives.com.mv/6abfec7afd7f4a4360fc1df4",
 "redirectUrl":"https://www.dhiraagu.com.mv/api/dhiraagu-bml-response.aspx",
 "expires":"…(10 min)…","customerReference":"WebApp - Topup", …}

The 24-hex id at the end of url is the transaction. Its /paynow page offers UnionPay + MPGS cards only, no BML Pay, so it's paid by card + 3-D Secure.


Reload record

sub=reload&act=list, {"paymentId"}, nonce from the receipt page — what the receipt page shows:

{"oid":"ET20260006911381","transId":"<BML txn id>","serviceNumber":"7XXXXXX",
 "amountPay":20.00,"amountTopup":18.52,"amountGST":1.48,
 "paidStatus":1,"topupStatus":1,"reloadStatusDesc":"Successful", …}

Not used by Thijooree yet.


Cloudflare

www.dhiraagu.com.mv is behind Cloudflare. The browser capture carries a cf_clearance cookie, but Number Lookup already works from the app with plain okhttp and a browser UA, so these calls are made the same way.


 


Related: Number Lookup · BML Merchant Card Payment · App side: Transfer Flows

← Number Lookup · Bill Pay →