Paytabs implemented in Wallet payment

pull/317/head
Haroon Amjad 4 weeks ago
parent 0db762fa2c
commit cdc82c83f8

@ -220,7 +220,7 @@
"request": "الطلبات",
"memberName": "اسم العضو",
"switchLogin": "عرض الملف",
"removeMember": "إزالة",
"removeMember": "حذف",
"allowView": "السماح",
"rejectView": "رفض",
"deleteView": "حذف",

@ -280,7 +280,12 @@ class HabibWalletViewModel extends ChangeNotifier {
paymentMethodName: paymentMethodName, paidAmount: paidAmount, paymentReference: paymentReference, patientID: patientID, projectID: projectID, depositorName: depositorName);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
// (failure) async => await errorHandlerService.handleError(failure: failure),
(failure) async {
if(onError != null) {
onError(failure.message);
}
},
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});

@ -12,7 +12,7 @@ class PaytabsTransactionResponseModel {
String? transactionType;
bool? isAuthorized;
String? trace;
int? cartAmount;
dynamic cartAmount;
int? merchantId;
int? profileId;
bool? isProcessed;
@ -62,7 +62,7 @@ class PaytabsTransactionResponseModel {
isProcessed = json['isProcessed'];
serviceId = json['serviceId'];
paymentInfo = json['paymentInfo'] != null
? new PaymentInfo.fromJson(json['paymentInfo'])
? PaymentInfo.fromJson(Map<String, dynamic>.from(json['paymentInfo'] as Map))
: null;
isSuccess = json['isSuccess'];
}

@ -32,6 +32,7 @@ class PayTabsViewModel extends ChangeNotifier {
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,
screentTitle: paymentDescription,
@ -40,9 +41,10 @@ class PayTabsViewModel extends ChangeNotifier {
forceShippingInfo: false,
currencyCode: PaymentSdkDefaultConfig.defaultCurrency,
merchantCountryCode: PaymentSdkDefaultConfig.defaultMerchantCountryCode,
billingDetails: BillingDetails(appState.getAuthenticatedUser()!.firstName ?? "HMG Patient", "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
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 ?? "HMG Patient", "CustID_${appState.getAuthenticatedUser()!.patientId.toString()}@HMG.com",
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,
@ -52,14 +54,14 @@ class PayTabsViewModel extends ChangeNotifier {
// logoImage: "assets/images/png/hmg_logo.png",
backgroundColor: "ffffff",
backgroundColorDark: "ffffff",
secondaryColor: "ED1C2B",
secondaryColorDark: "ED1C2B",
secondaryColor: "191919",
secondaryColorDark: "191919",
primaryColor: "ffffff",
primaryColorDark: "ffffff",
primaryFont: "Poppins",
// primaryFont: "Poppins",
titleFontColor: "2E3039",
titleFontColorDark: "2E3039",
titleFont: "Poppins",
// titleFont: "Poppins",
primaryFontColor: "2E3039",
primaryFontColorDark: "2E3039",
inputFieldBackgroundColor: "ffffff",
@ -68,25 +70,27 @@ class PayTabsViewModel extends ChangeNotifier {
placeholderColorDark: "2E3039",
buttonColor: "ED1C2B",
buttonColorDark: "ED1C2B",
buttonFont: "Poppins",
// buttonFont: "Poppins",
);
paymentConfiguration.tokeniseType = PaymentSdkTokeniseType.MERCHANT_MANDATORY;
notifyListeners();
}
startCardPayment({Function(dynamic)? onSuccess, Function(String)? onError}) {
startCardPayment({Function(PaytabsTransactionResponseModel)? onSuccess, Function(String)? onError}) {
FlutterPaytabsBridge.startCardPayment(paymentConfiguration, (event) {
final transactionDetails = event["data"];
final transactionDetails = event["data"] as Map<Object?, Object?>?;
if (event["status"] == "success") {
paytabsTransactionResponseModel = PaytabsTransactionResponseModel.fromJson(event["data"]);
// 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.isNotEmpty ? "Transaction failed (Code: $responseCode): $reason" : "Transaction failed: $reason";
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") {

@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/paytabs/paytabs_view_model.dart';
import 'package:hmg_patient_app_new/features/weather/weather_view_model.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/features/ask_doctor/ask_doctor_view_model.dart';
@ -262,6 +263,8 @@ void main() async {
create: (_) => getIt.get<WeatherMonitorViewModel>(),
), ChangeNotifierProvider<DateRangCalenderModel>(
create: (_) => getIt.get<DateRangCalenderModel>(),
), ChangeNotifierProvider<PayTabsViewModel>(
create: (_) => getIt.get<PayTabsViewModel>(),
)
], child: MyApp()),
), // Wrap your app

@ -16,6 +16,8 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/features/paytabs/models/paytabs_transaction_response_model.dart';
import 'package:hmg_patient_app_new/features/paytabs/paytabs_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
@ -35,6 +37,7 @@ class WalletPaymentConfirmPage extends StatefulWidget {
class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
late PayfortViewModel payfortViewModel;
late PayTabsViewModel paytabsViewModel;
late AppState appState;
late HabibWalletViewModel habibWalletVM;
@ -56,6 +59,7 @@ class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
appState = getIt.get<AppState>();
habibWalletVM = Provider.of<HabibWalletViewModel>(context, listen: false);
payfortViewModel = Provider.of<PayfortViewModel>(context, listen: false);
paytabsViewModel = Provider.of<PayTabsViewModel>(context, listen: false);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
body: Column(
@ -102,7 +106,66 @@ class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "MADA";
openPaymentURL("mada");
if (appState.isPaytabsEnabled) {
paytabsViewModel.setPaymentConfiguration("Advance Payment", habibWalletVM.walletRechargeAmount);
paytabsViewModel.startCardPayment(onSuccess: (PaytabsTransactionResponseModel transactionData) async {
LoaderBottomSheet.showLoader();
await habibWalletVM.HISCreateAdvancePayment(
paymentMethodName: selectedPaymentMethod,
paidAmount: habibWalletVM.walletRechargeAmount,
paymentReference: transactionData.transactionReference!,
patientID: habibWalletVM.fileNumber,
projectID: habibWalletVM.selectedHospital!.iD!,
depositorName: habibWalletVM.depositorName,
onSuccess: (value) async {
await habibWalletVM.addAdvanceNumberRequest(
advanceNumber: Utils.isVidaPlusProject(habibWalletVM.selectedHospital!.iD)
? value.data['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
: value.data['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
paymentReference: transactionData.transactionReference!,
onSuccess: (value) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(getIt.get<NavigationService>().navigatorKey.currentContext!, child: Utils.getSuccessWidget(loadingText: "Payment Successful!"),
callBackFunc: () {
habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount();
Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).pop();
Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).pop();
}, isFullScreen: false, isCloseButtonVisible: true, isAutoDismiss: true);
},
onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
},
onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
}, onError: (err) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err.toString()),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else {
openPaymentURL("mada");
}
}),
SizedBox(height: 16.h),
Container(
@ -144,7 +207,66 @@ class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "VISA";
openPaymentURL("visa");
if (appState.isPaytabsEnabled) {
paytabsViewModel.setPaymentConfiguration("Advance Payment", habibWalletVM.walletRechargeAmount);
paytabsViewModel.startCardPayment(onSuccess: (PaytabsTransactionResponseModel transactionData) async {
LoaderBottomSheet.showLoader();
await habibWalletVM.HISCreateAdvancePayment(
paymentMethodName: selectedPaymentMethod,
paidAmount: habibWalletVM.walletRechargeAmount,
paymentReference: transactionData.transactionReference!,
patientID: habibWalletVM.fileNumber,
projectID: habibWalletVM.selectedHospital!.iD!,
depositorName: habibWalletVM.depositorName,
onSuccess: (value) async {
await habibWalletVM.addAdvanceNumberRequest(
advanceNumber: Utils.isVidaPlusProject(habibWalletVM.selectedHospital!.iD)
? value.data['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
: value.data['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
paymentReference: transactionData.transactionReference!,
onSuccess: (value) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(getIt.get<NavigationService>().navigatorKey.currentContext!, child: Utils.getSuccessWidget(loadingText: "Payment Successful!"),
callBackFunc: () {
habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount();
Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).pop();
Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).pop();
}, isFullScreen: false, isCloseButtonVisible: true, isAutoDismiss: true);
},
onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.paymentFailedPleaseTryAgain.tr(context: context)),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
},
onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
}, onError: (err) {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err.toString()),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else {
openPaymentURL("visa");
}
}),
],
),
@ -197,9 +319,7 @@ class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 12.h),
Platform.isIOS
? Utils.buildSvgWithAssets(
icon: AppAssets.apple_pay_button,
width: 200.h, height: 56.h, fit: BoxFit.contain, applyThemeColor: false).paddingSymmetrical(24.h, 0.h).onPress(() {
? Utils.buildSvgWithAssets(icon: AppAssets.apple_pay_button, width: 200.h, height: 56.h, fit: BoxFit.contain, applyThemeColor: false).paddingSymmetrical(24.h, 0.h).onPress(() {
if (Utils.havePrivilege(103)) {
startApplePay();
} else {
@ -321,16 +441,12 @@ class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
onSuccess: (value) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(getIt.get<NavigationService>().navigatorKey.currentContext!, child: Utils.getSuccessWidget(loadingText: "Payment Successful!"),
callBackFunc: () {
habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount();
callBackFunc: () {
habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount();
Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).pop();
Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).pop();
},
isFullScreen: false,
isCloseButtonVisible: true,
isAutoDismiss: true
);
}, isFullScreen: false, isCloseButtonVisible: true, isAutoDismiss: true);
},
onError: (err) {
LoaderBottomSheet.hideLoader();
@ -343,7 +459,16 @@ class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
);
});
},
onError: (err) {});
onError: (err) {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: err),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
});
} else {
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(

@ -432,13 +432,14 @@ class _FamilyCardsState extends State<FamilyCards> {
// ),
// SizedBox(height: 24.h),
CustomExpandableList(
expansionMode: ExpansionMode.exactlyOne,
expansionMode: ExpansionMode.multiple,
dividerColor: AppColors.dividerColor,
itemPadding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.h),
items: [
ExpandableListItem(
title: LocaleKeys.whoCanViewMyMedicalFile.tr(context: context).toText18(isBold: true),
expandedBackgroundColor: Colors.transparent,
initiallyExpanded: true,
children: [
SizedBox(height: 10.h),
manageFamily()

@ -5,6 +5,7 @@ import 'package:hmg_patient_app_new/extensions/int_extensions.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/emergency_services/emergency_services_view_model.dart';
import 'package:hmg_patient_app_new/features/habib_wallet/habib_wallet_view_model.dart';
import 'package:hmg_patient_app_new/features/immediate_livecare/immediate_livecare_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/todo_section/todo_section_view_model.dart';
@ -29,6 +30,7 @@ class _AppLanguageChangeState extends State<AppLanguageChange> {
late ImmediateLiveCareViewModel immediateLiveCareViewModel;
late EmergencyServicesViewModel emergencyServicesViewModel;
late TodoSectionViewModel todoSectionViewModel;
late HabibWalletViewModel habibWalletVM;
@override
void initState() {
@ -48,6 +50,7 @@ class _AppLanguageChangeState extends State<AppLanguageChange> {
immediateLiveCareViewModel = Provider.of<ImmediateLiveCareViewModel>(context, listen: false);
emergencyServicesViewModel = Provider.of<EmergencyServicesViewModel>(context, listen: false);
todoSectionViewModel = Provider.of<TodoSectionViewModel>(context, listen: false);
habibWalletVM = context.read<HabibWalletViewModel>();
return Column(
spacing: 24.h,
@ -72,6 +75,10 @@ class _AppLanguageChangeState extends State<AppLanguageChange> {
myAppointmentsViewModel.initAppointmentsViewModel();
myAppointmentsViewModel.getPatientAppointments(true, false);
habibWalletVM.initHabibWalletProvider();
habibWalletVM.getPatientBalanceAmount();
habibWalletVM.getLakumAccountInformation();
//Reload Immediate LiveCare Data
immediateLiveCareViewModel.initImmediateLiveCare();
immediateLiveCareViewModel.getPatientLiveCareHistory();

Loading…
Cancel
Save