233 lines
6.5 KiB
Markdown
233 lines
6.5 KiB
Markdown
# Account Lookup & Transfer
|
|
|
|
Two-step process: look up the recipient to validate the account and get the holder name, then execute the transfer.
|
|
|
|
All endpoints are on the WebView subdomain. See [README](README.md) for cookie and AJAX header format.
|
|
|
|
```
|
|
Referer: https://faisamobilex-wv.mib.com.mv/transfer/quick
|
|
```
|
|
|
|
---
|
|
|
|
## Step 1 — Account Lookup
|
|
|
|
The lookup endpoint depends on the format of the input:
|
|
|
|
| Input format | Endpoint | Body field |
|
|
|---|---|---|
|
|
| Starts with `7`, exactly 13 digits | `AjaxAlias/getIPSAccount` | `benefAccount` |
|
|
| Starts with `9`, exactly 17 digits | `ajaxBeneficiary/getAccountName` | `accountNo` |
|
|
| Starts with `7` or `9`, exactly 7 digits | `AjaxAlias/getAlias` | `aliasName` |
|
|
| Starts with `A` followed by 6 digits | `AjaxAlias/getAlias` | `aliasName` |
|
|
| Contains `@` (email) | `AjaxAlias/getAlias` | `aliasName` |
|
|
|
|
---
|
|
|
|
### 1a. IPS Account — BML / local bank (13 digits, starts with `7`)
|
|
|
|
```
|
|
POST https://faisamobilex-wv.mib.com.mv/AjaxAlias/getIPSAccount
|
|
```
|
|
|
|
Body: `benefAccount=7700000000000`
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"responseCode": "2",
|
|
"accountName": "ACCOUNT HOLDER NAME",
|
|
"bankBic": "MALBMVMV"
|
|
}
|
|
```
|
|
|
|
- `accountName` — account holder name
|
|
- `bankBic` — bank BIC (e.g. `MALBMVMV` for BML)
|
|
- Account number is the input itself — not returned in response
|
|
|
|
Use `bankNo=3` and `transferLocal` for the transfer.
|
|
|
|
> **USD cross-bank accounts**: `getIPSAccount` only succeeds for **MVR** cross-bank accounts. A 13-digit `7…` account that is denominated in USD returns `success: false` here and cannot be resolved via IPS at all. The client hardcodes `currency = "MVR"` for IPS results (`MibTransferClient.kt:135-137`). For USD BML→MIB transfers the user must first save a BML contact (see Notes below).
|
|
|
|
---
|
|
|
|
### 1b. MIB Internal Account (17 digits, starts with `9`)
|
|
|
|
```
|
|
POST https://faisamobilex-wv.mib.com.mv/ajaxBeneficiary/getAccountName
|
|
```
|
|
|
|
Body: `accountNo=90100000000000000`
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"accountName": "ACCOUNT HOLDER NAME",
|
|
"currencyCode": "462"
|
|
}
|
|
```
|
|
|
|
- `accountName` may be at root level or inside a `data` object — check both (`MibTransferClient.kt:160-161`)
|
|
- `currencyCode` may also be at root level or inside `data` (`MibTransferClient.kt:162-163`). `"462"` = MVR, `"840"` = USD. The client maps this into `MibIpsAccountInfo.currency` ∈ `{"MVR", "USD", ""}` — this is the **MIB→MIB USD detection** fix from commit `16fd909`.
|
|
- Bank is always MIB (`MADVMVMV`)
|
|
|
|
Use `bankNo=2` and `transferInternal` for the transfer.
|
|
|
|
---
|
|
|
|
### 1c. Favara Alias — shortcodes, A-IDs, emails
|
|
|
|
```
|
|
POST https://faisamobilex-wv.mib.com.mv/AjaxAlias/getAlias
|
|
```
|
|
|
|
Body: `aliasName=<alias>`
|
|
|
|
**Response**:
|
|
```json
|
|
{
|
|
"success": true,
|
|
"responseCode": "2",
|
|
"data": {
|
|
"BfyNm": "Account Holder Name",
|
|
"CdtrAcct": {
|
|
"Acct": "90100000000000000",
|
|
"FinInstnId": "MADVMVMV"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
- `BfyNm` — beneficiary name (trim whitespace)
|
|
- `CdtrAcct.Acct` — resolved account number to use for the transfer
|
|
- `CdtrAcct.FinInstnId` — bank BIC (`MADVMVMV` = MIB, `MALBMVMV` = BML)
|
|
|
|
Use `bankNo=2` (MIB) or `3` (BML/local) depending on `FinInstnId`, and the matching transfer endpoint.
|
|
|
|
---
|
|
|
|
### Lookup Errors
|
|
|
|
All three lookup endpoints return `success: false` with a human-readable `reasonText` on failure:
|
|
|
|
```json
|
|
{
|
|
"success": false,
|
|
"reasonText": "Account not found"
|
|
}
|
|
```
|
|
|
|
Always show `reasonText` directly to the user.
|
|
|
|
---
|
|
|
|
## Step 2 — Execute Transfer
|
|
|
|
Two endpoints depending on the destination bank:
|
|
|
|
| `bankNo` | Endpoint | Destination |
|
|
|---|---|---|
|
|
| `2` | `ajaxTransfer/transferInternal` | MIB internal account |
|
|
| `3` | `ajaxTransfer/transferLocal` | BML or other local bank |
|
|
|
|
```
|
|
POST https://faisamobilex-wv.mib.com.mv/ajaxTransfer/transferInternal
|
|
POST https://faisamobilex-wv.mib.com.mv/ajaxTransfer/transferLocal
|
|
```
|
|
|
|
### Request Body (form-urlencoded)
|
|
|
|
| Field | Description |
|
|
|---|---|
|
|
| `benefName` | Recipient name (from lookup) |
|
|
| `benefNo` | `0` (not a saved contact) |
|
|
| `fromAccountNo` | Source account number |
|
|
| `benefAccountNo` | Destination account number |
|
|
| `transferCy` | Currency numeric code (`"462"` = MVR, `"840"` = USD) |
|
|
| `benefCurrencyCode` | Same as `transferCy` |
|
|
| `amount` | Amount as string (e.g. `"100.00"`) |
|
|
| `bankNo` | `2` = MIB internal, `3` = local/BML |
|
|
| `purpose` | Transfer purpose; send `"-"` if blank |
|
|
| `otp` | OTP from the user |
|
|
| `otpType` | `"3"` (SMS/authenticator OTP) |
|
|
|
|
### Response — Success
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"trxId": "TRX20260516001",
|
|
"date": "2026-05-16 15:10:25"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
| Field | Description |
|
|
|---|---|
|
|
| `trxId` | Transaction ID |
|
|
| `date` | Completion timestamp |
|
|
|
|
### Response — Failure
|
|
|
|
```json
|
|
{
|
|
"success": false,
|
|
"reasonText": "Insufficient balance"
|
|
}
|
|
```
|
|
|
|
`reasonText` contains the error reason. On HTTP `419`, the session has expired — re-login required.
|
|
|
|
---
|
|
|
|
## Transfer Type Summary
|
|
|
|
| Recipient | Lookup endpoint | `bankNo` | Transfer endpoint |
|
|
|---|---|---|---|
|
|
| MIB (17-digit `9…`) | `getAccountName` | `2` | `transferInternal` |
|
|
| BML (13-digit `7…`) | `getIPSAccount` | `3` | `transferLocal` |
|
|
| Favara alias → MIB | `getAlias` | `2` | `transferInternal` |
|
|
| Favara alias → BML | `getAlias` | `3` | `transferLocal` |
|
|
|
|
---
|
|
|
|
## Currency Codes
|
|
|
|
| `transferCy` | Currency |
|
|
|---|---|
|
|
| `"462"` | MVR (Maldivian Rufiyaa) |
|
|
| `"840"` | USD |
|
|
|
|
---
|
|
|
|
## `MibIpsAccountInfo` (client model)
|
|
|
|
All three lookups return this unified structure (`MibModels.kt:42-47`):
|
|
|
|
| Field | Description |
|
|
|---|---|
|
|
| `accountName` | Account holder name (trimmed) |
|
|
| `accountNumber` | Resolved account number |
|
|
| `bankId` | Bank BIC (`MADVMVMV` = MIB, `MALBMVMV` = BML, etc.) |
|
|
| `currency` | `"MVR"`, `"USD"`, or `""` (unknown). Populated from `currencyCode` for MIB internal lookups; hardcoded `"MVR"` for IPS lookups; default `""` for alias lookups. |
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- **BML → MIB USD transfers** require a saved BML contact first. Because `getIPSAccount` rejects USD accounts (`success: false`), the app cannot validate the BML USD account number directly. The workaround in `TransferFragment.kt` is to call `MibContactsClient.createContact` (see [09-contacts.md](09-contacts.md)) to auto-add the BML account as a beneficiary, then transfer to that beneficiary. Introduced in commit `16fd909`.
|
|
- **Session expiry**: HTTP `419` on either lookup or transfer means the session expired. See [README](README.md) for the unified expiry detection rules.
|
|
|
|
---
|
|
|
|
|
|
|
|
---
|
|
|
|
[← Personal Profile](07-profile.md) **Next →** [Contacts](09-contacts.md)
|