easymerchantsdk 1.0.6 copy "easymerchantsdk: ^1.0.6" to clipboard
easymerchantsdk: ^1.0.6 copied to clipboard

Flutter SDK for EasyMerchant's native mobile checkout integration.

EasyMerchantSDK for Flutter #

The easymerchantsdk package provides a Flutter interface for integrating payment processing capabilities into mobile applications, supporting both iOS and Android platforms. It enables one-time and recurring payments with extensive customization options for theming, billing fields, metadata, and GrailPay integration. This README offers a detailed guide for setting up and using the SDK, including parameter explanations and example code based on a fully-featured implementation.

Installation #

Add the easymerchantsdk package to your Flutter project by including it in your pubspec.yaml file:

dependencies:
  easymerchantsdk: ^1.0.6
  flutter:
    sdk: flutter

Run the following command to install the package:

flutter pub get

Setup #

Android Setup #

  1. Update build.gradle: Open android/build.gradle and add the following to the allprojects.repositories section to include necessary Maven repositories:

    allprojects {
        repositories {
            google()
            mavenCentral()
            maven { url 'https://jitpack.io' }
            maven {
                url = uri(properties.getProperty('GITHUB_URL'))
                credentials {
                    username = properties.getProperty('GITHUB_USERNAME')
                    password = properties.getProperty('GITHUB_PASSWORD')
                }
            }
        }
    }
    

    Define GITHUB_URL, GITHUB_USERNAME, and GITHUB_PASSWORD in gradle.properties or replace them with values provided by the SDK documentation.

  2. Permissions: Add the Internet permission to android/app/src/main/AndroidManifest.xml:

    <uses-permission android:name="android.permission.INTERNET" />
    
  3. Native Integration: Follow any additional native setup instructions in the official easymerchantsdk documentation to ensure proper integration.

iOS Setup #

Requirements

  • Ruby 3.2.8

Steps

  1. Add Permissions: Update ios/Runner/Info.plist to include network access permissions:

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    
  2. Podfile Configuration: Update ios/Podfile to include the easymerchantsdk dependency. Run pod install in the ios directory:

    cd ios
    pod install
    
  3. Native Integration: Ensure the SDK's ViewController is initialized in ios/Runner/AppDelegate.swift. Refer to the official SDK documentation for specific iOS setup steps.

Note: Consult the official easymerchantsdk documentation for complete iOS integration details or contact the SDK provider for assistance.

Usage #

The easymerchantsdk supports flexible payment processing with a rich UI for testing configurations. Below are the key steps to integrate and use the SDK, based on the provided implementation.

Initializing the SDK #

Initialize the Easymerchantsdk instance and set up platform-specific configurations, including event listeners for payment responses.

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:easymerchantsdk/easymerchantsdk.dart';

final Easymerchantsdk easymerchant = Easymerchantsdk();

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

  // Setup event listeners
  easymerchant.setupEventListeners(
    onPaymentSuccess: (data) {
      try {
        final Map<String, dynamic> newMap = jsonDecode(data);
        final sdkResult = SDKResult.fromJson(newMap);
        setState(() {
          result = jsonEncode(newMap, toEncodable: (obj) => obj.toString());
          referenceToken = sdkResult.additionalInfo?['threeDSecureStatus']?['data']?['ref_token'] ?? '';
        });
      } catch (e) {
        setState(() {
          result = 'Payment success but error parsing response: $e';
        });
      }
    },
    onPaymentStatus: (data) {
      setState(() {
        result = 'Payment Status: $data';
      });
    },
    onPaymentStatusError: (error) {
      setState(() {
        result = 'Payment Error: $error';
      });
    },
  );

  WidgetsBinding.instance.addPostFrameCallback((_) {
    initPlatformState();
    if (Platform.isIOS) {
      initializeViewController();
    }
    _configureEnvironment();
  });
}

Future<void> initializeViewController() async {
  try {
    await easymerchant.setViewController();
    debugPrint('ViewController initialized successfully');
  } catch (e) {
    debugPrint('Failed to initialize ViewController: $e');
  }
}

