open_payment 4.0.7 copy "open_payment: ^4.0.7" to clipboard
open_payment: ^4.0.7 copied to clipboard

Flutter plugin which lets you seamlessly integrate OPEN Payment Gateway with your Flutter app and start collecting payments from your customers.

example/lib/main.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:http/http.dart' as http;

import 'package:open_payment/open_payment.dart';

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

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final TextEditingController _accessTokenController = TextEditingController();
  final TextEditingController _paymentTokenController = TextEditingController();
  final TextEditingController _mainColorController = TextEditingController();
  final TextEditingController _errorColorController = TextEditingController();
  final TextEditingController _logoUrlController = TextEditingController();
  PaymentEnvironment environment = PaymentEnvironment.preprod;
  String? result;
  bool isLoading = false;
  bool isGetDataButtonEnabled = true; // Control Get Data button state

  @override
  void initState() {
    super.initState();
    print('isGetDataButtonEnabled: $isGetDataButtonEnabled'); // Debug print
  }

  @override
  void dispose() {
    _accessTokenController.dispose();
    _paymentTokenController.dispose();
    _mainColorController.dispose();
    _errorColorController.dispose();
    _logoUrlController.dispose();
    super.dispose();
  }

  // API call to fetch data
  Future<void> fetchDataFromAPI() async {
    setState(() {
      isLoading = true;
      result = null;
    });

    try {
      final response = await http.get(
        Uri.parse('https://571252e6-bbb9-49ad-a77e-7a1fa2d722e4.mock.pstmn.io/initApp'),
      );

      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        
        setState(() {
          _accessTokenController.text = data['accessToken'] ?? '';
          _paymentTokenController.text = data['paymentToken'] ?? '';
          _mainColorController.text = data['mainColor'] ?? '';
          _errorColorController.text = data['errorColor'] ?? '';
          _logoUrlController.text = data['logo'] ?? '';
          result = 'Data loaded successfully from API!';
        });
      } else {
        setState(() {
          result = 'Error: Failed to load data. Status: ${response.statusCode}';
        });
      }
    } catch (e) {
      setState(() {
        result = 'Error: Failed to connect to API. $e';
      });
    } finally {
      setState(() {
        isLoading = false;
      });
    }
  }

  // Clear all input fields
  void clearData() {
    setState(() {
      _accessTokenController.clear();
      _paymentTokenController.clear();
      _mainColorController.clear();
      _errorColorController.clear();
      _logoUrlController.clear();
      result = null;
    });
  }

  // Validation method for hex color codes
  bool isValidHexColor(String color) {
    if (color.isEmpty) return false;
    // Remove # if present
    String hexColor = color.startsWith('#') ? color.substring(1) : color;
    // Check if it's 3 or 6 characters and contains only valid hex characters
    return RegExp(r'^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$').hasMatch(hexColor);
  }

  // Validation method for URL
  bool isValidUrl(String url) {
    if (url.isEmpty) return true; // URL is optional
    try {
      Uri.parse(url);
      return true;
    } catch (e) {
      return false;
    }
  }

  // Get validation error message for color fields
  String? getColorValidationError(String color, String fieldName) {
    if (color.isEmpty) {
      return null; // Color is optional
    }
    if (!isValidHexColor(color)) {
      return '$fieldName must be a valid hex color (e.g., #FF0000 or #F00)';
    }
    return null;
  }

  // Get validation error message for URL field
  String? getUrlValidationError(String url) {
    if (url.isEmpty) {
      return null; // URL is optional
    }
    if (!isValidUrl(url)) {
      return 'Logo URL must be a valid URL';
    }
    return null;
  }

  Future<void> onPaymentClick() async {
    final accessToken = _accessTokenController.text.trim();
    final paymentToken = _paymentTokenController.text.trim();
    final mainColor = _mainColorController.text.trim();
    final errorColor = _errorColorController.text.trim();
    final logoUrl = _logoUrlController.text.trim();

    // Validate required fields
    if (accessToken.isEmpty) {
      setState(() {
        result = 'Error: Access Token is required';
      });
      return;
    }

    if (paymentToken.isEmpty) {
      setState(() {
        result = 'Error: Payment Token is required';
      });
      return;
    }

    // Validate optional fields only if they have values
    if (mainColor.isNotEmpty && !isValidHexColor(mainColor)) {
      setState(() {
        result = 'Error: Main Color must be a valid hex color';
      });
      return;
    }

    if (errorColor.isNotEmpty && !isValidHexColor(errorColor)) {
      setState(() {
        result = 'Error: Error Color must be a valid hex color';
      });
      return;
    }

    if (logoUrl.isNotEmpty && !isValidUrl(logoUrl)) {
      setState(() {
        result = 'Error: Logo URL must be a valid URL';
      });
      return;
    }

    OpenPaymentPayload openPaymentPayload = OpenPaymentPayload(
      accessToken: accessToken,
      paymentToken: paymentToken,
      environment: environment,
      mainColor: mainColor.isNotEmpty ? mainColor : null,
      errorColor: errorColor.isNotEmpty ? errorColor : null,
      logoUrl: logoUrl.isNotEmpty ? logoUrl : null,
    );

    await OpenPayment.initiatePayment(
      openPaymentPayload: openPaymentPayload,
      onTransactionComplete: (TransactionDetails transactionDetails) {
        setState(() {
          result = jsonEncode(transactionDetails.toJson());
        });
      },
      onError: (String error) {
        setState(() {
          result = error;
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Open Payment Demo'),
        ),
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // Environment selector dropdown
              DropdownButtonFormField<PaymentEnvironment>(
                value: environment,
                decoration: const InputDecoration(
                  labelText: 'Environment',
                  border: OutlineInputBorder(),
                ),
                items: const [
                  DropdownMenuItem(
                    value: PaymentEnvironment.preprod,
                    child: Text('Preprod'),
                  ),
                  DropdownMenuItem(
                    value: PaymentEnvironment.live,
                    child: Text('Live'),
                  ),
                ],
                onChanged: (env) {
                  if (env != null) {
                    setState(() {
                      environment = env;
                    });
                  }
                },
              ),
              const SizedBox(height: 16),
              TextField(
                controller: _accessTokenController,
                decoration: const InputDecoration(
                  labelText: 'Access Token',
                  border: OutlineInputBorder(),
                  hintText: 'Enter your access token',
                  hintStyle: TextStyle(color: Colors.grey),
                ),
              ),
              const SizedBox(height: 16),
              TextField(
                controller: _paymentTokenController,
                decoration: const InputDecoration(
                  labelText: 'Payment Token',
                  border: OutlineInputBorder(),
                  hintText: 'Enter your payment token',
                  hintStyle: TextStyle(color: Colors.grey),
                ),
              ),
              const SizedBox(height: 16),
              // Main Color and Error Color in horizontal layout
              Row(
                children: [
                  Expanded(
                    child: TextField(
                      controller: _mainColorController,
                      decoration: InputDecoration(
                        labelText: 'Main Color (#83025c)',
                        border: const OutlineInputBorder(),
                        hintText: '#83025c',
                        hintStyle: const TextStyle(color: Colors.grey),
                        errorText: getColorValidationError(_mainColorController.text, 'Main Color'),
                      ),
                      onChanged: (value) {
                        setState(() {
                          // Trigger validation on change
                        });
                      },
                    ),
                  ),
                  const SizedBox(width: 16),
                  Expanded(
                    child: TextField(
                      controller: _errorColorController,
                      decoration: InputDecoration(
                        labelText: 'Error Color (#ff0000)',
                        border: const OutlineInputBorder(),
                        hintText: '#ff0000',
                        hintStyle: const TextStyle(color: Colors.grey),
                        errorText: getColorValidationError(_errorColorController.text, 'Error Color'),
                      ),
                      onChanged: (value) {
                        setState(() {
                          // Trigger validation on change
                        });
                      },
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 16),
              TextField(
                controller: _logoUrlController,
                decoration: InputDecoration(
                  labelText: 'Logo URL',
                  border: const OutlineInputBorder(),
                  hintText: 'https://example.com/logo.png',
                  hintStyle: const TextStyle(color: Colors.grey),
                  errorText: getUrlValidationError(_logoUrlController.text),
                ),
                onChanged: (value) {
                  setState(() {
                    // Trigger validation on change
                  });
                },
              ),
              const SizedBox(height: 24),
              // Get Data and Clear Data buttons in horizontal layout
              Row(
                children: [
                  Expanded(
                    child: SizedBox(
                      height: 48, // Standard Material Design button height
                      child: ElevatedButton(
                        onPressed: isGetDataButtonEnabled ? fetchDataFromAPI : null,
                        style: ElevatedButton.styleFrom(
                          backgroundColor: isGetDataButtonEnabled ? Colors.blue : Colors.grey,
                          foregroundColor: Colors.white,
                          disabledBackgroundColor: Colors.grey,
                          disabledForegroundColor: Colors.white70,
                          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                          textStyle: const TextStyle(
                            fontSize: 16,
                            fontWeight: FontWeight.w500,
                          ),
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(4),
                          ),
                        ),
                        child: const Text('Get Data'),
                      ),
                    ),
                  ),
                  const SizedBox(width: 16),
                  Expanded(
                    child: SizedBox(
                      height: 48, // Standard Material Design button height
                      child: ElevatedButton(
                        onPressed: clearData,
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.orange,
                          foregroundColor: Colors.white,
                          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                          textStyle: const TextStyle(
                            fontSize: 16,
                            fontWeight: FontWeight.w500,
                          ),
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(4),
                          ),
                        ),
                        child: const Text('Clear Data'),
                      ),
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 16),
              SizedBox(
                height: 48, // Standard Material Design button height
                width: double.infinity, // Full width
                child: ElevatedButton(
                  onPressed: onPaymentClick,
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Theme.of(context).primaryColor,
                    foregroundColor: Colors.white,
                    padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                    textStyle: const TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w500,
                    ),
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(4),
                    ),
                  ),
                  child: const Text('Initiate Payment'),
                ),
              ),
              const SizedBox(height: 24),
              if (result != null)
                Container(
                  padding: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.grey),
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Text(
                    'Result: $result',
                    style: const TextStyle(fontSize: 14),
                  ),
                ),
              const SizedBox(height: 24),
            ],
          ),
        ),
      ),
    );
  }
}
8
likes
160
points
670
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter plugin which lets you seamlessly integrate OPEN Payment Gateway with your Flutter app and start collecting payments from your customers.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

analyzer, flutter, json_annotation

More

Packages that depend on open_payment

Packages that implement open_payment