最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Does Monnify Payment gateway support flutter web? - Stack Overflow

programmeradmin1浏览0评论

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
Add a comment  | 

1 Answer 1

Reset to default 0

The package says only Android and iOS, so they don't.

You can use the checkout url API in their documentation for web.

发布评论

评论列表(0)

  1. 暂无评论