[Parked – do not merge] UPI Scan & Pay (not production-ready)#6
Draft
SuTechs wants to merge 4 commits into
Draft
[Parked – do not merge] UPI Scan & Pay (not production-ready)#6SuTechs wants to merge 4 commits into
SuTechs wants to merge 4 commits into
Conversation
* feat: scan UPI QR to track expense and pay via UPI apps Adds a scan-and-pay flow: from the home app bar, scan any UPI QR, enter amount/category/optional note, save the expense locally first, then hand off to an installed UPI app (GPay, PhonePe, Paytm, BHIM…) to complete the actual payment. This is tracking-only — the app never moves money and stores just amount + category (plus existing note/date/type), no payee details and no payment-status tracking. - upi_uri.dart: pure-Dart UPI QR parser (pa/pn/am), rejects non-UPI QRs - upi_scan_screen.dart: mobile_scanner camera + permission fallback - upi_payment_screen.dart: amount/category/note form, saves via ExpenseCommand then opens the app picker - upi_app_picker_sheet.dart: lists installed UPI apps, launches the chosen one (only file importing upi_pay, for easy future swap) - platform config: Android camera permission + upi query; iOS camera usage description + UPI app schemes - home_app_bar.dart: QR-scan entry point Deps: mobile_scanner ^7.2.0, upi_pay ^1.1.0 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(upi): polish scanner + payment UX, save only on app tap Scanner page: - Full-bleed camera with a stable, centered dimmed-cutout overlay (custom painter with corner brackets) — fixes the box animating in from the top-left - Transparent app bar with a close (X) button and a flash toggle that reflects real torch state via ValueListenableBuilder - scanWindow constrains detection to the framed area Payment page (redesign): - Payee header: avatar + name (big) + UPI id (muted) - Hero centered amount input - Note rendered as a compact chip-style field - Category quick-pick chips (most relevant) + "More" opening a new CategoryPickerSheet with search + "Most used" + full list - Single "Select app to pay" button Behavior change: the expense is now saved ONLY when a UPI app is actually tapped (UpiAppPickerSheet.onBeforeLaunch), not on form submit. The picker disables tiles while launching and returns success so the screen pops with a confirmation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(upi): white scanner app bar text/icons, drop note field icon - Force the scanner app bar title and icons (close + flash) to white so they read clearly over the camera/overlay - Remove the edit icon from the payment note chip Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(upi): replace widget-returning methods with widget classes Per review feedback, extract all `Widget _foo()` helper methods into proper Stateless/Painter widget classes: - components/category_chip.dart: shared CategoryChip (was duplicated in the payment screen and the category sheet) - components/payment_widgets.dart: PayeeHeader, AmountField, NoteField, CategorySection, PayBar — payment screen now only has build() + logic - category_picker_sheet.dart: uses CategoryChip + a _SectionLabel widget, inlined the chip builders - upi_app_picker_sheet.dart: extract _AppTile widget (enabled/onTap) No behavior change. flutter analyze clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(upi): restore QR scanning by removing scanWindow The scanWindow added during UI polish restricted detection to the cutout rect, which silently broke scanning on-device (coordinate-space mismatch with BoxFit.cover — camera previews but never detects). Detection now runs on the full frame again; the cutout overlay remains as a purely visual guide. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
upi_pay (discontinued) detected apps from a stale hardcoded signature list, so newer GPay/PhonePe builds never appeared — only iMobile showed. Switch to upi_intent, which detects apps via the live Android intent resolver and ships the correct package-visibility <queries>. - Vendor the package into packages/upi_intent (path dependency) so we can theme its built-in picker; dropped example/ and unit tests - Theme the picker to our navy palette via Theme.of(context).colorScheme .primary (no app->package coupling) - Removed the deprecated package= attribute from the vendored manifest (conflicts with the AGP 8 namespace) - Payment flow now uses UpiIntent.pay() and saves the expense ONLY when the app reports status == success; failure/unknown/submitted -> not saved, with a snackbar prompting manual entry - Deleted our old custom UpiAppPickerSheet (replaced by themed built-in) - Broadened the app manifest upi query (removed host="pay") - Bumped version to 1.0.1+2 Caveat (documented in code): UPI status is unreliable — GPay often returns no status on success and iOS returns none at all, so strict success-only saving can miss genuine payments. Debug APK builds; flutter analyze clean (one pre-existing bloc info). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
App:
- Add a themed PaymentConfirmDialog ("Did the payment go through?") shown
whenever the UPI app does not report a clear success status. This avoids
silently dropping genuine payments — GPay often returns no status on
success and iOS returns none at all. Confirm -> save; decline -> skip.
Vendored package (packages/upi_intent) — aligned as a standalone, internal fork:
- Rewrote README to document it as a vendored/customized copy (why, what
changed, usage, platform setup, MIT attribution)
- Deleted dead `flutter create plugin` boilerplate (root-level
upi_intent_method_channel.dart / upi_intent_platform_interface.dart);
real impl is in lib/src/platform/
- Removed screenshots; set publish_to: "none"; updated description + CHANGELOG
flutter analyze clean; debug APK builds.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Status:🅿️ Parked / do-not-merge. This preserves the full UPI scan-and-pay feature for the future. It has been removed from
main(reset to the pre-feature commit77481bb) because device testing surfaced blockers that can't be solved from an unregistered app.What the feature does
Scan any UPI QR → enter amount / category / note → launch a UPI app to pay the scanned payee → track the expense locally. (Scanning via
mobile_scanner; launch + app picker via a vendored, themedupi_intent; expense tracking only — we never move money.)Why it's parked — limitations found in testing
App detection is unreliable across devices.
upi_pay(now discontinued) used a stale hardcoded list → only iMobile/ICICI showed, not GPay/PhonePe.upi_intentuses the live Android resolver, butqueryIntentActivities("upi://pay")returns empty on some devices (e.g. Infinix) even though the merged manifest has the correct broad<data scheme="upi">query and explicit<package>entries. Apps are installed but not detected.The payment itself is blocked by UPI/NPCI rules — the real wall.
upi://pay?…intent without a verified merchant signature (mc/sign), which only a registered PSP/merchant can produce — so apps treat it as an unverified payment and/or reject third-party-initiated intents.iOS is effectively unsupported.
upi://handler; each app uses a private scheme (gpay://,phonepe://, …).upi://pay?…, which no iOS app handles → payment can't complete on iOS.Payment gateways (Razorpay etc.) don't fit this use case.
What's preserved here (for future pickup)
mobile_scannerscan screen with dimmed-cutout overlay, close + flash controlslib/data/utils/upi_uri.dart)upi_intentinpackages/upi_intent(themed picker; dead boilerplate stripped;publish_to: none)<queries>+ camera permission, iOS camera + UPI scheme entriesTo revisit in future
🤖 Generated with Claude Code