Does Monnify Payment gateway support flutter web?
I am trying to implement monnify payment gateway for a flutter web application but I keep getting this error:
Failed to initialize Monnify: MissingPluginException(No implementation found for method initialize on channel monnify_payment_sdk)
Error initializing payment: Exception: Payment gateway could not be initialized
Error: google_fonts was unable to load font Urbanist-Bold because the following exception occurred
This is my code:
import 'package:flutter/material.dart';
import 'package:monnify_payment_sdk/monnify_payment_sdk.dart';
import 'package:puzzleinvoicing/general/model/purchased_product_records.dart';
import 'package:puzzleinvoicing/general/service/bank_service.dart';
import 'package:puzzleinvoicing/general/widgets/payment_verification_dialog.dart';
import 'package:puzzleinvoicing/mobile/src/puzzleinvoice_app/sections/core/features/products/product_model/productmodel.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class PaymentProvider with ChangeNotifier {
Monnify? _monnify;
bool _isInitialized = false;
PaymentProvider() {
_initializeMonnify();
}
Future<void> _initializeMonnify() async {
try{
_monnify = await Monnify.initialize(
applicationMode: ApplicationMode.TEST, // Change to TEST for production
apiKey: 'MK_TEST_1PAGHBZ450', // TEST API key
contractCode: '6290106582', // TEST contract code
);
_isInitialized = true;
notifyListeners();
}catch(e){
print('Failed to initialize Monnify: $e');
}
}
Future<void> initializePayment({
required double amount,
required String customerName,
required String customerEmail,
required Product_Model product,
required String businessId,
required BuildContext context,
}) async {
// Generate a unique payment reference
final paymentReference = 'PZL_${DateTime.now().millisecondsSinceEpoch}';
try {
// Make sure Monnify is initialized
if (_monnify == null) {
// Wait for initialization to complete
if (!_isInitialized) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Initializing payment gateway, please wait...')),
);
await _initializeMonnify();
}
// Check again after initialization attempt
if (_monnify == null) {
throw Exception('Payment gateway could not be initialized');
}
}
// Create transaction details
final transaction = TransactionDetails(
amount: amount,
currencyCode: 'NGN',
customerName: customerName,
customerEmail: customerEmail,
paymentReference: paymentReference,
paymentDescription: 'Payment for ${product.productName}',
paymentMethods: [PaymentMethod.CARD, PaymentMethod.ACCOUNT_TRANSFER, PaymentMethod.USSD],
incomeSplitConfig: [],
);
// Initialize and launch the payment interface
final response = await _monnify?.initializePayment(transaction: transaction);
if (response != null && response.transactionStatus == 'PAID') {
// Store initial payment data to Firebase for tracking
await _createPendingPaymentRecord(
paymentReference: paymentReference,
businessId: businessId,
customerEmail: customerEmail,
customerName: customerName,
product: product,
amount: amount,
);
// Verify payment and update records
await confirmPayment(
paymentReference: paymentReference,
businessId: businessId,
context: context,
customerEmail: customerEmail,
product: product,
);
} else {
// Payment was not successful or was cancelled
if (response != null) {
print('Payment failed or cancelled: ${response.transactionStatus}');
} else {
print('No response received from payment gateway');
}
}
} catch (e) {
print('Error initializing payment: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Payment initialization failed: $e')),
);
}
}
// Helper method to create a pending payment record
// Helper method to create a pending payment record
Future<void> _createPendingPaymentRecord({
required String paymentReference,
required String businessId,
required String customerEmail,
required String customerName,
required Product_Model product,
required double amount,
}) async {
try {
final pendingRecord = PurchasedProductRecords(
stashedAmount: 0.0,
paymentMethod: 'Monnify',
paymentStatus: 'Pending',
customerName: customerName,
customerEmail: customerEmail,
id: paymentReference,
businessId: businessId,
paymentReference: paymentReference,
transactionReference: paymentReference,
createdOn: DateTime.now(),
completedOn: DateTime.fromMillisecondsSinceEpoch(0),
completed: false,
currencyCode: 'NGN',
costPrice: product.costPrice,
totalPricePaid: amount,
dateAndTimeOfPurchase: DateTime.now(),
productName: product.productName,
productDescription: product.productDescription,
productImage: product.image ?? '',
);
await FirebaseFirestore.instance
.collection('users')
.doc(businessId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.set(pendingRecord.toJson());
} catch (e) {
print('Error creating pending payment record: $e');
}
}
Future<bool> confirmPayment({
required String paymentReference,
required String businessId,
required BuildContext context,
required String customerEmail,
required Product_Model product,
}) async {
// Show loading dialog
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => const PaymentVerificationDialog(),
);
try {
// Verify the payment status with Monnify
final paymentResult = await BankService.verifyPaymentWithMonnify(
context: context,
paymentReference: paymentReference,
businessId: businessId,
customerEmail: customerEmail,
product: product,
);
// Check if verification was successful
if (paymentResult['success']) {
final paymentData = paymentResult['data'];
final amountPaid = paymentData['amountPaid'] as double;
final expectedAmount = product.sellingPrice;
// Create a new record or update existing one
final purchasedProductRecord = PurchasedProductRecords(
stashedAmount: amountPaid < expectedAmount ? amountPaid : 0.0,
paymentMethod: paymentData['paymentMethod'] ?? 'Monnify',
paymentStatus: amountPaid >= expectedAmount ? 'Completed' : 'Incomplete Amount',
customerName: paymentData['customerName'] ?? 'Customer',
customerEmail: customerEmail,
id: paymentReference,
businessId: businessId,
paymentReference: paymentReference,
transactionReference: paymentData['transactionReference'] ?? paymentReference,
createdOn: DateTime.now(),
completedOn: amountPaid >= expectedAmount ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(0),
completed: amountPaid >= expectedAmount,
currencyCode: paymentData['currencyCode'] ?? 'NGN',
costPrice: product.costPrice,
totalPricePaid: amountPaid,
dateAndTimeOfPurchase: DateTime.now(),
productName: product.productName,
productDescription: product.productDescription,
productImage: product.image ?? '',
);
// Save record to Firebase
await FirebaseFirestore.instance
.collection('users')
.doc(businessId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.set(purchasedProductRecord.toJson());
// If payment is complete, update wallet balance
if (amountPaid >= expectedAmount) {
await BankService.updateWalletBalance(
businessId: businessId,
costPrice: product.costPrice,
);
// Increment product sold count
await _incrementProductSoldCount(businessId, product.id);
}
// Hide loading dialog
if (context.mounted) {
Navigator.of(context).pop();
}
// Show appropriate message
if (amountPaid < expectedAmount) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Partial payment received. Remaining amount: NGN${(expectedAmount - amountPaid).toStringAsFixed(2)}',
),
),
);
}
return false;
}
return true;
}
// Hide loading dialog
if (context.mounted) {
Navigator.of(context).pop();
}
return false;
} catch (e) {
// Hide loading dialog in case of error
if (context.mounted) {
Navigator.of(context).pop();
}
print('Error confirming payment: $e');
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Payment verification failed: $e')),
);
}
return false;
}
}
// Helper method to increment product sold count
Future<void> _incrementProductSoldCount(String businessId, String productId) async {
try {
await FirebaseFirestore.instance
.collection('users')
.doc(businessId)
.collection('products')
.doc(productId)
.update({'soldCount': FieldValue.increment(1)});
} catch (e) {
print('Error incrementing product sold count: $e');
}
}
Future<Map<String, dynamic>?> _getTransactionByPaymentRef(String paymentReference) async {
final userId = FirebaseAuth.instance.currentUser?.uid ?? '';
if (userId.isEmpty) return null;
final doc = await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.get();
return doc.data();
}
Future<void> _updatePaymentStatus(String paymentReference, String status) async {
final userId = FirebaseAuth.instance.currentUser?.uid ?? '';
if (userId.isEmpty) return;
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.update({'paymentStatus': status});
}
Future<void> _updateStashedAmount(String paymentReference, double stashedAmount) async {
final userId = FirebaseAuth.instance.currentUser?.uid ?? '';
if (userId.isEmpty) return;
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.update({'stashedAmount': stashedAmount});
}
}
Does Monnify Payment gateway support flutter web?
I am trying to implement monnify payment gateway for a flutter web application but I keep getting this error:
Failed to initialize Monnify: MissingPluginException(No implementation found for method initialize on channel monnify_payment_sdk)
Error initializing payment: Exception: Payment gateway could not be initialized
Error: google_fonts was unable to load font Urbanist-Bold because the following exception occurred
This is my code:
import 'package:flutter/material.dart';
import 'package:monnify_payment_sdk/monnify_payment_sdk.dart';
import 'package:puzzleinvoicing/general/model/purchased_product_records.dart';
import 'package:puzzleinvoicing/general/service/bank_service.dart';
import 'package:puzzleinvoicing/general/widgets/payment_verification_dialog.dart';
import 'package:puzzleinvoicing/mobile/src/puzzleinvoice_app/sections/core/features/products/product_model/productmodel.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class PaymentProvider with ChangeNotifier {
Monnify? _monnify;
bool _isInitialized = false;
PaymentProvider() {
_initializeMonnify();
}
Future<void> _initializeMonnify() async {
try{
_monnify = await Monnify.initialize(
applicationMode: ApplicationMode.TEST, // Change to TEST for production
apiKey: 'MK_TEST_1PAGHBZ450', // TEST API key
contractCode: '6290106582', // TEST contract code
);
_isInitialized = true;
notifyListeners();
}catch(e){
print('Failed to initialize Monnify: $e');
}
}
Future<void> initializePayment({
required double amount,
required String customerName,
required String customerEmail,
required Product_Model product,
required String businessId,
required BuildContext context,
}) async {
// Generate a unique payment reference
final paymentReference = 'PZL_${DateTime.now().millisecondsSinceEpoch}';
try {
// Make sure Monnify is initialized
if (_monnify == null) {
// Wait for initialization to complete
if (!_isInitialized) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Initializing payment gateway, please wait...')),
);
await _initializeMonnify();
}
// Check again after initialization attempt
if (_monnify == null) {
throw Exception('Payment gateway could not be initialized');
}
}
// Create transaction details
final transaction = TransactionDetails(
amount: amount,
currencyCode: 'NGN',
customerName: customerName,
customerEmail: customerEmail,
paymentReference: paymentReference,
paymentDescription: 'Payment for ${product.productName}',
paymentMethods: [PaymentMethod.CARD, PaymentMethod.ACCOUNT_TRANSFER, PaymentMethod.USSD],
incomeSplitConfig: [],
);
// Initialize and launch the payment interface
final response = await _monnify?.initializePayment(transaction: transaction);
if (response != null && response.transactionStatus == 'PAID') {
// Store initial payment data to Firebase for tracking
await _createPendingPaymentRecord(
paymentReference: paymentReference,
businessId: businessId,
customerEmail: customerEmail,
customerName: customerName,
product: product,
amount: amount,
);
// Verify payment and update records
await confirmPayment(
paymentReference: paymentReference,
businessId: businessId,
context: context,
customerEmail: customerEmail,
product: product,
);
} else {
// Payment was not successful or was cancelled
if (response != null) {
print('Payment failed or cancelled: ${response.transactionStatus}');
} else {
print('No response received from payment gateway');
}
}
} catch (e) {
print('Error initializing payment: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Payment initialization failed: $e')),
);
}
}
// Helper method to create a pending payment record
// Helper method to create a pending payment record
Future<void> _createPendingPaymentRecord({
required String paymentReference,
required String businessId,
required String customerEmail,
required String customerName,
required Product_Model product,
required double amount,
}) async {
try {
final pendingRecord = PurchasedProductRecords(
stashedAmount: 0.0,
paymentMethod: 'Monnify',
paymentStatus: 'Pending',
customerName: customerName,
customerEmail: customerEmail,
id: paymentReference,
businessId: businessId,
paymentReference: paymentReference,
transactionReference: paymentReference,
createdOn: DateTime.now(),
completedOn: DateTime.fromMillisecondsSinceEpoch(0),
completed: false,
currencyCode: 'NGN',
costPrice: product.costPrice,
totalPricePaid: amount,
dateAndTimeOfPurchase: DateTime.now(),
productName: product.productName,
productDescription: product.productDescription,
productImage: product.image ?? '',
);
await FirebaseFirestore.instance
.collection('users')
.doc(businessId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.set(pendingRecord.toJson());
} catch (e) {
print('Error creating pending payment record: $e');
}
}
Future<bool> confirmPayment({
required String paymentReference,
required String businessId,
required BuildContext context,
required String customerEmail,
required Product_Model product,
}) async {
// Show loading dialog
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => const PaymentVerificationDialog(),
);
try {
// Verify the payment status with Monnify
final paymentResult = await BankService.verifyPaymentWithMonnify(
context: context,
paymentReference: paymentReference,
businessId: businessId,
customerEmail: customerEmail,
product: product,
);
// Check if verification was successful
if (paymentResult['success']) {
final paymentData = paymentResult['data'];
final amountPaid = paymentData['amountPaid'] as double;
final expectedAmount = product.sellingPrice;
// Create a new record or update existing one
final purchasedProductRecord = PurchasedProductRecords(
stashedAmount: amountPaid < expectedAmount ? amountPaid : 0.0,
paymentMethod: paymentData['paymentMethod'] ?? 'Monnify',
paymentStatus: amountPaid >= expectedAmount ? 'Completed' : 'Incomplete Amount',
customerName: paymentData['customerName'] ?? 'Customer',
customerEmail: customerEmail,
id: paymentReference,
businessId: businessId,
paymentReference: paymentReference,
transactionReference: paymentData['transactionReference'] ?? paymentReference,
createdOn: DateTime.now(),
completedOn: amountPaid >= expectedAmount ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(0),
completed: amountPaid >= expectedAmount,
currencyCode: paymentData['currencyCode'] ?? 'NGN',
costPrice: product.costPrice,
totalPricePaid: amountPaid,
dateAndTimeOfPurchase: DateTime.now(),
productName: product.productName,
productDescription: product.productDescription,
productImage: product.image ?? '',
);
// Save record to Firebase
await FirebaseFirestore.instance
.collection('users')
.doc(businessId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.set(purchasedProductRecord.toJson());
// If payment is complete, update wallet balance
if (amountPaid >= expectedAmount) {
await BankService.updateWalletBalance(
businessId: businessId,
costPrice: product.costPrice,
);
// Increment product sold count
await _incrementProductSoldCount(businessId, product.id);
}
// Hide loading dialog
if (context.mounted) {
Navigator.of(context).pop();
}
// Show appropriate message
if (amountPaid < expectedAmount) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Partial payment received. Remaining amount: NGN${(expectedAmount - amountPaid).toStringAsFixed(2)}',
),
),
);
}
return false;
}
return true;
}
// Hide loading dialog
if (context.mounted) {
Navigator.of(context).pop();
}
return false;
} catch (e) {
// Hide loading dialog in case of error
if (context.mounted) {
Navigator.of(context).pop();
}
print('Error confirming payment: $e');
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Payment verification failed: $e')),
);
}
return false;
}
}
// Helper method to increment product sold count
Future<void> _incrementProductSoldCount(String businessId, String productId) async {
try {
await FirebaseFirestore.instance
.collection('users')
.doc(businessId)
.collection('products')
.doc(productId)
.update({'soldCount': FieldValue.increment(1)});
} catch (e) {
print('Error incrementing product sold count: $e');
}
}
Future<Map<String, dynamic>?> _getTransactionByPaymentRef(String paymentReference) async {
final userId = FirebaseAuth.instance.currentUser?.uid ?? '';
if (userId.isEmpty) return null;
final doc = await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.get();
return doc.data();
}
Future<void> _updatePaymentStatus(String paymentReference, String status) async {
final userId = FirebaseAuth.instance.currentUser?.uid ?? '';
if (userId.isEmpty) return;
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.update({'paymentStatus': status});
}
Future<void> _updateStashedAmount(String paymentReference, double stashedAmount) async {
final userId = FirebaseAuth.instance.currentUser?.uid ?? '';
if (userId.isEmpty) return;
await FirebaseFirestore.instance
.collection('users')
.doc(userId)
.collection('purchasedProductRecords')
.doc(paymentReference)
.update({'stashedAmount': stashedAmount});
}
}
Share
Improve this question
edited Mar 12 at 16:17
marc_s
756k184 gold badges1.4k silver badges1.5k bronze badges
asked Mar 12 at 15:54
Bob-Daawid NwobodoBob-Daawid Nwobodo
232 bronze badges
1 Answer
Reset to default 0The package says only Android
and iOS
, so they don't.
You can use the checkout url API in their documentation for web.