easymerchantsdk 1.0.7
easymerchantsdk: ^1.0.7 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.7
flutter:
sdk: flutter
Run the following command to install the package:
flutter pub get
Setup #
Android Setup #
-
Update
build.gradle: Openandroid/build.gradleand add the following to theallprojects.repositoriessection 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, andGITHUB_PASSWORDingradle.propertiesor replace them with values provided by the SDK documentation. -
Permissions: Add the Internet permission to
android/app/src/main/AndroidManifest.xml:<uses-permission android:name="android.permission.INTERNET" /> -
Native Integration: Follow any additional native setup instructions in the official
easymerchantsdkdocumentation to ensure proper integration.
iOS Setup #
Requirements
- Ruby 3.2.8
Steps
-
Add Permissions: Update
ios/Runner/Info.plistto include network access permissions:<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> -
Podfile Configuration: Update
ios/Podfileto include theeasymerchantsdkdependency. Runpod installin theiosdirectory:cd ios pod install -
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': 'apiKey', // Replace with your API key
'secretKey': 'secretKey', // 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': 'apiKey',
'secretKey': '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);
// 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
easymerchantsdkis correctly integrated inpubspec.yaml, Androidbuild.gradle, and iOSPodfile. - Invalid Amount: Ensure the amount is a valid number greater than 0.
- Empty Payment Methods: At least one payment method (
cardorach) must be selected. - JSON Serialization Errors: Ensure all configuration maps are properly formatted before encoding to JSON.
- Authentication Errors: Verify that the
apiKeyandsecretKeymatch the selected environment. - iOS ViewController Issues: Ensure
setViewControlleris called beforebillingon 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.