easymerchantsdk 1.0.5 copy "easymerchantsdk: ^1.0.5" to clipboard
easymerchantsdk: ^1.0.5 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 your mobile application. It supports both iOS and Android platforms, enabling one-time and recurring payments with customizable configurations, themes, and metadata. This README provides a comprehensive guide to setting up and using the SDK, with detailed parameter explanations and example code.

Installation #

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

dependencies:
  easymerchantsdk: ^1.0.5

Run the following command to install the package:

flutter pub get

Setup #

Android Setup #

  1. Update build.gradle: Open the android/build.gradle file in your project and add the following code to the allprojects.repositories section to include the 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')
                }
            }
        }
    }
    

    Ensure you have the GITHUB_URL, GITHUB_USERNAME, and GITHUB_PASSWORD defined in your gradle.properties file or replace them with the appropriate values provided by the SDK documentation.

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

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

iOS Setup #

Requirements

  • Ruby 3.2.8

Steps

  1. Add Permissions: Ensure your ios/Runner/Info.plist includes necessary permissions for network access, such as:

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    
  2. Podfile Configuration: Update your ios/Podfile to include the easymerchantsdk dependency. Run pod install in the ios directory to install the SDK. Refer to the official SDK documentation for specific Podfile configurations.

    cd ios
    pod install
    
  3. Native Integration: Follow any additional iOS-specific setup instructions provided by the easymerchantsdk documentation to ensure proper integration.

Note: The iOS setup section is incomplete. Please refer to the official easymerchantsdk documentation for detailed iOS integration steps or contact the SDK provider for assistance.

Usage #

The easymerchantsdk package supports flexible payment processing for both one-time and recurring transactions. Below are the key steps to integrate and use the SDK in your Flutter app.

Initializing the SDK #

Initialize the Easymerchantsdk instance and set up platform-specific configurations, such as the view controller for iOS.

import 'dart:io';
import 'package:easymerchantsdk/easymerchantsdk.dart';

final Easymerchantsdk easymerchant = Easymerchantsdk();

@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) {
    initPlatformState();
    if (Platform.isIOS) {
      initializeViewController();
    }
  });
}

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 appropriate environment (sandbox or staging) and API keys.