Future<void> initPlatformState() async {
  try {
    final platformVersion = await easymerchant.getPlatformVersion() ?? 'Unknown';
    setState(() {
      _platformVersion = platformVersion;
    });
  } catch (e) {
    setState(() {
      _platformVersion = 'Failed to get platform version: $e';
    });
  }
}

Configuring the Environment #

Configure the SDK with the desired environment and API keys.

Future<void> _configureEnvironment() async {
  try {
    final keys = {
      'apiKey': '75e47d32521175e04b4b65234', // Replace with your API key
      'secretKey': '556f980d99f15599adaad1b56', // Replace with your secret key
    };
    await easymerchant.configureEnvironment(
      'sandbox', // or 'staging'
      keys['apiKey']!,
      keys['secretKey']!,
    );
    debugPrint('Environment configured: sandbox');
  } catch (e) {
    debugPrint('Configuration error: $e');
  }
}

Starting a Payment #

Initiate payments using the billing method for iOS or makePayment for Android, with extensive configuration options.

Future<void> _startBilling() async {
  if (amountController.text.isEmpty || double.tryParse(amountController.text) == null || double.parse(amountController.text) <= 0) {
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Please enter a valid amount')));
    return;
  }
  if (emailController.text.isEmpty) {
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Please enter an email address')));
    return;
  }

  setState(() {
    result = 'Processing payment...';
  });

  try {
    if (Platform.isIOS) {
      await easymerchant.setViewController();
      final response = await easymerchant.billing(
        amount: amountController.text.trim(),
        currency: 'usd',
        fields: jsonEncode({
          'visibility': {'billing': isBillingVisible, 'additional': isAdditionalVisible},
          'billing': {
            'address': 'Address',
            'country': 'Country',
            'state': 'State',
            'city': 'City',
            'postal_code': 'Postal Code',
          },
          'billingRequired': {
            'address': true,
            'country': true,
            'state': true,
            'city': true,
            'postal_code': true,
          },
          'additional': {
            'phone_number': '0000000000',
            'description': 'Test Payment',
          },
          'additionalRequired': {
            'phone_number': true,
            'description': true,
          },
        }),
        paymentMethods: ['card', 'ach'],
        appearanceSettings: {
          'bodyBackgroundColor': '#0f1715',
          'containerBackgroundColor': '#152321',
          'primaryFontColor': '#FFFFFF',
          'secondaryFontColor': '#A0B5A4',
          'primaryButtonBackgroundColor': '#10B981',
          'primaryButtonHoverColor': '#059669',
          'primaryButtonFontColor': '#FFFFFF',
          'secondaryButtonBackgroundColor': '#374151',
          'secondaryButtonHoverColor': '#4B5563',
          'secondaryButtonFontColor': '#E5E7EB',
          'borderRadius': '8',
          'fontSize': '14',
        },
        tokenOnly: false,
        saveCard: true,
        saveAccount: true,
        authenticatedACH: isAuthenticatedACH,
        grailPayParams: {
          'role': 'business',
          'timeout': 10,
          'isSandbox': true,
          'brandingName': 'Lyfecycle Payments',
          'finderSubtitle': 'Search for your bank',
          'searchPlaceholder': 'Enter bank name',
        },
        submitButtonText: 'Submit',
        isRecurring: isRecurring,
        numOfCycle: 2,
        recurringIntervals: ['weekly', 'monthly'],
        recurringStartDateType: 'custom',
        recurringStartDate: '07/08/2030',
        secureAuthentication: isSecureAuthentication,
        showReceipt: true,
        showTotal: true,
        showSubmitButton: true,
        isEmail: isEmail,
        email: emailController.text.trim(),
        name: nameController.text.trim().isNotEmpty ? nameController.text.trim() : 'Test User',
        enable3DS: isSecureAuthentication,
        metadata: {
          'metaKey': 'metaValue',
          'metaKey1': 'metaValue1',
        },
      );

      final responseJson = jsonDecode(response!);
      setState(() {
        result = jsonEncode(responseJson, toEncodable: (obj) => obj.toString());
      });
    } else {
      final config = {
        'environment': 'sandbox',
        'apiKey': '75e47d32521175e04b4b65234',
        'secretKey': '556f980d99f15599adaad1b56',
        'amount': amountController.text.trim(),
        'currency': 'usd',
        'email': emailController.text.trim(),
        'paymentMethods': ['card', 'ach'],
        'fields': {
          'visibility': {'billing': isBillingVisible, 'additional': isAdditionalVisible},
          'billing': [
            {'name': 'address', 'required': true, 'value': 'Address'},
            {'name': 'country', 'required': true, 'value': 'Country'},
            {'name': 'state', 'required': true, 'value': 'State'},
            {'name': 'city', 'required': true, 'value': 'City'},
            {'name': 'postal_code', 'required': true, 'value': 'Postal Code'},
          ],
          'additional': [
            {'name': 'phone_number', 'required': true, 'value': '0000000000'},
            {'name': 'description', 'required': true, 'value': 'Test Payment'},
          ],
        },
        'appearanceSettings': {
          'theme': 'dark',
          'bodyBackgroundColor': '#121212',
          'containerBackgroundColor': '#1E1E1E',
          'primaryFontColor': '#FFFFFF',
          'secondaryFontColor': '#B0B0B0',
          'primaryButtonBackgroundColor': '#2563EB',
          'primaryButtonHoverColor': '#1D4ED8',
          'primaryButtonFontColor': '#FFFFFF',
          'secondaryButtonBackgroundColor': '#374151',
          'secondaryButtonHoverColor': '#4B5563',
          'secondaryButtonFontColor': '#E5E7EB',
          'borderRadius': '8',
          'fontSize': '14',
          'fontWeight': '500',
          'fontFamily': 'Inter, sans-serif',
        },
        'recurring': {
          'enableRecurring': isRecurring,
          'recurringData': {
            'allowCycles': '2',
            'intervals': ['weekly', 'monthly'],
            'recurringStartType': 'custom',
            'recurringStartDate': '07/08/2030',
          },
        },
        'metadata': {
          'metaKey': 'metaValue',
          'metaKey1': 'metaValue1',
        },
      };

      final configJson = jsonEncode(config);
      await easymerchant.makePayment(configJson);
      // Response handled by event listeners
    }
  } catch (e) {
    setState(() {
      result = 'Billing failed: $e';
    });
  }
}

