Flutter app integration


Flutter supports using shared packages contributed by other developers to the Flutter and Dart ecosystems. This allows quickly building an app without having to develop everything from scratch. This plugin will support in integrating payment gateway into your flutter application.
To refer offical doumentation of the flutter plugin click here .

In our API Specifications you can find a full list of parameters that can be sent in the initial request.


Use this package as a library

Run this command with flutter :

$ flutter pub add standard_checkout_plugin

This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get):

dependencies:
  standard_checkout_plugin: ^1.0.0

Now in your Dart code, you can use:

import 'package:standard_checkout_plugin/checkout_plugin.dart';

Below is the example of the sample code

example/lib/main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:standard_checkout_plugin/checkout_plugin.dart';
import 'package:standard_checkout_plugin/model/pay_request.dart';
import 'package:http/http.dart' as http;
import 'package:standard_checkout_plugin/model/pay_result.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Checkout Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: true,
      ),
      home: const CheckoutActivity(),
    );
  }
}

class CheckoutActivity extends StatefulWidget {
  const CheckoutActivity({super.key});

  @override
  State createState() => _CheckoutActivityState();
}

class _CheckoutActivityState extends State {
  final TextEditingController _descriptionController = TextEditingController();
  final TextEditingController _amountController = TextEditingController();
  final _formKey = GlobalKey();
  late PayRequest _payRequest;
  bool _isProcessing = false;
  String _ipAddress = 'Fetching IP...';

  @override
  void initState() {
    super.initState();
    _initializePayRequest();
    _getRealIPAddress();
  }

  void _initializePayRequest() {
    _payRequest = PayRequest(
      memberId: '14691',
      toType: 'TWPayz',
      memberKey: 'KsidL3VNx4rNaxPG9eYBNXNVmxlbZXvn',
      amount: '',
      currency: 'GBP',
      merchantTransactionId: '',
      hostUrl: 'https://sandbox.twpayz.com/transaction/Checkout',
    );

    _payRequest.orderDescription = 'Testing Transaction';
    _payRequest.country = 'IN';
    _payRequest.city = 'Mumbai';
    _payRequest.state = 'MH';
    _payRequest.postCode = '400064';
    _payRequest.street = 'Malad';
    _payRequest.telnocc = '91';
    _payRequest.phone = '8668459089';
    _payRequest.email = 'riya.patel@gmail.com';
    _payRequest.paymentBrand = '';      // Added - matches Android
    _payRequest.paymentMode = '';       // Added - matches Android
    _payRequest.terminalId = '';        // Added - matches Android
    _payRequest.ipAddress = '';
    _payRequest.device = 'flutter';
  }

  // Method to get IP address
  static Future getIPForTransaction() async {
    try {
      final response = await http.get(Uri.parse('https://api.ipify.org?format=json'));
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        final ip = data['ip'] as String?;
        return ip;
      }
      return null;
    } catch (e) {
      print('Failed to get IP: $e');
      return null;
    }
  }

// Method to fetch and set IP in the UI
  Future _getRealIPAddress() async {
    final ip = await getIPForTransaction();
    if (mounted) {
      setState(() {
        _ipAddress = ip ?? 'Not available';
        _payRequest.ipAddress = ip ?? '';
      });
    }
  }
  void _startPayment() async {
    // Check if IP is empty FIRST - before anything else
    if (_payRequest.ipAddress == null || _payRequest.ipAddress!.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('❌ IP Address is empty. Please check your internet connection.'),
          backgroundColor: Colors.red,
          duration: Duration(seconds: 3),
        ),
      );
      return;
    }

    // Then validate the form
    if (_formKey.currentState!.validate()) {
      setState(() => _isProcessing = true);

      _payRequest.merchantTransactionId = _descriptionController.text;
      _payRequest.amount = double.parse(_amountController.text).toStringAsFixed(2);

      try {
        await FlutterPaymentCheckout.initPayment(
          context: context,
          payRequest: _payRequest,
          onSuccess: (PayResult result) {
            if (mounted) {
              setState(() => _isProcessing = false);
             
              // ✅ Just reset the form and navigate if needed
              _resetForm();
            }
          },
          onFailure: (PayResult result) {
            if (mounted) {
              setState(() => _isProcessing = false);
             
              // ✅ Just reset the form
              _resetForm();
            }
          },
        );
      } catch (e) {
        if (mounted) {
          setState(() => _isProcessing = false);
          ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(content: Text('Error: ${e.toString()}'))
          );
        }
      }
    }
  }

// ✅ Add this helper method to reset form
  void _resetForm() {
    _descriptionController.clear();
    _amountController.clear();
    _formKey.currentState?.reset();

  }

  String? _validateDescription(String? value) {
    if (value == null || value.isEmpty) return 'Order description is required';
    if (value.length < 3) return 'Description must be at least 3 characters';
    return null;
  }

  String? _validateAmount(String? value) {
    if (value == null || value.isEmpty) return 'Amount is required';
    final amount = double.tryParse(value);
    if (amount == null || amount <= 0) return 'Please enter a valid amount';
    if (amount > 999999.99) return 'Amount is too high';
    return null;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Checkout Demo'),
        backgroundColor: Colors.blue,
        foregroundColor: Colors.white,
      ),
      body: Form(
        key: _formKey,
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              TextFormField(
                controller: _descriptionController,
                decoration: const InputDecoration(
                  labelText: 'Order Description',
                  hintText: 'Enter order description',
                  border: OutlineInputBorder(),
                  prefixIcon: Icon(Icons.description),
                ),
                validator: _validateDescription,
              ),
              const SizedBox(height: 16),
              TextFormField(
                controller: _amountController,
                decoration: const InputDecoration(
                  labelText: 'Amount',
                  hintText: 'Enter amount',
                  border: OutlineInputBorder(),
                  prefixIcon: Icon(Icons.currency_pound),
                  suffixText: 'GBP',
                ),
                keyboardType: TextInputType.numberWithOptions(decimal: true),
                validator: _validateAmount,
              ),
              const SizedBox(height: 24),
              Card(
                elevation: 2,
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text('Payment Details:', style: TextStyle(fontWeight: FontWeight.bold)),
                      const Divider(),
                      _buildInfoRow('Member ID:', _payRequest.memberId ?? ''),
                      _buildInfoRow('Currency:', _payRequest.currency ?? ''),
                      _buildInfoRow('IP Address:', _ipAddress),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 24),
              ElevatedButton(
                onPressed: _isProcessing ? null : _startPayment,
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.blue,
                  foregroundColor: Colors.white,
                  padding: const EdgeInsets.symmetric(vertical: 16),
                ),
                child: _isProcessing
                    ? const SizedBox(height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2))
                    : const Text('Pay Now', style: TextStyle(fontSize: 18)),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildInfoRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        children: [
          SizedBox(width: 100, child: Text(label)),
          Expanded(child: Text(value)),
        ],
      ),
    );
  }

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

Payment Modes and Brands

Find below the list of payment modes and brands for standard checkout.

Show all modes and brands

Mode Brand