forked from thijooree/android
176 lines
6.4 KiB
Markdown
176 lines
6.4 KiB
Markdown
# 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](../bmlapi/16-card-payment.md)).
|
||
|
||
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](../bmlapi/16-card-payment.md#7-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](01-number-lookup.md)) |
|
||
| `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.
|
||
|
||
```json
|
||
{"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`.
|
||
|
||
```json
|
||
{"formId":2,"serviceNumber":"7XXXXXX","amount":20,"amountGST":1.48,"amountRecharge":18.52,
|
||
"gstRate":0.08,"memberId":"","memberName":"","memberNId":"","customerId":"","customerCode":"","version":2}
|
||
```
|
||
```json
|
||
{"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](01-number-lookup.md) 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).
|
||
|
||
```json
|
||
[{"merchantId":"98de333c-…","merchantId2":"3f5cf6b7-…","formId":2,"gatewayId":1,
|
||
"gatewayName":"Bank of Maldives", …}, …]
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Payment
|
||
|
||
`sub=payment&act=create`
|
||
|
||
```json
|
||
{"formId":2,"cartId":"<cartId>","gatewayId":1,"dhiraaguPayNumber":"","amount":"20.00",
|
||
"paymentMerchantId":"<BML merchantId>","memberId":"","tokenize":"","paymentType":"",
|
||
"recurringFrequency":"","bmlTokenId":""}
|
||
```
|
||
```json
|
||
{"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):
|
||
|
||
```json
|
||
{"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:
|
||
|
||
```json
|
||
{"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](01-number-lookup.md) already works from the app with plain okhttp and a browser
|
||
UA, so these calls are made the same way.
|
||
|
||
---
|
||
|
||
|
||
|
||
---
|
||
|
||
**Related:** [Number Lookup](01-number-lookup.md) · [BML Merchant Card Payment](../bmlapi/16-card-payment.md) ·
|
||
App side: [Transfer Flows](../thijooree/20-transfer-flows.md#carrier-services-by-bml-card)
|
||
|
||
[← Number Lookup](01-number-lookup.md) · [Bill Pay →](03-bill-pay.md)
|