Checking Payment Reference (iOS Only) #

Retrieve payment details using a reference token on iOS.

Future<void> _paymentReference() async {
  if (referenceToken.isEmpty) {
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('No reference token available')));
    return;
  }
  try {
    final response = await easymerchant.paymentReference(referenceToken);
    setState(() {
      result = jsonEncode(jsonDecode(response!), toEncodable: (obj) => obj.toString());
    });
  } catch (e) {
    setState(() {
      result = 'Payment reference failed: $e';
    });
  }
}

Full Example App #

Below is a complete example of a Flutter app with a UI for configuring and testing payments, based on the provided implementation.

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:easymerchantsdk/easymerchantsdk.dart';

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

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

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

class _MyAppState extends State<MyApp> {
  final Easymerchantsdk easymerchant = Easymerchantsdk();
  final GlobalKey<ScaffoldMessengerState> _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
  final TextEditingController amountController = TextEditingController();
  final TextEditingController emailController = TextEditingController();
  final TextEditingController nameController = TextEditingController();
  String environment = 'sandbox';
  bool isRecurring = false;
  bool isAuthenticatedACH = false;
  bool isSecureAuthentication = false;
  bool isBillingVisible = false;
  bool isAdditionalVisible = false;
  bool isEmail = true; // iOS
  bool emailEditable = true; // Android
  bool isLoading = false;
  bool showConfig = true;
  String result = 'No response yet';
  String referenceToken = '';
  String _platformVersion = 'Unknown';

  final Map<String, Map<String, String>> apiKeys = {
    'sandbox': {
      'apiKey': 'apiKey',
      'secretKey': 'secretKey',
    },
    'staging': {
      'apiKey': 'apiKey',
      'secretKey': 'secretKey',
    },
  };

