Files
thijooree/docs/mfaisaapi/03-history.md
T
shihaam 43f3cca2aa
Auto Tag on Version Change / check-version (push) Failing after 13m41s
ooredoo mfaisa
2026-06-27 14:25:46 +05:00

5.1 KiB

Transaction History

Fetch a paginated list of transactions for the active subscriber session.


Endpoint

POST https://superapp.ooredoo.mv/api/mfaisaa-bff/mfino/v1.1/web/transactionInquiry/fetchSummary

Requires an active session (i.e. a valid loginExchangeKey) obtained from doMobileLogin. Sessions expire after mobileLoginSessionTimeout seconds (240s) — see Session expiry below.


Request

Content-Type: application/x-www-form-urlencoded

Field Value
role RETAIL_SUBSCRIBER (constant)
channel SubscriberAppnot C03 as in login
loginExchangeKey From the login response
mdnId <encryptMobile(msisdn), base64> — same routine as mdnId in login
formData JSON object (see below), html-safe-escaped
rndValue Anti-replay nonce
csValue Adler32 integrity check

formData JSON

{
  "actorRole":       "RETAIL_SUBSCRIBER",
  "actorRoleId":     "<suscriberId from login response>",
  "fromDate":        "",
  "mdnId":           "<encryptMobile(msisdn), base64>",
  "pageNo":          "1",
  "recordSize":      "70",
  "toDate":          "",
  "transactionType": ""
}
  • actorRoleId comes from suscriberId at the top level of doMobileLogin's success body — see 02-login.md. It also appears as pocketDetails[0].roleId in the same response.
  • The inner mdnId is independently encrypted from the outer mdnId — same plaintext, different ciphertext (OAEP random padding).
  • fromDate / toDate are empty strings in the official app — the server returns all available history.

curl Example

# Requires a valid loginExchangeKey + suscriberId from a fresh login call
python tmp/mfaisa_history.py <msisdn> <mpin> 1

See tmp/mfaisa_history.py for the full Python reference (it does the login, captures the session, then calls fetchSummary).


Response

{
  "transactionInquiryDTOList": [
    {
      "requestId":     "<request id>",
      "referenceId":   "<reference id>",
      "sourceMDN":     "<Subscriber Name>-DT Pocket-<msisdn>",
      "sourcePocketId":"<pocket id>",
      "actorRoleType": "RETAIL_SUBSCRIBER",
      "actorRoleId":   "<subscriber id>",
      "commodityType": "WALLET",
      "channel":       "SubscriberApp",
      "transactionAmount": { "amount": 1, "currencyCode": "MVR" },
      "userStatus":    "CONFIRMED",
      "trnStage":      "AUTO_REVERSED",
      "trnType":       "CASH_IN",
      "status":        "FAILED",
      "trnDate":       "2026-06-13 13:04:19",
      "narrationString": "Load Money",
      "typeSummaryString": "[{\"Transaction Type\":\"Load Money\",\"Deposit Pocket\":\"DT Pocket\",\"Reference\":\"<ref>\"}]",
      "errorCode":     "INT_002",
      "errorDesc":     "QR_CODE_GENERATED",
      "resolutionDetails": "Please reconcile with the payment gateway..."
    },
    "..."
  ]
}

Key fields used by Thijooree:

Field Maps to BankTransaction
trnDate date (already in YYYY-MM-DD HH:mm:ss form)
narrationString description (suffixed with · Failed when status == "FAILED")
transactionAmount.amount amount (signed — see direction rule below)
transactionAmount.currencyCode currency
referenceId (fallback requestId) id + reference
typeSummaryStringMerchant Name / Receiver Name / Sender Name counterpartyName
sourceMDN (e.g. "<Name>-DT Pocket-<msisdn>") counterpartyName fallback (first segment before -)

Debit / credit direction

The response does not include a signed amount or direction flag. Direction is inferred from trnType:

trnType Direction
CASH_IN, RECEIVE_MONEY, *_IN credit (positive amount)
everything else (PURCHASE, TRANSFER, …) debit (negative amount)

Pagination

The server does not return a total field. Thijooree treats "received a full recordSize (= 70) records" as the only signal that further pages may exist; the next call uses pageNo = pageNo + 1. Once a page comes back with fewer than 70 records, no more pages are fetched.

Session expiry

When the 240-second session lapses, the server still returns HTTP 200 but the body is its standard error envelope:

[
  {
    "success": false,
    "message": "validation errors",
    "error": [
      {
        "objectName": "LoginLog",
        "attributeName": "LoginLog",
        "attributeValue": "SESSION_EXPIRED",
        "errorCode": "SESSION_EXPIRED",
        "errorMessage": "SESSION_EXPIRED"
      }
    ]
  }
]

MfaisaHistoryClient parses this into MfaisaSessionExpiredException. Callers (HistoryFetcher, TransferHistoryFragment) catch it, call BasedBankApp.refreshMfaisaSession(loginId) to re-login transparently, and retry the same page once.


 


Next → Transfer Money | ← Back to Login | README