This commit is contained in:
@@ -211,6 +211,16 @@ GET https://www.bankofmaldives.com.mv/internetbanking/web/profile
|
||||
|
||||
`302` redirect (to `/web/redirect` or similar). The server has auto-activated the sole profile and set the `blaze_identity` cookie. Skip Step 6 and proceed directly to [OAuth Token Exchange](03-oauth-token.md).
|
||||
|
||||
In this fast-path the client has no real `profile_id` to track, so a placeholder `BmlProfile` is synthesized (`BmlLoginFlow.kt:127-135`):
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| `profileId` | `username` (used as a stable temporary ID — replaced by the real customer number after `fetchUserInfo`) |
|
||||
| `name` | `"Personal"` |
|
||||
| `type` | `"Profile"` |
|
||||
| `profileType` | `"default"` |
|
||||
| `autoActivated` | `true` — sentinel; `activateProfile` skips the Step 6 GET and goes straight to OAuth |
|
||||
|
||||
---
|
||||
|
||||
## Step 6 — Activate Profile
|
||||
|
||||
@@ -135,19 +135,21 @@ POST https://www.bankofmaldives.com.mv/internetbanking/oauth/token
|
||||
|
||||
**Content-Type:** `application/x-www-form-urlencoded`
|
||||
|
||||
**HTTP `User-Agent` header**: the browser/web UA (same as the initial token exchange), not the app UA. See `BmlLoginFlow.kt:341`.
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| `grant_type` | `refresh_token` |
|
||||
| `refresh_token` | Stored refresh token |
|
||||
| `client_id` | `98C83590-513F-4716-B02B-EC68B7D9E7E7` |
|
||||
| `Device-ID` | Same device ID from the original login |
|
||||
| `User-Agent` | App user agent string |
|
||||
| `User-Agent` | App user agent string (form field — distinct from the HTTP header above) |
|
||||
| `x-app-version` | `2.1.44.348` |
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url 'https://www.bankofmaldives.com.mv/internetbanking/oauth/token' \
|
||||
--header 'User-Agent: bml-mobile-banking/348 ({manufacturer}; Android {version}; {model})' \
|
||||
--header 'User-Agent: Mozilla/5.0 (Linux; Android {version}; {model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/... Mobile Safari/537.36' \
|
||||
--data 'grant_type=refresh_token' \
|
||||
--data 'refresh_token=def50200aabbcc...' \
|
||||
--data 'client_id=98C83590-513F-4716-B02B-EC68B7D9E7E7' \
|
||||
|
||||
@@ -78,7 +78,7 @@ curl --request GET \
|
||||
"currency": "MVR",
|
||||
"account_status": "Active",
|
||||
"prepaid_card": false,
|
||||
"product_code": "VISA",
|
||||
"product_code": "C1007",
|
||||
"account_visible": false,
|
||||
"cardBalance": {
|
||||
"AvailableLimit": 0.0,
|
||||
@@ -94,7 +94,7 @@ curl --request GET \
|
||||
"currency": "MVR",
|
||||
"account_status": "Active",
|
||||
"prepaid_card": true,
|
||||
"product_code": "VISA",
|
||||
"product_code": "C1007",
|
||||
"account_visible": true,
|
||||
"cardBalance": {
|
||||
"AvailableLimit": 200.00,
|
||||
@@ -164,7 +164,7 @@ curl --request GET \
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `prepaid_card` | `bool` | `true` for prepaid cards |
|
||||
| `product_code` | `string` | Card scheme (e.g. `"VISA"`) |
|
||||
| `product_code` | `string` | BML product code, always `Cxxxx` (e.g. `"C1007"`) — see mapping below |
|
||||
| `account_visible` | `bool` | `true` for credit cards, `false` for debit cards |
|
||||
| `cardBalance.AvailableLimit` | `number` | Available credit/prepaid balance |
|
||||
| `cardBalance.CurrentBalance` | `number` | Current outstanding balance |
|
||||
@@ -179,7 +179,12 @@ curl --request GET \
|
||||
|
||||
### Product Code → Card Name
|
||||
|
||||
The `product_code` field identifies the specific card product. Known mappings:
|
||||
The `product_code` field identifies the specific card product. Resolution is two-tiered (`util/bmlapi/BmlCardParser.kt`):
|
||||
|
||||
1. **Network icon** (Visa / Mastercard / Amex chip in the corner) — by prefix: `C1*` → Visa, `C3*` → Amex, `C8*` → Mastercard, with `C8905` and `C8995` overridden to Visa.
|
||||
2. **Card image asset** — by exact-match list below; unknown codes fall back to `defaultcard.png`.
|
||||
|
||||
Known asset mappings:
|
||||
|
||||
| `product_code` | Card name | Asset |
|
||||
|---|---|---|
|
||||
@@ -202,12 +207,12 @@ The `product_code` field identifies the specific card product. Known mappings:
|
||||
| `C3009`, `C3019`, `C3029`, `C3099`, `C3088`, `C3188` | Amex Credit Gold | `amex_credit_gold` |
|
||||
| `C1001`, `C1011`, `C1082`, `C1081`, `C1101`, `C1111`, `C1181`, `C1182` | Visa Debit Generic | `visa_debit_generic` |
|
||||
| `C1003`, `C1013`, `C1083`, `C1084`, `C1103`, `C1113`, `C1183`, `C1184` | Visa Gold | `visa_gold` |
|
||||
| `C1005`, `C1006`, `C1089` | Visa Debit Islamic | `visa_debit_islamic` |
|
||||
| `C1005`, `C1006`, `C1030`, `C1089` | Visa Debit Islamic | `visa_debit_islamic` |
|
||||
| `C1007`, `C1027`, `C1097`, `C1107`, `C1197`, `C1077`, `C1177` | Visa Debit | `visa_debit` |
|
||||
| `C1009`, `C1019`, `C1085`, `C1086`, `C1109`, `C1119`, `C1185`, `C1186` | Visa Platinum | `visa_platinum` |
|
||||
| `C1017` | Visa Infinite | `visa_infinite` |
|
||||
| `C1020`, `C1021` | Visa Debit Platinum | `visa_debit_platinum` |
|
||||
| `C1030`, `C1090`, `C1130`, `C1033`, `C1133` | Visa Corporate | `visa_corporate` |
|
||||
| `C1090`, `C1130`, `C1033`, `C1133` | Visa Corporate | `visa_corporate` |
|
||||
| `C1040`, `C1041`, `C1047`, `C1048`, `C1050`, `C1051`, `C1087`, `C1088`, `C1140`, `C1141`, `C1147`, `C1148`, `C1150`, `C1151`, `C1187`, `C1188` | Visa Student Black | `visa_student_black` |
|
||||
| `C1059`, `C1062`, `C1070`, `C1072`, `C1159`, `C1162` | Mastercard Prepaid Business | `master_prepaid_business` |
|
||||
| `C1061`, `C1063`, `C1071`, `C1073`, `C1161`, `C1163` | Mastercard | `master` |
|
||||
|
||||
@@ -187,6 +187,76 @@ Fall back to `bookingDate` as-is.
|
||||
|
||||
---
|
||||
|
||||
## Pending History
|
||||
|
||||
Locked / pending amounts for a CASA account (e.g. unsettled card authorisations, holds). Returned as a flat list — no pagination.
|
||||
|
||||
### Endpoint
|
||||
|
||||
```
|
||||
GET https://www.bankofmaldives.com.mv/internetbanking/api/mobile/history/pending/{accountId}
|
||||
```
|
||||
|
||||
| Path parameter | Description |
|
||||
|---|---|
|
||||
| `accountId` | Internal account ID (`id` field from [dashboard](04-dashboard.md)) |
|
||||
|
||||
### Headers
|
||||
|
||||
| Header | Value |
|
||||
|---|---|
|
||||
| `Authorization` | `Bearer <access_token>` |
|
||||
| `User-Agent` | `bml-mobile-banking/348 ({manufacturer}; Android {version}; {model})` |
|
||||
| `x-app-version` | `2.1.44.348` |
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url 'https://www.bankofmaldives.com.mv/internetbanking/api/mobile/history/pending/abc123def456' \
|
||||
--header 'Authorization: Bearer <access_token>' \
|
||||
--header 'User-Agent: bml-mobile-banking/348 ({manufacturer}; Android {version}; {model})' \
|
||||
--header 'x-app-version: 2.1.44.348'
|
||||
```
|
||||
|
||||
### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"payload": [
|
||||
{
|
||||
"LockedID": "L00012345",
|
||||
"FromDate": "2026-05-16",
|
||||
"LockedAmount": 75.00,
|
||||
"Description": "Card authorisation — Merchant Name"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `success` | `bool` | `true` on success |
|
||||
| `payload` | `array` | List of pending entries (top-level array, **not** under `payload.history`) |
|
||||
|
||||
### Pending Entry
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `LockedID` | `string` | Unique ID for the pending entry |
|
||||
| `FromDate` | `string` | Date the hold was placed |
|
||||
| `LockedAmount` | `number` | Held amount — always a positive number on the wire; the client treats it as a **debit** by negating (`BmlHistoryClient.kt:184`) |
|
||||
| `Description` | `string` | Free-form description (counterparty/merchant) |
|
||||
|
||||
> **Amount sign:** the server returns `LockedAmount` as a positive number with no debit/credit indicator. All pending entries are debits (funds reserved out of the available balance), so the client negates the value before display.
|
||||
|
||||
> **Currency:** not returned by the server. The client assumes MVR.
|
||||
|
||||
Called from `AccountHistoryFragment.kt:263` to populate the pending tab of the account history view.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -224,7 +224,14 @@ curl --request POST \
|
||||
}
|
||||
```
|
||||
|
||||
`success: false` — the `message` field contains the reason. Common causes: wrong OTP, insufficient balance, invalid account.
|
||||
`success: false` — the error text may appear in either of two fields. The client prefers `payload` (when it is a non-blank string and not `"null"`) and falls back to `message` (`BmlTransferClient.kt:86-88`):
|
||||
|
||||
| Field | When used |
|
||||
|---|---|
|
||||
| `payload` (string) | Validation-style errors — e.g. insufficient balance, account-specific failures |
|
||||
| `message` | Generic errors — e.g. invalid OTP, generic transfer failure |
|
||||
|
||||
Common causes: wrong OTP, insufficient balance, invalid account, currency mismatch.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -148,6 +148,10 @@ curl --request GET \
|
||||
| `name` | `string` | Account holder name |
|
||||
| `agnt` | `string` | BIC of MIB — send as the `bank` field in the [transfer](08-transfer.md) request |
|
||||
|
||||
> **Client-synthesized fields**: when the app wraps this response for downstream code (`BmlValidateClient.kt:68`), it sets `trnType = "DOT"` and `validationType = "MIB"`. Neither is returned by the server.
|
||||
>
|
||||
> **No currency**: this endpoint does NOT return the MIB account's currency. The client sets `currency = ""` (`BmlValidateClient.kt:74-75`). Important for USD-vs-MVR transfer routing — currency must be sourced elsewhere (e.g. MIB's own lookup, see [MIB transfer docs](../mibapi/08-transfer.md)).
|
||||
|
||||
### Failure
|
||||
|
||||
```json
|
||||
|
||||
@@ -77,6 +77,16 @@ Expected response: `{ "code": 0, "payload": [...] }`
|
||||
|
||||
The OTP is a standard TOTP (RFC 6238, SHA-1, 30-second window, 6 digits) derived from the stored BML authenticator seed.
|
||||
|
||||
### Failure Handling
|
||||
|
||||
Each of the three POSTs validates the server's `code` field and throws on mismatch (`BmlTapToPayClient.kt:37, 42, 47`). The exception message is the server's `message` field:
|
||||
|
||||
| Step | Expected code | Throws if |
|
||||
|---|---|---|
|
||||
| 1a | `0` (rare) or `99` | code is neither — `message` propagated |
|
||||
| 1b | `22` | code is not `22` — `message` propagated |
|
||||
| 1c | `0` | code is not `0` — `message` propagated |
|
||||
|
||||
### Token Response
|
||||
|
||||
```json
|
||||
@@ -239,6 +249,33 @@ All APDU responses use BER-TLV encoding. Tags are 1 or 2 bytes (hex string). Len
|
||||
|
||||
---
|
||||
|
||||
## Lifecycle
|
||||
|
||||
The HCE service (`BmlHostCardEmulatorService`) keeps a single active `BmlWalletToken` in a volatile companion-object field. Tokens are single-use — exactly one tap consumes one token.
|
||||
|
||||
### Companion API
|
||||
|
||||
```kotlin
|
||||
BmlHostCardEmulatorService.setToken(token: BmlWalletToken)
|
||||
BmlHostCardEmulatorService.clearToken()
|
||||
BmlHostCardEmulatorService.onTransactionComplete: (success: Boolean) -> Unit
|
||||
```
|
||||
|
||||
| Call | When |
|
||||
|---|---|
|
||||
| `setToken(token)` | After fetching a token, before prompting the user to tap |
|
||||
| `clearToken()` | After the tap completes, when the prompt is dismissed, or on error |
|
||||
| `onTransactionComplete(true)` | Fired immediately after the `READ RECORD` response (`BmlHostCardEmulatorService.kt:78`) |
|
||||
| `onTransactionComplete(false)` | Fired from `onDeactivated` if GPO was never seen (`BmlHostCardEmulatorService.kt:35-38`) — i.e. the reader walked away before completing the EMV exchange |
|
||||
|
||||
### State Rules
|
||||
|
||||
- A token MUST be installed via `setToken` before the user taps. With no active token, `SELECT PPSE` launches `BmlTapToPayActivity` (a redirector to `MainActivity`) and returns `6F00`.
|
||||
- The service tracks `gpoSent` to distinguish "user pulled the phone away" from a successful read. A successful `handleReadRecord` resets `gpoSent` to `false` via `onDeactivated` after the success callback has already fired.
|
||||
- `BmlTapToPayActivity` provides the "Tap your phone…" prompt UI. The activity is responsible for calling `setToken` before showing the prompt and `clearToken` when dismissed.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Valid `access_token` from [OAuth Token Exchange](03-oauth-token.md)
|
||||
|
||||
@@ -150,7 +150,7 @@ POST https://www.bankofmaldives.com.mv/internetbanking/api/mobile/walletpayments
|
||||
|
||||
Expected response: `{ "success": true, "code": 99 }` (OTP required)
|
||||
|
||||
> **Note:** This step may be skipped. The app proceeds directly to Step 2b if the gateway already indicates OTP is required.
|
||||
> **When this step is used:** the client only calls `preInitiatePayment` for **gateway QRs** — QR URLs that begin with `https://pay.bml.com.mv/app/` (`TransferFragment.kt:349, 1419-1423`). For PayMV-native static QRs (`QRS`), Step 2a is skipped and the flow starts at Step 2b.
|
||||
|
||||
### Step 2b — Request OTP Channel
|
||||
|
||||
@@ -195,6 +195,8 @@ Expected response:
|
||||
}
|
||||
```
|
||||
|
||||
> **Currency fallback:** if the server's `payload.currency` is blank, the client falls back to the `currency` value sent in the request (`BmlQrPayClient.kt:148`). The same applies to `merchant` and `amount` at the UI layer.
|
||||
|
||||
On failure:
|
||||
|
||||
```json
|
||||
@@ -240,4 +242,4 @@ The OTP is a standard TOTP (RFC 6238, SHA-1, 30-second window, 6 digits) derived
|
||||
|
||||
---
|
||||
|
||||
[← Tap-to-Pay](12-tap-to-pay.md)
|
||||
[← Tap-to-Pay](12-tap-to-pay.md) **Next →** [Notifications](14-notifications.md)
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
# Notifications
|
||||
|
||||
In-app notifications (transaction alerts, security events, marketing) are served from a separate host. Notifications are fetched in pages and can be bulk-marked as read.
|
||||
|
||||
The polling service runs in the background and posts an Android system notification for each unseen item (`service/NotificationPollingService.kt:64`).
|
||||
|
||||
---
|
||||
|
||||
## Base URL
|
||||
|
||||
```
|
||||
https://app.bankofmaldives.com.mv/api/v2
|
||||
```
|
||||
|
||||
Distinct from the main `internetbanking/api/mobile` host, but uses the same Bearer token.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Valid `access_token` from [OAuth Token Exchange](03-oauth-token.md)
|
||||
|
||||
---
|
||||
|
||||
## Fetch Notifications
|
||||
|
||||
```
|
||||
GET https://app.bankofmaldives.com.mv/api/v2/notifications?group={group}&page={page}
|
||||
```
|
||||
|
||||
### Query Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|---|---|---|
|
||||
| `group` | `string` | Filter by group — `ALL` (default), or a specific group (e.g. `ALERTS`) |
|
||||
| `page` | `int` | 1-based page number |
|
||||
|
||||
### Headers
|
||||
|
||||
| Header | Value |
|
||||
|---|---|
|
||||
| `Authorization` | `Bearer <access_token>` |
|
||||
| `User-Agent` | `bml-mobile-banking/348 ({manufacturer}; Android {version}; {model})` |
|
||||
| `x-app-version` | `2.1.44.348` |
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url 'https://app.bankofmaldives.com.mv/api/v2/notifications?group=ALL&page=1' \
|
||||
--header 'Authorization: Bearer <access_token>' \
|
||||
--header 'User-Agent: bml-mobile-banking/348 ({manufacturer}; Android {version}; {model})' \
|
||||
--header 'x-app-version: 2.1.44.348'
|
||||
```
|
||||
|
||||
### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"total": 137,
|
||||
"payload": [
|
||||
{
|
||||
"id": "abc123",
|
||||
"group": "ALERTS",
|
||||
"type": "TRANSACTION",
|
||||
"title": "Transaction Alert",
|
||||
"message": "MVR 100.00 debited from 7730000000001",
|
||||
"created_at": "2026-05-16T15:10:25",
|
||||
"is_read": false,
|
||||
"data": {
|
||||
"account_number": "7730000000001",
|
||||
"amount": "100.00",
|
||||
"currency": "MVR",
|
||||
"reference": "FT20260516123456"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Top-level Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `success` | `bool` | `true` on success |
|
||||
| `total` | `int` | Total notification count across all pages |
|
||||
| `payload` | `array` | List of notifications for this page |
|
||||
|
||||
### Notification Object
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `id` | `string` | Unique notification ID |
|
||||
| `group` | `string` | Logical grouping (e.g. `ALERTS`) — also the value passed back to the `group` filter |
|
||||
| `type` | `string` | Sub-type within the group (e.g. `TRANSACTION`) |
|
||||
| `title` | `string` | Short headline |
|
||||
| `message` | `string` | Body text |
|
||||
| `created_at` | `string` | Timestamp — `yyyy-MM-dd'T'HH:mm:ss` (no timezone) |
|
||||
| `is_read` | `bool` | Read state |
|
||||
| `data` | `object?` | Optional structured detail payload — fields vary by type |
|
||||
|
||||
### `data` Field Flattening
|
||||
|
||||
Where present, the `data` object is flattened into the notification's detail view as key-value rows. The client transforms each `data` key with underscore → space and title-case (`BmlNotificationsClient.kt:93-94`):
|
||||
|
||||
```
|
||||
"account_number" → "Account Number"
|
||||
"reference" → "Reference"
|
||||
```
|
||||
|
||||
Three synthetic rows are prepended:
|
||||
|
||||
| Row | Value |
|
||||
|---|---|
|
||||
| `Bank` | `BML` |
|
||||
| `Group` | from `group` field |
|
||||
| `Type` | from `type` field |
|
||||
|
||||
---
|
||||
|
||||
## Mark All Read
|
||||
|
||||
```
|
||||
PUT https://app.bankofmaldives.com.mv/api/v2/notifications/read
|
||||
```
|
||||
|
||||
### Headers
|
||||
|
||||
| Header | Value |
|
||||
|---|---|
|
||||
| `Authorization` | `Bearer <access_token>` |
|
||||
| `User-Agent` | `bml-mobile-banking/348 ({manufacturer}; Android {version}; {model})` |
|
||||
| `x-app-version` | `2.1.44.348` |
|
||||
| `accept` | `application/json` |
|
||||
| `Content-Type` | `application/json` |
|
||||
|
||||
### Request Body
|
||||
|
||||
```json
|
||||
{
|
||||
"all": true
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
curl --request PUT \
|
||||
--url 'https://app.bankofmaldives.com.mv/api/v2/notifications/read' \
|
||||
--header 'Authorization: Bearer <access_token>' \
|
||||
--header 'User-Agent: bml-mobile-banking/348 ({manufacturer}; Android {version}; {model})' \
|
||||
--header 'x-app-version: 2.1.44.348' \
|
||||
--header 'accept: application/json' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{"all":true}'
|
||||
```
|
||||
|
||||
### Response
|
||||
|
||||
The client treats any 2xx response as success — the response body is discarded.
|
||||
|
||||
---
|
||||
|
||||
## Polling
|
||||
|
||||
`service/NotificationPollingService.kt:64` polls page 1 of every active BML session at a fixed interval, diffs the result against a local cache, and posts an Android system notification for each new item.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
[← QR Payment](13-qr-payment.md) **Next →** [Card Freeze](15-card-freeze.md)
|
||||
@@ -0,0 +1,121 @@
|
||||
# Card Freeze / Unfreeze
|
||||
|
||||
Lock or unlock a BML card to block / allow new authorisations. The same endpoint handles both actions, distinguished by the `action` field.
|
||||
|
||||
---
|
||||
|
||||
## Endpoint
|
||||
|
||||
```
|
||||
POST https://www.bankofmaldives.com.mv/internetbanking/api/mobile/services/card/freeze
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Valid `access_token` from [OAuth Token Exchange](03-oauth-token.md)
|
||||
- `cardId` is the **internal card UUID** (`BankAccount.internalId`, sourced from the `id` field of a `Card` entry in the [dashboard](04-dashboard.md) response) — NOT the displayed 16-digit card number
|
||||
|
||||
---
|
||||
|
||||
## Request
|
||||
|
||||
### Body
|
||||
|
||||
**Content-Type:** `application/json`
|
||||
|
||||
```json
|
||||
{
|
||||
"card": "<internalId>",
|
||||
"action": "freeze"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Notes |
|
||||
|---|---|---|
|
||||
| `card` | `string` | Internal card UUID — the `id` from the dashboard Card object |
|
||||
| `action` | `string` | `"freeze"` to lock the card; `"unfreeze"` to unlock |
|
||||
|
||||
### Headers
|
||||
|
||||
| Header | Value |
|
||||
|---|---|
|
||||
| `Authorization` | `Bearer <access_token>` |
|
||||
| `User-Agent` | `bml-mobile-banking/348 ({manufacturer}; Android {version}; {model})` |
|
||||
| `x-app-version` | `2.1.44.348` |
|
||||
| `accept` | `application/json` |
|
||||
| `Content-Type` | `application/json` |
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url 'https://www.bankofmaldives.com.mv/internetbanking/api/mobile/services/card/freeze' \
|
||||
--header 'Authorization: Bearer <access_token>' \
|
||||
--header 'User-Agent: bml-mobile-banking/348 ({manufacturer}; Android {version}; {model})' \
|
||||
--header 'x-app-version: 2.1.44.348' \
|
||||
--header 'accept: application/json' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{"card":"abc-123-def-456","action":"freeze"}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Response
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"code": 0,
|
||||
"payload": "Card frozen successfully",
|
||||
"message": ""
|
||||
}
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `success` | `bool` | `true` on success |
|
||||
| `code` | `int` | `0` on success; non-zero indicates an error |
|
||||
| `payload` | `string` | Human-readable confirmation text (may be blank) |
|
||||
| `message` | `string` | Fallback error/info text |
|
||||
|
||||
Success is determined by **both** `success == true` AND `code == 0` (`BmlCardClient.kt:46`). Either condition alone is not enough.
|
||||
|
||||
### Display Message
|
||||
|
||||
The client prefers `payload` for the confirmation text and falls back to `message` when `payload` is blank (`BmlCardClient.kt:49`):
|
||||
|
||||
```
|
||||
payload (if non-blank) → fallback message
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Failure
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"code": 1,
|
||||
"payload": "",
|
||||
"message": "Card cannot be frozen at this time"
|
||||
}
|
||||
```
|
||||
|
||||
Returned with HTTP `200` for application-level errors. The `message` (or `payload`) field contains the reason.
|
||||
|
||||
### Server / Auth Errors
|
||||
|
||||
| HTTP Code | Behaviour |
|
||||
|---|---|
|
||||
| `401` / `419` | Throws `AuthExpiredException` — refresh the token or re-login |
|
||||
| `5xx` | Throws `BankServerException("BML")` — server-side failure, retry |
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
[← Notifications](14-notifications.md)
|
||||
@@ -25,6 +25,7 @@ The login process is stateful and must be executed in order:
|
||||
| Web login / OAuth | `https://www.bankofmaldives.com.mv/internetbanking` |
|
||||
| REST API (authenticated) | `https://www.bankofmaldives.com.mv/internetbanking/api/mobile` |
|
||||
| Foreign limits API | `https://app.bankofmaldives.com.mv/api/v2` |
|
||||
| Notifications API | `https://app.bankofmaldives.com.mv/api/v2` |
|
||||
|
||||
---
|
||||
|
||||
@@ -190,6 +191,8 @@ The access token expires after `expires_in` seconds (typically 3600). On a `401`
|
||||
| 11 | [Foreign Limits](11-foreign-limits.md) | USD foreign transaction limits by card and channel |
|
||||
| 12 | [Tap-to-Pay](12-tap-to-pay.md) | NFC HCE contactless payment — token fetch and EMV APDU exchange |
|
||||
| 13 | [QR Payment](13-qr-payment.md) | PayMV QR payment — QR formats, payrequest lookup, 3-step pay flow |
|
||||
| 14 | [Notifications](14-notifications.md) | Notifications list, mark-as-read, and polling |
|
||||
| 15 | [Card Freeze](15-card-freeze.md) | Freeze / unfreeze a BML card |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user