  @override
  void initState() {
    super.initState();
    easymerchant.setupEventListeners(
      onPaymentSuccess: (data) {
        try {
          final Map<String, dynamic> newMap = jsonDecode(data);
          final sdkResult = SDKResult.fromJson(newMap);
          setState(() {
            result = jsonEncode(newMap, toEncodable: (obj) => obj.toString());
            referenceToken = sdkResult.additionalInfo?['threeDSecureStatus']?['data']?['ref_token'] ?? '';
            isLoading = false;
          });
        } catch (e) {
          setState(() {
            result = 'Payment success but error parsing response: $e';
            isLoading = false;
          });
        }
      },
      onPaymentStatus: (data) {
        setState(() {
          result = 'Payment Status: $data';
        });
      },
      onPaymentStatusError: (error) {
        setState(() {
          result = 'Payment Error: $error';
          isLoading = false;
        });
      },
    );

    WidgetsBinding.instance.addPostFrameCallback((_) {
      initPlatformState();
      if (Platform.isIOS) {
        initializeViewController();
      }
      _configureEnvironment();
    });
  }

  Future<void> initializeViewController() async {
    try {
      await easymerchant.setViewController();
    } catch (e) {
      _showSnackBar('Failed to initialize ViewController: $e');
    }
  }

  Future<void> initPlatformState() async {
    try {
      final platformVersion = await easymerchant.getPlatformVersion() ?? 'Unknown';
      setState(() {
        _platformVersion = platformVersion;
      });
    } catch (e) {
      setState(() {
        _platformVersion = 'Failed to get platform version: $e';
      });
    }
  }

  Future<void> _configureEnvironment() async {
    try {
      final keys = apiKeys[environment]!;
      await easymerchant.configureEnvironment(environment, keys['apiKey']!, keys['secretKey']!);
      _showSnackBar('Environment configured: $environment');
    } catch (e) {
      setState(() {
        result = 'Configuration failed: $e';
      });
      _showSnackBar(result);
    }
  }

