patial support for BML business profile accounts
Auto Tag on Version Change / check-version (push) Successful in 3s

This commit is contained in:
2026-05-19 23:30:36 +05:00
parent 35a1748055
commit 15a02cac1c
8 changed files with 829 additions and 167 deletions
@@ -5,6 +5,7 @@ import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import android.util.Base64
import org.json.JSONObject
import sh.sar.basedbank.api.bml.BmlProfile
import java.security.KeyStore
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
@@ -193,24 +194,83 @@ class CredentialStore(context: Context) {
}
fun clearBmlCredentials(loginId: String) {
loadBmlProfiles(loginId).forEach { clearBmlProfileSession(it.profileId) }
removeBmlLoginId(loginId)
prefs.edit()
.remove("bml_${loginId}_enc_username")
.remove("bml_${loginId}_enc_password")
.remove("bml_${loginId}_enc_otp_seed")
.remove("bml_${loginId}_profiles")
.remove("bml_${loginId}_hidden_profile_ids")
// legacy single-profile session keys
.remove("bml_${loginId}_enc_token")
.remove("bml_${loginId}_enc_device_id")
.apply()
}
// ── BML session token (per loginId) ───────────────────────────────────────
// ── BML profiles (per loginId) ────────────────────────────────────────────
fun saveBmlSession(loginId: String, accessToken: String, deviceId: String) {
fun saveBmlProfiles(loginId: String, profiles: List<BmlProfile>) {
val arr = org.json.JSONArray()
for (p in profiles) arr.put(org.json.JSONObject().apply {
put("profileId", p.profileId)
put("name", p.name)
put("type", p.type)
put("profileType", p.profileType)
})
prefs.edit().putString("bml_${loginId}_profiles", arr.toString()).apply()
}
fun loadBmlProfiles(loginId: String): List<BmlProfile> {
val raw = prefs.getString("bml_${loginId}_profiles", null) ?: return emptyList()
return try {
val arr = org.json.JSONArray(raw)
(0 until arr.length()).map { i ->
val o = arr.getJSONObject(i)
BmlProfile(
profileId = o.optString("profileId"),
name = o.optString("name"),
type = o.optString("type"),
profileType = o.optString("profileType", "default")
)
}
} catch (_: Exception) { emptyList() }
}
fun getHiddenBmlProfileIds(loginId: String): Set<String> =
prefs.getStringSet("bml_${loginId}_hidden_profile_ids", emptySet()) ?: emptySet()
fun setHiddenBmlProfileIds(loginId: String, ids: Set<String>) =
prefs.edit().putStringSet("bml_${loginId}_hidden_profile_ids", ids).apply()
// ── BML per-profile session token (keyed by profileId, a globally unique GUID) ──
fun saveBmlProfileSession(profileId: String, accessToken: String, deviceId: String) {
val key = getOrCreateKey()
prefs.edit()
.putString("bml_${loginId}_enc_token", encrypt(accessToken, key))
.putString("bml_${loginId}_enc_device_id", encrypt(deviceId, key))
.putString("bml_profile_${profileId}_enc_token", encrypt(accessToken, key))
.putString("bml_profile_${profileId}_enc_device_id", encrypt(deviceId, key))
.apply()
}
fun loadBmlProfileSession(profileId: String): Pair<String, String>? {
val key = getOrCreateKey()
val encToken = prefs.getString("bml_profile_${profileId}_enc_token", null) ?: return null
val encDeviceId = prefs.getString("bml_profile_${profileId}_enc_device_id", null) ?: return null
return try {
Pair(decrypt(encToken, key), decrypt(encDeviceId, key))
} catch (_: Exception) { null }
}
fun clearBmlProfileSession(profileId: String) {
prefs.edit()
.remove("bml_profile_${profileId}_enc_token")
.remove("bml_profile_${profileId}_enc_device_id")
.apply()
}
// ── Legacy single-profile BML session (kept for backward compat reading) ─
fun loadBmlSession(loginId: String): Pair<String, String>? {
val key = getOrCreateKey()
val encToken = prefs.getString("bml_${loginId}_enc_token", null) ?: return null
@@ -220,13 +280,6 @@ class CredentialStore(context: Context) {
} catch (_: Exception) { null }
}
fun clearBmlSession(loginId: String) {
prefs.edit()
.remove("bml_${loginId}_enc_token")
.remove("bml_${loginId}_enc_device_id")
.apply()
}
// ── Fahipay login credentials (multi-login, keyed by loginId = profileId) ──
fun getFahipayLoginIds(): List<String> {