add transfers

This commit is contained in:
2026-05-14 06:15:39 +05:00
parent 4c91a1aa0e
commit eda8797552
10 changed files with 533 additions and 63 deletions
@@ -311,6 +311,98 @@ class BmlLoginFlow {
return parseContacts(json)
}
/**
* Step 1 of BML transfer: POST without OTP. Returns true if server responds code=22 (OTP ready).
*/
fun initiateTransfer(
session: BmlSession,
debitAccount: String,
creditAccount: String,
amount: Double,
transferType: String,
currency: String,
bank: String? = null
): Boolean {
val jo = JSONObject().apply {
put("debitAccount", debitAccount)
put("creditAccount", creditAccount)
put("debitAmount", amount)
put("transfertype", transferType)
put("currency", currency)
put("channel", "token")
if (bank != null) put("bank", bank)
}
val body = jo.toString().toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("$BASE_URL/api/mobile/transfer")
.post(body)
.header("Authorization", "Bearer ${session.accessToken}")
.header("User-Agent", APP_USER_AGENT)
.header("x-app-version", APP_VERSION)
.header("accept", "application/json")
.build()
return apiClient.newCall(request).execute().use { response ->
val bodyStr = response.body?.string() ?: return@use false
try {
val json = JSONObject(bodyStr)
json.optBoolean("success") && json.optInt("code") == 22
} catch (_: Exception) { false }
}
}
/**
* Step 2 of BML transfer: POST with OTP + remarks. Returns BmlTransferResult.
*/
fun confirmTransfer(
session: BmlSession,
debitAccount: String,
creditAccount: String,
amount: Double,
transferType: String,
currency: String,
otp: String,
remarks: String = "",
bank: String? = null
): BmlTransferResult {
val jo = JSONObject().apply {
put("debitAccount", debitAccount)
put("creditAccount", creditAccount)
put("debitAmount", amount)
put("transfertype", transferType)
put("currency", currency)
put("channel", "token")
put("otp", otp)
if (remarks.isNotBlank()) put("remarks", remarks)
if (bank != null) put("bank", bank)
}
val body = jo.toString().toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("$BASE_URL/api/mobile/transfer")
.post(body)
.header("Authorization", "Bearer ${session.accessToken}")
.header("User-Agent", APP_USER_AGENT)
.header("x-app-version", APP_VERSION)
.header("accept", "application/json")
.build()
return apiClient.newCall(request).execute().use { response ->
val bodyStr = response.body?.string()
?: return@use BmlTransferResult(false, errorMessage = "No response")
try {
val json = JSONObject(bodyStr)
if (!json.optBoolean("success")) {
BmlTransferResult(false, errorMessage = json.optString("message").ifBlank { "Transfer failed" })
} else {
val payload = json.optJSONObject("payload")
BmlTransferResult(
success = true,
reference = payload?.optString("reference") ?: "",
timestamp = payload?.optString("timestamp") ?: ""
)
}
} catch (_: Exception) { BmlTransferResult(false, errorMessage = "Parse error") }
}
}
fun deleteContact(session: BmlSession, contactId: String): Boolean {
val body = """{"_method":"delete"}""".toRequestBody("application/json".toMediaType())
val request = Request.Builder()
@@ -350,6 +442,8 @@ class BmlLoginFlow {
val accountNumber = item.optString("account")
val status = item.optString("account_status", "Active")
val internalId = item.optString("id", "")
if (accountType == "CASA") {
val available = item.optDouble("availableBalance", 0.0)
casaAccounts.add(MibAccount(
@@ -365,7 +459,8 @@ class BmlLoginFlow {
mvrBalance = if (currency == "MVR") "%.2f".format(available) else "0.00",
statusDesc = status,
profileImageHash = null,
loginTag = loginTag
loginTag = loginTag,
internalId = internalId
))
} else if (accountType == "Card") {
val isPrepaid = item.optBoolean("prepaid_card", false)
@@ -385,7 +480,8 @@ class BmlLoginFlow {
mvrBalance = if (currency == "MVR") "%.2f".format(available) else "0.00",
statusDesc = status,
profileImageHash = null,
loginTag = loginTag
loginTag = loginTag,
internalId = internalId
))
} else {
// Linked debit cards have no independent balance or account link — skip
@@ -16,6 +16,13 @@ data class BmlAccountValidation(
val agnt: String? = null // BIC for DOT (MIB account on BML)
)
data class BmlTransferResult(
val success: Boolean,
val reference: String = "",
val timestamp: String = "",
val errorMessage: String = ""
)
data class BmlForeignLimit(
val type: String,
val used: Double,