Future<void> _configureEnvironment() async {
  try {
    final keys = {
      'apiKey': 'your_api_key',
      'secretKey': '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 a payment using the billing method for iOS or makePayment method for Android. The SDK supports different configurations for each platform.

import 'dart:convert';

Future<void> _startBilling() async {
  try {
    if (Platform.isIOS) {
      final billingParams = {
        'amount': '10.00',
        'currency': 'usd',
        'billingInfo': jsonEncode({
          'visibility': {'billing': false, 'additional': false},
          'billing': {'address': '', 'country': '', 'state': '', 'city': '', 'postal_code': ''},
          'billingRequired': {'address': true, 'country': true, 'state': true, 'city': true, 'postal_code': true},
          'additional': {'name': 'Test User', 'email_address': 'test@gmail.com', 'phone_number': '', 'description': 'Test Payment'},
          'additionalRequired': {'name': true, 'email_address': true, 'phone_number': true, 'description': false},
        }),
        'paymentMethods': ['card', 'ach'],
        'themeConfiguration': {
          'bodyBackgroundColor': '#0f1715',
          'containerBackgroundColor': '#152321',
          'primaryFontColor': '#FFFFFF',
          'secondaryFontColor': '#A0B5A4',
          'primaryButtonBackgroundColor': '#10B981',
          'primaryButtonHoverColor': '#059669',
          'primaryButtonFontColor': '#FFFFFF',
          'secondaryButtonBackgroundColor': '#374151',
          'secondaryButtonHoverColor': '#4B5563',
          'secondaryButtonFontColor': '#E5E7EB',
          'borderRadius': '8',
          'fontSize': '14',
          'fontWeight': 500,
          'fontFamily': '"Inter", sans-serif',
        },
        'tokenOnly': false,
        'saveCard': true,
        'saveAccount': true,
        'authenticatedACH': false,
        'grailPayParams': {
          'role': 'business',
          'timeout': 10,
          'isSandbox': true,
          'brandingName': 'Lyfecycle Payments',
          'finderSubtitle': 'Search for your bank',
          'searchPlaceholder': 'Enter bank name',
        },
        'submitButtonText': 'Submit',
        'isRecurring': false,
        'numOfCycle': 2,
        'recurringIntervals': ['weekly', 'monthly'],
        'recurringStartDateType': 'custom',
        'recurringStartDate': '07/08/2030',
        'secureAuthentication': false,
        'showReceipt': true,
        'showTotal': true,
        'showSubmitButton': true,
        'isEmail': true,
        'email': 'test@gmail.com',
        'name': 'Test User',
        'enable3DS': false,
        'metadata': {'metaKey': 'metaValue', 'metaKey1': 'metaValue1'},
      };

      final response = await easymerchant.billing(
        amount: billingParams['amount'],
        currency: billingParams['currency'],
        billingInfo: billingParams['billingInfo'],
        paymentMethods: List<String>.from(billingParams['paymentMethods']),
        themeConfiguration: billingParams['themeConfiguration'],
        tokenOnly: billingParams['tokenOnly'],
        saveCard: billingParams['saveCard'],
        saveAccount: billingParams['saveAccount'],
        authenticatedACH: billingParams['authenticatedACH'],
        grailPayParams: billingParams['grailPayParams'],
        submitButtonText: billingParams['submitButtonText'],
        isRecurring: billingParams['isRecurring'],
        numOfCycle: billingParams['numOfCycle'],
        recurringIntervals: List<String>.from(billingParams['recurringIntervals']),
        recurringStartDateType: billingParams['recurringStartDateType'],
        recurringStartDate: billingParams['recurringStartDate'],
        secureAuthentication: billingParams['secureAuthentication'],
        showReceipt: billingParams['showReceipt'],
        showTotal: billingParams['showTotal'],
        showSubmitButton: billingParams['showSubmitButton'],
        isEmail: billingParams['isEmail'],
        email: billingParams['email'],
        name: billingParams['name'],
        enable3DS: billingParams['enable3DS'],
        metadata: billingParams['metadata'],
      );

      final responseJson = jsonDecode(response!);
      final sdkResult = SDKResult.fromJson(responseJson);
      debugPrint('SDKResult: type=${sdkResult.type}, billingInfo=${sdkResult.billingInfo}');
    } else {
      final config = {
        'environment': 'sandbox',
        'apiKey': 'your_api_key',
        'secretKey': 'your_secret_key',
        'amount': '10.00',
        'currency': 'usd',
        'email': 'test@gmail.com',
        'paymentMethods': ['card', 'ach'],
        'fields': {
          'visibility': {'billing': false, 'additional': false},
          'billing': [
            {'name': 'address', 'required': true, 'value': ''},
            {'name': 'country', 'required': true, 'value': ''},
            {'name': 'state', 'required': true, 'value': ''},
            {'name': 'city', 'required': true, 'value': 'Goa'},
            {'name': 'postal_code', 'required': true, 'value': ''},
          ],
          'additional': [
            {'name': 'name', 'required': true, 'value': 'Test User'},
            {'name': 'email_address', 'required': true, 'value': 'test@gmail.com'},
            {'name': 'phone_number', 'required': true, 'value': ''},
            {'name': 'description', 'required': true, 'value': 'Hi This is description'},
          ],
        },
        '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',
        },
        'metadata': {'metaKey': 'metaValue', 'metaKey1': 'metaValue1'},
      };

      final configJson = jsonEncode(config);
      final response = await easymerchant.makePayment(configJson);
      final responseJson = jsonDecode(response);
      final sdkResult = SDKResult.fromJson(responseJson);
      debugPrint('SDKResult: type=${sdkResult.type}, billingInfo=${sdkResult.billingInfo}');
    }
  } catch (e) {
    debugPrint('Billing error: $e');
  }
}

Checking Payment Reference (iOS Only) #

Retrieve payment reference details using a reference token on iOS.

Future<void> _paymentReference() async {
  if (referenceToken.isEmpty) {
    debugPrint('No reference token available');
    return;
  }
  try {
    final response = await easymerchant.paymentReference(referenceToken);
    final responseJson = jsonDecode(response!);
    debugPrint('Payment Reference: $responseJson');
  } catch (e) {
    debugPrint('Payment reference failed: $e');
  }
}

Parameters #

Below is a detailed breakdown of the parameters supported by the easymerchantsdk.

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
billingInfo String (JSON) JSON-encoded billing information. See example below
paymentMethods List Payment methods (card, ach). ['card', 'ach']
themeConfiguration 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 billingInfo:

final billingInfo = {
  'visibility': {'billing': false, 'additional': false},
  'billing': {'address': '', 'country': '', 'state': '', 'city': '', 'postal_code': ''},
  'billingRequired': {'address': true, 'country': true, 'state': true, 'city': true, 'postal_code': true},
  'additional': {'name': 'Test User', 'email_address': 'test@gmail.com', 'phone_number': '', 'description': 'Test Payment'},
  'additionalRequired': {'name': true, 'email_address': true, 'phone_number': true, 'description': false},
};

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. 75e47d32521175e04b4b65234
secretKey String The secret key for authentication. 556f980d99f15599adaad1b56
amount String The payment amount. 10.00
tokenOnly bool Return only a token. false
currency String The currency code (e.g., usd). usd
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
paymentMethods List Payment methods (card, ach). ['card', 'ach']
emailEditable bool Allow email field to be editable. true
email String Email address for the transaction. test@gmail.com
name String Name associated with the transaction. Test User
showFields bool Show billing/additional fields. false
fields Map<String, dynamic> Billing and additional field configurations. See example below
recurring Map<String, dynamic> Recurring payment configuration. See Recurring Payment Parameters
grailPayParams Map<String, dynamic> GrailPay-specific parameters. See GrailPay Parameters
appearanceSettings Map<String, dynamic> UI theme settings. See Theme Configuration Parameters
metadata Map<String, dynamic> Additional metadata for the transaction. See Metadata Parameters

Example fields:

final fields = {
  'visibility': {'billing': false, 'additional': false},
  'billing': [
    {'name': 'address', 'required': true, 'value': ''},
    {'name': 'country', 'required': true, 'value': ''},
    {'name': 'state', 'required': true, 'value': ''},
    {'name': 'city', 'required': true, 'value': 'Goa'},
    {'name': 'postal_code', 'required': true, 'value': ''},
  ],
  'additional': [
    {'name': 'name', 'required': true, 'value': 'Test User'},
    {'name': 'email_address', 'required': true, 'value': 'test@gmail.com'},
    {'name': 'phone_number', 'required': true, 'value': ''},
    {'name': 'description', 'required': true, 'value': 'Hi This is description'},
  ],
};

Metadata Parameters #

The metadata parameter allows you to include custom key-value pairs for tracking additional data with the transaction.

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

Example:

final metadata = {
  'metaKey': 'metaValue',
  'metaKey1': 'metaValue1',
  'metaKey2': 'metaValue2',
};

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 int Font weight for text. 500
fontFamily String Font family for text. "Inter", sans-serif

GrailPay Parameters #

Configure GrailPay-specific settings for bank search and branding.

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 #

Configure recurring payment settings.

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

Android-Specific Configuration Parameters #

Additional settings for Android.

Parameter Type Description Example Value
currency String Currency code. usd
saveCard bool Save card details. true
saveAccount bool Save account details. true
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
name String Name associated with the transaction. Pavan
appearanceSettings Map<String, dynamic> UI theme settings. See Theme Configuration

Example Code #

Below is a complete example of a Flutter app integrating the easymerchantsdk, based on the provided implementation. This example includes a UI for entering payment details and handling responses.

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 TextEditingController amountController = TextEditingController();
  final TextEditingController emailController = TextEditingController();
  String result = 'No response yet';
  String environment = 'sandbox';
  final Map<String, String> apiKeys = {
    'sandbox': {
      'apiKey': '75e47d32521175e04b4b65234',
      'secretKey': '556f980d99f15599adaad1b56',
    },
    'staging': {
      'apiKey': '13bcb1f54b894ddbbd75a86d5',
      'secretKey': '94f7ebd5384f6985f23920c13',
    },
  }.cast<String, Map<String, String>>();

  @override
  void initState() {
    super.initState();
    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';
      });
    }
  }

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

  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) {
        final billingParams = {
          'amount': amountController.text.trim(),
          'currency': 'usd',
          'billingInfo': jsonEncode({
            'visibility': {'billing': false, 'additional': false},
            'billing': {'address': '', 'country': '', 'state': '', 'city': '', 'postal_code': ''},
            'billingRequired': {'address': true, 'country': true, 'state': true, 'city': true, 'postal_code': true},
            'additional': {'name': 'Test User', 'email_address': emailController.text.trim(), 'phone_number': '', 'description': 'Test Payment'},
            'additionalRequired': {'name': true, 'email_address': true, 'phone_number': true, 'description': false},
          }),
          'paymentMethods': ['card', 'ach'],
          'themeConfiguration': {
            'bodyBackgroundColor': '#0f1715',
            'containerBackgroundColor': '#152321',
            'primaryFontColor': '#FFFFFF',
            'secondaryFontColor': '#A0B5A4',
            'primaryButtonBackgroundColor': '#10B981',
            'primaryButtonHoverColor': '#059669',
            'primaryButtonFontColor': '#FFFFFF',
            'secondaryButtonBackgroundColor': '#374151',
            'secondaryButtonHoverColor': '#4B5563',
            'secondaryButtonFontColor': '#E5E7EB',
            'borderRadius': '8',
            'fontSize': '14',
            'fontWeight': 500,
            'fontFamily': '"Inter", sans-serif',
          },
          'tokenOnly': false,
          'saveCard': true,
          'saveAccount': true,
          'authenticatedACH': false,
          'grailPayParams': {
            'role': 'business',
            'timeout': 10,
            'isSandbox': true,
            'brandingName': 'Lyfecycle Payments',
            'finderSubtitle': 'Search for your bank',
            'searchPlaceholder': 'Enter bank name',
          },
          'submitButtonText': 'Submit',
          'isRecurring': false,
          'numOfCycle': 2,
          'recurringIntervals': ['weekly', 'monthly'],
          'recurringStartDateType': 'custom',
          'recurringStartDate': '07/08/2030',
          'secureAuthentication': false,
          'showReceipt': true,
          'showTotal': true,
          'showSubmitButton': true,
          'isEmail': true,
          'email': emailController.text.trim(),
          'name': 'Test User',
          'enable3DS': false,
          'metadata': {'metaKey': 'metaValue', 'metaKey1': 'metaValue1'},
        };

        final response = await easymerchant.billing(
          amount: billingParams['amount'],
          currency: billingParams['currency'],
          billingInfo: billingParams['billingInfo'],
          paymentMethods: List<String>.from(billingParams['paymentMethods']),
          themeConfiguration: billingParams['themeConfiguration'],
          tokenOnly: billingParams['tokenOnly'],
          saveCard: billingParams['saveCard'],
          saveAccount: billingParams['saveAccount'],
          authenticatedACH: billingParams['authenticatedACH'],
          grailPayParams: billingParams['grailPayParams'],
          submitButtonText: billingParams['submitButtonText'],
          isRecurring: billingParams['isRecurring'],
          numOfCycle: billingParams['numOfCycle'],
          recurringIntervals: List<String>.from(billingParams['recurringIntervals']),
          recurringStartDateType: billingParams['recurringStartDateType'],
          recurringStartDate: billingParams['recurringStartDate'],
          secureAuthentication: billingParams['secureAuthentication'],
          showReceipt: billingParams['showReceipt'],
          showTotal: billingParams['showTotal'],
          showSubmitButton: billingParams['showSubmitButton'],
          isEmail: billingParams['isEmail'],
          email: billingParams['email'],
          name: billingParams['name'],
          enable3DS: billingParams['enable3DS'],
          metadata: billingParams['metadata'],
        );

        final responseJson = jsonDecode(response!);
        setState(() {
          result = jsonEncode(responseJson, toEncodable: (obj) => obj.toString());
        });
      } 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'],
          'metadata': {'metaKey': 'metaValue', 'metaKey1': 'metaValue1'},
        };

        final configJson = jsonEncode(config);
        final response = await easymerchant.makePayment(configJson);
        final responseJson = jsonDecode(response);
        setState(() {
          result = jsonEncode(responseJson, toEncodable: (obj) => obj.toString());
        });
      }
    } catch (e) {
      setState(() {
        result = 'Billing failed: $e';
      });
      debugPrint('Billing error: $e');
    }
  }

  String _platformVersion = 'Unknown';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('EasyMerchantSDK Demo')),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              TextField(
                controller: amountController,
                decoration: const InputDecoration(labelText: 'Amount (e.g., 10.00)'),
                keyboardType: TextInputType.number,
              ),
              TextField(
                controller: emailController,
                decoration: const InputDecoration(labelText: 'Email'),
                keyboardType: TextInputType.emailAddress,
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: _startBilling,
                child: const Text('Pay'),
              ),
              const SizedBox(height: 20),
              Text('Result: $result'),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    amountController.dispose();
    emailController.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'],
    );
  }
}

Troubleshooting #

  • MissingPluginException: Ensure the easymerchantsdk is properly integrated into your native iOS and Android projects. Verify pubspec.yaml, Android build.gradle, and iOS Podfile configurations.
  • Invalid Amount: Ensure the amount is a valid number greater than 0.
  • Empty Payment Methods: Select at least one payment method (card or ach).
  • JSON Serialization Errors: Validate that all configuration maps are correctly formatted before encoding to JSON.
  • Authentication Errors: Verify that the apiKey and secretKey are correct for the selected environment.