add support for multiple BML accounts, and BML credit cards
Auto Tag on Version Change / check-version (push) Successful in 2s
Auto Tag on Version Change / check-version (push) Successful in 2s
This commit is contained in:
@@ -9,9 +9,10 @@ object AccountCache {
|
||||
|
||||
private const val PREFS = "account_cache"
|
||||
private const val KEY_MIB = "mib_accounts"
|
||||
private const val KEY_BML = "bml_accounts"
|
||||
private const val KEY_FAHIPAY = "fahipay_accounts"
|
||||
|
||||
private fun bmlKey(loginId: String) = "bml_accounts_$loginId"
|
||||
|
||||
fun save(context: Context, accounts: List<MibAccount>) {
|
||||
val arr = JSONArray()
|
||||
for (acc in accounts) {
|
||||
@@ -36,7 +37,7 @@ object AccountCache {
|
||||
.edit().putString(KEY_MIB, CacheEncryption.encrypt(arr.toString())).apply()
|
||||
}
|
||||
|
||||
fun saveBml(context: Context, accounts: List<MibAccount>) {
|
||||
fun saveBml(context: Context, loginId: String, accounts: List<MibAccount>) {
|
||||
val arr = JSONArray()
|
||||
for (acc in accounts) {
|
||||
arr.put(JSONObject().apply {
|
||||
@@ -56,15 +57,14 @@ object AccountCache {
|
||||
})
|
||||
}
|
||||
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
||||
.edit().putString(KEY_BML, CacheEncryption.encrypt(arr.toString())).apply()
|
||||
.edit().putString(bmlKey(loginId), CacheEncryption.encrypt(arr.toString())).apply()
|
||||
}
|
||||
|
||||
fun loadBml(context: Context): List<MibAccount> {
|
||||
fun loadBml(context: Context, loginId: String): List<MibAccount> {
|
||||
val raw = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
||||
.getString(KEY_BML, null) ?: return emptyList()
|
||||
.getString(bmlKey(loginId), null) ?: return emptyList()
|
||||
return try {
|
||||
val json = CacheEncryption.decrypt(raw)
|
||||
val arr = JSONArray(json)
|
||||
val arr = JSONArray(CacheEncryption.decrypt(raw))
|
||||
(0 until arr.length()).map { i ->
|
||||
val o = arr.getJSONObject(i)
|
||||
MibAccount(
|
||||
@@ -84,9 +84,12 @@ object AccountCache {
|
||||
internalId = o.optString("internalId", "")
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) { emptyList() }
|
||||
} catch (_: Exception) { emptyList() }
|
||||
}
|
||||
|
||||
fun loadBml(context: Context, loginIds: List<String>): List<MibAccount> =
|
||||
loginIds.flatMap { loadBml(context, it) }
|
||||
|
||||
fun saveFahipay(context: Context, accounts: List<MibAccount>) {
|
||||
val arr = JSONArray()
|
||||
for (acc in accounts) {
|
||||
|
||||
@@ -84,7 +84,9 @@ object ContactsCache {
|
||||
}
|
||||
}
|
||||
|
||||
fun saveBml(context: Context, contacts: List<MibBeneficiary>) {
|
||||
private fun bmlKey(loginId: String) = "bml_contacts_$loginId"
|
||||
|
||||
fun saveBml(context: Context, loginId: String, contacts: List<MibBeneficiary>) {
|
||||
val arr = JSONArray()
|
||||
for (c in contacts) {
|
||||
arr.put(JSONObject().apply {
|
||||
@@ -99,18 +101,18 @@ object ContactsCache {
|
||||
put("benefStatus", c.benefStatus)
|
||||
put("transferCyDesc", c.transferCyDesc)
|
||||
put("benefCategoryId", c.benefCategoryId)
|
||||
put("profileId", c.profileId)
|
||||
})
|
||||
}
|
||||
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
||||
.edit().putString("bml_contacts", CacheEncryption.encrypt(arr.toString())).apply()
|
||||
.edit().putString(bmlKey(loginId), CacheEncryption.encrypt(arr.toString())).apply()
|
||||
}
|
||||
|
||||
fun loadBml(context: Context): List<MibBeneficiary> {
|
||||
fun loadBml(context: Context, loginId: String): List<MibBeneficiary> {
|
||||
val raw = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
||||
.getString("bml_contacts", null) ?: return emptyList()
|
||||
.getString(bmlKey(loginId), null) ?: return emptyList()
|
||||
return try {
|
||||
val json = CacheEncryption.decrypt(raw)
|
||||
val arr = JSONArray(json)
|
||||
val arr = JSONArray(CacheEncryption.decrypt(raw))
|
||||
(0 until arr.length()).map { i ->
|
||||
val o = arr.getJSONObject(i)
|
||||
MibBeneficiary(
|
||||
@@ -125,12 +127,16 @@ object ContactsCache {
|
||||
benefStatus = o.optString("benefStatus"),
|
||||
transferCyDesc = o.optString("transferCyDesc", "MVR"),
|
||||
customerImgHash = null,
|
||||
benefCategoryId = o.optString("benefCategoryId", "BML")
|
||||
benefCategoryId = o.optString("benefCategoryId", "BML"),
|
||||
profileId = o.optString("profileId", "")
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) { emptyList() }
|
||||
} catch (_: Exception) { emptyList() }
|
||||
}
|
||||
|
||||
fun loadBml(context: Context, loginIds: List<String>): List<MibBeneficiary> =
|
||||
loginIds.flatMap { loadBml(context, it) }
|
||||
|
||||
fun saveFahipay(context: Context, contacts: List<MibBeneficiary>, categories: List<MibBeneficiaryCategory>) {
|
||||
val prefs = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).edit()
|
||||
val arr = JSONArray()
|
||||
|
||||
@@ -24,7 +24,6 @@ class CredentialStore(context: Context) {
|
||||
// ── MIB login credentials ─────────────────────────────────────────────────
|
||||
|
||||
fun hasMibCredentials(): Boolean = prefs.contains("mib_enc_username")
|
||||
fun hasBmlCredentials(): Boolean = prefs.contains("bml_enc_username")
|
||||
fun hasFahipayCredentials(): Boolean = prefs.contains("fahipay_enc_id_card")
|
||||
|
||||
fun saveMibCredentials(username: String, passwordHash: String, otpSeed: String) {
|
||||
@@ -91,58 +90,106 @@ class CredentialStore(context: Context) {
|
||||
return try { decrypt(enc, key) } catch (_: Exception) { null }
|
||||
}
|
||||
|
||||
// ── BML login credentials ─────────────────────────────────────────────────
|
||||
// ── BML login credentials (multi-login, keyed by loginId = username) ────────
|
||||
|
||||
fun saveBmlCredentials(username: String, password: String, otpSeed: String) {
|
||||
fun getBmlLoginIds(): List<String> {
|
||||
val json = prefs.getString("bml_login_ids", null)
|
||||
if (json != null) {
|
||||
return try {
|
||||
val arr = org.json.JSONArray(json)
|
||||
(0 until arr.length()).map { arr.getString(it) }
|
||||
} catch (_: Exception) { emptyList() }
|
||||
}
|
||||
// One-time migration from single-slot BML storage
|
||||
val oldEncUsername = prefs.getString("bml_enc_username", null) ?: return emptyList()
|
||||
return try {
|
||||
val key = getOrCreateKey()
|
||||
val loginId = decrypt(oldEncUsername, key)
|
||||
val edit = prefs.edit()
|
||||
prefs.getString("bml_enc_password", null)?.let { edit.putString("bml_${loginId}_enc_password", it) }
|
||||
prefs.getString("bml_enc_otp_seed", null)?.let { edit.putString("bml_${loginId}_enc_otp_seed", it) }
|
||||
prefs.getString("bml_enc_token", null)?.let { edit.putString("bml_${loginId}_enc_token", it) }
|
||||
prefs.getString("bml_enc_device_id", null)?.let { edit.putString("bml_${loginId}_enc_device_id", it) }
|
||||
prefs.getString("bml_enc_profile", null)?.let { edit.putString("bml_${loginId}_enc_profile", it) }
|
||||
edit.putString("bml_${loginId}_enc_username", oldEncUsername)
|
||||
edit.remove("bml_enc_username").remove("bml_enc_password").remove("bml_enc_otp_seed")
|
||||
.remove("bml_enc_token").remove("bml_enc_device_id")
|
||||
.remove("bml_enc_profile").remove("bml_enc_full_name")
|
||||
val ids = org.json.JSONArray(listOf(loginId)).toString()
|
||||
edit.putString("bml_login_ids", ids)
|
||||
edit.apply()
|
||||
listOf(loginId)
|
||||
} catch (_: Exception) { emptyList() }
|
||||
}
|
||||
|
||||
fun hasBmlCredentials(): Boolean = getBmlLoginIds().isNotEmpty()
|
||||
|
||||
private fun addBmlLoginId(loginId: String) {
|
||||
val ids = getBmlLoginIds().toMutableList()
|
||||
if (loginId !in ids) {
|
||||
ids.add(loginId)
|
||||
prefs.edit().putString("bml_login_ids", org.json.JSONArray(ids).toString()).apply()
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeBmlLoginId(loginId: String) {
|
||||
val ids = getBmlLoginIds().toMutableList()
|
||||
if (ids.remove(loginId))
|
||||
prefs.edit().putString("bml_login_ids", org.json.JSONArray(ids).toString()).apply()
|
||||
}
|
||||
|
||||
fun saveBmlCredentials(loginId: String, username: String, password: String, otpSeed: String) {
|
||||
addBmlLoginId(loginId)
|
||||
val key = getOrCreateKey()
|
||||
prefs.edit()
|
||||
.putString("bml_enc_username", encrypt(username, key))
|
||||
.putString("bml_enc_password", encrypt(password, key))
|
||||
.putString("bml_enc_otp_seed", encrypt(otpSeed, key))
|
||||
.putString("bml_${loginId}_enc_username", encrypt(username, key))
|
||||
.putString("bml_${loginId}_enc_password", encrypt(password, key))
|
||||
.putString("bml_${loginId}_enc_otp_seed", encrypt(otpSeed, key))
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun loadBmlCredentials(): BmlCredentials? {
|
||||
fun loadBmlCredentials(loginId: String): BmlCredentials? {
|
||||
val key = getOrCreateKey()
|
||||
val encUsername = prefs.getString("bml_enc_username", null) ?: return null
|
||||
val encPassword = prefs.getString("bml_enc_password", null) ?: return null
|
||||
val encSeed = prefs.getString("bml_enc_otp_seed", null) ?: return null
|
||||
val encUsername = prefs.getString("bml_${loginId}_enc_username", null) ?: return null
|
||||
val encPassword = prefs.getString("bml_${loginId}_enc_password", null) ?: return null
|
||||
val encSeed = prefs.getString("bml_${loginId}_enc_otp_seed", null) ?: return null
|
||||
return try {
|
||||
BmlCredentials(decrypt(encUsername, key), decrypt(encPassword, key), decrypt(encSeed, key))
|
||||
} catch (_: Exception) { null }
|
||||
}
|
||||
|
||||
fun clearBmlCredentials() {
|
||||
fun clearBmlCredentials(loginId: String) {
|
||||
removeBmlLoginId(loginId)
|
||||
prefs.edit()
|
||||
.remove("bml_enc_username")
|
||||
.remove("bml_enc_password")
|
||||
.remove("bml_enc_otp_seed")
|
||||
.remove("bml_${loginId}_enc_username")
|
||||
.remove("bml_${loginId}_enc_password")
|
||||
.remove("bml_${loginId}_enc_otp_seed")
|
||||
.apply()
|
||||
}
|
||||
|
||||
// ── BML session token ─────────────────────────────────────────────────────
|
||||
// ── BML session token (per loginId) ───────────────────────────────────────
|
||||
|
||||
fun saveBmlSession(accessToken: String, deviceId: String) {
|
||||
fun saveBmlSession(loginId: String, accessToken: String, deviceId: String) {
|
||||
val key = getOrCreateKey()
|
||||
prefs.edit()
|
||||
.putString("bml_enc_token", encrypt(accessToken, key))
|
||||
.putString("bml_enc_device_id", encrypt(deviceId, key))
|
||||
.putString("bml_${loginId}_enc_token", encrypt(accessToken, key))
|
||||
.putString("bml_${loginId}_enc_device_id", encrypt(deviceId, key))
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun loadBmlSession(): Pair<String, String>? {
|
||||
fun loadBmlSession(loginId: String): Pair<String, String>? {
|
||||
val key = getOrCreateKey()
|
||||
val encToken = prefs.getString("bml_enc_token", null) ?: return null
|
||||
val encDeviceId = prefs.getString("bml_enc_device_id", null) ?: return null
|
||||
val encToken = prefs.getString("bml_${loginId}_enc_token", null) ?: return null
|
||||
val encDeviceId = prefs.getString("bml_${loginId}_enc_device_id", null) ?: return null
|
||||
return try {
|
||||
Pair(decrypt(encToken, key), decrypt(encDeviceId, key))
|
||||
} catch (_: Exception) { null }
|
||||
}
|
||||
|
||||
fun clearBmlSession() {
|
||||
fun clearBmlSession(loginId: String) {
|
||||
prefs.edit()
|
||||
.remove("bml_enc_token")
|
||||
.remove("bml_enc_device_id")
|
||||
.remove("bml_${loginId}_enc_token")
|
||||
.remove("bml_${loginId}_enc_device_id")
|
||||
.apply()
|
||||
}
|
||||
|
||||
@@ -315,16 +362,6 @@ class CredentialStore(context: Context) {
|
||||
return try { decrypt(enc, key) } catch (_: Exception) { null }
|
||||
}
|
||||
|
||||
fun saveBmlFullName(name: String) {
|
||||
val key = getOrCreateKey()
|
||||
prefs.edit().putString("bml_enc_full_name", encrypt(name, key)).apply()
|
||||
}
|
||||
|
||||
fun loadBmlFullName(): String? {
|
||||
val key = getOrCreateKey()
|
||||
val enc = prefs.getString("bml_enc_full_name", null) ?: return null
|
||||
return try { decrypt(enc, key) } catch (_: Exception) { null }
|
||||
}
|
||||
|
||||
fun saveMibUserProfile(p: MibUserProfile) {
|
||||
val json = JSONObject().apply {
|
||||
@@ -355,7 +392,7 @@ class CredentialStore(context: Context) {
|
||||
} catch (_: Exception) { null }
|
||||
}
|
||||
|
||||
fun saveBmlUserProfile(p: BmlUserProfile) {
|
||||
fun saveBmlUserProfile(loginId: String, p: BmlUserProfile) {
|
||||
val json = JSONObject().apply {
|
||||
put("fullName", p.fullName)
|
||||
put("email", p.email)
|
||||
@@ -365,13 +402,12 @@ class CredentialStore(context: Context) {
|
||||
put("birthdate", p.birthdate)
|
||||
}.toString()
|
||||
val key = getOrCreateKey()
|
||||
prefs.edit().putString("bml_enc_profile", encrypt(json, key)).apply()
|
||||
prefs.edit().putString("bml_enc_full_name", encrypt(p.fullName, key)).apply()
|
||||
prefs.edit().putString("bml_${loginId}_enc_profile", encrypt(json, key)).apply()
|
||||
}
|
||||
|
||||
fun loadBmlUserProfile(): BmlUserProfile? {
|
||||
fun loadBmlUserProfile(loginId: String): BmlUserProfile? {
|
||||
val key = getOrCreateKey()
|
||||
val enc = prefs.getString("bml_enc_profile", null) ?: return null
|
||||
val enc = prefs.getString("bml_${loginId}_enc_profile", null) ?: return null
|
||||
return try {
|
||||
val o = JSONObject(decrypt(enc, key))
|
||||
BmlUserProfile(
|
||||
|
||||
Reference in New Issue
Block a user