flick_payment_sdk 1.0.1 copy "flick_payment_sdk: ^1.0.1" to clipboard
flick_payment_sdk: ^1.0.1 copied to clipboard

A Flutter SDK for Flick Payment processing

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flick_payment_sdk/flick_payment_sdk.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Simple Payment Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const AmountInputPage(),
    );
  }
}

// First page where user inputs amount
class AmountInputPage extends StatefulWidget {
  const AmountInputPage({super.key});

  @override
  State<AmountInputPage> createState() => _AmountInputPageState();
}

class _AmountInputPageState extends State<AmountInputPage> {
  final TextEditingController _amountController = TextEditingController();
  final _formKey = GlobalKey<FormState>();

  @override
  void dispose() {
    _amountController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Enter Payment Amount'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Form(
          key: _formKey,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              TextFormField(
                controller: _amountController,
                decoration: const InputDecoration(
                  labelText: 'Amount (£)',
                  hintText: 'e.g. 5.00 (minimum £5)',
                  border: OutlineInputBorder(),
                  prefixIcon: Icon(Icons.attach_money),
                ),
                keyboardType: TextInputType.number,
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Please enter an amount';
                  }
                  final amount = double.tryParse(value);
                  if (amount == null) {
                    return 'Please enter a valid number';
                  }
                  if (amount <= 0) return 'Amount must be positive';
                  return null;
                },
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    // Valid amount entered - navigate to payment page
                    final userAmount = double.parse(_amountController.text);
                    final amountInPence = (userAmount * 100).toInt();
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => PaymentPage(
                          userAmount: userAmount,
                          backendAmount: amountInPence.toString(),
                        ),
                      ),
                    );
                  }
                },
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 40,
                    vertical: 15,
                  ),
                ),
                child: const Text('Proceed to Payment'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// Payment page that uses the FlickPayment SDK
class PaymentPage extends StatefulWidget {
  final double userAmount; // What user sees (e.g. 5.0)
  final String backendAmount; // What gets sent to backend (e.g. "500")

  const PaymentPage({
    super.key,
    required this.userAmount,
    required this.backendAmount,
  });

  @override
  State<PaymentPage> createState() => _PaymentPageState();
}

class _PaymentPageState extends State<PaymentPage> {
  final FlickPayment _flickPayment = FlickPayment();

  @override
  void initState() {
    super.initState();
    _initializePayment();
  }

  Future<void> _initializePayment() async {
    final success = await _flickPayment.initialize(
      PaymentConfig(
          customerEmail: 'user@example.com',
          amount: widget.backendAmount,
          currency: 'GBP',
          transactionId: 'Flick-${DateTime.now().millisecondsSinceEpoch}',
          bearerToken: 'your-api-bearer-token',
          redirectUrl: "https://merchant.getflick.co/"),
      onPaymentCompleted: _showPaymentResult,
    );

    if (!mounted) return;

    setState(() {});

    if (!success) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(
            _flickPayment.initializationError ??
                'Payment initialization failed',
          ),
          duration: const Duration(seconds: 5),
        ),
      );
    }
  }

  // Add this reset function
  Future<void> _resetApp() async {
    // First reset the SDK
    await _flickPayment.reset();

    // Then navigate back to the amount input page
    if (!mounted) return;
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(
        builder: (context) => const AmountInputPage(),
      ),
    );
  }

  void _showPaymentResult(PaymentStatusDetails statusDetails) {
    if (statusDetails.transactionStatus.toLowerCase() == 'successful') {
      _showSuccessDialog(
        'Payment Successful',
        'Amount: £${(int.parse(statusDetails.transactionAmount)).toStringAsFixed(2)}\n'
            'Reference: ${statusDetails.transactionRef}',
      );
    } else {
      _showErrorDialog(
        'Payment ${statusDetails.transactionStatus}',
        statusDetails.description,
      );
    }
  }

  void _showSuccessDialog(String title, String message) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Row(
          children: [
            const Icon(Icons.check_circle, color: Colors.green),
            const SizedBox(width: 8),
            Text(title),
          ],
        ),
        content: Text(message),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.of(context).popUntil((route) => route.isFirst);
            },
            child: const Text('Done'),
          ),
        ],
      ),
    );
  }

  void _showErrorDialog(String title, String message) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Row(
          children: [
            const Icon(Icons.error, color: Colors.red),
            const SizedBox(width: 8),
            Text(title),
          ],
        ),
        content: Text(message),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Try Again'),
          ),
          TextButton(
            onPressed: () {
              Navigator.of(context).popUntil((route) => route.isFirst);
            },
            child: const Text('Cancel'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Complete Payment'),
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            tooltip: 'Start over',
            onPressed: _resetApp,
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            // Payment amount display at the top
            Container(
              padding: const EdgeInsets.all(16.0),
              decoration: BoxDecoration(
                color: Colors.grey.shade100,
                borderRadius: BorderRadius.circular(12),
              ),
              child: Column(
                children: [
                  const Text(
                    'Amount to Pay',
                    style: TextStyle(fontSize: 16, color: Colors.grey),
                  ),
                  const SizedBox(height: 8),
                  Text(
                    '£${widget.userAmount.toStringAsFixed(2)}',
                    style: const TextStyle(
                      fontSize: 36,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 20),

            Expanded(
              child: Container(),
            ),

            // Payment button at the very bottom
            _flickPayment.createPaymentButton(context),
          ],
        ),
      ),
    );
  }
}
0
likes
0
points
69
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter SDK for Flick Payment processing

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, google_fonts, http, shared_preferences, url_launcher

More

Packages that depend on flick_payment_sdk