pok_payments_flutter
Flutter payment SDK for the POK platform. Provides card tokenization, native JWE (RSA-OAEP + A256GCM) encryption, and natively presented 3D Secure / Cybersource device-data-collection flows on iOS and Android.
Features
- Three payment flows ready to drop into a screen:
GuestCheckoutwidget — one-shot checkout for an existing orderAddCardFormwidget — collects + encrypts card details, returns encrypted data to your backendPokPayments.payByToken(...)— pay an existing order with a saved card
- Native JWE encryption — JOSESwift on iOS, nimbus-jose-jwt on Android
- Native 3DS challenge modal — the WebView lives inside a
UIViewController(iOS) orActivity(Android); your Flutter tree never sees the WebView - Visa Terminal / ProCard support — automatic branching for cards with
the
hasTerminalflag - Theming — light, dark, and system-aware modes plus
PokStyleOverrides - Localization — English, Italian, Albanian out of the box
- Type-safe native bridge — Pigeon-generated bindings, no string-keyed Method Channel calls
Installation
dependencies:
pok_payments_flutter: ^0.0.1
Then:
flutter pub get
cd ios && pod install
The iOS side adds JOSESwift ~> 3.0 to your Podfile transitively. The
Android side pulls in com.nimbusds:nimbus-jose-jwt,
androidx.appcompat:appcompat, and androidx.localbroadcastmanager.
You also need to register the challenge Activity in your host Android app's
AndroidManifest.xml, inside the <application> element:
<activity
android:name="com.nebula.pok_payments_flutter.ChallengeActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:exported="false" />
Quick start
Guest checkout
import 'package:flutter/material.dart';
import 'package:pok_payments_flutter/pok_payments_flutter.dart';
class CheckoutScreen extends StatelessWidget {
const CheckoutScreen({super.key, required this.orderId});
final String orderId;
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('Checkout')),
body: GuestCheckout(
env: Environment.production,
orderId: orderId,
onSuccess: (result) => Navigator.of(context).pop(result),
onError: (error) =>
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(error.message)),
),
),
);
}
Pay by saved token
import 'package:pok_payments_flutter/pok_payments_flutter.dart';
Future<PaymentResult> pay({
required String orderId,
required String creditDebitCardId,
required String payerAuthSetupReferenceId,
}) {
return PokPayments.payByToken(
PayByTokenOptions(
env: Environment.production,
orderId: orderId,
payerAuth: PayerAuthentication(
creditDebitCardId: creditDebitCardId,
payerAuthSetupReferenceId: payerAuthSetupReferenceId,
),
),
);
}
Add card (encrypt only)
AddCardForm(
env: Environment.production,
onComplete: (data) {
// Send `data.encryptedCard`, `data.billing`, etc. to your backend.
},
onError: (error) => print(error),
)
Theming
GuestCheckout(
env: Environment.production,
orderId: orderId,
themeMode: ThemeMode.system, // light | dark | system
styleOverrides: PokStyleOverrides(
radius: 12,
fontFamily: 'Inter',
),
onSuccess: ...,
onError: ...,
)
Localization
Pass locale: Locale.it (or Locale.al) to any of the public widgets to
swap the form strings.
GuestCheckout(
env: Environment.production,
orderId: orderId,
locale: Locale.it,
onSuccess: ...,
onError: ...,
)
Error handling
Every flow surfaces failures as a typed PokError with a code
(PokErrorCode) and a human-readable
message. Use isPokError(e) to discriminate from generic exceptions.
try {
final result = await PokPayments.payByToken(options);
} catch (e) {
if (isPokError(e)) {
final pokError = e as PokError;
switch (pokError.code) {
case PokErrorCode.challengeDismissed:
// user cancelled 3DS
case PokErrorCode.networkError:
// retryable
default:
// surface message to user
}
}
}
Requirements
- Flutter 3.16 or later
- Dart 3.2 or later
- iOS 13.0 or later
- Android
minSdkVersion21 or later - Custom dev build — Expo Go / standard runners don't include the native modules
License
ISC. See LICENSE.
Libraries
- pok_payments_flutter
- Public surface of the pok_payments_flutter SDK.