  Future<void> _startBilling() async {
    if (amountController.text.isEmpty || double.tryParse(amountController.text) == null || double.parse(amountController.text) <= 0) {
      _showSnackBar('Please enter a valid amount');
      return;
    }
    if (emailController.text.isEmpty) {
      _showSnackBar('Please enter an email address');
      return;
    }

    setState(() {
      isLoading = true;
      result = 'Processing payment...';
    });

    try {
      if (Platform.isIOS) {
        await easymerchant.setViewController();
        final response = await easymerchant.billing(
          amount: amountController.text.trim(),
          currency: 'usd',
          fields: jsonEncode({
            'visibility': {'billing': isBillingVisible, 'additional': isAdditionalVisible},
            'billing': {
              'address': 'Address',
              'country': 'Country',
              'state': 'State',
              'city': 'City',
              'postal_code': 'Postal Code',
            },
            'billingRequired': {
              'address': true,
              'country': true,
              'state': true,
              'city': true,
              'postal_code': true,
            },
            'additional': {
              'phone_number': '0000000000',
              'description': 'Test Payment',
            },
            'additionalRequired': {
              'phone_number': true,
              'description': true,
            },
          }),
          paymentMethods: ['card', 'ach'],
          appearanceSettings: {
            'bodyBackgroundColor': '#0f1715',
            'containerBackgroundColor': '#152321',
            'primaryFontColor': '#FFFFFF',
            'secondaryFontColor': '#A0B5A4',
            'primaryButtonBackgroundColor': '#10B981',
            'primaryButtonHoverColor': '#059669',
            'primaryButtonFontColor': '#FFFFFF',
            'secondaryButtonBackgroundColor': '#374151',
            'secondaryButtonHoverColor': '#4B5563',
            'secondaryButtonFontColor': '#E5E7EB',
            'borderRadius': '8',
            'fontSize': '14',
          },
          tokenOnly: false,
          saveCard: true,
          saveAccount: true,
          authenticatedACH: isAuthenticatedACH,
          grailPayParams: {
            'role': 'business',
            'timeout': 10,
            'isSandbox': true,
            'brandingName': 'Lyfecycle Payments',
            'finderSubtitle': 'Search for your bank',
            'searchPlaceholder': 'Enter bank name',
          },
          submitButtonText: 'Submit',
          isRecurring: isRecurring,
          numOfCycle: 2,
          recurringIntervals: ['weekly', 'monthly'],
          recurringStartDateType: 'custom',
          recurringStartDate: '07/08/2030',
          secureAuthentication: isSecureAuthentication,
          showReceipt: true,
          showTotal: true,
          showSubmitButton: true,
          isEmail: isEmail,
          email: emailController.text.trim(),
          name: nameController.text.trim().isNotEmpty ? nameController.text.trim() : 'Test User',
          enable3DS: isSecureAuthentication,
          metadata: {
            'metaKey': 'metaValue',
            'metaKey1': 'metaValue1',
          },
        );

        final responseJson = jsonDecode(response!);
        setState(() {
          result = jsonEncode(responseJson, toEncodable: (obj) => obj.toString());
          isLoading = false;
        });
      } else {
        final config = {
          'environment': environment,
          'apiKey': apiKeys[environment]!['apiKey'],
          'secretKey': apiKeys[environment]!['secretKey'],
          'amount': amountController.text.trim(),
          'currency': 'usd',
          'email': emailController.text.trim(),
          'paymentMethods': ['card', 'ach'],
          'fields': {
            'visibility': {'billing': isBillingVisible, 'additional': isAdditionalVisible},
            'billing': [
              {'name': 'address', 'required': true, 'value': 'Address'},
              {'name': 'country', 'required': true, 'value': 'Country'},
              {'name': 'state', 'required': true, 'value': 'State'},
              {'name': 'city', 'required': true, 'value': 'City'},
              {'name': 'postal_code', 'required': true, 'value': 'Postal Code'},
            ],
            'additional': [
              {'name': 'phone_number', 'required': true, 'value': '0000000000'},
              {'name': 'description', 'required': true, 'value': 'Test Payment'},
            ],
          },
          'appearanceSettings': {
            'theme': 'dark',
            'bodyBackgroundColor': '#121212',
            'containerBackgroundColor': '#1E1E1E',
            'primaryFontColor': '#FFFFFF',
            'secondaryFontColor': '#B0B0B0',
            'primaryButtonBackgroundColor': '#2563EB',
            'primaryButtonHoverColor': '#1D4ED8',
            'primaryButtonFontColor': '#FFFFFF',
            'secondaryButtonBackgroundColor': '#374151',
            'secondaryButtonHoverColor': '#4B5563',
            'secondaryButtonFontColor': '#E5E7EB',
            'borderRadius': '8',
            'fontSize': '14',
            'fontWeight': '500',
            'fontFamily': 'Inter, sans-serif',
          },
          'recurring': {
            'enableRecurring': isRecurring,
            'recurringData': {
              'allowCycles': '2',
              'intervals': ['weekly', 'monthly'],
              'recurringStartType': 'custom',
              'recurringStartDate': '07/08/2030',
            },
          },
          'metadata': {
            'metaKey': 'metaValue',
            'metaKey1': 'metaValue1',
          },
        };

        final configJson = jsonEncode(config);
        await easymerchant.makePayment(configJson);
      }
    } catch (e) {
      setState(() {
        result = 'Billing failed: $e';
        isLoading = false;
      });
      _showSnackBar('Billing failed: $e');
    }
  }

  void _showSnackBar(String message) {
    _scaffoldMessengerKey.currentState?.showSnackBar(SnackBar(content: Text(message)));
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      scaffoldMessengerKey: _scaffoldMessengerKey,
      theme: ThemeData(
        primaryColor: const Color(0xFF2563EB),
        scaffoldBackgroundColor: const Color(0xFFF9FAFB),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
            backgroundColor: const Color(0xFF2563EB),
            foregroundColor: Colors.white,
            shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
          ),
        ),
        inputDecorationTheme: const InputDecorationTheme(
          border: OutlineInputBorder(),
          contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
        ),
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('EasyMerchant Flutter App', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
          centerTitle: true,
        ),
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(20),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Text('Basic Info', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
              const SizedBox(height: 10),
              TextField(
                controller: amountController,
                decoration: const InputDecoration(
                  labelText: 'Amount (e.g., 10.00)',
                  border: OutlineInputBorder(),
                ),
                keyboardType: TextInputType.numberWithOptions(decimal: true),
              ),
              const SizedBox(height: 10),
              TextField(
                controller: emailController,
                decoration: const InputDecoration(
                  labelText: 'Email',
                  border: OutlineInputBorder(),
                ),
                keyboardType: TextInputType.emailAddress,
              ),
              const SizedBox(height: 10),
              TextField(
                controller: nameController,
                decoration: const InputDecoration(
                  labelText: 'Name',
                  border: OutlineInputBorder(),
                ),
                keyboardType: TextInputType.text,
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: isLoading ? null : _startBilling,
                child: const Text('Pay'),
              ),
              const SizedBox(height: 20),
              Text('Result: $result'),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    amountController.dispose();
    emailController.dispose();
    nameController.dispose();
    super.dispose();
  }
}

