You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HMG_Patient_App_New/lib/features/paytabs/paytabs_view_model.dart

403 lines
20 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_paytabs_bridge/BaseBillingShippingInfo.dart';
import 'package:flutter_paytabs_bridge/IOSThemeConfiguration.dart';
import 'package:flutter_paytabs_bridge/PaymentSDKNetworks.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkApms.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkConfigurationDetails.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkLocale.dart';
3 months ago
import 'package:flutter_paytabs_bridge/PaymentSdkTokenFormat.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkTokeniseType.dart';
import 'package:flutter_paytabs_bridge/PaymentSdkTransactionType.dart';
import 'package:flutter_paytabs_bridge/flutter_paytabs_bridge.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/paytabs_config.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/paytabs/models/paytabs_transaction_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_response_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
class PayTabsViewModel extends ChangeNotifier {
late PaymentSdkConfigurationDetails paymentConfiguration;
final AppState appState;
final PayfortRepo payfortRepo;
final ErrorHandlerService errorHandlerService;
late PaytabsTransactionResponseModel paytabsTransactionResponseModel;
PayTabsViewModel({
required this.appState,
required this.payfortRepo,
required this.errorHandlerService,
});
setPaymentConfiguration(String paymentDescription, num amount, {bool isAddCard = false}) {
String cartID = DateTime.now().millisecondsSinceEpoch.toString();
paymentConfiguration = PaymentSdkConfigurationDetails(
profileId: PaymentSdkDefaultConfig.profileID,
serverKey: PaymentSdkDefaultConfig.serverKey,
clientKey: PaymentSdkDefaultConfig.clientKey,
transactionType: PaymentSdkTransactionType.SALE,
cartId: cartID.substring((cartID.length - 5), cartID.length),
cartDescription: paymentDescription,
merchantName: PaymentSdkDefaultConfig.defaultMerchantName,
locale: appState.isArabic() ? PaymentSdkLocale.AR : PaymentSdkLocale.EN,
merchantApplePayIndentifier: ApiConsts.appEnvironmentType == AppEnvironmentTypeEnum.uat
? PaymentSdkDefaultConfig.defaultMerchantAppleBundleIDUAT
: PaymentSdkDefaultConfig.defaultMerchantAppleBundleID,
// merchantApplePayIndentifier: PaymentSdkDefaultConfig.defaultMerchantAppleBundleIDUAT,
screentTitle: paymentDescription,
amount: amount.toDouble(),
showBillingInfo: false,
forceShippingInfo: false,
currencyCode: PaymentSdkDefaultConfig.defaultCurrency,
merchantCountryCode: PaymentSdkDefaultConfig.defaultMerchantCountryCode,
billingDetails: BillingDetails(
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}" ?? "HMG Patient",
"CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
appState.getAuthenticatedUser()!.mobileNumber ?? "0000000000",
"Riyadh",
"SA",
"Riyadh",
"Riyadh",
"12626"),
shippingDetails: ShippingDetails(
"${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}" ?? "HMG Patient",
"CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
appState.getAuthenticatedUser()!.mobileNumber ?? "0000000000",
"Riyadh",
"SA",
"Riyadh",
"Riyadh",
"12626"),
alternativePaymentMethods: [],
linkBillingNameWithCardHolderName: true,
2 months ago
simplifyApplePayValidation: true,
3 months ago
);
paymentConfiguration.iOSThemeConfigurations = IOSThemeConfigurations(
// logoImage: "assets/images/png/hmg_logo.png",
backgroundColor: "ffffff",
backgroundColorDark: "ffffff",
secondaryColor: "191919",
secondaryColorDark: "191919",
primaryColor: "ffffff",
primaryColorDark: "ffffff",
// primaryFont: "Poppins",
titleFontColor: "2E3039",
titleFontColorDark: "2E3039",
// titleFont: "Poppins",
primaryFontColor: "2E3039",
primaryFontColorDark: "2E3039",
inputFieldBackgroundColor: "ffffff",
inputFieldBackgroundColorDark: "ffffff",
placeholderColor: "2E3039",
placeholderColorDark: "2E3039",
buttonColor: "ED1C2B",
buttonColorDark: "ED1C2B",
3 months ago
inputsCornerRadius: 12
// buttonFont: "Poppins",
);
paymentConfiguration.tokeniseType = PaymentSdkTokeniseType.USER_OPTIONAL_DEFAULT_ON;
3 months ago
paymentConfiguration.tokenFormat = PaymentSdkTokenFormat.Hex32Format;
notifyListeners();
}
setAlternatePaymentConfiguration(String paymentDescription, num amount, {bool isAddCard = false}) {
String cartID = DateTime.now().millisecondsSinceEpoch.toString();
paymentConfiguration = PaymentSdkConfigurationDetails(
profileId: PaymentSdkDefaultConfig.profileID,
serverKey: PaymentSdkDefaultConfig.serverKey,
clientKey: PaymentSdkDefaultConfig.clientKey,
transactionType: PaymentSdkTransactionType.SALE,
cartId: cartID.substring((cartID.length - 5), cartID.length),
cartDescription: paymentDescription,
merchantName: PaymentSdkDefaultConfig.defaultMerchantName,
locale: appState.isArabic() ? PaymentSdkLocale.AR : PaymentSdkLocale.EN,
screentTitle: paymentDescription,
amount: amount.toDouble(),
showBillingInfo: false,
forceShippingInfo: false,
currencyCode: PaymentSdkDefaultConfig.defaultCurrency,
merchantCountryCode: PaymentSdkDefaultConfig.defaultMerchantCountryCode,
billingDetails: BillingDetails("${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}" ?? "HMG Patient",
"CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com", appState.getAuthenticatedUser()!.mobileNumber ?? "0000000000", "Riyadh", "SA", "Riyadh", "Riyadh", "12626"),
shippingDetails: ShippingDetails("${appState.getAuthenticatedUser()!.firstName} ${appState.getAuthenticatedUser()!.lastName}" ?? "HMG Patient",
"CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com", appState.getAuthenticatedUser()!.mobileNumber ?? "0000000000", "Riyadh", "SA", "Riyadh", "Riyadh", "12626"),
alternativePaymentMethods: [PaymentSdkAPms.TAMARA],
linkBillingNameWithCardHolderName: false,
simplifyApplePayValidation: true,
);
paymentConfiguration.iOSThemeConfigurations = IOSThemeConfigurations(
// logoImage: "assets/images/png/hmg_logo.png",
backgroundColor: "ffffff",
backgroundColorDark: "ffffff",
secondaryColor: "191919",
secondaryColorDark: "191919",
primaryColor: "ffffff",
primaryColorDark: "ffffff",
// primaryFont: "Poppins",
titleFontColor: "2E3039",
titleFontColorDark: "2E3039",
// titleFont: "Poppins",
primaryFontColor: "2E3039",
primaryFontColorDark: "2E3039",
inputFieldBackgroundColor: "ffffff",
inputFieldBackgroundColorDark: "ffffff",
placeholderColor: "2E3039",
placeholderColorDark: "2E3039",
buttonColor: "ED1C2B",
buttonColorDark: "ED1C2B",
inputsCornerRadius: 12
// buttonFont: "Poppins",
);
paymentConfiguration.tokeniseType = PaymentSdkTokeniseType.USER_OPTIONAL_DEFAULT_ON;
paymentConfiguration.tokenFormat = PaymentSdkTokenFormat.Hex32Format;
notifyListeners();
}
Future<void> paytabsRequestInsert({required PayfortRequestInsertModel payfortRequestInsertModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await payfortRepo.payfortRequestInsert(payfortRequestInsertModel: payfortRequestInsertModel);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> paytabsResponseInsert({required PayfortResponseInsertModel payfortResponseInsertModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await payfortRepo.payfortResponseInsert(payfortResponseInsertModel: payfortResponseInsertModel);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
3 months ago
startApplePayPayment({Function(PaytabsTransactionResponseModel)? onSuccess, Function(String)? onError}) async {
bool _callbackFired = false; // prevent duplicate callback invocations
await FlutterPaytabsBridge.startApplePayPayment(paymentConfiguration, (event) {
if (_callbackFired) return; // ignore any subsequent callback calls
final transactionDetails = event["data"] as Map<Object?, Object?>?;
if (event["status"] == "success") {
3 months ago
_callbackFired = true;
// Cast Map<Object?, Object?> to Map<String, dynamic>
final data = Map<String, dynamic>.from(event["data"] as Map);
paytabsTransactionResponseModel = PaytabsTransactionResponseModel.fromJson(data);
if (paytabsTransactionResponseModel.isSuccess!) {
onSuccess!(paytabsTransactionResponseModel);
} else {
// Transaction was processed but failed
final reason =
transactionDetails?["payResponseReturn"] ?? transactionDetails?["responseMessage"] ?? transactionDetails?["message"] ?? "Unknown error";
final responseCode = transactionDetails?["responseCode"] ?? "";
final errorMessage =
responseCode.toString().isNotEmpty ? "Transaction failed (Code: $responseCode): $reason" : "Transaction failed: $reason";
onError!(errorMessage);
}
} else if (event["status"] == "error") {
3 months ago
_callbackFired = true;
final errorMessage = event["message"] ?? "An error occurred";
debugPrint("Error occurred in transaction: $errorMessage");
debugPrint("Full error event: $event");
onError!(errorMessage);
} else if (event["status"] == "event") {
3 months ago
// Intermediate SDK events do NOT mark _callbackFired, just log
final eventMessage = event["message"] ?? "Event occurred";
debugPrint("Event occurred: $eventMessage");
}
});
}
startCardPayment({
required String paymentOption,
required String liveServiceID,
required String isScheduleLiveCare,
required String appointmentDate,
required String appointmentNo,
required String doctorID,
required String transactionID,
required String amount,
required String fileNumber,
required String orderDescription,
required String serviceID,
required String projectID,
Function(PaytabsTransactionResponseModel)? onSuccess,
Function(String)? onError,
}) async {
3 months ago
bool _callbackFired = false; // prevent duplicate callback invocations
try {
LoaderBottomSheet.showLoader();
3 months ago
// Create PayfortRequestInsertModel (same as Payfort implementation)
PayfortRequestInsertModel payfortRequestInsertModel = PayfortRequestInsertModel();
payfortRequestInsertModel.commandType = "SALE";
payfortRequestInsertModel.amount = num.parse(amount);
payfortRequestInsertModel.customerEmail = getIt.get<AppState>().getAuthenticatedUser()!.emailAddress;
payfortRequestInsertModel.orderDescription = orderDescription;
payfortRequestInsertModel.serviceID = serviceID;
payfortRequestInsertModel.paymentOption = paymentOption;
payfortRequestInsertModel.clientRequestID = transactionID;
payfortRequestInsertModel.projectID = projectID;
payfortRequestInsertModel.fileNumber = getIt.get<AppState>().getAuthenticatedUser()!.patientId.toString();
payfortRequestInsertModel.customerName = "${getIt.get<AppState>().getAuthenticatedUser()!.firstName} ${getIt.get<AppState>().getAuthenticatedUser()!.lastName}";
payfortRequestInsertModel.currency = getIt.get<AppState>().getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED";
payfortRequestInsertModel.liveServiceID = liveServiceID;
payfortRequestInsertModel.latitude = getIt.get<AppState>().userLat.toString();
payfortRequestInsertModel.longitude = getIt.get<AppState>().userLong.toString();
payfortRequestInsertModel.merchantReference = transactionID;
payfortRequestInsertModel.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
payfortRequestInsertModel.language = getIt.get<AppState>().isArabic() ? "ar" : "en";
payfortRequestInsertModel.integrationId = "2"; // PayTabs integration ID
payfortRequestInsertModel.isSchedule = isScheduleLiveCare;
payfortRequestInsertModel.appointmentDate = appointmentDate;
payfortRequestInsertModel.appointmentNo = appointmentNo;
payfortRequestInsertModel.doctorID = doctorID;
// Call request insert API before payment
await paytabsRequestInsert(payfortRequestInsertModel: payfortRequestInsertModel);
LoaderBottomSheet.hideLoader();
// Start PayTabs payment
FlutterPaytabsBridge.startCardPayment(paymentConfiguration, (event) async {
if (_callbackFired) return; // ignore any subsequent callback calls
final transactionDetails = event["data"] as Map<Object?, Object?>?;
if (event["status"] == "success") {
_callbackFired = true;
LoaderBottomSheet.showLoader();
// Cast Map<Object?, Object?> to Map<String, dynamic>
final data = Map<String, dynamic>.from(event["data"] as Map);
paytabsTransactionResponseModel = PaytabsTransactionResponseModel.fromJson(data);
// Create PayfortResponseInsertModel (same as Payfort implementation)
PayfortResponseInsertModel payfortResponseInsertModel = PayfortResponseInsertModel();
payfortResponseInsertModel.fortId = paytabsTransactionResponseModel.transactionReference ?? "";
payfortResponseInsertModel.commandType = paytabsTransactionResponseModel.transactionType ?? "SALE";
// payfortResponseInsertModel.amount = paytabsTransactionResponseModel.tranTotal ?? 0;
payfortResponseInsertModel.amount = num.parse(amount);
payfortResponseInsertModel.sadadOLP = "";
payfortResponseInsertModel.paymentOption = paytabsTransactionResponseModel.paymentInfo?.paymentMethod ?? "";
payfortResponseInsertModel.customerIP = "";
payfortResponseInsertModel.eCI = "";
payfortResponseInsertModel.responseMessage = paytabsTransactionResponseModel.payResponseReturn ?? "";
payfortResponseInsertModel.cardNumber = paytabsTransactionResponseModel.paymentInfo!.paymentDescription;
payfortResponseInsertModel.cardBin = "";
payfortResponseInsertModel.installmentsNumber = 0;
payfortResponseInsertModel.status = paytabsTransactionResponseModel.isSuccess! ? "success" : "failed";
payfortResponseInsertModel.merchantRef = transactionID;
payfortResponseInsertModel.isRefund = false;
payfortResponseInsertModel.remmeberMe = true;
payfortResponseInsertModel.reconciliationReference = "";
// Call response insert API after payment
await paytabsResponseInsert(payfortResponseInsertModel: payfortResponseInsertModel);
LoaderBottomSheet.hideLoader();
if (paytabsTransactionResponseModel.isSuccess!) {
if (onSuccess != null) {
onSuccess(paytabsTransactionResponseModel);
}
} else {
// Transaction was processed but failed
final reason = transactionDetails?["payResponseReturn"] ?? transactionDetails?["responseMessage"] ?? transactionDetails?["message"] ?? "Unknown error";
final responseCode = transactionDetails?["responseCode"] ?? "";
final errorMessage = responseCode.toString().isNotEmpty ? "Transaction failed (Code: $responseCode): $reason" : "Transaction failed: $reason";
if (onError != null) {
onError(errorMessage);
}
}
} else if (event["status"] == "error") {
_callbackFired = true;
final errorMessage = event["message"] ?? "An error occurred";
debugPrint("Error occurred in transaction: $errorMessage");
debugPrint("Full error event: $event");
if (onError != null) {
onError(errorMessage);
}
} else if (event["status"] == "event") {
// Intermediate SDK events do NOT mark _callbackFired, just log
final eventMessage = event["message"] ?? "Event occurred";
debugPrint("Event occurred: $eventMessage");
}
});
} catch (error) {
debugPrint("PayTabs Payment Error: $error");
LoaderBottomSheet.hideLoader();
if (onError != null) {
onError("Payment initialization failed: $error");
}
}
}
startAlternatePayment({Function(PaytabsTransactionResponseModel)? onSuccess, Function(String)? onError}) {
bool _callbackFired = false; // prevent duplicate callback invocations
FlutterPaytabsBridge.startAlternativePaymentMethod(paymentConfiguration, (event) {
if (_callbackFired) return; // ignore any subsequent callback calls
final transactionDetails = event["data"] as Map<Object?, Object?>?;
if (event["status"] == "success") {
_callbackFired = true;
// Cast Map<Object?, Object?> to Map<String, dynamic>
final data = Map<String, dynamic>.from(event["data"] as Map);
paytabsTransactionResponseModel = PaytabsTransactionResponseModel.fromJson(data);
if (paytabsTransactionResponseModel.isSuccess!) {
onSuccess!(paytabsTransactionResponseModel);
} else {
// Transaction was processed but failed
final reason = transactionDetails?["payResponseReturn"] ?? transactionDetails?["responseMessage"] ?? transactionDetails?["message"] ?? "Unknown error";
final responseCode = transactionDetails?["responseCode"] ?? "";
final errorMessage = responseCode.toString().isNotEmpty ? "Transaction failed (Code: $responseCode): $reason" : "Transaction failed: $reason";
onError!(errorMessage);
}
} else if (event["status"] == "error") {
_callbackFired = true;
final errorMessage = event["message"] ?? "An error occurred";
debugPrint("Error occurred in transaction: $errorMessage");
debugPrint("Full error event: $event");
onError!(errorMessage);
} else if (event["status"] == "event") {
// Intermediate SDK events do NOT mark _callbackFired, just log
final eventMessage = event["message"] ?? "Event occurred";
debugPrint("Event occurred: $eventMessage");
}
});
}
}