rootfi_tap_to_pay 0.1.1
rootfi_tap_to_pay: ^0.1.1 copied to clipboard
Official RootFi SDK: NFC phone-to-phone tap-to-pay between RootFi accounts, plus a typed client for the RootFi Cards API. One key, sandbox and live.
rootfi_tap_to_pay #
Official RootFi Flutter SDK for NFC tap-to-pay — instant phone-to-phone payments between two RootFi accounts — plus a typed client for the RootFi Cards API.
The NFC handshake reads the payer/payee RootFi account numbers; settlement runs RootFi → RootFi automatically. You never touch bank codes, name-enquiry, or any settlement endpoint.
Install #
dependencies:
rootfi_tap_to_pay: ^0.1.1
Android — nothing to configure #
This package ships its own Android manifest. The NFC permission and NFC/HCE
feature flags are merged into your app automatically — you do not edit
your AndroidManifest.xml. Min SDK 21.
Receiving (HCE broadcast) is Android only. Scanning/paying works on Android and iOS.
Authentication #
Use your RootFi API key — the same key that authorises banking and cards.
A sandbox key (rf_test_…) targets sandbox; a live key (rf_live_…) targets
production. One key, everything.
final tap = RootFiTapToPay(apiKey: 'rf_live_xxx');
Tap-to-pay (event-driven) #
Wire up the callbacks you care about, then start… / stop.
final tap = RootFiTapToPay(apiKey: 'rf_live_xxx')
..onStatus = (s) => setState(() => _status = s) // TapStatus enum
..onScanning = () => print('reading the other phone…')
..onSuccess = (r) => print('Paid ${r.recipientName} — ${r.transferId}')
..onFailure = (e) => print('Failed: $e');
Payee (receiving) — broadcast your RootFi account:
await tap.startReceiving(accountNumber: myAccountNumber);
// …show "waiting for payment" UI…
await tap.stop();
Payer (sending) — scan the payee's phone and settle:
await tap.startPaying(
debitAccountNumber: myAccountNumber,
amount: 1500,
narration: 'Lunch',
);
// onSuccess / onFailure fire when done. Cancel anytime with:
await tap.stop();
Prefer await? Use scanAndPay(...) which returns a TapPaymentResult.
NFC capability checks #
if (!await tap.isNfcSupported()) { /* hide the feature */ }
else if (!await tap.isNfcEnabled()) { await tap.openNfcSettings(); }
TapStatus lifecycle #
idle → checkingNfc → (nfcUnsupported | nfcDisabled) | waitingForTap → scanning → settling → (success | failure); stop() → stopped.
Cards API #
The same client wraps the RootFi Cards API (processor handled by RootFi):
final customer = await tap.client.call('POST', '/v1/cards/customers', body: {
'type': 'individual',
'name': 'Jane Doe',
'phoneNumber': '+2348100000000',
'status': 'active',
'billingAddress': {'line1': '1 Marina', 'city': 'Lagos', 'country': 'NG'},
});
final card = await tap.client.call('POST', '/v1/cards', body: {
'customerId': customer['data']['_id'],
'type': 'virtual',
'currency': 'NGN',
'status': 'active',
});
// Render PAN/CVV/PIN securely — token never exposes data to your backend:
final token = await tap.client.call(
'GET', '/v1/cards/${card['data']['_id']}/token');
Error handling #
onFailure/RootFiApiException— auth (401/403) or transport failures.onFailure/NfcUnavailableException— NFC off / unsupported / nothing read.onFailure/TimeoutException— no device tapped in time.
A declined-but-delivered settlement is reported through onFailure with a
RootFiApiException carrying the decline message (not a thrown crash).
License #
MIT © RootFi