class SDKResult {
  final String type;
  final Map<String, dynamic>? chargeData;
  final Map<String, dynamic>? billingInfo;
  final Map<String, dynamic>? additionalInfo;
  final String? error;

  SDKResult({
    required this.type,
    this.chargeData,
    this.billingInfo,
    this.additionalInfo,
    this.error,
  });

  factory SDKResult.fromJson(Map<String, dynamic> json) {
    return SDKResult(
      type: json['type'] ?? 'success',
      chargeData: json['chargeData'],
      billingInfo: json['billingInfo'],
      additionalInfo: json['additionalInfo'] ?? json['additional_info'],
      error: json['error'],
    );
  }
}

Parameters #

Environment Configuration Parameters #

Parameter Type Description Example Value
environment String The environment to use (sandbox or staging). sandbox
apiKey String The API key for authentication. apiKey
secretKey String The secret key for authentication. secretkey

Billing Parameters (iOS) #

Used in the billing method for iOS.

Parameter Type Description Example Value
amount String The payment amount. 10.00
currency String The currency code (e.g., usd). usd
fields String (JSON) JSON-encoded billing and additional fields. See example below
paymentMethods List Payment methods (card, ach). ['card', 'ach']
appearanceSettings Map<String, dynamic> UI theme settings. See Theme Configuration
tokenOnly bool Return only a token. false
saveCard bool Save card details. true
saveAccount bool Save account details. true
authenticatedACH bool Enable authenticated ACH payments. false
grailPayParams Map<String, dynamic> GrailPay-specific parameters. See GrailPay Parameters
submitButtonText String Text for the submit button. Submit
isRecurring bool Enable recurring payments. false
numOfCycle int Number of recurring cycles. 2
recurringIntervals List Recurring intervals (weekly, monthly). ['weekly', 'monthly']
recurringStartDateType String Type of recurring start date (custom). custom
recurringStartDate String Start date for recurring payments (MM/DD/YYYY). 07/08/2030
secureAuthentication bool Enable 3D Secure authentication. false
showReceipt bool Show payment receipt. true
showTotal bool Show total amount in UI. true
showSubmitButton bool Show submit button in UI. true
isEmail bool Allow email input (iOS only). true
email String Email address for the transaction. test@gmail.com
name String Name associated with the transaction. Test User
enable3DS bool Enable 3D Secure for the transaction. false
metadata Map<String, dynamic> Additional metadata for the transaction. See Metadata Parameters

Example fields:

final fields = {
  'visibility': {'billing': false, 'additional': false},
  'billing': {
    'address': 'Address',
    'country': 'Country',
    'state': 'State',
    'city': 'City',
    'postal_code': 'Postal Code',
  },
  'billingRequired': {
    'address': true,
    'country': true,
    'state': true,
    'city': true,
    'postal_code': true,
  },
  'additional': {
    'phone_number': '0000000000',
    'description': 'Test Payment',
  },
  'additionalRequired': {
    'phone_number': true,
    'description': true,
  },
};

Payment Configuration Parameters (Android) #

Used in the makePayment method for Android.

