fix paymv qr generation part 1
Auto Tag on Version Change / check-version (push) Successful in 5s

This commit is contained in:
2026-05-28 20:29:24 +05:00
parent 907757c893
commit b4e1f57347
3 changed files with 86 additions and 6 deletions
@@ -36,6 +36,7 @@ import sh.sar.basedbank.BasedBankApp
import sh.sar.basedbank.R
import sh.sar.basedbank.api.models.BankAccount
import sh.sar.basedbank.databinding.FragmentPayMvQrBinding
import sh.sar.basedbank.util.CredentialStore
import sh.sar.basedbank.databinding.ItemAccountDropdownBinding
import sh.sar.basedbank.util.AccountListParser
import sh.sar.basedbank.util.PaymvQrParser
@@ -98,6 +99,8 @@ class PayMvQrFragment : Fragment() {
}
setupDropdown()
binding.etAmount.addTextChangedListener { scheduleGenerate() }
binding.etReference.addTextChangedListener { scheduleGenerate() }
binding.switchIncludePhone.setOnCheckedChangeListener { _, _ -> scheduleGenerate() }
binding.btnShare.isEnabled = false
binding.btnSave.isEnabled = false
binding.btnShare.setOnClickListener { shareQr() }
@@ -147,8 +150,28 @@ class PayMvQrFragment : Fragment() {
?.let { "%.2f".format(it) }
val ctx = requireContext()
val includePhone = binding.switchIncludePhone.isChecked
val loginId = sh.sar.basedbank.util.ProfileImageStore.loginIdFromTag(account.loginTag)
val store = CredentialStore(ctx)
val mobile = if (includePhone) {
when (account.bank) {
"BML" -> store.loadBmlUserProfile(loginId)?.mobile
"FAHIPAY" -> store.loadFahipayUserProfile(loginId)?.mobile
else -> null
}?.let { m ->
when {
m.startsWith("+") -> m
m.length == 7 -> "+960$m"
else -> m
}
}
} else null
val purpose = binding.etReference.text?.toString()?.trim()
?.takeIf { it.isNotBlank() } ?: getString(R.string.paymvqr_reference_default)
val bmp = withContext(Dispatchers.Default) {
val payload = buildQrPayload(account.accountNumber, account.accountBriefName, acquirer, amountFormatted)
val payload = buildQrPayload(account.accountNumber, account.accountBriefName, acquirer, amountFormatted, mobile, purpose)
renderQrCard(ctx, account, payload, amountFormatted)
}
if (_binding == null) return
@@ -166,7 +189,9 @@ class PayMvQrFragment : Fragment() {
accountNumber: String,
accountName: String,
acquirer: String,
amountStr: String?
amountStr: String?,
mobile: String?,
purpose: String
): String {
fun tlv(tag: String, value: String): String {
val len = value.length
@@ -176,17 +201,30 @@ class PayMvQrFragment : Fragment() {
val poi = tlv("01", "11")
val sub00 = tlv("00", "mv.favara.mpqr")
val sub01 = tlv("01", acquirer)
val sub02 = tlv("02", acquirer) // repeated acquirer, as per official PayMV app
val sub03 = tlv("03", accountNumber)
val sub05 = if (!mobile.isNullOrBlank()) tlv("05", mobile) else ""
val sub10 = tlv("10", "IPAY")
val merchantAcct = tlv("26", sub00 + sub01 + sub03 + sub10)
val merchantAcct = tlv("26", sub00 + sub01 + sub02 + sub03 + sub05 + sub10)
val mcc = tlv("52", "0000")
val currency = tlv("53", "462")
val amountTLV = if (!amountStr.isNullOrBlank()) tlv("54", amountStr) else ""
val country = tlv("58", "MV")
val name = tlv("59", accountName.take(25))
val prefix = format + poi + merchantAcct + currency + amountTLV + country + name + "6304"
val ref = generateReference()
val addlData = tlv("62", tlv("05", ref) + tlv("08", purpose))
val timestamp = java.time.LocalDateTime.now()
.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.00000"))
val tag80 = tlv("80", tlv("00", "mv.favara.mpqr") + tlv("01", timestamp))
val prefix = format + poi + merchantAcct + mcc + currency + amountTLV + country + name + addlData + tag80 + "6304"
return prefix + crc16(prefix)
}
private fun generateReference(): String {
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
return (1..9).map { chars.random() }.joinToString("")
}
private fun crc16(data: String): String {
var crc = 0xFFFF
for (c in data) {
+41 -1
View File
@@ -64,7 +64,6 @@
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:hint="@string/paymvqr_amount_hint"
app:helperText="@string/paymvqr_amount_helper"
app:prefixText="MVR ">
<com.google.android.material.textfield.TextInputEditText
@@ -76,6 +75,47 @@
</com.google.android.material.textfield.TextInputLayout>
<!-- Reference / purpose (optional) -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilReference"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:hint="@string/paymvqr_reference_hint">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etReference"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<!-- Include phone number toggle -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginBottom="12dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/paymvqr_include_phone"
android:textAppearance="?attr/textAppearanceBodyMedium" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switchIncludePhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true" />
</LinearLayout>
<!-- Action buttons — always visible; share/save disabled until QR is rendered -->
<LinearLayout
android:id="@+id/layoutActions"
+3 -1
View File
@@ -115,11 +115,13 @@
<!-- PayMV QR Generator -->
<string name="paymvqr_select_account">Select account</string>
<string name="paymvqr_amount_hint">Amount (optional)</string>
<string name="paymvqr_amount_helper">Leave empty to allow payer to enter any amount</string>
<string name="paymvqr_share">Share</string>
<string name="paymvqr_save_image">Save Image</string>
<string name="paymvqr_saved">QR saved to gallery</string>
<string name="paymvqr_save_failed">Failed to save image</string>
<string name="paymvqr_include_phone">Include phone number</string>
<string name="paymvqr_reference_hint">Reference (optional)</string>
<string name="paymvqr_reference_default">PayMV QR Transfer</string>
<!-- Toolbar -->
<string name="action_lock">Lock app</string>