# Bangla QR payer (Flutter)

The payer's phone app for the Bangla QR simulator. It scans a merchant's QR, asks the **issuer** to verify it, pays it, and follows the
payment to its end. It talks only to the issuer's JSON API (see [docs/ISSUER.md](../../docs/ISSUER.md#mobile-api)); the issuer talks to the
switch and the acquirer.

```
scan QR ─▶ issuer: verify ─▶ review (merchant, amount) ─▶ pay ─▶ follow the payment ─▶ paid | not charged | waiting for confirmation
```

## The rules the app follows

* **"Payment successful" is shown only when the issuer reports the outcome `paid`.** Everything else uses different words.
* **Waiting for confirmation** (outcome `unconfirmed`) is neither success nor failure: the money is held, not spent. The payer is told not to
  pay again and can tap *Check again*, which re-sends the same payment (same transaction id), so they are never charged twice.
* **Losing the connection never changes a payment.** The app says it cannot reach the issuer and keeps asking; it does not guess.
* Pay can be tapped once: a second tap while a payment is starting is ignored.
* Money is always the issuer's decimal strings (`"250.00"`), never a float.

## Run it

You need the three servers running first: `.\scripts\dev.ps1` from the repo root ([docs/RUNNING.md](../../docs/RUNNING.md)).

**On this PC (Chrome)** — camera scanning works in Chrome on `localhost`:

```powershell
cd mobile\bqr_payer
flutter run -d chrome
```

**On an Android phone (same Wi-Fi as the PC):**

1. One time: accept the Android SDK licences: `flutter doctor --android-licenses`. Enable *Developer options → USB debugging* on the phone.
2. Start the servers with the issuer listening on the network: `.\scripts\dev.ps1 -Lan` (it prints your PC's address).
   Allow port 34300 in the Windows firewall prompt.
3. `flutter run` (with the phone connected), then in the app: **Settings** → issuer address `http://<your PC's Wi-Fi address>:34300` →
   **Test connection** → **Save**.
4. Make a QR with `tools\qr-generator.html` on the PC and scan it from the screen.

The Android emulator reaches the PC at `http://10.0.2.2:34300` (the default there). The API key defaults to the issuer's dev-only key
(`dev-only-mobile-api-key-0123456789`); change it in Settings if the issuer is configured differently.

No camera (Windows desktop, or permission denied)? Use **Paste QR text** instead: copy the text from the HTML tool.

## Tests

```powershell
flutter test        # 65 tests: API client, payment/verify/home/settings/scan screens
flutter analyze
dart run tool/smoke.dart --qr "<QR text>" --url http://localhost:34300     # the real client against a running issuer
```

The camera itself cannot be exercised by `flutter test`; those tests replace it with a stand-in that "reads" a QR, and cover everything
the app does with the text afterwards.

## Layout

```
lib/main.dart                      app entry
lib/src/api_client.dart            the issuer's JSON API; failures are classified (a transport error never means paid or failed)
lib/src/models.dart                Payer, QrPreview, PaymentInfo, Outcome (only the exact string "paid" is paid)
lib/src/app_controller.dart        settings (address, key, last payer) and the API client built from them
lib/src/screens/                   home, scan, verify, payment, settings
tool/smoke.dart                    drives the real client against a live issuer
```

Targets generated: Android, web, Windows. (No iOS: it needs a Mac.) Android allows plain `http://` to the dev server
(`usesCleartextTraffic`); this is a simulator client, not a production banking app.