Parameter Type Description Example Value
environment String The environment (sandbox or staging). sandbox
apiKey String The API key for authentication. apiKey
secretKey String The secret key for authentication. secretkey
amount String The payment amount. 10.00
currency String The currency code (e.g., usd). usd
email String Email address for the transaction. test@gmail.com
paymentMethods List Payment methods (card, ach). ['card', 'ach']
fields Map<String, dynamic> Billing and additional field configurations. See example below
appearanceSettings Map<String, dynamic> UI theme settings. See Theme Configuration
recurring Map<String, dynamic> Recurring payment configuration. See Recurring Payment Parameters
metadata Map<String, dynamic> Additional metadata for the transaction. See Metadata Parameters
tokenOnly bool Return only a token. false
saveCard bool Save card details. true
saveAccount bool Save account details. true
authenticatedACH bool Enable authenticated ACH payments. false
secureAuthentication bool Enable 3D Secure authentication. false
showReceipt bool Show payment receipt. true
showDonate bool Show donate option. false
showTotal bool Show total amount in UI. true
showSubmitButton bool Show submit button in UI. true
emailEditable bool Allow email field to be editable. true

Example fields:

final fields = {
  'visibility': {'billing': false, 'additional': false},
  'billing': [
    {'name': 'address', 'required': true, 'value': 'Address'},
    {'name': 'country', 'required': true, 'value': 'Country'},
    {'name': 'state', 'required': true, 'value': 'State'},
    {'name': 'city', 'required': true, 'value': 'City'},
    {'name': 'postal_code', 'required': true, 'value': 'Postal Code'},
  ],
  'additional': [
    {'name': 'phone_number', 'required': true, 'value': '0000000000'},
    {'name': 'description', 'required': true, 'value': 'Test Payment'},
  ],
};

Metadata Parameters #

Parameter Type Description Example Value
metadata Map<String, dynamic> Custom key-value pairs for additional data. {'metaKey': 'metaValue', 'metaKey1': 'metaValue1'}

Theme Configuration Parameters #

Customize the UI appearance for both iOS and Android.

Parameter Type Description Example Value
bodyBackgroundColor String Background color of the body. #0f1715
containerBackgroundColor String Background color of containers. #152321
primaryFontColor String Primary font color. #FFFFFF
secondaryFontColor String Secondary font color. #A0B5A4
primaryButtonBackgroundColor String Background color of primary buttons. #10B981
primaryButtonHoverColor String Hover color for primary buttons. #059669
primaryButtonFontColor String Font color for primary buttons. #FFFFFF
secondaryButtonBackgroundColor String Background color of secondary buttons. #374151
secondaryButtonHoverColor String Hover color for secondary buttons. #4B5563
secondaryButtonFontColor String Font color for secondary buttons. #E5E7EB
borderRadius String Border radius for UI elements. 8
fontSize String Font size for text. 14
fontWeight String Font weight for text (Android only). 500
fontFamily String Font family for text (Android only). Inter, sans-serif
theme String Theme setting (Android only, e.g., dark). dark

GrailPay Parameters #

Parameter Type Description Example Value
role String Role of the user (e.g., business). business
timeout int Timeout duration in seconds. 10
isSandbox bool Use sandbox environment for GrailPay. true
brandingName String Name for branding in the UI. Lyfecycle Payments
finderSubtitle String Subtitle for bank search UI. Search for your bank
searchPlaceholder String Placeholder text for bank search input. Enter bank name

Recurring Payment Parameters #

Parameter Type Description Example Value
enableRecurring bool Enable recurring payments. true
recurringData Map<String, dynamic> Recurring payment details. See below
recurringData.allowCycles String Number of recurring cycles. 2
recurringData.intervals List Recurring intervals (weekly, monthly). ['weekly', 'monthly']
recurringData.recurringStartType String Type of recurring start date (custom, fixed). custom
recurringData.recurringStartDate String Start date for recurring payments (MM/DD/YYYY). 07/08/2030

Troubleshooting #

  • MissingPluginException: Verify that easymerchantsdk is correctly integrated in pubspec.yaml, Android build.gradle, and iOS Podfile.
  • Invalid Amount: Ensure the amount is a valid number greater than 0.
  • Empty Payment Methods: At least one payment method (card or ach) must be selected.
  • JSON Serialization Errors: Ensure all configuration maps are properly formatted before encoding to JSON.
  • Authentication Errors: Verify that the apiKey and secretKey match the selected environment.
  • iOS ViewController Issues: Ensure setViewController is called before billing on iOS.
  • No Response Timeout: A fallback timeout is implemented to handle delayed responses; check the payment screen if no response is received within 10 seconds.