digetpay_plugin 0.2.0 copy "digetpay_plugin: ^0.2.0" to clipboard
digetpay_plugin: ^0.2.0 copied to clipboard

Pure-Dart DigetPay payment plugin: hosted (PCI-safe) checkout via WebView plus transaction management over the DigetPay REST API.

example/lib/main.dart

import 'dart:developer' as developer;

import 'package:digetpay_plugin/digetpay_plugin.dart';
import 'package:flutter/material.dart';
import 'package:uuid/uuid.dart';

/// A pretty, greppable logger for the DigetPay flow.
///
/// The SDK hands us plain messages; here we tag each with an emoji so the whole
/// request/checkout flow is easy to scan in the console during development.
void digetPayLog(String message) {
  final m = message.toLowerCase();
  final icon =
      (m.contains('fail') ||
          m.contains('error') ||
          m.contains('✗') ||
          m.contains('✖'))
      ? '❌'
      : (m.contains('success') || m.contains(' ok ') || m.contains('✓'))
      ? '✅'
      : (m.contains('dismiss') || m.contains('cancel'))
      ? '↩️'
      : m.startsWith('webview')
      ? '🌐'
      : m.startsWith('→')
      ? '➡️'
      : m.startsWith('←')
      ? '⬅️'
      : '💳';
  developer.log('$icon $message', name: 'DigetPay');
}

/// Your DigetPay **publishable / restricted mobile** API key.
///
/// Use a client-scoped key here — never a server secret (anything shipped in an
/// app can be extracted). Prefer passing it at build time, e.g.
/// `flutter run --dart-define=DIGETPAY_API_KEY=...`.
const String _apiKey = String.fromEnvironment(
  'DIGETPAY_API_KEY',
  defaultValue: '<your-api-key>',
);

void main() {
  // Initialize the SDK once at startup.
  DigetPaySdk.initialize(
    apiKey: _apiKey,
    baseUrl: kDigetPayDefaultBaseUrl,
    logger: digetPayLog, // remove in production, or gate behind kDebugMode
  );
  runApp(const DigetPayExampleApp());
}

/// A demo product in the example store.
class Product {
  final String name;
  final double price;
  final String currency;
  const Product(this.name, this.price, this.currency);
}

const List<Product> _products = [
  Product('Coffee', 15, 'SAR'),
  Product('Book', 60, 'SAR'),
  Product('Headphones', 250, 'SAR'),
];

class DigetPayExampleApp extends StatelessWidget {
  const DigetPayExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'DigetPay Example',
      theme: ThemeData(colorSchemeSeed: Colors.indigo, useMaterial3: true),
      home: const ProductsPage(),
    );
  }
}

class ProductsPage extends StatelessWidget {
  const ProductsPage({super.key});

  Future<void> _pay(BuildContext context, Product product) async {
    final messenger = ScaffoldMessenger.of(context);
    void banner(String message, Color color) {
      messenger
        ..clearSnackBars()
        ..showSnackBar(
          SnackBar(content: Text(message), backgroundColor: color),
        );
    }

    final orderId = const Uuid().v4();
    digetPayLog(
      'tap Pay → ${product.name} (${product.price} ${product.currency})',
    );

    // The THREE callbacks below are exactly how you learn the outcome after the
    // user returns from the hosted WebView. Exactly one of them fires:
    //   • onTransactionSuccess → paid    (handle: fulfil the order)
    //   • onTransactionFailure → failed  (handle: show retry)
    //   • onDismiss            → cancelled (user backed out; do nothing/retry)
    await DigetPaySdk.cardPay()
        .setOrder(
          DigetPaySaleOrder(
            id: orderId,
            description: product.name,
            currency: product.currency,
            amount: product.price,
          ),
        )
        .setPayer(
          const DigetPayPayer(
            firstName: 'Demo',
            lastName: 'User',
            address: 'King Fahd Rd',
            country: 'SA',
            city: 'Riyadh',
            zip: '00000',
            email: 'demo@example.com',
            phone: '+966500000000',
          ),
        )
        .setDesignType(DigetPayDesignType.one)
        .setLanguage(DigetPayLanguage.en)
        // setResultUrls(...) is optional — the SDK uses built-in defaults.
        .onTransactionSuccess((r) {
          digetPayLog(
            '✅ SUCCESS status=${r.status} txn=${r.transactionId} rrn=${r.rrn}',
          );
          banner('Paid ✓  (${r.status ?? 'APPROVED'})', Colors.green.shade700);
        })
        .onTransactionFailure((r) {
          // Prefer the transaction's own reason/status; NOT r.message, which is
          // the envelope text ("Success") even when the payment did not go through.
          final reason =
              r.declineReason ?? r.status ?? r.errorCode ?? 'declined/failed';
          digetPayLog('❌ FAILED status=${r.status} reason=$reason');
          banner('Failed ✗  $reason', Colors.red.shade700);
        })
        .onDismiss(() {
          digetPayLog('↩️ CANCELLED by user');
          banner('Checkout cancelled', Colors.grey.shade700);
        })
        .start(context);
  }

  /// Demonstrates the paginated sessions listing.
  ///
  /// Note we read `gatewayTransactionId` (the id to use for refunds/lookups),
  /// NOT the session `id`.
  Future<void> _showRecentSessions(BuildContext context) async {
    final messenger = ScaffoldMessenger.of(context);
    final page = await DigetPaySdk.getCheckoutSessions(
      const CheckoutSessionFilter(page: 1, limit: 20),
    );
    final sessions = page?.content ?? const <CheckoutSession>[];
    digetPayLog('sessions: ${sessions.length} of ${page?.totalElements ?? 0}');

    final summary = sessions.isEmpty
        ? 'No sessions found (check your API key).'
        : 'Latest: ${sessions.first.merchantOrderId} → '
            'txn ${sessions.first.gatewayTransactionId} '
            '(${page?.totalElements} total)';
    messenger
      ..clearSnackBars()
      ..showSnackBar(SnackBar(content: Text(summary)));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('DigetPay Store'),
        actions: [
          IconButton(
            icon: const Icon(Icons.receipt_long_outlined),
            tooltip: 'Recent sessions',
            onPressed: () => _showRecentSessions(context),
          ),
        ],
      ),
      body: ListView.separated(
        itemCount: _products.length,
        separatorBuilder: (_, _) => const Divider(height: 1),
        itemBuilder: (context, index) {
          final product = _products[index];
          return ListTile(
            leading: const Icon(Icons.shopping_bag_outlined),
            title: Text(product.name),
            subtitle: Text('${product.price} ${product.currency}'),
            trailing: FilledButton(
              onPressed: () => _pay(context, product),
              child: const Text('Pay'),
            ),
          );
        },
      ),
    );
  }
}
1
likes
0
points
257
downloads

Publisher

unverified uploader

Weekly Downloads

Pure-Dart DigetPay payment plugin: hosted (PCI-safe) checkout via WebView plus transaction management over the DigetPay REST API.

Homepage
Repository (GitHub)
View/report issues

Topics

#payments #payment-gateway #checkout #webview

License

unknown (license)

Dependencies

flutter, http, uuid, webview_flutter

More

Packages that depend on digetpay_plugin