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.

This is the Flutter counterpart to @nebula-ltd/pok-payments-rn; it talks to the same backend (api.pokpay.io).

Features

  • Three payment flows ready to drop into a screen:
    • GuestCheckout widget — one-shot checkout for an existing order
    • AddCardForm widget — collects + encrypts card details, returns encrypted data to your backend
    • PokPayments.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) or Activity (Android); your Flutter tree never sees the WebView
  • Visa Terminal / ProCard support — automatic branching for cards with the hasTerminal flag
  • 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 minSdkVersion 21 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.