diff --git a/android/app/build.gradle b/android/app/build.gradle index 44d134ee..e8fb92f1 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -41,7 +41,7 @@ configurations.all { } android { - compileSdkVersion 33 + compileSdkVersion 34 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -57,7 +57,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.ejada.hmg" minSdkVersion 21 - targetSdkVersion 33 + targetSdkVersion 34 versionCode flutterVersionCode.toInteger() versionName flutterVersionName multiDexEnabled true diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements index 0821ccf0..44ce1b68 100644 --- a/ios/Runner/Runner.entitlements +++ b/ios/Runner/Runner.entitlements @@ -8,6 +8,12 @@ com.apple.developer.healthkit.access + com.apple.developer.in-app-payments + + merchant.com.hmgwebsersives + merchant.com.hmgwebservices.uat + merchant.com.hmgwebservices + com.apple.developer.networking.HotspotConfiguration com.apple.developer.networking.wifi-info diff --git a/lib/config/config.dart b/lib/config/config.dart index 24712062..6fbcfa95 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:amazon_payfort/amazon_payfort.dart'; import 'package:diplomaticquarterapp/models/Request.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; @@ -343,7 +344,7 @@ var UPDATE_COVID_QUESTIONNAIRE = 'Services/Doctors.svc/REST/COVID19_Questionnari var CHANNEL = 3; var GENERAL_ID = 'Cs2020@2016\$2958'; var IP_ADDRESS = '10.20.10.20'; -var VERSION_ID = 11.9; +var VERSION_ID = 12.0; var SETUP_ID = '91877'; var LANGUAGE = 2; // var PATIENT_OUT_SA = 0; @@ -658,6 +659,17 @@ var PLACE_MEAL_PLAN_ORDER = 'Services/MOP.svc/REST/UpdateOrMakeNewOrder'; var CHECK_PATIENT_NPHIES_ELIGIBILITY = 'Services/Doctors.svc/REST/checkPatientInsuranceCompanyValidity'; var CONVERT_PATIENT_TO_CASH = 'Services/Doctors.svc/REST/deActivateInsuranceCompany'; + + +//PAYFORT +var getPayFortProjectDetails = "Services/PayFort_Serv.svc/REST/GetPayFortProjectDetails"; +var addPayFortApplePayResponse = "Services/PayFort_Serv.svc/REST/AddResponse"; +// var payFortEnvironment = FortEnvironment.production; +// var applePayMerchantId = "merchant.com.hmgwebservices"; +var payFortEnvironment = FortEnvironment.test; +var applePayMerchantId = "merchant.com.hmgwebservices.uat"; + + class AppGlobal { static var context; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 011e3997..248ea851 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1951,4 +1951,5 @@ const Map localizedValues = { "patientRelationOffice": {"en": "Patient Relation Office", "ar": "علاقات المرضى"}, "upcoming": {"en": "Upcoming", "ar": "المواعيد القادمة"}, "noUpcomingAppointment": {"en": "No upcoming appointments", "ar": "لا توجد مواعيد القادمة"}, + "locationTimeoutError": {"en": "Unable to fetch your location, Please try again.", "ar": "غير قادر على جلب موقعك، يرجى المحاولة مرة أخرى."}, }; \ No newline at end of file diff --git a/lib/core/enum/PayfortEnums.dart b/lib/core/enum/PayfortEnums.dart new file mode 100644 index 00000000..2951eed8 --- /dev/null +++ b/lib/core/enum/PayfortEnums.dart @@ -0,0 +1,44 @@ +enum ServiceTypeEnum { + advancePayment, //3 + ancillaryOrder, //3 + appointmentPayment, //2 + covidPayment, //2 + erOnlineCheckIn, //3 + liveCareAppointment //4 +} + +extension ServiceTypeEnumExt on ServiceTypeEnum { + String value() { + switch (this) { + case ServiceTypeEnum.advancePayment: + return "Advance Payment"; + case ServiceTypeEnum.ancillaryOrder: + return "Ancillary Order"; + case ServiceTypeEnum.appointmentPayment: + return "Appointment Payment"; + case ServiceTypeEnum.covidPayment: + return "Covid Payment"; + case ServiceTypeEnum.erOnlineCheckIn: + return "ER Online Check In"; + case ServiceTypeEnum.liveCareAppointment: + return "LiveCare Appointment"; + } + } + + int getIdFromServiceEnum() { + switch (this) { + case ServiceTypeEnum.advancePayment: + return 3; + case ServiceTypeEnum.ancillaryOrder: + return 3; + case ServiceTypeEnum.appointmentPayment: + return 2; + case ServiceTypeEnum.covidPayment: + return 2; + case ServiceTypeEnum.erOnlineCheckIn: + return 3; + case ServiceTypeEnum.liveCareAppointment: + return 4; + } + } +} diff --git a/lib/core/model/my_balance/tamara_installment_details.dart b/lib/core/model/my_balance/tamara_installment_details.dart index 891b9a86..12769cdd 100644 --- a/lib/core/model/my_balance/tamara_installment_details.dart +++ b/lib/core/model/my_balance/tamara_installment_details.dart @@ -7,7 +7,7 @@ class TamaraInstallmentDetails { TamaraInstallmentDetails({this.name, this.description, this.minLimit, this.maxLimit, this.supportedInstalments}); - TamaraInstallmentDetails.fromJson(Map json) { + TamaraInstallmentDetails.fromJson(Map json) { name = json['name']; description = json['description']; minLimit = json['minLimit'] != null ? new MinLimit.fromJson(json['minLimit']) : null; diff --git a/lib/core/service/client/base_app_client.dart b/lib/core/service/client/base_app_client.dart index 70502112..ed37e745 100644 --- a/lib/core/service/client/base_app_client.dart +++ b/lib/core/service/client/base_app_client.dart @@ -174,8 +174,8 @@ class BaseAppClient { } // body['IdentificationNo'] = 1023854217; - // body['MobileNo'] = "531940021"; - // body['PatientID'] = 1400563; //3844083 + // body['MobileNo'] = "531940021"; //0560717232 + // body['PatientID'] = 1400563; //4609100 // body['TokenID'] = "@dm!n"; // Patient ID: 3027574 @@ -280,7 +280,7 @@ class BaseAppClient { } catch (e) { print(e); onFailure(e.toString(), -1); - _analytics.errorTracking.log(endPoint, error: "api exception: $e"); + _analytics.errorTracking.log(endPoint, error: "api exception: $e - API Path: $url"); } } diff --git a/lib/core/service/er/er_service.dart b/lib/core/service/er/er_service.dart index 9e981680..f1aa6c3c 100644 --- a/lib/core/service/er/er_service.dart +++ b/lib/core/service/er/er_service.dart @@ -20,6 +20,7 @@ class ErService extends BaseService { var long = await sharedPref.getDouble(USER_LONG); body['Latitude'] = lat ?? 0; body['Longitude'] = long ?? 0; + body['IsForER'] = true; dynamic localRes; diff --git a/lib/core/service/hospital_service.dart b/lib/core/service/hospital_service.dart index e71e6116..7d724e54 100644 --- a/lib/core/service/hospital_service.dart +++ b/lib/core/service/hospital_service.dart @@ -58,6 +58,7 @@ class HospitalService extends BaseService { body['IsOnlineCheckIn'] = isResBasedOnLoc; body['IsAdvancePayment'] = isAdvancePayment; body['LanguageID'] = languageID; + body['IsForER'] = true; await baseAppClient.post(GET_PROJECT, onSuccess: (dynamic response, int statusCode) { _hospitals.clear(); diff --git a/lib/locator.dart b/lib/locator.dart index ec696865..61ed983b 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -13,6 +13,8 @@ import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/PharmacyAddr import 'package:diplomaticquarterapp/core/viewModels/product_categories_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/order_model_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/weather/weather_view_model.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_service.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_view_model.dart'; import 'package:diplomaticquarterapp/services/pharmacy_services/cancelOrder_service.dart'; import 'package:diplomaticquarterapp/services/pharmacy_services/order_service.dart'; import 'package:diplomaticquarterapp/services/pharmacy_services/recommendedProduct_service.dart'; @@ -202,6 +204,7 @@ void setupLocator() { locator.registerLazySingleton(() => VaccinationTableService()); locator.registerLazySingleton(() => AncillaryOrdersService()); locator.registerLazySingleton(() => EdOnlineServices()); + locator.registerLazySingleton(() => PayfortService()); //pharmacy // locator.registerLazySingleton(() => PharmacyCategoriseService()); @@ -309,6 +312,7 @@ void setupLocator() { locator.registerFactory(() => BestSellerViewModel()); locator.registerFactory(() => LastVisitedViewModel()); locator.registerFactory(() => MostViewedViewModel()); + locator.registerFactory(() => PayfortViewModel()); // Offer And Packages //---------------------- diff --git a/lib/main.dart b/lib/main.dart index b06c21d0..c4299d46 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:diplomaticquarterapp/core/viewModels/PharmacyPagesViewModel.dart import 'package:diplomaticquarterapp/core/viewModels/dashboard_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/routes.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_view_model.dart'; import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/services/robo_search/search_provider.dart'; import 'package:diplomaticquarterapp/splashPage.dart'; @@ -74,8 +75,8 @@ class _MyApp extends State { //0567184134 mobile //246305493 - - + + // checkForUpdate() { // // todo need to verify 'imp' // InAppUpdate.checkForUpdate().then((info) { @@ -157,6 +158,7 @@ class _MyApp extends State { ChangeNotifierProvider( create: (context) => OrderPreviewViewModel(), ), + ChangeNotifierProvider(create: (context) => PayfortViewModel()), ], child: Consumer( builder: (context, projectProvider, child) => MaterialApp( diff --git a/lib/models/LiveCare/ApplePayInsertRequest.dart b/lib/models/LiveCare/ApplePayInsertRequest.dart index 1b247a7c..6a7f1ac6 100644 --- a/lib/models/LiveCare/ApplePayInsertRequest.dart +++ b/lib/models/LiveCare/ApplePayInsertRequest.dart @@ -35,44 +35,63 @@ class ApplePayInsertRequest { String? sessionID; bool? isDentalAllowedBackend; int? deviceTypeID; + bool? isMobSDK; + String? merchantReference; + String? merchantIdentifier; + String? commandType; + String? signature; + String? accessCode; + String? shaRequestPhrase; + String? shaResponsePhrase; + String? returnURL; ApplePayInsertRequest( {this.clientRequestID, - this.clinicID, - this.currency, - this.customerEmail, - this.customerID, - this.customerName, - this.deviceToken, - this.voipToken, - this.doctorID, - this.projectID, - this.serviceID, - this.channelID, - this.patientID, - this.patientTypeID, - this.patientOutSA, - this.appointmentDate, - this.appointmentNo, - this.orderDescription, - this.liveServiceID, - this.latitude, - this.longitude, - this.amount, - this.isSchedule, - this.language, - this.userName, - this.responseContinueURL, - this.backClickUrl, - this.paymentOption, - this.versionID, - this.channel, - this.languageID, - this.iPAdress, - this.generalid, - this.sessionID, - this.isDentalAllowedBackend, - this.deviceTypeID}); + this.clinicID, + this.currency, + this.customerEmail, + this.customerID, + this.customerName, + this.deviceToken, + this.voipToken, + this.doctorID, + this.projectID, + this.serviceID, + this.channelID, + this.patientID, + this.patientTypeID, + this.patientOutSA, + this.appointmentDate, + this.appointmentNo, + this.orderDescription, + this.liveServiceID, + this.latitude, + this.longitude, + this.amount, + this.isSchedule, + this.language, + this.userName, + this.responseContinueURL, + this.backClickUrl, + this.paymentOption, + this.versionID, + this.channel, + this.languageID, + this.iPAdress, + this.generalid, + this.sessionID, + this.isDentalAllowedBackend, + this.deviceTypeID, + this.isMobSDK, + this.merchantReference, + this.merchantIdentifier, + this.commandType, + this.signature, + this.accessCode, + this.shaRequestPhrase, + this.shaResponsePhrase, + this.returnURL, + }); ApplePayInsertRequest.fromJson(Map json) { clientRequestID = json['ClientRequestID']; @@ -128,6 +147,7 @@ class ApplePayInsertRequest { data['Service_ID'] = this.serviceID; data['Channel_ID'] = this.channelID; data['PatientID'] = this.patientID; + data['PatientId'] = this.patientID; data['PatientTypeID'] = this.patientTypeID; data['PatientOutSA'] = this.patientOutSA; data['AppointmentDate'] = this.appointmentDate; @@ -151,6 +171,17 @@ class ApplePayInsertRequest { data['SessionID'] = this.sessionID; data['isDentalAllowedBackend'] = this.isDentalAllowedBackend; data['DeviceTypeID'] = this.deviceTypeID; + + data['IsMobSDK'] = this.isMobSDK; + data['Merchant_Reference'] = this.merchantReference; + data['Merchant_Identifier'] = this.merchantIdentifier; + data['CommandType'] = this.commandType; + data['Signature'] = this.signature; + data['Access_code'] = this.accessCode; + data['SHA_RequestPhase'] = this.shaRequestPhrase; + data['SHA_ResponsePhase'] = this.shaResponsePhrase; + data['ReturnURL'] = this.returnURL; + return data; } } diff --git a/lib/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrdersDetails.dart b/lib/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrdersDetails.dart index 915703aa..980f0889 100644 --- a/lib/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrdersDetails.dart +++ b/lib/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrdersDetails.dart @@ -1,17 +1,27 @@ +import 'dart:developer'; import 'dart:io'; +import "package:collection/collection.dart"; import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/enum/PayfortEnums.dart'; import 'package:diplomaticquarterapp/core/service/ancillary_orders_service.dart'; import 'package:diplomaticquarterapp/core/viewModels/ancillary_orders_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/models/LiveCare/ApplePayInsertRequest.dart'; import 'package:diplomaticquarterapp/models/anicllary-orders/ancillary_order_proc_model.dart'; import 'package:diplomaticquarterapp/models/anicllary-orders/ancillary_orders_proc_list.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/payment_method_select.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_project_details_resp_model.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_view_model.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; +import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; @@ -41,7 +51,7 @@ class _AnicllaryOrdersState extends State with SingleTic late ProjectViewModel projectViewModel; bool _agreeTerms = false; String selectedPaymentMethod = ""; - late MyInAppBrowser browser; + MyInAppBrowser? browser; String transID = ""; late BuildContext localContext; String? selectedInstallmentPlan; @@ -63,6 +73,14 @@ class _AnicllaryOrdersState extends State with SingleTic super.dispose(); } + addSelectedProcedure(AncillaryOrderProcDetailsList ancillaryOrderProcDetailsList) { + if (!checkIfProcedureSelected(ancillaryOrderProcDetailsList)) { + selectedProcList.add(ancillaryOrderProcDetailsList); + } else { + selectedProcList.remove(ancillaryOrderProcDetailsList); + } + } + void getAncillaryOrderDetails() { GifLoaderDialogUtils.showMyDialog(context); AncillaryOrdersService ancillaryOrdersService = new AncillaryOrdersService(); @@ -375,23 +393,9 @@ class _AnicllaryOrdersState extends State with SingleTic ); } - - Widget getAncillaryDetails() { - Map> newMap = {}; - _ancillaryProcLists[0].ancillaryOrderProcDetailsList!.forEach((obj) { - String key = obj.procedureCategoryName!; - if (newMap.containsKey(key)) { - newMap[key]!.add(obj); - } else { - newMap[key] = [obj]; - } - }); - - return Padding( - padding: EdgeInsets.only(top: 0, bottom: 200), - child: getHeaderDetails(newMap), - ); + Map newMap = groupBy(_ancillaryProcLists[0].ancillaryOrderProcDetailsList as Iterable, (AncillaryOrderProcDetailsList obj) => obj.procedureCategoryName); + return Padding(padding: EdgeInsets.only(top: 0, bottom: 200), child: getHeaderDetails(newMap)); } Widget getHeaderDetails(newMap) { @@ -479,6 +483,73 @@ class _AnicllaryOrdersState extends State with SingleTic return total.toStringAsFixed(2); } + + bool checkIfProcedureSelected(AncillaryOrderProcDetailsList ancillaryOrderProcDetailsList) { + if (selectedProcList.length > 0) { + if (selectedProcList.contains(ancillaryOrderProcDetailsList)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + bool isProcedureDisabled(AncillaryOrderProcDetailsList ancillaryOrderProcDetailsList) { + if ((ancillaryOrderProcDetailsList.isApprovalRequired! && !ancillaryOrderProcDetailsList.isApprovalCreated!) || + (ancillaryOrderProcDetailsList.isApprovalCreated! && ancillaryOrderProcDetailsList.approvalNo == 0) || + (ancillaryOrderProcDetailsList.isApprovalRequired! && ancillaryOrderProcDetailsList.isApprovalCreated! && ancillaryOrderProcDetailsList.approvalNo == 0)) { + return true; + } else { + return false; + } + } + addToSelectedProcedures() { + if (_ancillaryProcLists.isNotEmpty) { + selectedProcList.clear(); + if (_ancillaryProcLists[0].ancillaryOrderProcDetailsList != null) { + _ancillaryProcLists[0].ancillaryOrderProcDetailsList!.forEach((element) { + if (!isProcedureDisabled(element)) { + selectedProcList.add(element); + } + }); + } else {} + } + setState(() {}); + } + + String getInsuranceText(value) { + String insuranceText = ""; + if (!value.isApprovalRequired) { + insuranceText = "Cash"; + } else { + if (value.isApprovalCreated && value.approvalNo != 0) { + insuranceText = "Approved"; + } else if (value.isApprovalRequired && value.isApprovalCreated && value.approvalNo == 0) { + insuranceText = "Approval Rejected - Please visit receptionist"; + } else { + insuranceText = "Sent For Approval"; + } + } + return insuranceText; + } + + Color getCardColor(value) { + Color color = Color(0xff); + if (!value.isApprovalRequired) { + color = Color(0xff2E303A); + } else { + if (value.isApprovalCreated && value.approvalNo != 0) { + color = Color(0xff359846); + } else if (value.isApprovalRequired && value.isApprovalCreated && value.approvalNo == 0) { + color = Color(0xffD02127); + } else { + color = Color(0xffCC9B14); + } + } + return color; + } + List fullData(context, value) { List tableRow = []; @@ -519,19 +590,103 @@ class _AnicllaryOrdersState extends State with SingleTic onSelectedMethod: (String method, [String? selectedInstallmentPlan]) { selectedPaymentMethod = method; this.selectedInstallmentPlan = selectedInstallmentPlan; - openPayment(selectedPaymentMethod, projectViewModel.user, double.parse(getTotalValue()), AppoitmentAllHistoryResultList(), selectedInstallmentPlan); + if (selectedPaymentMethod == "ApplePay") { + startApplePay(); + } else { + openPayment(selectedPaymentMethod, projectViewModel.user, double.parse(getTotalValue()), null, selectedInstallmentPlan); + } }, patientShare: double.parse(getTotalValue()), isFromAdvancePayment: !projectViewModel.havePrivilege(94), )); } + void startApplePay() async { + transID = Utils.getAdvancePaymentTransID(widget.projectID, projectViewModel.user.patientID!); - openPayment(String paymentMethod, AuthenticatedUser authenticatedUser, num amount, AppoitmentAllHistoryResultList appo, [String? selectedInstallmentPlan]) { - browser = new MyInAppBrowser(onExitCallback: onBrowserExit, appo: appo, onLoadStartCallback: onBrowserLoadStart); + print("TransactionID: $transID"); + GifLoaderDialogUtils.showMyDialog(context); + + LiveCareService service = new LiveCareService(); + ApplePayInsertRequest applePayInsertRequest = new ApplePayInsertRequest(); + + PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel; + await context.read().getProjectDetailsForPayfort(projectId: widget.projectID, serviceId: ServiceTypeEnum.ancillaryOrder.getIdFromServiceEnum()).then((value) { + payfortProjectDetailsRespModel = value; + }); + + applePayInsertRequest.clientRequestID = transID; + applePayInsertRequest.clinicID = 0; + applePayInsertRequest.currency = projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR"; + applePayInsertRequest.customerEmail = projectViewModel.authenticatedUserObject.user.emailAddress; + applePayInsertRequest.customerID = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.customerName = projectViewModel.authenticatedUserObject.user.firstName! + " " + projectViewModel.authenticatedUserObject.user.lastName!; + applePayInsertRequest.deviceToken = await AppSharedPreferences().getString(PUSH_TOKEN); + applePayInsertRequest.voipToken = await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN); + applePayInsertRequest.doctorID = 0; + applePayInsertRequest.projectID = widget.projectID.toString(); + applePayInsertRequest.serviceID = ServiceTypeEnum.advancePayment.getIdFromServiceEnum().toString(); + applePayInsertRequest.channelID = 3; + applePayInsertRequest.patientID = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.patientTypeID = projectViewModel.authenticatedUserObject.user.patientType; + applePayInsertRequest.patientOutSA = projectViewModel.authenticatedUserObject.user.outSA; + applePayInsertRequest.appointmentDate = null; + applePayInsertRequest.appointmentNo = 0; + applePayInsertRequest.orderDescription = "Advance Payment"; + applePayInsertRequest.liveServiceID = "0"; + applePayInsertRequest.latitude = "0.0"; + applePayInsertRequest.longitude = "0.0"; + applePayInsertRequest.amount = double.parse(getTotalValue()).toString(); + applePayInsertRequest.isSchedule = "0"; + applePayInsertRequest.language = projectViewModel.isArabic ? 'ar' : 'en'; + applePayInsertRequest.languageID = projectViewModel.isArabic ? 1 : 2; + applePayInsertRequest.userName = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.paymentOption = "ApplePay"; + + applePayInsertRequest.isMobSDK = true; + applePayInsertRequest.merchantReference = transID; + applePayInsertRequest.merchantIdentifier = payfortProjectDetailsRespModel!.merchantIdentifier; + applePayInsertRequest.commandType = "PURCHASE"; + applePayInsertRequest.signature = payfortProjectDetailsRespModel!.signature; + applePayInsertRequest.accessCode = payfortProjectDetailsRespModel!.accessCode; + applePayInsertRequest.shaRequestPhrase = payfortProjectDetailsRespModel!.shaRequest; + applePayInsertRequest.shaResponsePhrase = payfortProjectDetailsRespModel!.shaResponse; + applePayInsertRequest.returnURL = ""; + + service.applePayInsertRequest(applePayInsertRequest, context).then((res) async { + await context.read().initiateApplePayWithPayfort( + customerName: projectViewModel.authenticatedUserObject.user.firstName! + " " + projectViewModel.authenticatedUserObject.user!.lastName!, + customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress, + orderDescription: "Ancillary Order Payment", + orderAmount: double.parse(getTotalValue()), + merchantReference: transID, + payfortProjectDetailsRespModel: payfortProjectDetailsRespModel, + currency: projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR", + onFailed: (failureResult) async { + log("failureResult: ${failureResult.toString()}"); + AppToast.showErrorToast(message: failureResult.toString()); + }, + onSuccess: (successResult) async { + log("Payfort: ${successResult.responseMessage}"); + await context.read().addPayfortApplePayResponse(result: successResult); + checkPaymentStatus(AppoitmentAllHistoryResultList()); + }, + projectId: widget.projectID, + serviceTypeEnum: ServiceTypeEnum.ancillaryOrder, + ); + }).catchError((err) { + print(err); + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + }); + } + openPayment(String paymentMethod, AuthenticatedUser authenticatedUser, num amount, AppoitmentAllHistoryResultList? appo, [String? selectedInstallmentPlan]) { + browser = new MyInAppBrowser(onExitCallback: onBrowserExit, appo: appo, onLoadStartCallback: onBrowserLoadStart); transID = Utils.getAdvancePaymentTransID(widget.projectID, projectViewModel.user.patientID!); - browser.openPaymentBrowser( + browser!.openPaymentBrowser( amount, "Ancillary Orders Payment", transID, @@ -542,7 +697,7 @@ class _AnicllaryOrdersState extends State with SingleTic projectViewModel.user.firstName! + " " + projectViewModel.user.lastName!, projectViewModel.user.patientID, authenticatedUser, - browser, + browser!, false, "3", // Need to get new Service ID from Ayman for Ancillary Tamara @@ -573,7 +728,7 @@ class _AnicllaryOrdersState extends State with SingleTic MyInAppBrowser.successURLS.forEach((element) { if (url.contains(element)) { - if (browser.isOpened()) browser.close(); + if (browser!.isOpened()) browser!.close(); MyInAppBrowser.isPaymentDone = true; return; } @@ -581,7 +736,7 @@ class _AnicllaryOrdersState extends State with SingleTic MyInAppBrowser.errorURLS.forEach((element) { if (url.contains(element)) { - if (browser.isOpened()) browser.close(); + if (browser!.isOpened()) browser!.close(); MyInAppBrowser.isPaymentDone = false; return; } @@ -660,7 +815,6 @@ class _AnicllaryOrdersState extends State with SingleTic // selectedProcList.forEach((element) { // ancillaryOrdersProcedureList.add(new AncillaryOrdersProcedureList(procedureID: num.parse(element.procedureID), procedureDescription: element.procedureName)); // }); - service.HIS_createAdvancePayment(appo, widget.projectID.toString(), res['Amount'], res['Fort_id'], res['PaymentMethod'], projectViewModel.user.patientType, projectViewModel.user.firstName! + " " + projectViewModel.user.lastName!, projectViewModel.user.patientID, localContext, isAncillaryOrder: true) @@ -679,17 +833,6 @@ class _AnicllaryOrdersState extends State with SingleTic }); } - addAdvancedNumberRequest(String advanceNumber, String paymentReference, dynamic appointmentID, AppoitmentAllHistoryResultList appo) { - DoctorsListService service = new DoctorsListService(); - service.addAdvancedNumberRequest(advanceNumber, paymentReference, appointmentID, localContext).then((res) { - autoGenerateInvoice(); - }).catchError((err) { - GifLoaderDialogUtils.hideDialog(localContext); - AppToast.showErrorToast(message: err.toString()); - print(err); - }); - } - autoGenerateInvoice() { List selectedProcListAPI = []; @@ -714,6 +857,17 @@ class _AnicllaryOrdersState extends State with SingleTic }); } + + addAdvancedNumberRequest(String advanceNumber, String paymentReference, dynamic appointmentID, AppoitmentAllHistoryResultList appo) { + DoctorsListService service = new DoctorsListService(); + service.addAdvancedNumberRequest(advanceNumber, paymentReference, appointmentID, localContext).then((res) { + autoGenerateInvoice(); + }).catchError((err) { + GifLoaderDialogUtils.hideDialog(localContext); + AppToast.showErrorToast(message: err.toString()); + print(err); + }); + } showAlertDialog(dynamic invoiceNo, dynamic projectID) { AlertDialogBox( context: context, @@ -722,82 +876,11 @@ class _AnicllaryOrdersState extends State with SingleTic okFunction: () { AlertDialogBox.closeAlertDialog(context); Navigator.of(context).pop(); + Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) => LandingPage()), (Route r) => false); }).showAlertDialog(context); } - bool checkIfProcedureSelected(AncillaryOrderProcDetailsList ancillaryOrderProcDetailsList) { - if (selectedProcList.length > 0) { - if (selectedProcList.contains(ancillaryOrderProcDetailsList)) { - return true; - } else { - return false; - } - } else { - return false; - } - } - - addToSelectedProcedures() { - if (_ancillaryProcLists.isNotEmpty) { - selectedProcList.clear(); - if (_ancillaryProcLists[0].ancillaryOrderProcDetailsList != null) { - _ancillaryProcLists[0].ancillaryOrderProcDetailsList!.forEach((element) { - if (!isProcedureDisabled(element)) { - selectedProcList.add(element); - } - }); - } else {} - } - setState(() {}); - } - - String getInsuranceText(value) { - String insuranceText = ""; - if (!value.isApprovalRequired) { - insuranceText = "Cash"; - } else { - if (value.isApprovalCreated && value.approvalNo != 0) { - insuranceText = "Approved"; - } else if (value.isApprovalRequired && value.isApprovalCreated && value.approvalNo == 0) { - insuranceText = "Approval Rejected - Please visit receptionist"; - } else { - insuranceText = "Sent For Approval"; - } - } - return insuranceText; - } - Color getCardColor(value) { - Color color = Color(0xff); - if (!value.isApprovalRequired) { - color = Color(0xff2E303A); - } else { - if (value.isApprovalCreated && value.approvalNo != 0) { - color = Color(0xff359846); - } else if (value.isApprovalRequired && value.isApprovalCreated && value.approvalNo == 0) { - color = Color(0xffD02127); - } else { - color = Color(0xffCC9B14); - } - } - return color; - } - bool isProcedureDisabled(AncillaryOrderProcDetailsList ancillaryOrderProcDetailsList) { - if ((ancillaryOrderProcDetailsList.isApprovalRequired! && !ancillaryOrderProcDetailsList.isApprovalCreated!) || - (ancillaryOrderProcDetailsList.isApprovalCreated! && ancillaryOrderProcDetailsList.approvalNo == 0) || - (ancillaryOrderProcDetailsList.isApprovalRequired! && ancillaryOrderProcDetailsList.isApprovalCreated! && ancillaryOrderProcDetailsList.approvalNo == 0)) { - return true; - } else { - return false; - } - } - addSelectedProcedure(AncillaryOrderProcDetailsList ancillaryOrderProcDetailsList) { - if (!checkIfProcedureSelected(ancillaryOrderProcDetailsList)) { - selectedProcList.add(ancillaryOrderProcDetailsList); - } else { - selectedProcList.remove(ancillaryOrderProcDetailsList); - } - } } diff --git a/lib/pages/BookAppointment/BookConfirm.dart b/lib/pages/BookAppointment/BookConfirm.dart index d2644d72..ec7eec2c 100644 --- a/lib/pages/BookAppointment/BookConfirm.dart +++ b/lib/pages/BookAppointment/BookConfirm.dart @@ -263,7 +263,7 @@ class _BookConfirmState extends State { service.cancelAppointment(appo, context, isReschedule: true).then((res) { GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { - Future.delayed(Duration(milliseconds: 1500), () async { + Future.delayed(Duration(milliseconds: 500), () async { if (isLiveCareSchedule != null && isLiveCareSchedule) { insertLiveCareScheduledAppointment(context, widget.doctor); } else { diff --git a/lib/pages/BookAppointment/BookSuccess.dart b/lib/pages/BookAppointment/BookSuccess.dart index 8d1d2943..7466ef6f 100644 --- a/lib/pages/BookAppointment/BookSuccess.dart +++ b/lib/pages/BookAppointment/BookSuccess.dart @@ -1,16 +1,22 @@ +import 'dart:developer'; import 'dart:io'; +import 'package:diplomaticquarterapp/core/enum/PayfortEnums.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/models/LiveCare/ApplePayInsertRequest.dart'; import 'package:diplomaticquarterapp/models/header_model.dart'; import 'package:diplomaticquarterapp/pages/ToDoList/payment_method_select.dart'; import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dart'; import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_project_details_resp_model.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_view_model.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; @@ -28,6 +34,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:provider/provider.dart'; +import '../../config/shared_pref_kay.dart'; import 'QRCode.dart'; class BookSuccess extends StatefulWidget { @@ -57,12 +64,15 @@ class _BookSuccessState extends State { String? selectedInstallments = ""; String? tamaraPaymentStatus; String? tamaraOrderID; + String? transID; @override initState() { WidgetsBinding.instance.addPostFrameCallback((_) async { if (widget.patientShareResponse.isLiveCareAppointment! && - (widget.patientShareResponse.patientShareWithTax.toString() == "0" || widget.patientShareResponse.patientShareWithTax.toString() == "0.0")) { + (widget.patientShareResponse.patientShareWithTax.toString() == "0" || + widget.patientShareResponse.patientShareWithTax.toString() == + "0.0")) { setOnlineCheckInForAppointment(); } }); @@ -106,18 +116,26 @@ class _BookSuccessState extends State { alignment: Alignment.center, color: CustomColors.green, child: Table( - border: TableBorder(verticalInside: BorderSide(width: 0.5, color: Colors.white)), + border: TableBorder(verticalInside: BorderSide( + width: 0.5, color: Colors.white)), children: [ TableRow( children: [ - TableCell(child: _getNormalText(TranslationBase.of(context).patientShare)), - TableCell(child: _getNormalText(TranslationBase.of(context).patientShareWithTax)), + TableCell(child: _getNormalText(TranslationBase + .of(context) + .patientShare)), + TableCell(child: _getNormalText(TranslationBase + .of(context) + .patientShareWithTax)), ], ), TableRow( children: [ - TableCell(child: _getHeadingText("SR " + widget.patientShareResponse.patientShare.toString())), - TableCell(child: _getHeadingText("SR " + widget.patientShareResponse.patientShareWithTax.toString())), + TableCell(child: _getHeadingText("SR " + + widget.patientShareResponse.patientShare.toString())), + TableCell(child: _getHeadingText("SR " + + widget.patientShareResponse.patientShareWithTax + .toString())), ], ), ], @@ -160,7 +178,10 @@ class _BookSuccessState extends State { return Container( alignment: Alignment.bottomCenter, margin: EdgeInsets.all(14), - height: MediaQuery.of(context).size.height * 0.18, + height: MediaQuery + .of(context) + .size + .height * 0.18, child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -172,7 +193,10 @@ class _BookSuccessState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), - minWidth: MediaQuery.of(context).size.width * 0.7, + minWidth: MediaQuery + .of(context) + .size + .width * 0.7, height: 45.0, child: CustomTextButton( backgroundColor: CustomColors.green, @@ -181,7 +205,10 @@ class _BookSuccessState extends State { GifLoaderDialogUtils.showMyDialog(context); getAppoQR(context); }, - child: Text(TranslationBase.of(context).checkinOptions, style: TextStyle(fontSize: 18.0, color: Colors.white)), + child: Text(TranslationBase + .of(context) + .checkinOptions, + style: TextStyle(fontSize: 18.0, color: Colors.white)), ), ), ), @@ -192,7 +219,10 @@ class _BookSuccessState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), - minWidth: MediaQuery.of(context).size.width * 0.7, + minWidth: MediaQuery + .of(context) + .size + .width * 0.7, height: 45.0, child: CustomTextButton( backgroundColor: Color(0xffc5272d), @@ -202,7 +232,10 @@ class _BookSuccessState extends State { // GifLoaderDialogUtils.showMyDialog(context); // getAppoQR(context); }, - child: Text(TranslationBase.of(context).done, style: TextStyle(fontSize: 18.0, color: Colors.white)), + child: Text(TranslationBase + .of(context) + .done, + style: TextStyle(fontSize: 18.0, color: Colors.white)), ), ), ), @@ -237,9 +270,16 @@ class _BookSuccessState extends State { elevation: 0, onPressed: () { startPaymentProcess(); - projectViewModel.analytics.appointment.pay_now_for_appointment(appointment_type: 'regular', doctorDetail: widget.docObject, payNow: true); + projectViewModel.analytics.appointment + .pay_now_for_appointment( + appointment_type: 'regular', + doctorDetail: widget.docObject, + payNow: true); }, - child: Text(TranslationBase.of(context).payNow.toUpperCase(), + child: Text(TranslationBase + .of(context) + .payNow + .toUpperCase(), style: TextStyle( fontSize: 18.0, color: Colors.white, @@ -260,9 +300,17 @@ class _BookSuccessState extends State { elevation: 0, onPressed: () { navigateToHome(context); - projectViewModel.analytics.appointment.pay_now_for_appointment(appointment_type: 'regular', doctorDetail: widget.docObject, payNow: false); + projectViewModel.analytics.appointment + .pay_now_for_appointment( + appointment_type: 'regular', + doctorDetail: widget.docObject, + payNow: false); }, - child: Text(TranslationBase.of(context).payLater.toUpperCase(), style: TextStyle(fontSize: 18.0, color: Colors.white)), + child: Text(TranslationBase + .of(context) + .payLater + .toUpperCase(), style: TextStyle( + fontSize: 18.0, color: Colors.white)), ), ), ), @@ -270,33 +318,37 @@ class _BookSuccessState extends State { ), widget.isCash ? Column( - children: [ - mHeight(10.0), - Text( - TranslationBase.of(context).cashAmountUpdateInsurance, - style: TextStyle( - fontSize: 14.0, - fontWeight: FontWeight.w600, - color: Color(0xff2E303A), - ), - ), - mHeight(5.0), - DefaultButton( - TranslationBase.of(context).updateInsuranceText, - () { - Navigator.pop(context, null); - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) => LandingPage()), - (Route route) => false, - ); - Navigator.push(context, FadePage(page: InsuranceUpdate())); - }, - color: Color(0xffEAA118), - textColor: Colors.white, - ), - ], - ) + children: [ + mHeight(10.0), + Text( + TranslationBase + .of(context) + .cashAmountUpdateInsurance, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w600, + color: Color(0xff2E303A), + ), + ), + mHeight(5.0), + DefaultButton( + TranslationBase + .of(context) + .updateInsuranceText, + () { + Navigator.pop(context, null); + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => LandingPage()), + (Route route) => false, + ); + Navigator.push(context, FadePage(page: InsuranceUpdate())); + }, + color: Color(0xffEAA118), + textColor: Colors.white, + ), + ], + ) : Container(), ], ), @@ -328,17 +380,23 @@ class _BookSuccessState extends State { AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList(); appo.clinicID = widget.docObject.clinicID; appo.projectID = widget.docObject.projectID; - appo.appointmentNo = widget.patientShareResponse.appointmentNo; + appo.appointmentNo = + widget.patientShareResponse.appointmentNo; appo.serviceID = widget.patientShareResponse.serviceID; - appo.isLiveCareAppointment = widget.patientShareResponse.isLiveCareAppointment; + appo.isLiveCareAppointment = + widget.patientShareResponse.isLiveCareAppointment; appo.doctorID = widget.patientShareResponse.doctorID; - appo.appointmentDate = widget.patientShareResponse.appointmentDate; + appo.appointmentDate = + widget.patientShareResponse.appointmentDate; if (appo.isLiveCareAppointment!) insertLiveCareVIDARequest(appo); else navigateToHome(context); }, - child: Text(TranslationBase.of(context).confirmLater, style: TextStyle(fontSize: 16.0, color: Colors.white)), + child: Text(TranslationBase + .of(context) + .confirmLater, + style: TextStyle(fontSize: 16.0, color: Colors.white)), ), ), ), @@ -357,9 +415,11 @@ class _BookSuccessState extends State { AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList(); appo.clinicID = widget.docObject.clinicID; appo.projectID = widget.docObject.projectID; - appo.appointmentNo = widget.patientShareResponse.appointmentNo; + appo.appointmentNo = + widget.patientShareResponse.appointmentNo; appo.serviceID = widget.patientShareResponse.serviceID; - appo.isLiveCareAppointment = widget.patientShareResponse.isLiveCareAppointment; + appo.isLiveCareAppointment = + widget.patientShareResponse.isLiveCareAppointment; appo.doctorID = widget.patientShareResponse.doctorID; if (appo.isLiveCareAppointment!) { navigateToHome(context); @@ -367,7 +427,13 @@ class _BookSuccessState extends State { confirmAppointment(appo); } }, - child: Text(widget.patientShareResponse.isLiveCareAppointment! ? TranslationBase.of(context).confirmLiveCare : TranslationBase.of(context).confirm, + child: Text(widget.patientShareResponse.isLiveCareAppointment! + ? TranslationBase + .of(context) + .confirmLiveCare + : TranslationBase + .of(context) + .confirm, style: TextStyle(fontSize: 16.0, color: Colors.white)), ), ), @@ -437,7 +503,10 @@ class _BookSuccessState extends State { Container( margin: EdgeInsets.only(top: 30.0, bottom: 40.0), alignment: Alignment.center, - child: Text(TranslationBase.of(context).confirmAppo, style: TextStyle(fontSize: 18.0, letterSpacing: 0.8)), + child: Text(TranslationBase + .of(context) + .confirmAppo, + style: TextStyle(fontSize: 18.0, letterSpacing: 0.8)), ), Flex( direction: Axis.horizontal, @@ -451,8 +520,14 @@ class _BookSuccessState extends State { children: [ _getBulletPoint("1"), Container( - width: MediaQuery.of(context).size.width * 0.8, - child: Text(TranslationBase.of(context).upcomingConfirm, overflow: TextOverflow.clip, style: TextStyle(fontSize: 13.0)), + width: MediaQuery + .of(context) + .size + .width * 0.8, + child: Text(TranslationBase + .of(context) + .upcomingConfirm, overflow: TextOverflow.clip, + style: TextStyle(fontSize: 13.0)), ), ], ), @@ -472,8 +547,14 @@ class _BookSuccessState extends State { children: [ _getBulletPoint("2"), Container( - width: MediaQuery.of(context).size.width * 0.8, - child: Text(TranslationBase.of(context).upcomingConfirmMore, overflow: TextOverflow.clip, style: TextStyle(fontSize: 13.0)), + width: MediaQuery + .of(context) + .size + .width * 0.8, + child: Text(TranslationBase + .of(context) + .upcomingConfirmMore, overflow: TextOverflow.clip, + style: TextStyle(fontSize: 13.0)), ), ], ), @@ -481,7 +562,8 @@ class _BookSuccessState extends State { ), ], ), - Container(margin: EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 5.0), child: getPaymentMethods()), + Container(margin: EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 5.0), + child: getPaymentMethods()), ], ); } @@ -493,13 +575,17 @@ class _BookSuccessState extends State { setOnlineCheckInForAppointment() { DoctorsListService service = new DoctorsListService(); GifLoaderDialogUtils.showMyDialog(context); - service.setOnlineCheckInForAppointment(widget.patientShareResponse.appointmentNo.toString(), widget.patientShareResponse.projectID!, projectViewModel.isArabic ? 1 : 2, context).then((res) { + service.setOnlineCheckInForAppointment( + widget.patientShareResponse.appointmentNo.toString(), + widget.patientShareResponse.projectID!, + projectViewModel.isArabic ? 1 : 2, context).then((res) { AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList(); appo.clinicID = widget.docObject.clinicID; appo.projectID = widget.docObject.projectID; appo.appointmentNo = widget.patientShareResponse.appointmentNo; appo.serviceID = widget.patientShareResponse.serviceID; - appo.isLiveCareAppointment = widget.patientShareResponse.isLiveCareAppointment; + appo.isLiveCareAppointment = + widget.patientShareResponse.isLiveCareAppointment; appo.doctorID = widget.patientShareResponse.doctorID; appo.appointmentDate = widget.patientShareResponse.appointmentDate; insertLiveCareVIDARequest(appo, isMoveHome: false); @@ -514,7 +600,9 @@ class _BookSuccessState extends State { confirmAppointment(AppoitmentAllHistoryResultList appo) { DoctorsListService service = new DoctorsListService(); GifLoaderDialogUtils.showMyDialog(context); - service.confirmAppointment(appo.appointmentNo!, appo.clinicID!, appo.projectID!, appo.isLiveCareAppointment!, context).then((res) { + service.confirmAppointment( + appo.appointmentNo!, appo.clinicID!, appo.projectID!, + appo.isLiveCareAppointment!, context).then((res) { GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { AppToast.showSuccessToast(message: res['ErrorEndUserMessage']); @@ -533,12 +621,22 @@ class _BookSuccessState extends State { }); } - insertLiveCareVIDARequest(AppoitmentAllHistoryResultList appo, {bool isMoveHome = true}) { + insertLiveCareVIDARequest(AppoitmentAllHistoryResultList appo, + {bool isMoveHome = true}) { DoctorsListService service = new DoctorsListService(); GifLoaderDialogUtils.showMyDialog(context); service - .insertVIDARequest(appo.appointmentNo, appo.clinicID, appo.projectID, appo.serviceID, appo.doctorID, appo.appointmentDate!, - Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), projectViewModel.isArabic ? 1 : 2, context) + .insertVIDARequest( + appo.appointmentNo, + appo.clinicID, + appo.projectID, + appo.serviceID, + appo.doctorID, + appo.appointmentDate!, + Utils.getAppointmentTransID( + appo.projectID, appo.clinicID, appo.appointmentNo), + projectViewModel.isArabic ? 1 : 2, + context) .then((res) { GifLoaderDialogUtils.hideDialog(context); if (res['MessageStatus'] == 1) { @@ -561,7 +659,9 @@ class _BookSuccessState extends State { mainAxisSize: MainAxisSize.max, children: [ Text( - TranslationBase.of(context).payNowBookSuccess, + TranslationBase + .of(context) + .payNowBookSuccess, style: TextStyle( fontSize: 24.0, letterSpacing: -1.44, @@ -569,7 +669,9 @@ class _BookSuccessState extends State { ), ), Text( - TranslationBase.of(context).neverWait, + TranslationBase + .of(context) + .neverWait, style: TextStyle( fontSize: 12.0, letterSpacing: -0.54, @@ -577,15 +679,20 @@ class _BookSuccessState extends State { ), ), mHeight(24), - Text(TranslationBase.of(context).payNowBookSuccesstext1, + Text(TranslationBase + .of(context) + .payNowBookSuccesstext1, overflow: TextOverflow.fade, style: TextStyle( fontSize: 12.0, letterSpacing: -0.36, )), - Container(margin: EdgeInsets.fromLTRB(20.0, 5.0, 20.0, 5.0), child: getPaymentMethods()), + Container(margin: EdgeInsets.fromLTRB(20.0, 5.0, 20.0, 5.0), + child: getPaymentMethods()), Text( - TranslationBase.of(context).payNowBookSuccesstext2, + TranslationBase + .of(context) + .payNowBookSuccesstext2, overflow: TextOverflow.clip, style: TextStyle( fontSize: 12.0, @@ -601,42 +708,173 @@ class _BookSuccessState extends State { navigateToPaymentMethod(context, widget.patientShareResponse); } - Future navigateToPaymentMethod(context, PatientShareResponse patientShareResponse) async { + Future navigateToPaymentMethod(context, + PatientShareResponse patientShareResponse) async { AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList(); appo.projectID = widget.patientShareResponse.projectID; appo.clinicID = widget.patientShareResponse.clinicID; appo.clinicName = widget.patientShareResponse.clinicName; appo.projectName = widget.patientShareResponse.projectName; appo.appointmentNo = widget.patientShareResponse.appointmentNo; - appo.isLiveCareAppointment = widget.patientShareResponse.isLiveCareAppointment; + appo.isLiveCareAppointment = + widget.patientShareResponse.isLiveCareAppointment; appo.doctorID = widget.patientShareResponse.doctorID; appo.appointmentDate = widget.patientShareResponse.appointmentDate; appo.serviceID = widget.patientShareResponse.serviceID; Navigator.push( - context, - FadePage( - page: PaymentMethod( - onSelectedMethod: (String metohd, [String? selectedInstallmentPlan]) { - setState(() {}); - }, - patientShare: widget.patientShareResponse.patientShareWithTax))) + context, + FadePage( + page: PaymentMethod( + onSelectedMethod: (String metohd, + [String? selectedInstallmentPlan]) { + setState(() {}); + }, + patientShare: widget.patientShareResponse.patientShareWithTax))) .then((value) { + selectedPaymentMethod = value[0]; if (value != null) { - openPayment(value, projectViewModel.user!, double.parse(patientShareResponse.patientShareWithTax.toString()), patientShareResponse, appo); - projectViewModel.analytics.appointment.payment_method(appointment_type: 'regular', clinic: widget.docObject.clinicName, payment_method: value[0], payment_type: 'appointment'); + if (selectedPaymentMethod == "ApplePay") { + startApplePay(appo, patientShareResponse); + } else { + openPayment(value, projectViewModel.user, + double.parse(patientShareResponse.patientShareWithTax.toString()), + patientShareResponse, appo); + } + openPayment(value, projectViewModel.user!, + double.parse(patientShareResponse.patientShareWithTax.toString()), + patientShareResponse, appo); + projectViewModel.analytics.appointment.payment_method( + appointment_type: 'regular', + clinic: widget.docObject.clinicName, + payment_method: value[0], + payment_type: 'appointment'); } }); } + void startApplePay(AppoitmentAllHistoryResultList appo, + PatientShareResponse patientShareResponse) async { + transID = Utils.getAppointmentTransID( + appo.projectID, appo.clinicID, appo.appointmentNo); + print("TransactionID: $transID"); + GifLoaderDialogUtils.showMyDialog(context); + + LiveCareService service = new LiveCareService(); + ApplePayInsertRequest applePayInsertRequest = new ApplePayInsertRequest(); + + PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel; + await context.read() + .getProjectDetailsForPayfort(projectId: appo.projectID, + serviceId: ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum()) + .then((value) { + payfortProjectDetailsRespModel = value!; + }); + + applePayInsertRequest.clientRequestID = transID; + applePayInsertRequest.clinicID = appo.clinicID; + applePayInsertRequest.currency = + projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR"; + applePayInsertRequest.customerEmail = + projectViewModel.authenticatedUserObject.user.emailAddress; + applePayInsertRequest.customerID = + projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.customerName = + projectViewModel.authenticatedUserObject.user.firstName! + " " + + projectViewModel.authenticatedUserObject.user.lastName!; + applePayInsertRequest.deviceToken = + await AppSharedPreferences().getString(PUSH_TOKEN); + applePayInsertRequest.voipToken = + await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN); + applePayInsertRequest.doctorID = appo.doctorID; + applePayInsertRequest.projectID = appo.projectID.toString(); + applePayInsertRequest.serviceID = + ServiceTypeEnum.advancePayment.getIdFromServiceEnum().toString(); + applePayInsertRequest.channelID = 3; + applePayInsertRequest.patientID = + projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.patientTypeID = + projectViewModel.authenticatedUserObject.user.patientType; + applePayInsertRequest.patientOutSA = + projectViewModel.authenticatedUserObject.user.outSA; + applePayInsertRequest.appointmentDate = appo.appointmentDate; + applePayInsertRequest.appointmentNo = appo.appointmentNo; + applePayInsertRequest.orderDescription = "Advance Payment"; + applePayInsertRequest.liveServiceID = "0"; + applePayInsertRequest.latitude = "0.0"; + applePayInsertRequest.longitude = "0.0"; + applePayInsertRequest.amount = + patientShareResponse.patientShareWithTax.toString(); + applePayInsertRequest.isSchedule = appo.isLiveCareAppointment! ? "1" : "0"; + applePayInsertRequest.language = projectViewModel.isArabic ? 'ar' : 'en'; + applePayInsertRequest.languageID = projectViewModel.isArabic ? 1 : 2; + applePayInsertRequest.userName = + projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.responseContinueURL = + "http://hmg.com/Documents/success.html"; + applePayInsertRequest.backClickUrl = + "http://hmg.com/Documents/success.html"; + applePayInsertRequest.paymentOption = "ApplePay"; + + applePayInsertRequest.isMobSDK = true; + applePayInsertRequest.merchantReference = transID; + applePayInsertRequest.merchantIdentifier = + payfortProjectDetailsRespModel!.merchantIdentifier!; + applePayInsertRequest.commandType = "PURCHASE"; + applePayInsertRequest.signature = payfortProjectDetailsRespModel!.signature; + applePayInsertRequest.accessCode = + payfortProjectDetailsRespModel!.accessCode; + applePayInsertRequest.shaRequestPhrase = + payfortProjectDetailsRespModel!.shaRequest; + applePayInsertRequest.shaResponsePhrase = + payfortProjectDetailsRespModel!.shaResponse; + applePayInsertRequest.returnURL = ""; + + service.applePayInsertRequest(applePayInsertRequest, context).then(( + res) async { + await context.read().initiateApplePayWithPayfort( + customerName: projectViewModel.authenticatedUserObject.user.firstName! + + " " + projectViewModel.authenticatedUserObject.user.lastName!, + customerEmail: projectViewModel.authenticatedUserObject.user + .emailAddress, + orderDescription: "Appointment Payment", + orderAmount: double.parse( + patientShareResponse.patientShareWithTax.toString()), + merchantReference: transID, + payfortProjectDetailsRespModel: payfortProjectDetailsRespModel, + currency: projectViewModel.authenticatedUserObject.user.outSA == 1 + ? "AED" + : "SAR", + onFailed: (failureResult) async { + log("failureResult: ${failureResult.toString()}"); + AppToast.showErrorToast(message: failureResult.toString()); + }, + onSuccess: (successResult) async { + log("Payfort: ${successResult.responseMessage}"); + await context.read().addPayfortApplePayResponse( + result: successResult); + checkPaymentStatus(appo); + }, + projectId: appo.projectID, + serviceTypeEnum: ServiceTypeEnum.appointmentPayment, + ); + }).catchError((err) { + print(err); + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + }); + } + + openPayment(List paymentMethod, AuthenticatedUser authenticatedUser, num amount, PatientShareResponse patientShareResponse, AppoitmentAllHistoryResultList appo) async { widget.browser = new MyInAppBrowser(onExitCallback: onBrowserExit, appo: appo, onLoadStartCallback: onBrowserLoadStart, context: context); selectedPaymentMethod = paymentMethod[0]; selectedInstallments = paymentMethod[1]; + transID = Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo); widget.browser.openPaymentBrowser( amount, "Appointment check in", - Utils.getAppointmentTransID(appo.projectID!, appo.clinicID!, appo.appointmentNo!), + transID!, appo.projectID.toString(), authenticatedUser.emailAddress!, paymentMethod[0]!, @@ -791,7 +1029,7 @@ class _BookSuccessState extends State { final currency = projectViewModel.user!.outSA == 0 ? "sar" : 'aed'; GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); - service.checkPaymentStatus(Utils.getAppointmentTransID(appo.projectID!, appo.clinicID!, appo.appointmentNo!), false, context).then((res) { + service.checkPaymentStatus(transID!, false, context).then((res) { String paymentInfo = res['Response_Message']; if (paymentInfo == 'Success') { txn_ref = res['Merchant_Reference']; @@ -969,9 +1207,6 @@ class _BookSuccessState extends State { ); } - _getTextStyling() { - return TextStyle(fontSize: 14.0, color: Colors.white, letterSpacing: 0.7); - } _getBulletPoint(bulletPoint) { return Container( @@ -1062,4 +1297,8 @@ class _BookSuccessState extends State { )), ); } + +_getTextStyling() { + return TextStyle(fontSize: 14.0, color: Colors.white, letterSpacing: 0.7); +} } diff --git a/lib/pages/ToDoList/ToDo.dart b/lib/pages/ToDoList/ToDo.dart index bf48dd91..24efb5c9 100644 --- a/lib/pages/ToDoList/ToDo.dart +++ b/lib/pages/ToDoList/ToDo.dart @@ -1,7 +1,9 @@ +import 'dart:developer'; import 'dart:io'; import 'package:diplomaticquarterapp/analytics/google-analytics.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/enum/PayfortEnums.dart'; import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; @@ -10,6 +12,7 @@ import 'package:diplomaticquarterapp/models/Appointments/OBGyneProcedureListResp import 'package:diplomaticquarterapp/models/Appointments/PatientShareResposne.dart'; import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/models/LiveCare/ApplePayInsertRequest.dart'; import 'package:diplomaticquarterapp/models/anicllary-orders/ancillary_order_list_model.dart'; import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/ancillary-orders/ancillaryOrdersDetails.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/QRCode.dart'; @@ -21,6 +24,9 @@ import 'package:diplomaticquarterapp/pages/insurance/insurance_update_screen.dar import 'package:diplomaticquarterapp/pages/landing/landing_page.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; +import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_project_details_resp_model.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_view_model.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; @@ -86,6 +92,7 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { List appoList = []; List ancillaryLists = []; List obGyneAppoList = []; + String? transID; @override void initState() { @@ -1082,13 +1089,13 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { projectViewModel.analytics.todoList.to_do_list_pay_now(appo); } - openPayment(paymentMethod, AuthenticatedUser authenticatedUser, num amount, PatientShareResponse patientShareResponse, AppoitmentAllHistoryResultList appo) { - widget.browser = new MyInAppBrowser(onExitCallback: onBrowserExit, appo: appo, onLoadStartCallback: onBrowserLoadStart, context: context); - - widget.browser?.openPaymentBrowser( + openPayment(List paymentMethod, AuthenticatedUser authenticatedUser, num amount, PatientShareResponse patientShareResponse, AppoitmentAllHistoryResultList appo) { + browser = new MyInAppBrowser(onExitCallback: onBrowserExit, appo: appo, onLoadStartCallback: onBrowserLoadStart, context: context); + transID = Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo); + browser?.openPaymentBrowser( amount, "Appointment check in", - Utils.getAppointmentTransID(appo.projectID!, appo.clinicID!, appo.appointmentNo!), + transID!, appo.projectID.toString(), authenticatedUser.emailAddress!, paymentMethod[0]!, @@ -1237,7 +1244,7 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { final currency = projectViewModel.user!.outSA == 0 ? "sar" : 'aed'; GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); - service.checkPaymentStatus(Utils.getAppointmentTransID(appo.projectID!, appo.clinicID!, appo.appointmentNo!), false, context).then((res) { + service.checkPaymentStatus(transID!, false, context).then((res) { GifLoaderDialogUtils.hideDialog(context); String paymentInfo = res['Response_Message']; if (paymentInfo == 'Success') { @@ -1331,12 +1338,97 @@ class _ToDoState extends State with SingleTickerProviderStateMixin { if (value != null) { final appType = appo.isLiveCareAppointment! ? 'livecare' : 'regular'; - openPayment(value, projectViewModel.user, double.parse(patientShareResponse.patientShareWithTax.toString()), patientShareResponse, appo); + if (selectedPaymentMethod == "ApplePay") { + startApplePay(appo, patientShareResponse); + } else { + openPayment(value, projectViewModel.user, double.parse(patientShareResponse.patientShareWithTax.toString()), patientShareResponse, appo); + } projectViewModel.analytics.appointment.payment_method(appointment_type: appType, clinic: appo.clinicName, payment_method: value[0], payment_type: 'appointment'); } }); } + void startApplePay(AppoitmentAllHistoryResultList appo, PatientShareResponse patientShareResponse) async { + transID = Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo); + print("TransactionID: $transID"); + GifLoaderDialogUtils.showMyDialog(context); + + LiveCareService service = new LiveCareService(); + ApplePayInsertRequest applePayInsertRequest = new ApplePayInsertRequest(); + + PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel; + await context.read().getProjectDetailsForPayfort(projectId: appo.projectID, serviceId: ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum()).then((value) { + payfortProjectDetailsRespModel = value; + }); + + applePayInsertRequest.clientRequestID = transID; + applePayInsertRequest.clinicID = appo.clinicID; + applePayInsertRequest.currency = projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR"; + applePayInsertRequest.customerEmail = projectViewModel.authenticatedUserObject.user.emailAddress; + applePayInsertRequest.customerID = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.customerName = projectViewModel.authenticatedUserObject.user.firstName! + " " + projectViewModel.authenticatedUserObject.user!.lastName!; + applePayInsertRequest.deviceToken = await AppSharedPreferences().getString(PUSH_TOKEN); + applePayInsertRequest.voipToken = await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN); + applePayInsertRequest.doctorID = appo.doctorID; + applePayInsertRequest.projectID = appo.projectID.toString(); + applePayInsertRequest.serviceID = ServiceTypeEnum.advancePayment.getIdFromServiceEnum().toString(); + applePayInsertRequest.channelID = 3; + applePayInsertRequest.patientID = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.patientTypeID = projectViewModel.authenticatedUserObject.user.patientType; + applePayInsertRequest.patientOutSA = projectViewModel.authenticatedUserObject.user.outSA; + applePayInsertRequest.appointmentDate = appo.appointmentDate; + applePayInsertRequest.appointmentNo = appo.appointmentNo; + applePayInsertRequest.orderDescription = "Advance Payment"; + applePayInsertRequest.liveServiceID = "0"; + applePayInsertRequest.latitude = "0.0"; + applePayInsertRequest.longitude = "0.0"; + applePayInsertRequest.amount = patientShareResponse.patientShareWithTax.toString(); + applePayInsertRequest.isSchedule = appo.isLiveCareAppointment! ? "1" : "0"; + applePayInsertRequest.language = projectViewModel.isArabic ? 'ar' : 'en'; + applePayInsertRequest.languageID = projectViewModel.isArabic ? 1 : 2; + applePayInsertRequest.userName = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.paymentOption = "ApplePay"; + + applePayInsertRequest.isMobSDK = true; + applePayInsertRequest.merchantReference = transID; + applePayInsertRequest.merchantIdentifier = payfortProjectDetailsRespModel!.merchantIdentifier; + applePayInsertRequest.commandType = "PURCHASE"; + applePayInsertRequest.signature = payfortProjectDetailsRespModel!.signature; + applePayInsertRequest.accessCode = payfortProjectDetailsRespModel!.accessCode; + applePayInsertRequest.shaRequestPhrase = payfortProjectDetailsRespModel!.shaRequest; + applePayInsertRequest.shaResponsePhrase = payfortProjectDetailsRespModel!.shaResponse; + applePayInsertRequest.returnURL = ""; + + service.applePayInsertRequest(applePayInsertRequest, context).then((res) async { + await context.read().initiateApplePayWithPayfort( + customerName: projectViewModel.authenticatedUserObject.user.firstName! + " " + projectViewModel.authenticatedUserObject.user!.lastName!, + customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress, + orderDescription: "Appointment Payment", + orderAmount: double.parse(patientShareResponse.patientShareWithTax.toString()), + merchantReference: transID, + payfortProjectDetailsRespModel: payfortProjectDetailsRespModel, + currency: projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR", + onFailed: (failureResult) async { + log("failureResult: ${failureResult.toString()}"); + AppToast.showErrorToast(message: failureResult.toString()); + }, + onSuccess: (successResult) async { + log("Payfort: ${successResult.responseMessage}"); + await context.read().addPayfortApplePayResponse(result: successResult); + checkPaymentStatus(appo); + }, + projectId: appo.projectID, + serviceTypeEnum: ServiceTypeEnum.appointmentPayment, + ); + }).catchError((err) { + print(err); + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); + }); + } + confirmAppointment(AppoitmentAllHistoryResultList appo) { GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); diff --git a/lib/pages/ToDoList/payment_method_select.dart b/lib/pages/ToDoList/payment_method_select.dart index 926eb1a4..5adcb90f 100644 --- a/lib/pages/ToDoList/payment_method_select.dart +++ b/lib/pages/ToDoList/payment_method_select.dart @@ -15,12 +15,12 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; class PaymentMethod extends StatefulWidget { - Function? onSelectedMethod; + Function onSelectedMethod; bool? isShowInstallments; num? patientShare; bool? isFromAdvancePayment; - PaymentMethod({this.onSelectedMethod, this.isShowInstallments = false, this.patientShare, this.isFromAdvancePayment = false}); + PaymentMethod({required this.onSelectedMethod, this.isShowInstallments = false, this.patientShare, this.isFromAdvancePayment = false}); @override _PaymentMethodState createState() => _PaymentMethodState(); @@ -518,9 +518,8 @@ class _PaymentMethodState extends State { getTamaraPaymentDetails() { GifLoaderDialogUtils.showMyDialog(context); DoctorsListService service = new DoctorsListService(); - service.getTamaraPaymentDetails(context).then((Map res) { + service.getTamaraPaymentDetails(context).then((Map res) { tamaraInstallmentDetails = TamaraInstallmentDetails.fromJson(res); - print(tamaraInstallmentDetails!.name!); minTamaraLimit = tamaraInstallmentDetails!.supportedInstalments![0].minLimit!.amount!; maxTamaraLimit = tamaraInstallmentDetails!.supportedInstalments![0].maxLimit!.amount!; selectedInstallmentPlan = tamaraInstallmentDetails!.supportedInstalments![0].instalments.toString(); diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 10753340..72f9d719 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -24,6 +24,7 @@ import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart' import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart'; import 'package:diplomaticquarterapp/services/family_files/family_files_provider.dart' as family; import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_view_model.dart'; import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/LocalNotification.dart'; @@ -285,6 +286,9 @@ class _LandingPageState extends State with WidgetsBindingObserver { } }); + PayfortViewModel payfortViewModel = context.read(); + payfortViewModel.initPayfort(); + // HMG (Guest/Internet) Wifi Access [Zohaib Kambrani] // for now commented to reduce this call will enable it when needed // HMGNetworkConnectivity(context).start(); diff --git a/lib/pages/livecare/widgets/clinic_list.dart b/lib/pages/livecare/widgets/clinic_list.dart index 1e846ea7..752383e5 100644 --- a/lib/pages/livecare/widgets/clinic_list.dart +++ b/lib/pages/livecare/widgets/clinic_list.dart @@ -1,11 +1,15 @@ +import 'dart:developer'; import 'dart:io'; +import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/enum/PayfortEnums.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/main.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/models/LiveCare/ApplePayInsertRequest.dart'; import 'package:diplomaticquarterapp/models/LiveCare/ERAppointmentFeesResponse.dart'; import 'package:diplomaticquarterapp/models/LiveCare/LiveCareClinicsListResponse.dart'; import 'package:diplomaticquarterapp/models/LiveCare/LiveCareScheduleClinicsListResponse.dart'; @@ -19,6 +23,8 @@ import 'package:diplomaticquarterapp/pages/livecare/widgets/clinic_card.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart'; import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_project_details_resp_model.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_view_model.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/PlatformBridge.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; @@ -84,6 +90,9 @@ class _clinic_listState extends State { late String tamaraOrderID; late String selectedInstallmentPlan; + String? transID; + BuildContext? localContext; + @override void initState() { liveCareClinicsListResponse = new LiveCareClinicsListResponse(); @@ -109,6 +118,7 @@ class _clinic_listState extends State { @override Widget build(BuildContext context) { projectViewModel = Provider.of(context); + localContext = context; getLanguageID(); return Container( child: currentSelectedLiveCareType == "immediate" ? getLiveCareImmediateClinicList() : getLiveCareScheduleClinicList(), @@ -297,7 +307,8 @@ class _clinic_listState extends State { appo.clinicID = selectedClinicID; appo.appointmentNo = DateTime.now().millisecondsSinceEpoch; - appo.projectID = 12; + appo.projectID = BASE_URL.contains("uat.") ? 15 : 12; + appo.isLiveCareAppointment = false; if (await this.sharedPref.getObject(USER_PROFILE) != null) { var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE)); @@ -319,44 +330,124 @@ class _clinic_listState extends State { patientShare: num.parse(getERAppointmentFeesList.total!), isFromAdvancePayment: widget.isPharmacyLiveCare, ))).then((value) { - print(value); - widget.isPharmacyLiveCare = isPharmacyLiveCare; - widget.pharmacyLiveCareQRCode = pharmaLiveCareQRCodeValue; if (value != null) { - openPayment(value, authUser, num.parse(getERAppointmentFeesList.total!), appo); - projectViewModel.analytics.liveCare.payment_method(appointment_type: 'livecare', clinic: selectedClinicName, payment_method: value[0], payment_type: 'appointment'); + selectedPaymentMethod = value[0]; + print(value); + widget.isPharmacyLiveCare = isPharmacyLiveCare; + widget.pharmacyLiveCareQRCode = pharmaLiveCareQRCodeValue; + if (value != null) { + if (selectedPaymentMethod == "ApplePay") { + startApplePay(appo, getERAppointmentFeesList.total!); + } else { + openPayment(value, authUser, num.parse(getERAppointmentFeesList.total!), appo); + } + projectViewModel.analytics.liveCare.payment_method(appointment_type: 'livecare', clinic: selectedClinicName, payment_method: value[0], payment_type: 'appointment'); + } } }); } + void startApplePay(AppoitmentAllHistoryResultList appo, String amount) async { + try { + transID = Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo); + print("TransactionID: $transID"); + GifLoaderDialogUtils.showMyDialog(localContext!); + + LiveCareService service = new LiveCareService(); + ApplePayInsertRequest applePayInsertRequest = new ApplePayInsertRequest(); + + PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel; + await localContext + ?.read() + .getProjectDetailsForPayfort(projectId: appo.projectID, serviceId: ServiceTypeEnum.liveCareAppointment.getIdFromServiceEnum(), languageID: projectViewModel.isArabic ? 1 : 2) + .then((value) { + payfortProjectDetailsRespModel = value; + }); + + applePayInsertRequest.clientRequestID = transID; + applePayInsertRequest.clinicID = appo.clinicID; + applePayInsertRequest.currency = projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR"; + applePayInsertRequest.customerEmail = projectViewModel.authenticatedUserObject.user.emailAddress; + applePayInsertRequest.customerID = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.customerName = projectViewModel.authenticatedUserObject.user.firstName! + " " + projectViewModel.authenticatedUserObject.user.lastName!; + applePayInsertRequest.deviceToken = await AppSharedPreferences().getString(PUSH_TOKEN); + applePayInsertRequest.voipToken = await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN); + applePayInsertRequest.doctorID = appo.doctorID; + applePayInsertRequest.projectID = appo.projectID.toString(); + applePayInsertRequest.serviceID = ServiceTypeEnum.liveCareAppointment.getIdFromServiceEnum().toString(); + applePayInsertRequest.channelID = 3; + applePayInsertRequest.patientID = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.patientTypeID = projectViewModel.authenticatedUserObject.user.patientType; + applePayInsertRequest.patientOutSA = projectViewModel.authenticatedUserObject.user.outSA; + applePayInsertRequest.appointmentDate = appo.appointmentDate; + applePayInsertRequest.appointmentNo = appo.appointmentNo; + applePayInsertRequest.orderDescription = "LiveCare Payment"; + applePayInsertRequest.liveServiceID = "0"; + applePayInsertRequest.latitude = "0.0"; + applePayInsertRequest.longitude = "0.0"; + applePayInsertRequest.amount = amount; + applePayInsertRequest.isSchedule = appo.isLiveCareAppointment! ? "1" : "0"; + applePayInsertRequest.language = projectViewModel.isArabic ? 'ar' : 'en'; + applePayInsertRequest.languageID = projectViewModel.isArabic ? 1 : 2; + applePayInsertRequest.userName = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.paymentOption = "ApplePay"; + + applePayInsertRequest.isMobSDK = true; + applePayInsertRequest.merchantReference = transID; + applePayInsertRequest.merchantIdentifier = payfortProjectDetailsRespModel!.merchantIdentifier; + applePayInsertRequest.commandType = "PURCHASE"; + applePayInsertRequest.signature = payfortProjectDetailsRespModel!.signature; + applePayInsertRequest.accessCode = payfortProjectDetailsRespModel!.accessCode; + applePayInsertRequest.shaRequestPhrase = payfortProjectDetailsRespModel!.shaRequest; + applePayInsertRequest.shaResponsePhrase = payfortProjectDetailsRespModel!.shaResponse; + applePayInsertRequest.returnURL = ""; + + service.applePayInsertRequest(applePayInsertRequest, localContext!).then((res) async { + await localContext?.read().initiateApplePayWithPayfort( + customerName: projectViewModel.authenticatedUserObject.user.firstName! + " " + projectViewModel.authenticatedUserObject.user.lastName!, + customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress, + orderDescription: "LiveCare Payment", + orderAmount: double.parse(amount), + merchantReference: transID, + payfortProjectDetailsRespModel: payfortProjectDetailsRespModel, + currency: projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR", + onFailed: (failureResult) async { + log("failureResult: ${failureResult.toString()}"); + GifLoaderDialogUtils.hideDialog(localContext!); + AppToast.showErrorToast(message: failureResult.toString()); + }, + onSuccess: (successResult) async { + GifLoaderDialogUtils.hideDialog(localContext!); + log("Payfort: ${successResult.responseMessage}"); + await localContext!.read().addPayfortApplePayResponse(result: successResult); + checkPaymentStatus(appo); + }, + projectId: appo.projectID, + serviceTypeEnum: ServiceTypeEnum.appointmentPayment, + ); + }).catchError((err) { + print(err); + GifLoaderDialogUtils.hideDialog(localContext!); + AppToast.showErrorToast(message: err); + }); + } catch (ex) { + print(ex.toString()); + GifLoaderDialogUtils.hideDialog(localContext!); + } + } + openPayment(List paymentMethod, AuthenticatedUser authenticatedUser, num amount, AppoitmentAllHistoryResultList appo) { browser = new MyInAppBrowser(onExitCallback: onBrowserExit, appo: appo, onLoadStartCallback: onBrowserLoadStart, context: context); selectedPaymentMethod = paymentMethod[0]!; selectedInstallmentPlan = paymentMethod[1]!; + transID = Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo); this.amount = amount.toString(); - browser.openPaymentBrowser( - amount, - "LiveCare Payment", - widget.isPharmacyLiveCare ? widget.pharmacyLiveCareQRCode : Utils.getAppointmentTransID(appo.projectID!, appo.clinicID!, appo.appointmentNo!), - "12", - authenticatedUser.emailAddress!, - paymentMethod[0]!, - authenticatedUser.patientType, - authenticatedUser.firstName!, - authenticatedUser.patientID, - authenticatedUser, - browser, - false, - "4", - selectedClinicID, - context, - "", - "", - "", - "", - paymentMethod[1]); + browser.openPaymentBrowser(amount, "LiveCare Payment", widget.isPharmacyLiveCare ? widget.pharmacyLiveCareQRCode! : transID!, "12", authenticatedUser.emailAddress!, paymentMethod[0]!, + authenticatedUser.patientType, authenticatedUser.firstName!, authenticatedUser.patientID, authenticatedUser, browser, false, "4", selectedClinicID, context, "", "", "", "", paymentMethod[1]); } onBrowserLoadStart(String url) { @@ -464,10 +555,7 @@ class _clinic_listState extends State { final currency = projectViewModel.user!.outSA == 0 ? "sar" : 'aed'; DoctorsListService service = new DoctorsListService(); GifLoaderDialogUtils.showMyDialog(context); - service - .checkPaymentStatus( - widget.isPharmacyLiveCare ? widget.pharmacyLiveCareQRCode : Utils.getAppointmentTransID(appo.projectID!, appo.clinicID!, appo.appointmentNo!), widget.isPharmacyLiveCare, context) - .then((res) { + service.checkPaymentStatus(widget.isPharmacyLiveCare ? widget.pharmacyLiveCareQRCode! : transID!, widget.isPharmacyLiveCare, context).then((res) { GifLoaderDialogUtils.hideDialog(context); String paymentInfo = res['Response_Message']; amount = res['Amount'].toString(); @@ -515,7 +603,7 @@ class _clinic_listState extends State { isDataLoaded = false; LiveCareService service = new LiveCareService(); GifLoaderDialogUtils.showMyDialog(context); - service.getLivecareClinics(languageID == 'ar' ? 1: 2, context).then((res) { + service.getLivecareClinics(languageID == 'ar' ? 1 : 2, context).then((res) { GifLoaderDialogUtils.hideDialog(context); print(res['PatientER_GetClinicsList'].length); if (res['MessageStatus'] == 1) { diff --git a/lib/pages/medical/balance/confirm_payment_page.dart b/lib/pages/medical/balance/confirm_payment_page.dart index 1cfe1a74..8e85706b 100644 --- a/lib/pages/medical/balance/confirm_payment_page.dart +++ b/lib/pages/medical/balance/confirm_payment_page.dart @@ -1,5 +1,8 @@ +import 'dart:developer'; + import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/config/shared_pref_kay.dart'; +import 'package:diplomaticquarterapp/core/enum/PayfortEnums.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/AdvanceModel.dart'; import 'package:diplomaticquarterapp/core/model/my_balance/patient_info_and_mobile_number.dart'; @@ -7,11 +10,15 @@ import 'package:diplomaticquarterapp/core/viewModels/medical/my_balance_view_mod import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart'; import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart'; +import 'package:diplomaticquarterapp/models/LiveCare/ApplePayInsertRequest.dart'; import 'package:diplomaticquarterapp/models/apple_pay_request.dart'; import 'package:diplomaticquarterapp/models/apple_pay_response.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/routes.dart'; import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart'; +import 'package:diplomaticquarterapp/services/livecare_services/livecare_provider.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_project_details_resp_model.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_view_model.dart'; import 'package:diplomaticquarterapp/theme/colors.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; @@ -24,10 +31,7 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/otp/sms-popup.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; - -// import 'package:pay/pay.dart'; import 'package:provider/provider.dart'; - import 'new_text_Field.dart'; class ConfirmPaymentPage extends StatefulWidget { @@ -214,9 +218,13 @@ class _ConfirmPaymentPageState extends State { padding: EdgeInsets.all(20), child: DefaultButton( TranslationBase.of(context).confirm.toUpperCase(), - () { - if (widget.advanceModel!.fileNumber == projectViewModel.user!.patientID.toString()) { - openPayment(widget.selectedPaymentMethod!, widget.authenticatedUser!, double.parse(widget.advanceModel!.amount!), AppoitmentAllHistoryResultList()); + () async { + if (widget.advanceModel!.fileNumber == projectViewModel.user.patientID.toString()) { + if (widget.selectedPaymentMethod == "ApplePay") { + startApplePay(); + } else { + openPayment(widget.selectedPaymentMethod!, widget.authenticatedUser!, double.parse(widget.advanceModel!.amount!), AppoitmentAllHistoryResultList()); + } } else { GifLoaderDialogUtils.showMyDialog(context); model.sendActivationCodeForAdvancePayment(patientID: int.parse(widget.advanceModel!.fileNumber!), projectID: widget.advanceModel!.hospitalsModel!.iD).then((value) { @@ -241,70 +249,87 @@ class _ConfirmPaymentPageState extends State { ); } - // startApplePay() { - // ApplePayResponse applePayResponse; - // var _paymentItems = [ - // PaymentItem( - // label: 'Total', - // amount: widget.advanceModel.amount, - // status: PaymentItemStatus.final_price, - // ) - // ]; - // - // _payClient.userCanPay(PayProvider.apple_pay).then((value) async { - // print(value); - // final result = await _payClient.showPaymentSelector( - // provider: PayProvider.apple_pay, - // paymentItems: _paymentItems, - // ); - // print(result); - // applePayResponse = ApplePayResponse.fromJson(result); - // callPayfortApplePayAPI(applePayResponse); - // }).catchError((err) { - // print(err); - // }); - // } - - callPayfortApplePayAPI(ApplePayResponse applePayResponse) async { - DoctorsListService service = new DoctorsListService(); - ApplePayRequest applePayRequest = new ApplePayRequest(); - AppleHeader appleHeader = new AppleHeader(); - ApplePaymentMethod applePaymentMethod = new ApplePaymentMethod(); - - applePayRequest.amount = widget.advanceModel!.amount; - applePayRequest.currency = "SAR"; - applePayRequest.language = projectViewModel.isArabic ? "ar" : "en"; - applePayRequest.customername = projectViewModel.user!.firstName; - applePayRequest.customerEmail = projectViewModel.user!.emailAddress; - applePayRequest.orderdescription = "Advance Payment"; - applePayRequest.liveServiceid = ""; - applePayRequest.latitude = await this.sharedPref.getDouble(USER_LAT); - applePayRequest.longitude = await this.sharedPref.getDouble(USER_LONG); - applePayRequest.devicetoken = await sharedPref.getString(PUSH_TOKEN); - applePayRequest.clientrequestid = Utils.getAdvancePaymentTransID(widget.advanceModel!.hospitalsModel!.iD, int.parse(widget.advanceModel!.fileNumber!)); - applePayRequest.projectid = widget.advanceModel!.hospitalsModel!.iD.toString(); - applePayRequest.serviceid = "3"; - applePayRequest.patientid = projectViewModel.user!.patientID.toString(); - applePayRequest.appleData = applePayResponse.token!.data; - applePayRequest.appleSignature = applePayResponse.token!.signature; - - appleHeader.appleEphemeralPublicKey = applePayResponse.token!.header!.ephemeralPublicKey; - appleHeader.appleTransactionId = applePayResponse.token!.header!.transactionId; - appleHeader.applePublicKeyHash = applePayResponse.token!.header!.publicKeyHash; - applePaymentMethod.appleType = getApplePayPaymentType(applePayResponse.paymentMethod!.type); - applePaymentMethod.appleNetwork = applePayResponse.paymentMethod!.network; - applePaymentMethod.appleDisplayName = applePayResponse.paymentMethod!.displayName; - - applePayRequest.appleHeader = appleHeader; - applePayRequest.applePaymentMethod = applePaymentMethod; - - service.callPayfortApplePayAPI(applePayRequest, context).then((res) { - print(res); - GifLoaderDialogUtils.hideDialog(context); + void startApplePay() async { + transID = Utils.getAdvancePaymentTransID(widget.advanceModel!.hospitalsModel!.iD!, int.parse(widget.advanceModel!.fileNumber!)); + print("TransactionID: $transID"); + GifLoaderDialogUtils.showMyDialog(context); + + LiveCareService service = new LiveCareService(); + ApplePayInsertRequest applePayInsertRequest = new ApplePayInsertRequest(); + + PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel; + await context + .read() + .getProjectDetailsForPayfort(projectId: widget.advanceModel!.hospitalsModel!.iD, serviceId: ServiceTypeEnum.advancePayment.getIdFromServiceEnum()) + .then((value) { + payfortProjectDetailsRespModel = value!; + }); + + applePayInsertRequest.clientRequestID = transID; + applePayInsertRequest.clinicID = 0; + applePayInsertRequest.currency = projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR"; + applePayInsertRequest.customerEmail = projectViewModel.authenticatedUserObject.user.emailAddress; + applePayInsertRequest.customerID = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.customerName = projectViewModel.authenticatedUserObject.user.firstName! + " " + projectViewModel.authenticatedUserObject!.user.lastName!; + applePayInsertRequest.deviceToken = await AppSharedPreferences().getString(PUSH_TOKEN); + applePayInsertRequest.voipToken = await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN); + applePayInsertRequest.doctorID = 0; + applePayInsertRequest.projectID = widget.advanceModel!.hospitalsModel!.iD.toString(); + applePayInsertRequest.serviceID = ServiceTypeEnum.advancePayment.getIdFromServiceEnum().toString(); + applePayInsertRequest.channelID = 3; + applePayInsertRequest.patientID = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.patientTypeID = projectViewModel.authenticatedUserObject.user.patientType; + applePayInsertRequest.patientOutSA = projectViewModel.authenticatedUserObject.user.outSA; + applePayInsertRequest.appointmentDate = null; + applePayInsertRequest.appointmentNo = 0; + applePayInsertRequest.orderDescription = "Advance Payment"; + applePayInsertRequest.liveServiceID = "0"; + applePayInsertRequest.latitude = "0.0"; + applePayInsertRequest.longitude = "0.0"; + applePayInsertRequest.amount = widget.advanceModel!.amount.toString(); + applePayInsertRequest.isSchedule = "0"; + applePayInsertRequest.language = projectViewModel.isArabic ? 'ar' : 'en'; + applePayInsertRequest.languageID = projectViewModel.isArabic ? 1 : 2; + applePayInsertRequest.userName = projectViewModel.authenticatedUserObject.user.patientID; + applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html"; + applePayInsertRequest.paymentOption = "ApplePay"; + + applePayInsertRequest.isMobSDK = true; + applePayInsertRequest.merchantReference = transID; + applePayInsertRequest.merchantIdentifier = payfortProjectDetailsRespModel!.merchantIdentifier; + applePayInsertRequest.commandType = "PURCHASE"; + applePayInsertRequest.signature = payfortProjectDetailsRespModel!.signature; + applePayInsertRequest.accessCode = payfortProjectDetailsRespModel!.accessCode; + applePayInsertRequest.shaRequestPhrase = payfortProjectDetailsRespModel!.shaRequest; + applePayInsertRequest.shaResponsePhrase = payfortProjectDetailsRespModel!.shaResponse; + applePayInsertRequest.returnURL = ""; + + service.applePayInsertRequest(applePayInsertRequest, context).then((res) async { + await context.read().initiateApplePayWithPayfort( + customerName: projectViewModel.authenticatedUserObject.user.firstName! + " " + projectViewModel.authenticatedUserObject.user.lastName!, + customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress, + orderDescription: "Advance Payment", + orderAmount: double.parse(widget.advanceModel!.amount!), + merchantReference: transID, + payfortProjectDetailsRespModel: payfortProjectDetailsRespModel, + currency: projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR", + onFailed: (failureResult) async { + log("failureResult: ${failureResult.toString()}"); + AppToast.showErrorToast(message: failureResult.toString()); + }, + onSuccess: (successResult) async { + log("Payfort: ${successResult.responseMessage}"); + await context.read().addPayfortApplePayResponse(result: successResult); + checkPaymentStatus(AppoitmentAllHistoryResultList()); + }, + projectId: widget.advanceModel!.hospitalsModel!.iD, + serviceTypeEnum: ServiceTypeEnum.advancePayment, + ); }).catchError((err) { - GifLoaderDialogUtils.hideDialog(context); print(err); - // _showMyDialog(err, this.context); + GifLoaderDialogUtils.hideDialog(context); + AppToast.showErrorToast(message: err); }); } @@ -410,7 +435,7 @@ class _ConfirmPaymentPageState extends State { } onBrowserExit(AppoitmentAllHistoryResultList appo, bool isPaymentMade) { - print("onBrowserExit Called!!!!"); + print("onBrowserExit Called"); if (widget.selectedPaymentMethod == "TAMARA" && tamaraPaymentStatus != null && tamaraPaymentStatus == "approved") { var res = { "Amount": double.parse(widget.advanceModel!.amount!), diff --git a/lib/services/appointment_services/GetDoctorsList.dart b/lib/services/appointment_services/GetDoctorsList.dart index cf498e59..2bd1338b 100644 --- a/lib/services/appointment_services/GetDoctorsList.dart +++ b/lib/services/appointment_services/GetDoctorsList.dart @@ -807,7 +807,7 @@ class DoctorsListService extends BaseService { "DeviceTypeID": req.DeviceTypeID, "PatientID": authUser.patientID, "PatientTypeID": authUser.patientType, - "LanguageID": 1, + // "LanguageID": 1, "PatientType": authUser.patientType }; @@ -1564,10 +1564,9 @@ class DoctorsListService extends BaseService { return Future.value(localRes); } - Future> getTamaraPaymentDetails(BuildContext context) async { + Future getTamaraPaymentDetails(BuildContext context) async { dynamic localRes; await baseAppClient.get(GET_TAMARA_PLAN, isExternal: true, onSuccess: (response, statusCode) async { - print(response); localRes = response[0]; }, onFailure: (String error, int statusCode) { throw error; diff --git a/lib/services/payfort_services/payfort_project_details_resp_model.dart b/lib/services/payfort_services/payfort_project_details_resp_model.dart new file mode 100644 index 00000000..b4d9eae2 --- /dev/null +++ b/lib/services/payfort_services/payfort_project_details_resp_model.dart @@ -0,0 +1,37 @@ +class PayfortProjectDetailsRespModel { + String? accessCode; + int? integrationId; + String? merchantIdentifier; + int? projectID; + String? projectName; + int? servID; + String? shaRequest; + String? shaResponse; + String? signature; + + PayfortProjectDetailsRespModel({this.accessCode, this.integrationId, this.merchantIdentifier, this.projectID, this.projectName, this.servID, this.shaRequest, this.shaResponse, this.signature}); + + PayfortProjectDetailsRespModel.fromJson(Map json) { + accessCode = json['AccessCode']; + integrationId = json['Integration_Id']; + merchantIdentifier = json['MerchantIdentifier']; + projectID = json['ProjectID']; + projectName = json['ProjectName']; + servID = json['ServID']; + shaRequest = json['Sha_Request']; + shaResponse = json['Sha_Response']; + } + + Map toJson() { + final Map data = new Map(); + data['AccessCode'] = this.accessCode; + data['Integration_Id'] = this.integrationId; + data['MerchantIdentifier'] = this.merchantIdentifier; + data['ProjectID'] = this.projectID; + data['ProjectName'] = this.projectName; + data['ServID'] = this.servID; + data['Sha_Request'] = this.shaRequest; + data['Sha_Response'] = this.shaResponse; + return data; + } +} diff --git a/lib/services/payfort_services/payfort_service.dart b/lib/services/payfort_services/payfort_service.dart new file mode 100644 index 00000000..835a2627 --- /dev/null +++ b/lib/services/payfort_services/payfort_service.dart @@ -0,0 +1,193 @@ +import 'dart:convert'; + +import 'package:amazon_payfort/amazon_payfort.dart'; +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/service/base_service.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_project_details_resp_model.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/sdk_token_response_model.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:http/http.dart'; +import 'package:network_info_plus/network_info_plus.dart'; + +class PayfortService extends BaseService { + final AmazonPayfort _payfort = AmazonPayfort.instance; + + final NetworkInfo _info = NetworkInfo(); + + Future initPayfortSDK() async { + await AmazonPayfort.initialize( + PayFortOptions(environment: payFortEnvironment), + ); + } + + Future getPayfortConfigurations({int? serviceId, int? projectId, int integrationId = 2, int? languageID}) async { + Map body = {"Integration_Id": integrationId, "ServID": serviceId, "ProjectID": projectId, "LanguageID": languageID}; + + PayfortProjectDetailsRespModel payfortProjectDetailsRespModel = PayfortProjectDetailsRespModel(); + await baseAppClient.post( + getPayFortProjectDetails, + onSuccess: (response, statusCode) async { + payfortProjectDetailsRespModel = PayfortProjectDetailsRespModel.fromJson(response.isNotEmpty ? response.first : response); + }, + onFailure: (String error, int statusCode) { + Utils.showErrorToast(error); + return null; + }, + body: body, + isAllowAny: true, + ); + return payfortProjectDetailsRespModel; + } + + Future addPayfortApplePayResponse({PayFortResult? result}) async { + Map body = { + "Fort_id": result!.fortId, + "CommandType": result!.command, + "Amount": (num.parse(result.amount!) / 100), + "Payment_Option": result.paymentOption, + "Customer_IP": result.customerIp, + "ECI": result.eci, + "Response_Message": result.responseMessage, + "Card_Number": result.cardNumber, + "Status": result.status, + "Merchant_Ref": result.merchantReference, + "Pat_Token": result.tokenName, + "IsRefund": false, + "RemmeberMe": false, + "Reconciliation_Reference": result.reconciliationReference, + "LanguageID": 1, + }; + + await baseAppClient.post( + addPayFortApplePayResponse, + onSuccess: (response, statusCode) async { + // payfortProjectDetailsRespModel = PayfortProjectDetailsRespModel.fromJson(response.isNotEmpty ? response.first : response); + }, + onFailure: (String error, int statusCode) { + Utils.showErrorToast(error); + return null; + }, + body: body, + isAllowAny: true, + ); + } + + Future? generateSdkSignatureFromAPI(SdkTokenRequest request) async { + var response = await post( + Uri.parse(payFortEnvironment.paymentApi), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode(request.asRequest()), + ); + if (response.statusCode == 200) { + var decodedResponse = jsonDecode(response.body); + return SdkTokenResponse.fromMap(decodedResponse); + } + return null; + } + + Future _generateSdkResponse({ + String? applePayAccessCode, + String? merchantIdentifier, + String? applePayShaType, + String? applePayShaRequestPhrase, + }) async { + try { + String? deviceId = await _payfort.getDeviceId(); + + /// Step 2: Generate the Signature + SdkTokenRequest tokenRequest = SdkTokenRequest( + accessCode: applePayAccessCode!, + deviceId: deviceId ?? '', + merchantIdentifier: merchantIdentifier!, + ); + + String? signature = await _payfort.generateSignature( + shaType: applePayShaType!, + concatenatedString: tokenRequest.toConcatenatedString(applePayShaRequestPhrase!), + ); + + tokenRequest = tokenRequest.copyWith(signature: signature); + + /// Step 3: Generate the SDK Token + return await generateSdkSignatureFromAPI(tokenRequest); + } catch (e) { + print("Error here: ${e.toString()}"); + } + return null; + } + + Future getPayfortSignature( + String applePayAccessCode, + String merchantIdentifier, + String applePayShaRequestPhrase, + ) async { + String? deviceId = await _payfort.getDeviceId(); + SdkTokenRequest tokenRequest = SdkTokenRequest( + accessCode: applePayAccessCode, + deviceId: deviceId ?? '', + merchantIdentifier: merchantIdentifier, + ); + + String? signature = await _payfort.generateSignature( + shaType: "SHA-256", + concatenatedString: tokenRequest.toConcatenatedString(applePayShaRequestPhrase), + ); + + return signature!; + } + + Future paymentWithApplePay({ + SucceededCallback? onSucceeded, + FailedCallback? onFailed, + String? customerName, + String? customerEmail, + String? orderDescription, + double? orderAmount, + String? merchantIdentifier, + String? applePayAccessCode, + String? applePayShaRequestPhrase, + String? merchantReference, + String currency = "SAR", + String applePayShaType = "SHA-256", + String countryIsoCode = "SA", + }) async { + try { + SdkTokenResponse? sdkTokenResponse = await _generateSdkResponse( + applePayAccessCode: applePayAccessCode, + merchantIdentifier: merchantIdentifier, + applePayShaType: applePayShaType, + applePayShaRequestPhrase: applePayShaRequestPhrase, + ); + + if (sdkTokenResponse != null && sdkTokenResponse.sdkToken == null) { + onFailed!(sdkTokenResponse.responseMessage ?? ''); + return; + } + + /// Step 4: Processing Payment [Don't multiply with 100] + /// Amount value send always round ex. [100] not [100.00, 100.21] + FortRequest request = FortRequest( + amount: orderAmount!, + customerName: customerName!, + customerEmail: customerEmail!, + orderDescription: orderDescription!, + sdkToken: sdkTokenResponse?.sdkToken ?? '', + merchantReference: merchantReference!, + currency: currency, + customerIp: (await _info.getWifiIP() ?? ''), + ); + + _payfort.callPayFortForApplePay( + request: request, + countryIsoCode: countryIsoCode, + applePayMerchantId: applePayMerchantId, + callback: ApplePayResultCallback( + onSucceeded: onSucceeded!, + onFailed: onFailed!, + ), + ); + } catch (e) { + onFailed!(e.toString()); + } + } +} diff --git a/lib/services/payfort_services/payfort_view_model.dart b/lib/services/payfort_services/payfort_view_model.dart new file mode 100644 index 00000000..5d2ef302 --- /dev/null +++ b/lib/services/payfort_services/payfort_view_model.dart @@ -0,0 +1,85 @@ +import 'package:amazon_payfort/amazon_payfort.dart'; +import 'package:diplomaticquarterapp/config/config.dart'; +import 'package:diplomaticquarterapp/core/enum/PayfortEnums.dart'; +import 'package:diplomaticquarterapp/locator.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_project_details_resp_model.dart'; +import 'package:diplomaticquarterapp/services/payfort_services/payfort_service.dart'; +import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; +import 'package:diplomaticquarterapp/uitl/utils.dart'; +import 'package:flutter/cupertino.dart'; + +class PayfortViewModel extends ChangeNotifier { + PayfortService _payfortService = locator(); + + Future initPayfort() async { + await _payfortService.initPayfortSDK(); + } + + Future getProjectDetailsForPayfort({int? serviceId, int? projectId, int? languageID}) async { + PayfortProjectDetailsRespModel payfortProjectDetailsRespModel = PayfortProjectDetailsRespModel(); + try { + payfortProjectDetailsRespModel = await _payfortService.getPayfortConfigurations(serviceId: serviceId, projectId: projectId, languageID: languageID); + + String signature = + await _payfortService.getPayfortSignature(payfortProjectDetailsRespModel.accessCode!, payfortProjectDetailsRespModel.merchantIdentifier!, payfortProjectDetailsRespModel.shaRequest!); + payfortProjectDetailsRespModel.signature = signature; + + return payfortProjectDetailsRespModel; + } on Exception catch (e, s) { + print(s); + return null; + } + } + + Future addPayfortApplePayResponse({PayFortResult? result}) async { + try { + await _payfortService.addPayfortApplePayResponse(result: result); + } on Exception catch (e, s) { + print(s); + return null; + } + } + + Future initiateApplePayWithPayfort({ + String? customerName, + String? customerEmail, + String? orderDescription, + String? merchantReference, + double? orderAmount, + PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel, + SucceededCallback? onSuccess, + FailedCallback? onFailed, + ServiceTypeEnum? serviceTypeEnum, + int? projectId, + String? currency, + }) async { + // GifLoaderDialogUtils.showMyDialog(AppGlobal.context); + // PayfortProjectDetailsRespModel payfortProjectDetailsRespModel = await getProjectDetailsForPayfort(projectId: projectId, serviceId: serviceTypeEnum.getIdFromServiceEnum()); + // + // if (payfortProjectDetailsRespModel == null) { + // GifLoaderDialogUtils.hideDialog(AppGlobal.context); + // return; + // } + + try { + await _payfortService.paymentWithApplePay( + onSucceeded: onSuccess, + onFailed: onFailed, + customerName: customerName, + customerEmail: customerEmail, + orderDescription: orderDescription, + orderAmount: orderAmount, + merchantReference: merchantReference, + merchantIdentifier: payfortProjectDetailsRespModel!.merchantIdentifier ?? "", + applePayAccessCode: payfortProjectDetailsRespModel!.accessCode ?? "", + applePayShaRequestPhrase: payfortProjectDetailsRespModel.shaRequest ?? "", + currency: currency!, + ); + GifLoaderDialogUtils.hideDialog(AppGlobal.context); + } catch (e) { + Utils.showErrorToast(e.toString()); + GifLoaderDialogUtils.hideDialog(AppGlobal.context); + throw e; + } + } +} diff --git a/lib/services/payfort_services/sdk_token_response_model.dart b/lib/services/payfort_services/sdk_token_response_model.dart new file mode 100644 index 00000000..a0f48a4f --- /dev/null +++ b/lib/services/payfort_services/sdk_token_response_model.dart @@ -0,0 +1,55 @@ +class SdkTokenResponse { + SdkTokenResponse({ + this.responseCode, + this.deviceId, + this.responseMessage, + this.serviceCommand, + this.sdkToken, + this.signature, + this.merchantIdentifier, + this.accessCode, + this.language, + this.status, + }); + + String? responseCode; + String? deviceId; + String? responseMessage; + String? serviceCommand; + String? sdkToken; + String? signature; + String? merchantIdentifier; + String? accessCode; + String? language; + String? status; + + factory SdkTokenResponse.fromMap(Map data) { + return SdkTokenResponse( + responseCode: data['response_code'], + deviceId: data['device_id'], + responseMessage: data['response_message'], + serviceCommand: data['service_command'], + sdkToken: data['sdk_token'], + signature: data['signature'], + merchantIdentifier: data['merchant_identifier'], + accessCode: data['access_code'], + language: data['language'], + status: data['status'], + ); + } + + Map toMap() { + return { + 'response_code': responseCode, + 'device_id': deviceId, + 'response_message': responseMessage, + 'service_command': serviceCommand, + 'sdk_token': sdkToken, + 'signature': signature, + 'merchant_identifier': merchantIdentifier, + 'access_code': accessCode, + 'language': language, + 'status': status, + }; + } +} diff --git a/lib/splashPage.dart b/lib/splashPage.dart index 0de11156..cce92feb 100644 --- a/lib/splashPage.dart +++ b/lib/splashPage.dart @@ -32,6 +32,7 @@ class _SplashScreenState extends State { @override void initState() { super.initState(); + print("Splash init called............."); Timer( Duration(seconds: 1, milliseconds: 500), () async { diff --git a/lib/uitl/gif_loader_dialog_utils.dart b/lib/uitl/gif_loader_dialog_utils.dart index 937e1016..d95307de 100644 --- a/lib/uitl/gif_loader_dialog_utils.dart +++ b/lib/uitl/gif_loader_dialog_utils.dart @@ -8,11 +8,10 @@ class GifLoaderDialogUtils { } static hideDialog(BuildContext context) { - try { - Navigator.of(context).pop(); - } catch (error) { - Future.delayed(Duration(milliseconds: 250)).then((value) => Navigator.of(context).pop()); - } + try { + Navigator.of(context).pop(); + } catch (error) { + Future.delayed(Duration(milliseconds: 250)).then((value) => Navigator.of(context).canPop()); } - + } } diff --git a/lib/uitl/location_util.dart b/lib/uitl/location_util.dart index d4d88ff9..90119490 100644 --- a/lib/uitl/location_util.dart +++ b/lib/uitl/location_util.dart @@ -32,9 +32,12 @@ class LocationUtils { if (value) { await Geolocator.checkPermission().then((permission) async { if (permission == LocationPermission.always || permission == LocationPermission.whileInUse) { - Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.low, timeLimit: Duration(seconds: 10)).then((value) { + Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best, timeLimit: Duration(seconds: 5)).then((value) { setLocation(value); if (callBack != null) callBack(LatLng(value.latitude, value.longitude)); + }).catchError((err) { + print(err); + if (isShowConfirmDialog) showLocationTimeOutDialog(failureCallBack: (){}); }); } @@ -48,7 +51,7 @@ class LocationUtils { if (callBack != null) callBack(LatLng(value.latitude, value.longitude)); }); } else { - if (isShowConfirmDialog) showErrorLocationDialog(false); + if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: (){}); } }); } else { @@ -56,7 +59,7 @@ class LocationUtils { getCurrentLocation(callBack: callBack); } else { setZeroLocation(); - if (isShowConfirmDialog) showErrorLocationDialog(false); + if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: (){}); } } } @@ -155,6 +158,27 @@ class LocationUtils { } } + showLocationTimeOutDialog({Function()? failureCallBack}) { + ConfirmDialog dialog = new ConfirmDialog( + context: context, + confirmMessage: TranslationBase.of(context).locationTimeoutError, + okText: TranslationBase.of(context).ok, + cancelText: TranslationBase.of(context).cancel_nocaps, + okFunction: () { + ConfirmDialog.closeAlertDialog(context); + Navigator.of(context).canPop(); + if (failureCallBack != null) { + failureCallBack(); + } + }, + cancelFunction: () { + if (failureCallBack != null) { + failureCallBack(); + } + }); + return dialog.showAlertDialog(context); + } + showErrorLocationDialog(bool isPermissionError, {Function()? failureCallBack}) { ConfirmDialog dialog = new ConfirmDialog( context: context, diff --git a/lib/uitl/push-notification-handler.dart b/lib/uitl/push-notification-handler.dart index d7979e42..10538367 100644 --- a/lib/uitl/push-notification-handler.dart +++ b/lib/uitl/push-notification-handler.dart @@ -366,9 +366,9 @@ class PushNotificationHandler { } else if (Platform.isAndroid) { Map statuses = await [ Permission.notification, - Permission.camera, - Permission.audio, - Permission.microphone, + // Permission.camera, + // Permission.audio, + // Permission.microphone, ].request(); print("=-=-=-=-=-=-=-=-=-=-"); print(statuses[Permission.location]); diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 74853fe4..16a03340 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -2957,6 +2957,7 @@ class TranslationBase { String get locationCheckInError => localizedValues["locationCheckInError"][locale.languageCode]; String get upcoming => localizedValues["upcoming"][locale.languageCode]; String get noUpcomingAppointment => localizedValues["noUpcomingAppointment"][locale.languageCode]; + String get locationTimeoutError => localizedValues["locationTimeoutError"][locale.languageCode]; } diff --git a/lib/uitl/utils.dart b/lib/uitl/utils.dart index f4ce2ea7..a4733de2 100644 --- a/lib/uitl/utils.dart +++ b/lib/uitl/utils.dart @@ -154,7 +154,7 @@ class Utils { } static String getAppointmentTransID(int projectID, int clinicID, int appoNo) { - return projectID.toString() + '-' + clinicID.toString() + '-' + appoNo.toString(); + return projectID.toString() + '-' + clinicID.toString() + '-' + appoNo.toString() + '-' + DateTime.now().millisecondsSinceEpoch.toString(); } static String getAdvancePaymentTransID(int projectID, int fileNumber) {