forked from thijooree/android
update docs
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Transfer
|
||||
|
||||
The transfer screen initiates account-to-account fund transfers. It supports MIB, BML, and Fahipay as source banks and handles all bank-specific authentication and OTP steps.
|
||||
The transfer screen initiates account-to-account fund transfers and phone payments. It supports MIB, BML, Fahipay and M-Faisa as sources and handles all bank-specific authentication and OTP steps. A phone number can also be paid as a carrier service (reload, Raastas, bill pay) from the Fahipay wallet or, for Dhiraagu Reload, a verified BML card.
|
||||
|
||||
---
|
||||
|
||||
@@ -38,11 +38,12 @@ A dropdown lists all visible accounts parsed via `AccountListParser.from(acc)?.b
|
||||
|
||||
## Recipient Entry
|
||||
|
||||
The user can specify a recipient in three ways:
|
||||
The user can specify a recipient in these ways:
|
||||
|
||||
1. **Manual entry** — type an account number directly
|
||||
2. **Contact picker** — opens `ContactPickerSheetFragment` to select a saved contact
|
||||
1. **Manual entry** — type an account number or phone number directly
|
||||
2. **Contact picker** — opens `ContactPickerSheetFragment` to select a saved contact. A Fahipay favourite opens as its payout service straight away
|
||||
3. **QR scan** — launches [QrScannerActivity](25-qr-scanner.md); a PayMV QR result pre-fills the account number, amount, and remarks; a BML ebanking / pay.bml URL switches the form into [BML QR merchant payment](20-transfer-flows.md#bml-qr-merchant-payment-flow) mode
|
||||
4. **BML Merchant Services transaction ID or link** — paid through BML Pay (QR flow) or, for card-only merchants, a verified card ([Card Verification & Merchant Card Pay](29-card-verification-and-merchant-card-pay.md))
|
||||
|
||||
---
|
||||
|
||||
@@ -64,10 +65,22 @@ After the user finishes entering a recipient account number, the app calls the s
|
||||
|
||||
- **MIB**: account name lookup via MIB API
|
||||
- **BML**: beneficiary lookup via BML API
|
||||
- **Fahipay**: account name resolution via Fahipay API
|
||||
- **Fahipay**: phone numbers only — the Dhiraagu / Ooredoo carrier lookup decides which payout services apply
|
||||
|
||||
The resolved name is displayed below the account number field for the user to confirm.
|
||||
|
||||
### Phone numbers — Transfer Type picker
|
||||
|
||||
A phone number searched with no source yet (or from a BML card that can pay by card) is looked up every way it can be paid, in parallel: Favara (MIB / BML), and the carrier lookup when the user has a Fahipay wallet or a verified BML card. Each result is a **transfer type**:
|
||||
|
||||
| Type | Example | Pays from |
|
||||
|---|---|---|
|
||||
| Favara Transfer | bank account behind the number | MIB or BML account |
|
||||
| Fahipay service | Raastas, Ooredoo Bill Pay, Dhiraagu Reload, Dhiraagu Bill Pay | Fahipay wallet |
|
||||
| Card service | Dhiraagu Reload (BML badge) | Verified BML card |
|
||||
|
||||
One option is applied straight away; with more, a picker opens and Send stays disabled until one is chosen. Picking a type also picks a source that can pay it. Fahipay and card services clear and disable the Remarks field and apply their own amount rules (minimum, maximum, whole amounts, 8% GST note). Details: [Transfer Flows → Transfer Type picker](20-transfer-flows.md#transfer-type-picker).
|
||||
|
||||
---
|
||||
|
||||
## Biometric Gate
|
||||
@@ -100,18 +113,33 @@ When the source is a BML USD account and the destination is a MIB account but no
|
||||
5. Re-submits with OTP
|
||||
6. On success, shows `TransferReceiptFragment`
|
||||
|
||||
### Fahipay Transfer
|
||||
### Fahipay Payout (reload, Raastas, bill pay)
|
||||
|
||||
1. Validates fields
|
||||
2. (If biometric gate) prompts biometrics
|
||||
3. Submits via Fahipay API using stored `authID` + session cookie
|
||||
4. On success, shows `TransferReceiptFragment`
|
||||
1. Checks the amount against the picked service's rules
|
||||
2. Confirm dialog (with the GST note for Raastas), then the biometric gate if enabled
|
||||
3. One POST to the service's Fahipay payment endpoint ([Fahipay API → Payments](../fahipayapi/09-payments.md))
|
||||
4. On success, the result shows inside the dialog (no receipt page yet), then the form clears
|
||||
|
||||
See [Transfer Flows → Fahipay source](20-transfer-flows.md#fahipay-source).
|
||||
|
||||
### Carrier Service by BML Card (Dhiraagu Reload)
|
||||
|
||||
1. Checks the amount against Dhiraagu's rules (MVR 20–1000, whole amounts, 8% GST included)
|
||||
2. A "Processing..." dialog shows while Dhiraagu creates the order and its BML merchant transaction ([Dhiraagu API → Reload](../dhiraaguapi/02-reload.md))
|
||||
3. From there it is the card-only merchant flow: the same confirm dialog and warning, biometric gate, card + 3-D Secure payment, and the return to Dhiraagu (`?wait=1`) that tops the number up
|
||||
4. On success, the result shows inside the dialog; if Dhiraagu couldn't be notified, a toast gives the BML transaction id
|
||||
|
||||
See [Transfer Flows → Carrier services by BML card](20-transfer-flows.md#carrier-services-by-bml-card).
|
||||
|
||||
### BML Merchant Payment (QR / card-only link)
|
||||
|
||||
A BML QR, or a BML Merchant Services link whose merchant takes BML Pay, is paid from a BML card through the QR flow. A card-only merchant link is paid with a verified card (Pomelo + 3-D Secure), followed by the return to the merchant. Neither saves a receipt. See [Transfer Flows → BML QR Merchant Payment Flow](20-transfer-flows.md#bml-qr-merchant-payment-flow) and [Card Verification & Merchant Card Pay](29-card-verification-and-merchant-card-pay.md).
|
||||
|
||||
---
|
||||
|
||||
## Transfer Receipt
|
||||
|
||||
On success the fragment navigates to `TransferReceiptFragment` passing the completed transfer details.
|
||||
On success of a bank transfer (MIB, BML, M-Faisa) the fragment navigates to `TransferReceiptFragment` passing the completed transfer details. Fahipay payouts, card services and merchant payments show their result inside the confirm dialog instead.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -49,11 +49,13 @@ Each option is a `TransferType` (`ui/home/transfer/TransferType.kt`):
|
||||
|---|---|---|---|
|
||||
| `Favara(info)` | Favara Transfer | `favara_logo` | MIB or BML account |
|
||||
| `Fahipay(service, ownerName)` | the service's label, e.g. Raastas | `FahipayService.iconRes`: `ooredoo_logo` / `dhiraagu_logo` | Fahipay wallet |
|
||||
| `Card(service, ownerName, cards)` | the service's label, e.g. Dhiraagu Reload | `CardPayoutService.iconRes`, with a BML badge | One of `cards`: verified BML cards that can pay by card (see [Carrier services by BML card](#carrier-services-by-bml-card)) |
|
||||
|
||||
Picking an option also picks the source (`TransferFragment.applyTransferType`). If the selected source can't pay that type, Thijooree switches it:
|
||||
|
||||
- **Favara:** the default account, if it's MIB or BML. Otherwise the source is cleared and the user is asked to pick one.
|
||||
- **Fahipay:** the user's Fahipay wallet.
|
||||
- **Card:** the default card, if it's one of the type's cards. Otherwise the first of them.
|
||||
|
||||
Then the recipient card is filled in. The options, the number they were looked up for and the pick are kept in `TransferDraft`. If the view is recreated while the popup is still unanswered, it opens again.
|
||||
|
||||
@@ -64,9 +66,11 @@ The options are dropped when the "To" number is edited, the recipient is cleared
|
||||
Two lookups run in parallel:
|
||||
|
||||
- **Favara / IPS lookup.** Uses any logged-in MIB or BML session. The default account's bank goes first, the other is the fallback.
|
||||
- **Carrier lookup** (see Fahipay source below). Only runs when the user has a Fahipay wallet.
|
||||
- **Carrier lookup** (`CarrierLookup.query`, see Fahipay source below). Only runs when the user has a Fahipay wallet or a BML card that can pay by card. One lookup feeds both.
|
||||
|
||||
Everything that resolves is offered as a transfer type. Favara comes first, then the Fahipay services. If nothing resolves, the Favara lookup's error is shown as a toast.
|
||||
Everything that resolves is offered as a transfer type. Favara comes first, then the Fahipay services, then the card services.
|
||||
|
||||
The same lookup runs when the source is already a BML card that can pay by card and a phone number is searched. If nothing resolves, the Favara lookup's error is shown as a toast.
|
||||
|
||||
Any other input with no source selected falls back to the default account as the source, and then the normal lookup for that bank runs.
|
||||
|
||||
@@ -144,6 +148,49 @@ When the amount breaks a rule, the error replaces the helper text.
|
||||
|
||||
None of the Fahipay services take a reference. Picking one clears the Reference field and disables it, the same way BML merchant QR payments do. Clearing the service turns the field back on.
|
||||
|
||||
### Carrier services by BML card
|
||||
|
||||
A carrier service can also be paid with a verified BML card, through the carrier's own website
|
||||
and its BML merchant gateway, instead of the Fahipay wallet. Only **Dhiraagu Reload** so far
|
||||
(`CardPayoutService`, `ui/home/transfer/CardPayoutTransferHandler.kt`).
|
||||
|
||||
**Which cards.** A card qualifies when it's verified and its BML login has an OTP seed, the same
|
||||
rule as card-only merchant links (`BmlVerifiedCards`, see
|
||||
[Card Verification & Merchant Card Pay](29-card-verification-and-merchant-card-pay.md)). The
|
||||
type remembers those cards (`TransferType.Card.cards`). Picking a card that isn't one of them
|
||||
drops the pick, like any other source that can't pay the picked type.
|
||||
|
||||
**Which services.**
|
||||
|
||||
| Carrier result | Service |
|
||||
|---|---|
|
||||
| Dhiraagu `RELOAD` | Dhiraagu Reload |
|
||||
|
||||
**Amount rules.** The carrier website's, not Fahipay's. They're checked the same way, through
|
||||
the shared `PayoutAmountField`:
|
||||
|
||||
| Service | Min (MVR) | Max (MVR) | Decimals | GST |
|
||||
|---|---|---|---|---|
|
||||
| Dhiraagu Reload | 20 | 1,000 | no | 8%, included (credit = amount − round2(amount × 0.08 / 1.08)) |
|
||||
|
||||
**Reference.** None. The field is cleared and disabled, as for the Fahipay services.
|
||||
|
||||
**Sending.** The only part that differs from paying a card-only BML merchant link is where the
|
||||
BML transaction comes from:
|
||||
|
||||
1. `CardPayoutTransferHandler.submit()` has the carrier create it for the number and amount
|
||||
(`DhiraaguReloadClient.createBmlTransaction`, see [Dhiraagu API → Reload](../dhiraaguapi/02-reload.md)).
|
||||
That takes a few round trips, so the payment's "Processing..." box shows meanwhile
|
||||
(`TransferFragment.showProcessingDialog`) and closes before the confirm dialog opens.
|
||||
2. Its payment page is loaded (`BmlMerchantTxnClient.fetchPayPage`). If it doesn't take cards, or
|
||||
its amount isn't the one typed, the payment stops with a toast.
|
||||
3. The page goes to `BmlTransferHandler.confirmCardMerchant`, so from here it's the merchant-link
|
||||
card flow: the same confirm dialog and warning, biometric gate, Pomelo + 3-D Secure payment,
|
||||
and success / failure handling.
|
||||
|
||||
Nothing is charged before the confirm dialog. A cancelled confirm leaves an unpaid Dhiraagu order,
|
||||
which expires on its own.
|
||||
|
||||
### BML source
|
||||
|
||||
1. If the input type is `MIB_ACCOUNT`, calls `BmlValidateClient.verifyMibAccount()`.
|
||||
@@ -208,6 +255,13 @@ Source: Fahipay
|
||||
FAHIPAY_TRANSFER, RAASTAS, OOREDOO_BILL, DHIRAAGU_RELOAD, DHIRAAGU_BILL
|
||||
```
|
||||
|
||||
```
|
||||
Transfer type: Card (verified BML card)
|
||||
|
||||
└── Carrier creates a BML merchant transaction → card-only merchant flow
|
||||
DHIRAAGU_RELOAD
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rejected Combinations
|
||||
@@ -336,6 +390,7 @@ The transfer button is only enabled when all of the following are true:
|
||||
- Amount is greater than `0`
|
||||
- If transfer types are on offer, one has been picked
|
||||
- For a Fahipay service, the amount meets that service's rules (see [Amount rules](#amount-rules))
|
||||
- For a carrier service by card, the amount meets that service's rules (see [Carrier services by BML card](#carrier-services-by-bml-card))
|
||||
- No connectivity error for `NO_INTERNET` or for the source bank
|
||||
|
||||
---
|
||||
|
||||
@@ -7,7 +7,9 @@ Two linked features:
|
||||
full card details (PAN, expiry, CVV) encrypted on-device.
|
||||
2. **Merchant card payment** — on [Transfer](07-transfer.md), a BML Merchant Services transaction ID
|
||||
whose merchant has **no BML Pay** is paid with a verified card via the Pomelo + 3-D Secure flow
|
||||
([BML API → Merchant Card Payment](../bmlapi/16-card-payment.md)).
|
||||
([BML API → Merchant Card Payment](../bmlapi/16-card-payment.md)). The same flow pays
|
||||
[carrier services by BML card](20-transfer-flows.md#carrier-services-by-bml-card) (Dhiraagu
|
||||
Reload), once the carrier has created the transaction.
|
||||
|
||||
> ⚠️ The merchant card flow is scraped browser/ACS traffic, not a stable API. Storing the CVV is a
|
||||
> security/PCI liability. See the API doc's
|
||||
@@ -106,23 +108,28 @@ into the Transfer screen rather than a one-off dialog, mirroring the BML QR merc
|
||||
and empties the amount and re-enables remarks.
|
||||
|
||||
A card is only offered when it is **both** verified **and** belongs to a BML login the app has an
|
||||
OTP seed for (`verifiedCardCandidates`, `:428`; `isCardVerified`, `:463`) — the 3-D Secure step
|
||||
needs that seed.
|
||||
OTP seed for (`BmlVerifiedCards.payable` / `isPayable`, `ui/home/transfer/BmlVerifiedCards.kt`) —
|
||||
the 3-D Secure step needs that seed.
|
||||
|
||||
### Send
|
||||
|
||||
`submitCardPayment` (`:496`) → `confirmCardMerchant` (`:506`) shows the shared transfer confirm
|
||||
dialog (biometric-gated), then `executeCardMerchant` (`:534`) runs, off the main thread:
|
||||
`submitCardPayment` → `confirmCardMerchant` shows the shared transfer confirm dialog
|
||||
(biometric-gated), then `executeCardMerchant` runs, off the main thread.
|
||||
`CardPayoutTransferHandler` calls `confirmCardMerchant` directly with the page of the
|
||||
transaction a carrier created:
|
||||
|
||||
```
|
||||
BmlMerchantCardPayClient().pay(page, card) { Totp.generate(otpSeed) }
|
||||
```
|
||||
|
||||
where `card` comes from `VerifiedCardStore` (expiry split `MM/YY` → month/year) and `otpSeed` is the
|
||||
card's BML login seed. The client (`api/bml/BmlMerchantCardPayClient.kt`) performs the whole
|
||||
where `card` and `otpSeed` come from `BmlVerifiedCards.load` — the `VerifiedCardStore` entry
|
||||
(expiry split `MM/YY` → month/year) and the card's BML login seed. The client (`api/bml/BmlMerchantCardPayClient.kt`) performs the whole
|
||||
Pomelo + MPGS + Wibmo 3-D Secure sequence — feeding the BML token TOTP into the ACS OTP form
|
||||
automatically, retrying once if the first code expired. Outcome is shown in the shared
|
||||
processing/success dialog; failures surface as a toast.
|
||||
automatically, retrying once if the first code expired. Once BML confirms, it loads
|
||||
`<id>?wait=1` and follows the redirects to the merchant, which is how the merchant learns it was
|
||||
paid (Dhiraagu doesn't top up without it). Outcome is shown in the shared processing/success
|
||||
dialog; failures surface as a toast. If the merchant couldn't be reached, success also toasts
|
||||
the merchant name and BML transaction id (`bml_card_pay_merchant_not_notified`).
|
||||
|
||||
### Key assumption
|
||||
|
||||
@@ -145,6 +152,8 @@ another login/person, or a card whose 3-D Secure only offers SMS/email OTP.
|
||||
| `api/bml/BmlMerchantTxnClient.kt` | `fetchPayPage` (merchant-type detection), `announceBrowser`, QR payload |
|
||||
| `api/bml/BmlMerchantCardPayClient.kt` | Pomelo tokenise + 3-D Secure card payment |
|
||||
| `ui/home/transfer/BmlTransferHandler.kt` | On-screen card merchant mode + payment |
|
||||
| `ui/home/transfer/BmlVerifiedCards.kt` | Which cards can pay by card; loads their details |
|
||||
| `ui/home/transfer/CardPayoutTransferHandler.kt` | Carrier services by card: carrier creates the transaction, then `confirmCardMerchant` |
|
||||
| `ui/home/TransferFragment.kt` | Transaction-ID lookup + routing |
|
||||
|
||||
---
|
||||
|
||||
@@ -15,7 +15,7 @@ Documentation for app-specific logic — UI flows, routing decisions, and busine
|
||||
| [04 — Accounts](04-accounts.md) | Account list grouped display, AccountsAdapter, profile images, quick-transfer shortcut |
|
||||
| [05 — Account History](05-account-history.md) | Paginated transaction history, search, infinite scroll |
|
||||
| [06 — Transfer History](06-transfer-history.md) | Multi-bank merged transfer history, parallel loading |
|
||||
| [07 — Transfer](07-transfer.md) | Recipient lookup, MIB/BML/Fahipay transfer flows, QR, biometric gate, BML OTP |
|
||||
| [07 — Transfer](07-transfer.md) | Recipient lookup, transfer type picker, MIB/BML/Fahipay transfers, Fahipay payouts, Dhiraagu Reload by BML card, QR, biometric gate, BML OTP |
|
||||
| [08 — Contacts](08-contacts.md) | Contact list, add/edit/delete, categories, contact picker sheet |
|
||||
| [09 — Activities](09-activities.md) | Local transfer log, TransferReceiptFragment, share/save receipt |
|
||||
| [10 — OTP Screen](10-otp-screen.md) | TOTP display, real-time countdown, enrolled bank authenticators |
|
||||
@@ -34,7 +34,7 @@ Documentation for app-specific logic — UI flows, routing decisions, and busine
|
||||
| [26 — Circular Nav](26-circular-nav.md) | Radial 4-slot wheel UI with lock centre |
|
||||
| [27 — Settings: Notifications](27-settings-notifications.md) | Opt-in flow: permission → battery opt → service start |
|
||||
| [28 — Settings: About](28-settings-about.md) | Version, T&Cs, donate buttons |
|
||||
| [29 — Card Verification & Merchant Card Pay](29-card-verification-and-merchant-card-pay.md) | NFC/manual card verification + card-only BML merchant payment |
|
||||
| [29 — Card Verification & Merchant Card Pay](29-card-verification-and-merchant-card-pay.md) | NFC/manual card verification + card-only BML merchant payment (links and carrier services), return to merchant |
|
||||
|
||||
## Reference
|
||||
|
||||
@@ -42,5 +42,5 @@ Documentation for app-specific logic — UI flows, routing decisions, and busine
|
||||
|---|---|
|
||||
| [18 — PayMV QR Format](18-paymv-qr-format.md) | Decimal TLV encoding, all tags, CRC-16, per-bank references, real samples, Fahipay WIP, parsing reference |
|
||||
| [19 — Parsers](19-parsers.md) | Account display parser architecture — how raw bank API data is normalised into a unified `AccountListDisplay` model |
|
||||
| [20 — Transfer Flows](20-transfer-flows.md) | TransferFragment entry points, recipient lookup, transfer type routing, rejected combinations, BML business OTP flow, BML QR merchant payments |
|
||||
| [20 — Transfer Flows](20-transfer-flows.md) | TransferFragment entry points, recipient lookup, transfer type picker, Fahipay services, carrier services by BML card, routing, rejected combinations, BML business OTP flow, BML QR merchant payments |
|
||||
| [AI Security Audit](AI_SECURITY_CHECK.md) | Full source security audit — credential storage, network layer, manifest, data privacy |
|
||||
|
||||
Reference in New Issue
Block a user