Payment module implementation contd.

pull/13/head
haroon amjad 2 months ago
parent c27ba6ef09
commit 2c45356b07

File diff suppressed because one or more lines are too long

@ -102,7 +102,7 @@ class ApiClientImp implements ApiClient {
if (isRCService) {
url = RC_BASE_URL + endPoint;
} else {
url = BASE_URL + endPoint;
url = ApiConsts.baseUrl + endPoint;
}
}
try {
@ -152,21 +152,23 @@ class ApiClientImp implements ApiClient {
// request.patientOutSA = (request.zipCode == '966' || request.zipCode == '+966') ? 0 : 1;
// body['VersionID'] = ApiConsts.appVersionID.toString();
body['VersionID'] = "50.0";
body['Channel'] = ApiConsts.appChannelId.toString();
body['IPAdress'] = ApiConsts.appIpAddress;
body['generalid'] = ApiConsts.appGeneralId;
body['LanguageID'] = _appState.getLanguageID().toString();
body['Latitude'] = _appState.userLat.toString();
body['Longitude'] = _appState.userLong.toString();
body['DeviceTypeID'] = _appState.deviceTypeID;
if (_appState.appLoginTokenID.isNotEmpty) {
body['LogInTokenID'] = _appState.appLoginTokenID;
}
if (!isExternal) {
body['VersionID'] = "50.0";
body['Channel'] = ApiConsts.appChannelId.toString();
body['IPAdress'] = ApiConsts.appIpAddress;
body['generalid'] = ApiConsts.appGeneralId;
body['LanguageID'] = _appState.getLanguageID().toString();
body['Latitude'] = _appState.userLat.toString();
body['Longitude'] = _appState.userLong.toString();
body['DeviceTypeID'] = _appState.deviceTypeID;
if (_appState.appLoginTokenID.isNotEmpty) {
body['LogInTokenID'] = _appState.appLoginTokenID;
}
body['TokenID'] = "@dm!n";
body['PatientID'] = "3628599";
body['TokenID'] = "@dm!n";
body['PatientID'] = "4767477";
}
body.removeWhere((key, value) => value == null);
log("body: ${json.encode(body)}");
@ -194,7 +196,7 @@ class ApiClientImp implements ApiClient {
} else {
var parsed = json.decode(utf8.decode(response.bodyBytes));
if (isAllowAny) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);
onSuccess(parsed, statusCode, messageStatus: 1, errorMessage: "");
} else {
if (parsed['Response_Message'] != null) {
onSuccess(parsed, statusCode, messageStatus: parsed['MessageStatus'], errorMessage: parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage']);

@ -1,4 +1,5 @@
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:amazon_payfort/amazon_payfort.dart';
var MAX_SMALL_SCREEN = 660;
final OPENTOK_API_KEY = '46209962';
@ -697,7 +698,7 @@ var IS_DOCTOR_AVAILABLE_BY_CALENDAR_SCHEDULE = 'Services/OUTPs.svc/REST/HIS_IsDo
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 applePayMerchantId = "merchant.com.hmgwebservices";
// var payFortEnvironment = FortEnvironment.test;
// var applePayMerchantId = "merchant.com.hmgwebservices.uat";
@ -725,7 +726,7 @@ const DEACTIVATE_ACCOUNT = 'Services/Patients.svc/REST/PatientAppleActivation_In
class ApiConsts {
static const maxSmallScreen = 660;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.prod;
static AppEnvironmentTypeEnum appEnvironmentType = AppEnvironmentTypeEnum.uat;
// static String baseUrl = 'https://uat.hmgwebservices.com/'; // HIS API URL UAT
@ -735,25 +736,52 @@ class ApiConsts {
static num VERSION_ID = 18.9;
static var payFortEnvironment = FortEnvironment.production;
static var applePayMerchantId = "merchant.com.hmgwebservices";
static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE
// static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT
// var payFortEnvironment = FortEnvironment.test;
// var applePayMerchantId = "merchant.com.hmgwebservices.uat";
static setBackendURLs() {
switch (appEnvironmentType) {
case AppEnvironmentTypeEnum.prod:
baseUrl = "https://hmgwebservices.com/";
payFortEnvironment = FortEnvironment.production;
applePayMerchantId = "merchant.com.hmgwebservices";
SERVICE_URL = "https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx";
break;
case AppEnvironmentTypeEnum.dev:
baseUrl = "https://uat.hmgwebservices.com/";
payFortEnvironment = FortEnvironment.test;
applePayMerchantId = "merchant.com.hmgwebservices.uat";
SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx';
break;
case AppEnvironmentTypeEnum.uat:
baseUrl = "https://uat.hmgwebservices.com/";
payFortEnvironment = FortEnvironment.test;
applePayMerchantId = "merchant.com.hmgwebservices.uat";
SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx';
break;
case AppEnvironmentTypeEnum.preProd:
baseUrl = "https://webservices.hmg.com/";
payFortEnvironment = FortEnvironment.production;
applePayMerchantId = "merchant.com.hmgwebservices";
SERVICE_URL = "https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx";
break;
case AppEnvironmentTypeEnum.qa:
baseUrl = "https://uat.hmgwebservices.com/";
payFortEnvironment = FortEnvironment.test;
applePayMerchantId = "merchant.com.hmgwebservices.uat";
SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx';
break;
case AppEnvironmentTypeEnum.staging:
baseUrl = "https://uat.hmgwebservices.com/";
payFortEnvironment = FortEnvironment.test;
applePayMerchantId = "merchant.com.hmgwebservices.uat";
SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx';
break;
}
}

@ -110,4 +110,5 @@ class AppAnimations {
static const String login = '$lottieBasePath/login.json';
static const String register = '$lottieBasePath/register.json';
static const String checkmark = '$lottieBasePath/checkmark.json';
static const String loadingAnimation = '$lottieBasePath/Loader.json';
}

@ -1,4 +1,5 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:hmg_patient_app_new/core/common_models/VidaPlusProjectListModel.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/select_device_by_imei.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
@ -46,6 +47,10 @@ class AppState {
set setDeviceToken(v) => deviceToken = v;
String voipToken = "";
set setVoipToken(v) => voipToken = v;
String appAuthToken = "";
set setAppAuthToken(v) => appAuthToken = v;
@ -61,4 +66,10 @@ class AppState {
String deviceTypeID = "";
set setDeviceTypeID(v) => deviceTypeID = v;
List<VidaPlusProjectListModel> vidaPlusProjectList = [];
setVidaPlusProjectList(List<VidaPlusProjectListModel> vidaPlusProjectListModelInput) {
vidaPlusProjectList = vidaPlusProjectListModelInput;
}
}

@ -0,0 +1,15 @@
class VidaPlusProjectListModel {
int? projectID;
VidaPlusProjectListModel({this.projectID});
VidaPlusProjectListModel.fromJson(Map<String, dynamic> json) {
projectID = json['ProjectID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ProjectID'] = this.projectID;
return data;
}
}

@ -0,0 +1,120 @@
class TamaraRequestModel {
String? merchantReference;
String? merchantIdentifier;
String? clientRequestID;
num? amount;
String? currency;
String? language;
String? commandType;
String? signature;
String? customerEmail;
String? orderDescription;
bool? isInstallment;
num? projectID;
String? accessCode;
String? sHARequestPhase;
String? sHAResponsePhase;
String? customerName;
String? fileNumber;
bool? patientOutSA;
String? deviceToken;
String? longitude;
String? latitude;
String? appointmentNo;
var serviceID;
var liveServiceID;
String? doctorID;
var appointmentDate;
bool? isSchedule;
TamaraRequestModel(
{this.merchantReference,
this.merchantIdentifier,
this.clientRequestID,
this.amount,
this.currency,
this.language,
this.commandType,
this.signature,
this.customerEmail,
this.orderDescription,
this.isInstallment,
this.projectID,
this.accessCode,
this.sHARequestPhase,
this.sHAResponsePhase,
this.customerName,
this.fileNumber,
this.patientOutSA,
this.deviceToken,
this.longitude,
this.latitude,
this.appointmentNo,
this.serviceID,
this.liveServiceID,
this.appointmentDate,
this.doctorID,
this.isSchedule});
TamaraRequestModel.fromJson(Map<String, dynamic> json) {
merchantReference = json['Merchant_Reference'];
merchantIdentifier = json['Merchant_Identifier'];
clientRequestID = json['ClientRequestID'];
amount = json['Amount'];
currency = json['Currency'];
language = json['Language'];
commandType = json['CommandType'];
signature = json['Signature'];
customerEmail = json['CustomerEmail'];
orderDescription = json['OrderDescription'];
isInstallment = json['IsInstallment'];
projectID = json['ProjectID'];
accessCode = json['Access_code'];
sHARequestPhase = json['SHA_RequestPhase'];
sHAResponsePhase = json['SHA_ResponsePhase'];
customerName = json['CustomerName'];
fileNumber = json['FileNumber'];
patientOutSA = json['PatientOutSA'];
deviceToken = json['DeviceToken'];
longitude = json['Longitude'];
latitude = json['Latitude'];
appointmentNo = json['AppointmentNo'];
serviceID = json['Service_ID'];
liveServiceID = json['Live_ServiceID'];
doctorID = json['DoctorID'];
appointmentDate = json['AppointmentDate'];
isSchedule = json['IsSchedule'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Merchant_Reference'] = this.merchantReference;
data['Merchant_Identifier'] = this.merchantIdentifier;
data['ClientRequestID'] = this.clientRequestID;
data['Amount'] = this.amount;
data['Currency'] = this.currency;
data['Language'] = this.language;
data['CommandType'] = this.commandType;
data['Signature'] = this.signature;
data['CustomerEmail'] = this.customerEmail;
data['OrderDescription'] = this.orderDescription;
data['IsInstallment'] = this.isInstallment;
data['ProjectID'] = this.projectID;
data['Access_code'] = this.accessCode;
data['SHA_RequestPhase'] = this.sHARequestPhase;
data['SHA_ResponsePhase'] = this.sHAResponsePhase;
data['CustomerName'] = this.customerName;
data['FileNumber'] = this.fileNumber;
data['PatientOutSA'] = this.patientOutSA;
data['DeviceToken'] = this.deviceToken;
data['Longitude'] = this.longitude;
data['Latitude'] = this.latitude;
data['AppointmentNo'] = this.appointmentNo;
data['Service_ID'] = this.serviceID;
data['Live_ServiceID'] = this.liveServiceID;
data['DoctorID'] = this.doctorID;
data['AppointmentDate'] = this.appointmentDate;
data['IsSchedule'] = this.isSchedule;
return data;
}
}

@ -13,6 +13,8 @@ import 'package:hmg_patient_app_new/features/lab/lab_repo.dart';
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_repo.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_repo.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_repo.dart';
@ -77,6 +79,7 @@ class AppDependencies {
getIt.registerLazySingleton<RadiologyRepo>(() => RadiologyRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<PrescriptionsRepo>(() => PrescriptionsRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<InsuranceRepo>(() => InsuranceRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
getIt.registerLazySingleton<PayfortRepo>(() => PayfortRepoImp(loggerService: getIt<LoggerService>(), apiClient: getIt()));
// ViewModels
// Global/shared VMs LazySingleton
@ -116,6 +119,13 @@ class AppDependencies {
),
);
getIt.registerLazySingleton<PayfortViewModel>(
() => PayfortViewModel(
payfortRepo: getIt(),
errorHandlerService: getIt(),
),
);
getIt.registerLazySingleton<AuthenticationViewModel>(
() => AuthenticationViewModel(
authenticationRepo: getIt(),

@ -104,3 +104,49 @@ extension OTPTypeEnumExtension on OTPTypeEnum {
}
}
}
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;
}
}
}

@ -297,6 +297,29 @@ class Utils {
).center;
}
static Widget getLoadingWidget({String? loadingText}) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Lottie.asset(AppAnimations.loadingAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 100.h, height: 100.h, fit: BoxFit.fill),
SizedBox(height: 8.h),
(loadingText ?? LocaleKeys.loadingText.tr()).toText16(color: AppColors.blackColor),
SizedBox(height: 8.h),
],
).center;
}
static bool isVidaPlusProject(AppState appState, int projectID) {
bool isVidaPlus = false;
for (var element in appState.vidaPlusProjectList) {
if (element.projectID == projectID) {
isVidaPlus = true;
}
}
return isVidaPlus;
}
static getPhoneNumberWithoutZero(String number) {
String newNumber = "";
if (number.startsWith('0')) {

@ -13,6 +13,20 @@ abstract class MyAppointmentsRepo {
Future<Either<Failure, GenericApiModel<PatientAppointmentShareResponseModel>>> getPatientShareAppointment(
{required String patientId, required int projectID, required int clinicID, required String appointmentNo});
Future<Either<Failure, GenericApiModel<dynamic>>> createAdvancePayment(
{required String paymentMethodName,
required int projectID,
required int clinicID,
required String appointmentNo,
required num payedAmount,
required String paymentReference,
required String patientID,
required int patientType});
Future<Either<Failure, GenericApiModel<dynamic>>> addAdvanceNumberRequest({required String advanceNumber, required String paymentReference, required String appointmentNo});
Future<Either<Failure, GenericApiModel<dynamic>>> generateAppointmentQR({required String clinicID, required String projectID, required String appointmentNo, required int isFollowUp});
}
class MyAppointmentsRepoImp implements MyAppointmentsRepo {
@ -105,7 +119,6 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
final patientShareObj = PatientAppointmentShareResponseModel.fromJson(list[0]);
patientShareObj.isCash = response["IsCash"];
// patientShareObj.isCash = false;
patientShareObj.isEligible = response["IsEligible"];
patientShareObj.isInsured = response["IsInsured"];
@ -129,4 +142,139 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
throw UnimplementedError();
}
@override
Future<Either<Failure, GenericApiModel>> createAdvancePayment({
required String paymentMethodName,
required int projectID,
required int clinicID,
required String appointmentNo,
required num payedAmount,
required String paymentReference,
required String patientID,
required int patientType,
}) async {
final requestBody = {
"ProjectID": projectID,
"OnlineCheckInAppointment": {
"AppointmentNo": appointmentNo,
"PaymentMethodName": paymentMethodName,
"PaymentAmount": payedAmount == 0 ? "0" : payedAmount.toString(),
"PaymentDate": payedAmount == 0 ? "" : "/Date(${DateTime.now().millisecondsSinceEpoch})/",
"PaymentReferenceNumber": payedAmount == 0 ? "" : paymentReference,
"ProjectID": projectID,
"PatientID": patientID,
"ClinicID": clinicID,
"UserID": patientID,
"Status": patientType
}
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
CREATE_ADVANCE_PAYMENT,
body: requestBody,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel>> addAdvanceNumberRequest({required String advanceNumber, required String paymentReference, required String appointmentNo}) async {
final requestBody = {
"AdvanceNumber": advanceNumber,
"AdvanceNumber_VP": advanceNumber,
"PaymentReferenceNumber": paymentReference,
"AppointmentID": appointmentNo,
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
ADD_ADVANCE_NUMBER_REQUEST,
body: requestBody,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel>> generateAppointmentQR({required String clinicID, required String projectID, required String appointmentNo, required int isFollowUp}) async {
final requestBody = {
"AppointmentNo": appointmentNo,
"ClinicID": clinicID,
"ProjectID": projectID,
"IsFollowup": isFollowUp,
};
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(
GENERATE_QR_APPOINTMENT,
body: requestBody,
onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
},
onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
},
);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
}

@ -87,4 +87,78 @@ class MyAppointmentsViewModel extends ChangeNotifier {
},
);
}
Future<void> addAdvanceNumberRequest(
{required String advanceNumber, required String paymentReference, required String appointmentNo, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.addAdvanceNumberRequest(advanceNumber: advanceNumber, paymentReference: paymentReference, appointmentNo: appointmentNo);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> generateAppointmentQR(
{required String clinicID, required String projectID, required String appointmentNo, required int isFollowUp, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.generateAppointmentQR(clinicID: clinicID, projectID: projectID, appointmentNo: appointmentNo, isFollowUp: isFollowUp);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> createAdvancePayment(
{required String paymentMethodName,
required int projectID,
required int clinicID,
required String appointmentNo,
required num payedAmount,
required String paymentReference,
required String patientID,
required int patientType,
Function(dynamic)? onSuccess,
Function(String)? onError}) async {
final result = await myAppointmentsRepo.createAdvancePayment(
paymentMethodName: paymentMethodName,
projectID: projectID,
clinicID: clinicID,
appointmentNo: appointmentNo,
payedAmount: payedAmount,
paymentReference: paymentReference,
patientID: patientID,
patientType: patientType);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
}

@ -0,0 +1,187 @@
class ApplePayInsertRequest {
String? clientRequestID;
int? clinicID;
String? currency;
String? customerEmail;
dynamic customerID;
String? customerName;
String? deviceToken;
String? voipToken;
int? doctorID;
String? projectID;
String? serviceID;
int? channelID;
dynamic patientID;
int? patientTypeID;
int? patientOutSA;
dynamic appointmentDate;
int? appointmentNo;
String? orderDescription;
String? liveServiceID;
String? latitude;
String? longitude;
String? amount;
String? isSchedule;
String? language;
int? userName;
String? responseContinueURL;
String? backClickUrl;
String? paymentOption;
double? versionID;
int? channel;
int? languageID;
String? iPAdress;
String? generalid;
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.isMobSDK,
this.merchantReference,
this.merchantIdentifier,
this.commandType,
this.signature,
this.accessCode,
this.shaRequestPhrase,
this.shaResponsePhrase,
this.returnURL,
});
ApplePayInsertRequest.fromJson(Map<String, dynamic> json) {
clientRequestID = json['ClientRequestID'];
clinicID = json['ClinicID'];
currency = json['Currency'];
customerEmail = json['CustomerEmail'];
customerID = json['CustomerID'];
customerName = json['CustomerName'];
deviceToken = json['DeviceToken'];
voipToken = json['VoipToken'];
doctorID = json['DoctorID'];
projectID = json['ProjectID'];
serviceID = json['Service_ID'];
channelID = json['Channel_ID'];
patientID = json['PatientID'];
patientTypeID = json['PatientTypeID'];
patientOutSA = json['PatientOutSA'];
appointmentDate = json['AppointmentDate'];
appointmentNo = json['AppointmentNo'];
orderDescription = json['OrderDescription'];
liveServiceID = json['Live_ServiceID'];
latitude = json['Latitude'];
longitude = json['Longitude'];
amount = json['Amount'];
isSchedule = json['IsSchedule'];
language = json['Language'];
userName = json['userName'];
responseContinueURL = json['ResponseContinueURL'];
backClickUrl = json['BackClickUrl'];
paymentOption = json['PaymentOption'];
versionID = json['VersionID'];
channel = json['Channel'];
languageID = json['LanguageID'];
iPAdress = json['IPAdress'];
generalid = json['generalid'];
sessionID = json['SessionID'];
isDentalAllowedBackend = json['isDentalAllowedBackend'];
deviceTypeID = json['DeviceTypeID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ClientRequestID'] = this.clientRequestID;
data['ClinicID'] = this.clinicID;
data['Currency'] = this.currency;
data['CustomerEmail'] = this.customerEmail;
data['CustomerID'] = this.customerID;
data['CustomerName'] = this.customerName;
data['DeviceToken'] = this.deviceToken;
data['VoipToken'] = this.voipToken;
data['DoctorID'] = this.doctorID;
data['ProjectID'] = this.projectID;
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;
data['AppointmentNo'] = this.appointmentNo;
data['OrderDescription'] = this.orderDescription;
data['Live_ServiceID'] = this.liveServiceID;
data['Latitude'] = this.latitude;
data['Longitude'] = this.longitude;
data['Amount'] = this.amount;
data['IsSchedule'] = this.isSchedule;
data['Language'] = this.language;
data['userName'] = this.userName;
data['ResponseContinueURL'] = this.responseContinueURL;
data['BackClickUrl'] = this.backClickUrl;
data['PaymentOption'] = this.paymentOption;
data['VersionID'] = this.versionID;
data['Channel'] = this.channel;
data['LanguageID'] = this.languageID;
data['IPAdress'] = this.iPAdress;
data['generalid'] = this.generalid;
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;
}
}

@ -0,0 +1,60 @@
class PayfortCheckPaymentStatusResponseModel {
num? amount;
String? cardNumber;
dynamic clientRequsetID;
dynamic errorMessage;
String? fortId;
String? merchantReference;
dynamic orderDescription;
dynamic patientFileNumber;
String? paymentMethod;
dynamic rRN;
String? responseMessage;
dynamic vidaAdvancedNumber;
PayfortCheckPaymentStatusResponseModel(
{this.amount,
this.cardNumber,
this.clientRequsetID,
this.errorMessage,
this.fortId,
this.merchantReference,
this.orderDescription,
this.patientFileNumber,
this.paymentMethod,
this.rRN,
this.responseMessage,
this.vidaAdvancedNumber});
PayfortCheckPaymentStatusResponseModel.fromJson(Map<String, dynamic> json) {
amount = json['Amount'];
cardNumber = json['CardNumber'];
clientRequsetID = json['ClientRequsetID'];
errorMessage = json['ErrorMessage'];
fortId = json['Fort_id'];
merchantReference = json['Merchant_Reference'];
orderDescription = json['OrderDescription'];
patientFileNumber = json['PatientFileNumber'];
paymentMethod = json['PaymentMethod'];
rRN = json['RRN'];
responseMessage = json['Response_Message'];
vidaAdvancedNumber = json['VidaAdvancedNumber'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Amount'] = this.amount;
data['CardNumber'] = this.cardNumber;
data['ClientRequsetID'] = this.clientRequsetID;
data['ErrorMessage'] = this.errorMessage;
data['Fort_id'] = this.fortId;
data['Merchant_Reference'] = this.merchantReference;
data['OrderDescription'] = this.orderDescription;
data['PatientFileNumber'] = this.patientFileNumber;
data['PaymentMethod'] = this.paymentMethod;
data['RRN'] = this.rRN;
data['Response_Message'] = this.responseMessage;
data['VidaAdvancedNumber'] = this.vidaAdvancedNumber;
return data;
}
}

@ -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<String, dynamic> 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<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
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;
}
}

@ -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<String, dynamic> 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<String, dynamic> 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,
};
}
}

@ -0,0 +1,150 @@
import 'package:amazon_payfort/amazon_payfort.dart';
import 'package:dartz/dartz.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/generic_api_model.dart';
import 'package:hmg_patient_app_new/core/exceptions/api_failure.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_check_payment_status_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_project_details_resp_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/sdk_token_response_model.dart';
import 'package:hmg_patient_app_new/services/logger_service.dart';
abstract class PayfortRepo {
Future<Either<Failure, GenericApiModel<PayfortProjectDetailsRespModel>>> getPayfortConfigurations({int? serviceId, int? projectId, int integrationId = 2});
Future<Either<Failure, GenericApiModel<dynamic>>> applePayRequestInsert({required ApplePayInsertRequest applePayInsertRequest});
Future<Either<Failure, GenericApiModel<SdkTokenResponse>>> generateSdkSignatureFromAPI({required SdkTokenRequest tokenRequest});
Future<Either<Failure, GenericApiModel<PayfortCheckPaymentStatusResponseModel>>> checkPaymentStatus({required String transactionID});
}
class PayfortRepoImp implements PayfortRepo {
final ApiClient apiClient;
final LoggerService loggerService;
PayfortRepoImp({required this.loggerService, required this.apiClient});
@override
Future<Either<Failure, GenericApiModel<PayfortProjectDetailsRespModel>>> getPayfortConfigurations({int? serviceId, int? projectId, int integrationId = 2}) async {
Map<String, dynamic> body = {"Integration_Id": integrationId, "ServID": serviceId, "ProjectID": projectId};
try {
GenericApiModel<PayfortProjectDetailsRespModel>? apiResponse;
Failure? failure;
await apiClient.post(getPayFortProjectDetails, body: body, onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
}, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final list = response;
if (list == null || list.isEmpty) {
throw Exception("payfort list is empty");
}
final applePayConfigurationResponse = PayfortProjectDetailsRespModel.fromJson(list[0]);
apiResponse = GenericApiModel<PayfortProjectDetailsRespModel>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: applePayConfigurationResponse,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
}, isAllowAny: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel>> applePayRequestInsert({required ApplePayInsertRequest applePayInsertRequest}) async {
try {
GenericApiModel<dynamic>? apiResponse;
Failure? failure;
await apiClient.post(APPLE_PAY_INSERT_REQUEST, body: applePayInsertRequest.toJson(), onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
}, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
apiResponse = GenericApiModel<dynamic>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: response["result"],
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
}, isAllowAny: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<SdkTokenResponse>>> generateSdkSignatureFromAPI({required SdkTokenRequest tokenRequest}) async {
try {
GenericApiModel<SdkTokenResponse>? apiResponse;
Failure? failure;
await apiClient.post(ApiConsts.payFortEnvironment.paymentApi, body: tokenRequest.asRequest(), onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
}, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final sdkTokenResponse = SdkTokenResponse.fromMap(response);
apiResponse = GenericApiModel<SdkTokenResponse>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: sdkTokenResponse,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
}, isAllowAny: true, isExternal: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
@override
Future<Either<Failure, GenericApiModel<PayfortCheckPaymentStatusResponseModel>>> checkPaymentStatus({required String transactionID}) async {
Map<String, dynamic> body = {"ClientRequestID": transactionID, "IsPharmacy": false};
try {
GenericApiModel<PayfortCheckPaymentStatusResponseModel>? apiResponse;
Failure? failure;
await apiClient.post(CHECK_PAYMENT_STATUS, body: body, onFailure: (error, statusCode, {messageStatus, failureType}) {
failure = failureType;
}, onSuccess: (response, statusCode, {messageStatus, errorMessage}) {
try {
final paymentStatusResponse = PayfortCheckPaymentStatusResponseModel.fromJson(response);
apiResponse = GenericApiModel<PayfortCheckPaymentStatusResponseModel>(
messageStatus: messageStatus,
statusCode: statusCode,
errorMessage: null,
data: paymentStatusResponse,
);
} catch (e) {
failure = DataParsingFailure(e.toString());
}
}, isAllowAny: true);
if (failure != null) return Left(failure!);
if (apiResponse == null) return Left(ServerFailure("Unknown error"));
return Right(apiResponse!);
} catch (e) {
return Left(UnknownFailure(e.toString()));
}
}
}

@ -0,0 +1,198 @@
import 'package:amazon_payfort/amazon_payfort.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_check_payment_status_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/payfort_project_details_resp_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/sdk_token_response_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_repo.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:network_info_plus/network_info_plus.dart';
class PayfortViewModel extends ChangeNotifier {
PayfortRepo payfortRepo;
ErrorHandlerService errorHandlerService;
bool isApplePayConfigurationLoading = false;
PayfortProjectDetailsRespModel? payfortProjectDetailsRespModel;
PayfortCheckPaymentStatusResponseModel? payfortCheckPaymentStatusResponseModel;
late AmazonPayfort _payfort;
final NetworkInfo _info = NetworkInfo();
PayfortViewModel({required this.payfortRepo, required this.errorHandlerService});
setIsApplePayConfigurationLoading(bool value) {
isApplePayConfigurationLoading = value;
notifyListeners();
}
initPayfortViewModel() async {
_payfort = AmazonPayfort.instance;
await AmazonPayfort.initialize(
PayFortOptions(environment: ApiConsts.payFortEnvironment),
);
notifyListeners();
}
Future<void> getPayfortConfigurations({int? serviceId, int? projectId, int integrationId = 2, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await payfortRepo.getPayfortConfigurations(serviceId: serviceId, projectId: projectId, integrationId: integrationId);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
payfortProjectDetailsRespModel = apiResponse.data!;
// isApplePayConfigurationLoading = false;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> applePayRequestInsert({required ApplePayInsertRequest applePayInsertRequest, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await payfortRepo.applePayRequestInsert(applePayInsertRequest: applePayInsertRequest);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
// payfortProjectDetailsRespModel = apiResponse.data!;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<void> checkPaymentStatus({required String transactionID, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await payfortRepo.checkPaymentStatus(transactionID: transactionID);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
payfortCheckPaymentStatusResponseModel = apiResponse.data!;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
Future<SdkTokenResponse?> _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
final result = await payfortRepo.generateSdkSignatureFromAPI(tokenRequest: tokenRequest);
result.fold(
(failure) async => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
// payfortProjectDetailsRespModel = apiResponse.data!;
isApplePayConfigurationLoading = false;
notifyListeners();
}
},
);
} catch (e) {
print("Error here: ${e.toString()}");
}
return null;
}
Future<void> paymentWithApplePay({
SucceededCallback? onSucceeded,
FailedCallback? onFailed,
String? customerName,
String? customerEmail,
String? orderDescription,
num? 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 ?? '') as PayFortFailureResult);
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(
command: FortCommand.purchase,
amount: orderAmount!,
customerName: customerName!,
customerEmail: customerEmail!,
// orderDescription: orderDescription!,
orderDescription: "Dr. Sulaiman Al Habib Hospital",
sdkToken: sdkTokenResponse?.sdkToken ?? '',
merchantReference: merchantReference!,
currency: currency,
customerIp: (await _info.getWifiIP() ?? ''),
language: 'en');
isApplePayConfigurationLoading = false;
notifyListeners();
_payfort.callPayFortForApplePay(
request: request,
countryIsoCode: countryIsoCode,
applePayMerchantId: ApiConsts.applePayMerchantId,
callback: ApplePayResultCallback(
onSucceeded: onSucceeded!,
onFailed: onFailed!,
),
);
} catch (e) {
onFailed!(e.toString() as PayFortFailureResult);
}
}
}

@ -13,6 +13,7 @@ import 'package:hmg_patient_app_new/features/insurance/insurance_view_model.dart
import 'package:hmg_patient_app_new/features/lab/lab_view_model.dart';
import 'package:hmg_patient_app_new/features/medical_file/medical_file_view_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
import 'package:hmg_patient_app_new/features/radiology/radiology_view_model.dart';
import 'package:hmg_patient_app_new/routes/app_routes.dart';
@ -102,6 +103,12 @@ void main() async {
errorHandlerService: getIt(),
),
),
ChangeNotifierProvider<PayfortViewModel>(
create: (_) => PayfortViewModel(
payfortRepo: getIt(),
errorHandlerService: getIt(),
),
),
ChangeNotifierProvider<AuthenticationViewModel>(
create: (_) => AuthenticationViewModel(
authenticationRepo: getIt(),

@ -1,17 +1,29 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
import 'package:hmg_patient_app_new/features/payfort/models/apple_pay_request_insert_model.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/my_appointments/models/resp_models/patient_appointment_history_response_model.dart';
import 'package:hmg_patient_app_new/features/my_appointments/my_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/payfort/payfort_view_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/services/cache_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/in_app_browser/InAppBrowser.dart';
import 'package:hmg_patient_app_new/widgets/shimmer/movies_shimmer_widget.dart';
import 'package:provider/provider.dart';
import 'package:smooth_corner/smooth_corner.dart';
@ -27,10 +39,18 @@ class AppointmentPaymentPage extends StatefulWidget {
class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
late MyAppointmentsViewModel myAppointmentsViewModel;
late PayfortViewModel payfortViewModel;
late AppState appState;
MyInAppBrowser? browser;
String selectedPaymentMethod = "";
String transID = "";
@override
void initState() {
scheduleMicrotask(() {
payfortViewModel.initPayfortViewModel();
myAppointmentsViewModel.getPatientShareAppointment(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
@ -42,7 +62,9 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
@override
Widget build(BuildContext context) {
appState = getIt.get<AppState>();
myAppointmentsViewModel = Provider.of<MyAppointmentsViewModel>(context);
payfortViewModel = Provider.of<PayfortViewModel>(context);
return Scaffold(
backgroundColor: AppColors.bgScaffoldColor,
appBar: AppBar(
@ -89,7 +111,10 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "MADA";
openPaymentURL("mada");
}),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
@ -125,7 +150,10 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "VISA";
openPaymentURL("visa");
}),
SizedBox(height: 16.h),
Container(
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
@ -155,94 +183,312 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
),
],
).paddingSymmetrical(16.h, 16.h),
).paddingSymmetrical(24.h, 0.h),
).paddingSymmetrical(24.h, 0.h).onPress(() {
selectedPaymentMethod = "TAMARA";
openPaymentURL("tamara");
}),
],
),
),
),
Container(
// height: 200.h,
// width: double.infinity,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: AppColors.whiteColor,
borderRadius: 24.h,
hasShadow: false,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(myAppointmentsVM.patientAppointmentShareResponseModel!.isCash ?? true)
? Container(
height: 50.h,
decoration: ShapeDecoration(
color: AppColors.secondaryLightRedBorderColor,
shape: SmoothRectangleBorder(
borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
smoothness: 1,
),
),
child: Row(
child: Consumer<PayfortViewModel>(builder: (context, payfortVM, child) {
//TODO: Need to add loading state & animation for Apple Pay Configuration
return payfortVM.isApplePayConfigurationLoading
? const MoviesShimmerWidget().paddingAll(16.h)
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(myAppointmentsVM.patientAppointmentShareResponseModel!.isCash ?? true)
? Container(
height: 50.h,
decoration: ShapeDecoration(
color: AppColors.secondaryLightRedBorderColor,
shape: SmoothRectangleBorder(
borderRadius: BorderRadius.only(topLeft: Radius.circular(24), topRight: Radius.circular(24)),
smoothness: 1,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Insurance expired or inactive".needTranslation.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h),
CustomButton(
text: LocaleKeys.updateInsurance.tr(context: context),
onPressed: () {},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.secondaryLightRedBorderColor,
textColor: AppColors.whiteColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
height: 30.h,
).paddingSymmetrical(24.h, 0.h),
],
),
)
: const SizedBox(),
SizedBox(height: 24.h),
"Total amount to pay".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Insurance expired or inactive".needTranslation.toText14(color: AppColors.primaryRedColor, weight: FontWeight.w500).paddingSymmetrical(24.h, 0.h),
CustomButton(
text: LocaleKeys.updateInsurance.tr(context: context),
onPressed: () {},
backgroundColor: AppColors.primaryRedColor,
borderColor: AppColors.secondaryLightRedBorderColor,
textColor: AppColors.whiteColor,
fontSize: 10,
fontWeight: FontWeight.w500,
borderRadius: 8,
padding: EdgeInsets.fromLTRB(15, 0, 15, 0),
height: 30.h,
).paddingSymmetrical(24.h, 0.h),
"Total amount to pay".needTranslation.toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
isSaudiCurrency: true),
],
),
)
: const SizedBox(),
SizedBox(height: 24.h),
"Total amount to pay".needTranslation.toText18(isBold: true).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"Total amount to pay".needTranslation.toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShare!.toString().toText16(isBold: true), AppColors.blackColor, 13,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
Utils.getPaymentAmountWithSymbol(
myAppointmentsVM.patientAppointmentShareResponseModel!.patientTaxAmount!.toString().toText14(isBold: true, color: AppColors.greyTextColor), AppColors.greyTextColor, 13,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"".needTranslation.toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(myAppointmentsVM.patientAppointmentShareResponseModel!.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
Utils.buildSvgWithAssets(
icon: AppAssets.apple_pay_button,
width: 200.h,
height: 80.h,
fit: BoxFit.contain,
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 12.h),
],
),
).paddingSymmetrical(24.h, 0.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"VAT 15%".needTranslation.toText14(isBold: true, color: AppColors.greyTextColor),
Utils.getPaymentAmountWithSymbol(
myAppointmentsVM.patientAppointmentShareResponseModel!.patientTaxAmount!.toString().toText14(isBold: true, color: AppColors.greyTextColor),
AppColors.greyTextColor,
13,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 17.h),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"".needTranslation.toText14(isBold: true),
Utils.getPaymentAmountWithSymbol(
myAppointmentsVM.patientAppointmentShareResponseModel!.patientShareWithTax!.toString().toText24(isBold: true), AppColors.blackColor, 17,
isSaudiCurrency: true),
],
).paddingSymmetrical(24.h, 0.h),
//TODO: Add Apple Pay Privileges
Utils.buildSvgWithAssets(
icon: AppAssets.apple_pay_button,
width: 200.h,
height: 80.h,
fit: BoxFit.contain,
).paddingSymmetrical(24.h, 0.h).onPress(() {
payfortVM.setIsApplePayConfigurationLoading(true);
startApplePay();
}),
SizedBox(height: 12.h),
],
);
}),
),
],
);
}),
);
}
onBrowserLoadStart(String url) {
print("onBrowserLoadStart");
print(url);
if (selectedPaymentMethod == "tamara") {
if (Platform.isAndroid) {
Uri uri = new Uri.dataFromString(url);
// tamaraPaymentStatus = uri.queryParameters['status']!;
// tamaraOrderID = uri.queryParameters['AuthorizePaymentId']!;
} else {
Uri uri = new Uri.dataFromString(url);
// tamaraPaymentStatus = uri.queryParameters['paymentStatus']!;
// tamaraOrderID = uri.queryParameters['orderId']!;
}
}
// if(selectedPaymentMethod != "TAMARA") {
MyInAppBrowser.successURLS.forEach((element) {
if (url.contains(element)) {
browser?.close();
MyInAppBrowser.isPaymentDone = true;
return;
}
});
// }
// if(selectedPaymentMethod != "TAMARA") {
MyInAppBrowser.errorURLS.forEach((element) {
if (url.contains(element)) {
browser?.close();
MyInAppBrowser.isPaymentDone = false;
return;
}
});
// }
}
onBrowserExit(bool isPaymentMade) async {
print("onBrowserExit Called!!!!");
if (selectedPaymentMethod == "TAMARA") {
// checkTamaraPaymentStatus(transID!, appo);
// if (tamaraPaymentStatus != null && tamaraPaymentStatus.toLowerCase() == "approved") {
// updateTamaraRequestStatus("success", "14", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
// } else {
// updateTamaraRequestStatus("Failed", "00", Utils.getAppointmentTransID(appo.projectID, appo.clinicID, appo.appointmentNo), tamaraOrderID, num.parse(selectedInstallments), appo);
// }
} else {
showCommonBottomSheet(context,
child: Utils.getLoadingWidget(), callBackFunc: () {}, title: "", height: ResponsiveExtension.screenHeight * 0.3, isCloseButtonVisible: false, isDismissible: false, isFullScreen: false);
await payfortViewModel.checkPaymentStatus(
transactionID: transID,
onSuccess: (apiResponse) async {
print(apiResponse.data);
if (payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!.toLowerCase() == "success") {
await myAppointmentsViewModel.createAdvancePayment(
paymentMethodName: selectedPaymentMethod,
projectID: widget.patientAppointmentHistoryResponseModel.projectID,
clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
payedAmount: payfortViewModel.payfortCheckPaymentStatusResponseModel!.amount!,
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
patientID: "4767477",
patientType: 1,
onSuccess: (value) async {
print(value);
await myAppointmentsViewModel.addAdvanceNumberRequest(
advanceNumber: Utils.isVidaPlusProject(appState, widget.patientAppointmentHistoryResponseModel.projectID)
? value['data']['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString()
: value['data']['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(),
paymentReference: payfortViewModel.payfortCheckPaymentStatusResponseModel!.fortId!,
appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
onSuccess: (value) async {
if (widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment!) {
//TODO: Implement LiveCare Check-In API Call
} else {
await myAppointmentsViewModel.generateAppointmentQR(
clinicID: widget.patientAppointmentHistoryResponseModel.clinicID,
projectID: widget.patientAppointmentHistoryResponseModel.projectID,
appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(),
isFollowUp: myAppointmentsViewModel.patientAppointmentShareResponseModel!.isFollowup!);
}
});
});
Future.delayed(Duration(milliseconds: 500), () {
Navigator.of(context).pop();
print(payfortViewModel.payfortCheckPaymentStatusResponseModel!.responseMessage!);
});
} else {}
});
// checkPaymentStatus(appo);
}
}
openPaymentURL(String paymentMethod) {
browser = MyInAppBrowser(onExitCallback: onBrowserExit, onLoadStartCallback: onBrowserLoadStart, context: context);
transID = Utils.getAppointmentTransID(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
widget.patientAppointmentHistoryResponseModel.appointmentNo,
);
//TODO: Need to pass dynamic params to the payment request instead of static values
browser?.openPaymentBrowser(
myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!,
"Appointment check in",
transID,
widget.patientAppointmentHistoryResponseModel.projectID.toString(),
"CustID_3628599@HMG.com",
selectedPaymentMethod,
"1",
"Haroon Amjad",
"3628599",
AuthenticatedUser(outSA: 0, mobileNumber: "0593233758"),
browser!,
widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false,
"2",
widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? myAppointmentsViewModel.patientAppointmentShareResponseModel!.clinicID.toString() : "",
context,
myAppointmentsViewModel.patientAppointmentShareResponseModel!.appointmentDate,
myAppointmentsViewModel.patientAppointmentShareResponseModel!.appointmentNo,
myAppointmentsViewModel.patientAppointmentShareResponseModel!.clinicID,
myAppointmentsViewModel.patientAppointmentShareResponseModel!.doctorID,
"3");
}
startApplePay() async {
transID = Utils.getAppointmentTransID(
widget.patientAppointmentHistoryResponseModel.projectID,
widget.patientAppointmentHistoryResponseModel.clinicID,
widget.patientAppointmentHistoryResponseModel.appointmentNo,
);
ApplePayInsertRequest applePayInsertRequest = ApplePayInsertRequest();
await payfortViewModel.getPayfortConfigurations(
serviceId: ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum(), projectId: widget.patientAppointmentHistoryResponseModel.projectID, integrationId: 2);
applePayInsertRequest.clientRequestID = transID;
applePayInsertRequest.clinicID = widget.patientAppointmentHistoryResponseModel.clinicID;
//TODO: Need to pass dynamic params to the payment request instead of static values
applePayInsertRequest.currency = "SAR";
applePayInsertRequest.customerEmail = "CustID_3628599@HMG.com";
applePayInsertRequest.customerID = "3628599";
applePayInsertRequest.customerName = "Haroon Amjad";
applePayInsertRequest.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
applePayInsertRequest.voipToken = await Utils.getStringFromPrefs(CacheConst.voipToken);
applePayInsertRequest.doctorID = widget.patientAppointmentHistoryResponseModel.doctorID;
applePayInsertRequest.projectID = widget.patientAppointmentHistoryResponseModel.projectID.toString();
applePayInsertRequest.serviceID = ServiceTypeEnum.appointmentPayment.getIdFromServiceEnum().toString();
applePayInsertRequest.channelID = 3;
applePayInsertRequest.patientID = "3628599";
applePayInsertRequest.patientTypeID = 1;
applePayInsertRequest.patientOutSA = 0;
applePayInsertRequest.appointmentDate = widget.patientAppointmentHistoryResponseModel.appointmentDate;
applePayInsertRequest.appointmentNo = widget.patientAppointmentHistoryResponseModel.appointmentNo;
applePayInsertRequest.orderDescription = "Appointment Payment";
applePayInsertRequest.liveServiceID = "0";
applePayInsertRequest.latitude = "0.0";
applePayInsertRequest.longitude = "0.0";
applePayInsertRequest.amount = myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!.toString();
applePayInsertRequest.isSchedule = widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment! ? "1" : "0";
applePayInsertRequest.language = appState.isArabic() ? 'ar' : 'en';
applePayInsertRequest.languageID = appState.isArabic() ? 1 : 2;
applePayInsertRequest.userName = 3628599;
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 = payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier;
applePayInsertRequest.commandType = "PURCHASE";
applePayInsertRequest.signature = payfortViewModel.payfortProjectDetailsRespModel!.signature;
applePayInsertRequest.accessCode = payfortViewModel.payfortProjectDetailsRespModel!.accessCode;
applePayInsertRequest.shaRequestPhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaRequest;
applePayInsertRequest.shaResponsePhrase = payfortViewModel.payfortProjectDetailsRespModel!.shaResponse;
applePayInsertRequest.returnURL = "";
//TODO: Need to pass dynamic params to the Apple Pay instead of static values
await payfortViewModel.applePayRequestInsert(applePayInsertRequest: applePayInsertRequest).then((value) {
payfortViewModel.paymentWithApplePay(
customerName: "Haroon Amjad",
// customerEmail: projectViewModel.authenticatedUserObject.user.emailAddress,
customerEmail: "CustID_3628599@HMG.com",
orderDescription: "Appointment Payment",
orderAmount: double.parse(myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!.toString()),
merchantReference: transID,
merchantIdentifier: payfortViewModel.payfortProjectDetailsRespModel!.merchantIdentifier,
applePayAccessCode: payfortViewModel.payfortProjectDetailsRespModel!.accessCode,
applePayShaRequestPhrase: payfortViewModel.payfortProjectDetailsRespModel!.shaRequest,
currency: "SAR",
onFailed: (failureResult) async {
log("failureResult: ${failureResult.message.toString()}");
},
onSucceeded: (successResult) async {
log("successResult: ${successResult.responseMessage.toString()}");
},
// projectId: appo.projectID,
// serviceTypeEnum: ServiceTypeEnum.appointmentPayment,
);
});
}
}

@ -204,7 +204,13 @@ class _AppointmentCardState extends State<AppointmentCard> {
flex: 6,
child: CustomButton(
text: AppointmentType.getNextActionText(widget.patientAppointmentHistoryResponseModel.nextAction),
onPressed: () {},
onPressed: () {
Navigator.of(context).push(
FadePage(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
);
},
backgroundColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.1),
borderColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction).withOpacity(0.01),
textColor: AppointmentType.getNextActionButtonColor(widget.patientAppointmentHistoryResponseModel.nextAction),
@ -237,7 +243,13 @@ class _AppointmentCardState extends State<AppointmentCard> {
fit: BoxFit.contain,
),
),
),
).onPress(() {
Navigator.of(context).push(
FadePage(
page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel),
),
);
}),
),
],
),

@ -7,7 +7,7 @@ import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
void showCommonBottomSheet(BuildContext context,
{required Widget child, required VoidCallback callBackFunc, String? title, required double height, bool isCloseButtonVisible = true, bool isFullScreen = true}) {
{required Widget child, required VoidCallback callBackFunc, String? title, required double height, bool isCloseButtonVisible = true, bool isFullScreen = true, bool isDismissible = true}) {
showModalBottomSheet<String>(
sheetAnimationStyle: AnimationStyle(
duration: Duration(milliseconds: 500), // Custom animation duration
@ -16,6 +16,7 @@ void showCommonBottomSheet(BuildContext context,
context: context,
isScrollControlled: true,
showDragHandle: false,
isDismissible: isDismissible,
backgroundColor: AppColors.scaffoldBgColor,
builder: (BuildContext context) {
return Container(

@ -0,0 +1,489 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/common_models/tamara_request_model.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/authentication/models/resp_models/authenticated_user_resp_model.dart';
enum _PAYMENT_TYPE { PACKAGES, PHARMACY, PATIENT }
var _InAppBrowserOptions = InAppBrowserClassOptions(
inAppWebViewGroupOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(useShouldOverrideUrlLoading: true, transparentBackground: false),
ios: IOSInAppWebViewOptions(applePayAPIEnabled: true, isFraudulentWebsiteWarningEnabled: false)),
crossPlatform: InAppBrowserOptions(hideUrlBar: true, toolbarTopBackgroundColor: Colors.black),
android: AndroidInAppBrowserOptions(),
ios: IOSInAppBrowserOptions(
hideToolbarBottom: true,
toolbarBottomBackgroundColor: Colors.white,
closeButtonColor: Colors.white,
closeButtonCaption: "Close",
presentationStyle: IOSUIModalPresentationStyle.OVER_FULL_SCREEN));
class MyInAppBrowser extends InAppBrowser {
_PAYMENT_TYPE? paymentType;
static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWebLive/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL LIVE
// static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWebLive/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL UAT
// static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT
// static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE
// static String SERVICE_URL = 'https://uat.hmgwebservices.com/payfortforvidaplus/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL UAT VIDA PLUS
// static String PRESCRIPTION_PAYMENT_WITH_ORDERID =
// 'https://uat.hmgwebservices.com/epharmacy/checkout/OpcCompleteRedirectionPaymentClientbyOrder?orderID=';
static String PRESCRIPTION_PAYMENT_WITH_ORDERID = 'https://mdlaboratories.com/exacartapi/checkout/OpcCompleteRedirectionPaymentClientbyOrder?orderID='; //Live
static List<String> successURLS = ['success?', 'PayFortResponse', 'PayFortSucess', 'mobilepaymentcomplete', 'orderdetails', 'redirectToApplePay', 'mdlaboratories.com/?'];
static List<String> errorURLS = ['PayfortCancel', 'errorpage', 'Failed', 'orderdetails', 'redirectToApplePay', 'mdlaboratories.com/?', 'cancel', 'canceled'];
final Function onExitCallback;
final Function? onLoadStartCallback;
final BuildContext? context;
// AppSharedPreferences sharedPref = AppSharedPreferences();
// AuthProvider authProvider = new AuthProvider();
InAppBrowser browser = InAppBrowser();
// AuthenticatedUser authUser;
// late AppoitmentAllHistoryResultList? appo;
String deviceToken = "";
double lat = 0.0;
double long = 0.0;
static bool isPaymentDone = false;
late AppState appState;
MyInAppBrowser({required this.onExitCallback, this.onLoadStartCallback, this.context});
Future onBrowserCreated() async {
print("\n\nBrowser Created!\n\n");
}
@override
Future onLoadStart(Uri? url) async {
if (onLoadStartCallback != null) onLoadStartCallback!(url.toString());
}
@override
Future onLoadStop(Uri? url) async {
print("\n\nStopped $url\n\n");
}
@override
void onLoadError(Uri? url, int code, String message) {
print("Can't load $url.. Error: $message");
}
@override
void onProgressChanged(int progress) {}
@override
void onExit() {
print("\n\nBrowser closed before!\n\n");
// if (onExitCallback != null) {
try {
onExitCallback(isPaymentDone);
print("\n\nBrowser closed after!\n\n");
} catch (err) {
print(err.toString());
}
// }
}
@override
Future<NavigationActionPolicy> shouldOverrideUrlLoading(NavigationAction navigationAction) {
var url = navigationAction.request.url.toString();
debugPrint("redirecting/overriding to: $url");
// if (paymentType == _PAYMENT_TYPE.PACKAGES && [PACKAGES_PAYMENT_SUCCESS_URL, PACKAGES_PAYMENT_FAIL_URL].contains(url)) {
// isPaymentDone = (url == PACKAGES_PAYMENT_SUCCESS_URL);
// close();
// }
return Future.value(NavigationActionPolicy.ALLOW);
}
// getLanguageID() async {
// return await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar');
// }
// getDeviceToken() async {
// String deviceToken = await sharedPref.getString(PUSH_TOKEN);
// this.deviceToken = deviceToken;
// }
// openPackagesPaymentBrowser({required int customer_id, required int order_id}) {
// paymentType = _PAYMENT_TYPE.PACKAGES;
// var full_url = '$PACKAGES_REQUEST_PAYMENT_URL?customer_id=$customer_id&order_id=$order_id';
// this.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(full_url))), options: _InAppBrowserOptions);
// }
openPaymentBrowser(num amount, String orderDesc, String transactionID, String projId, String emailId, String paymentMethod, dynamic patientType, String patientName, dynamic patientID,
AuthenticatedUser authenticatedUser, InAppBrowser browser, bool isLiveCareAppo, var servID, var LiveServID, BuildContext context,
[var appoDate, var appoNo, var clinicID, var doctorID, var installments]) async {
appState = getIt.get<AppState>();
this.browser = browser;
// await getPatientData();
if (paymentMethod == "ApplePay") {
MyChromeSafariBrowser safariBrowser = MyChromeSafariBrowser(MyInAppBrowser(onExitCallback: browser.onExit), onExitCallback: browser.onExit, onLoadStartCallback: this.browser.onLoadStart);
// if (context != null) GifLoaderDialogUtils.showMyDialog(context);
// LiveCareService service = new LiveCareService();
// ApplePayInsertRequest applePayInsertRequest = new ApplePayInsertRequest();
// applePayInsertRequest.clientRequestID = transactionID;
// applePayInsertRequest.clinicID = (clinicID != null && clinicID != "") ? clinicID : 0;
// applePayInsertRequest.currency = authenticatedUser.outSA == 1 ? "AED" : "SAR";
// applePayInsertRequest.customerEmail = emailId;
// applePayInsertRequest.customerID = patientID;
// applePayInsertRequest.customerName = patientName;
// applePayInsertRequest.deviceToken = await AppSharedPreferences().getString(PUSH_TOKEN);
// applePayInsertRequest.voipToken = await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN);
// applePayInsertRequest.doctorID = (doctorID != null && doctorID != "") ? doctorID : 0;
// applePayInsertRequest.projectID = projId;
// applePayInsertRequest.serviceID = servID;
// applePayInsertRequest.channelID = 3;
// applePayInsertRequest.patientID = patientID;
// applePayInsertRequest.patientTypeID = authenticatedUser.patientType;
// applePayInsertRequest.patientOutSA = authenticatedUser.outSA;
// applePayInsertRequest.appointmentDate = (appoDate != null && appoDate != "") ? appoDate : null;
// applePayInsertRequest.appointmentNo = (appoNo != null && appoNo != "") ? appoNo : 0;
// applePayInsertRequest.orderDescription = orderDesc;
// applePayInsertRequest.liveServiceID = LiveServID.toString() == "" ? "0" : LiveServID.toString();
// applePayInsertRequest.latitude = this.lat.toString();
// applePayInsertRequest.longitude = this.long.toString();
// applePayInsertRequest.amount = amount.toString();
// applePayInsertRequest.isSchedule = ((appoNo != null && appoNo != "") && (appoDate != null && appoDate != "")) ? "1" : "0";
// applePayInsertRequest.language = await getLanguageID() == 'ar' ? 'ar' : 'en';
// applePayInsertRequest.userName = authenticatedUser.patientID;
// applePayInsertRequest.responseContinueURL = "http://hmg.com/Documents/success.html";
// applePayInsertRequest.backClickUrl = "http://hmg.com/Documents/success.html";
// applePayInsertRequest.paymentOption = "ApplePay";
//
// service.applePayInsertRequest(applePayInsertRequest, context).then((res) {
// if (context != null) GifLoaderDialogUtils.hideDialog(context);
// String url = "https://hmgwebservices.com/HMGApplePayLive/applepay/pay?apq=" + res['result']; // Prod
// // String url = "https://uat.hmgwebservices.com/HMGApplePayLive/applepay/pay?apq=" + res['result']; // UAT
// // safariBrowser.open(url: Uri.parse(url));
// this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(url))), options: _InAppBrowserOptions);
// }).catchError((err) {
// print(err);
// if (context != null) GifLoaderDialogUtils.hideDialog(context);
// AppToast.showErrorToast(message: err);
// });
} else if (paymentMethod == "TAMARA") {
// LiveCareService service = new LiveCareService();
TamaraRequestModel tamaraRequestModel = new TamaraRequestModel();
// if (context != null) GifLoaderDialogUtils.showMyDialog(context);
tamaraRequestModel.merchantReference = transactionID;
tamaraRequestModel.merchantIdentifier = "Tamara";
tamaraRequestModel.clientRequestID = transactionID;
tamaraRequestModel.amount = amount;
tamaraRequestModel.currency = "SR";
tamaraRequestModel.language = appState.isArabic() ? 'AR' : 'EN';
tamaraRequestModel.commandType = "PURCHASE";
tamaraRequestModel.customerEmail = emailId;
tamaraRequestModel.orderDescription = orderDesc;
tamaraRequestModel.isInstallment = true;
tamaraRequestModel.projectID = num.parse(projId);
tamaraRequestModel.accessCode = authenticatedUser.mobileNumber!;
tamaraRequestModel.appointmentNo = (appoNo != null && appoNo != "") ? appoNo.toString() : "0";
tamaraRequestModel.customerName = patientName;
tamaraRequestModel.fileNumber = patientID.toString();
tamaraRequestModel.patientOutSA = authenticatedUser.outSA == 1 ? true : false;
tamaraRequestModel.deviceToken = await Utils.getStringFromPrefs(CacheConst.pushToken);
tamaraRequestModel.latitude = appState.userLat.toString();
tamaraRequestModel.longitude = appState.userLong.toString();
tamaraRequestModel.serviceID = servID;
tamaraRequestModel.liveServiceID = LiveServID;
tamaraRequestModel.doctorID = (doctorID.toString() != null && doctorID != "") ? doctorID.toString() : "";
tamaraRequestModel.appointmentDate = (appoDate != null && appoDate != "") ? appoDate : null;
tamaraRequestModel.isSchedule = ((appoNo != null && appoNo != "") && (appoDate != null && appoDate != "")) ? true : false;
// service.tamaraInsertRequest(tamaraRequestModel, context).then((res) {
// // if (context != null) GifLoaderDialogUtils.hideDialog(context);
// generateTamaraURL(amount, orderDesc, transactionID, projId, emailId, paymentMethod, patientType, patientName, patientID, authenticatedUser, isLiveCareAppo, servID, LiveServID, appoDate,
// appoNo, clinicID, doctorID, "", installments)
// .then((value) {
// paymentType = _PAYMENT_TYPE.PATIENT;
// this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(value))), options: _InAppBrowserOptions);
// });
// }).catchError((err) {
// print(err);
// // if (context != null) GifLoaderDialogUtils.hideDialog(context);
// // AppToast.showErrorToast(message: err);
// });
} else {
generateURL(amount, orderDesc, transactionID, projId, emailId, paymentMethod, patientType, patientName, patientID, authenticatedUser, isLiveCareAppo, servID, LiveServID, appoDate, appoNo,
clinicID, doctorID)
.then((value) {
paymentType = _PAYMENT_TYPE.PATIENT;
this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(value))), options: _InAppBrowserOptions);
});
}
}
// openPharmacyPaymentBrowser(OrderDetailModel order, double amount, String orderDesc, String transactionID, String emailId, String paymentMethod, String patientName, dynamic patientID,
// AuthenticatedUser authenticatedUser, InAppBrowser browser) {
// this.browser = browser;
// MyChromeSafariBrowser safariBrowser =
// new MyChromeSafariBrowser(new MyInAppBrowser(onExitCallback: browser.onExit), onExitCallback: browser.onExit, onLoadStartCallback: this.browser.onLoadStart, appo: this.appo!);
// // getPatientData();
// generatePharmacyURL(order, amount, orderDesc, transactionID, emailId, paymentMethod, patientName, patientID, authenticatedUser).then((value) {
// if (order.customValuesXml!.contains("ApplePay")) {
// safariBrowser.open(url: WebUri.uri(Uri.parse(value)));
// } else {
// this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(value))), options: _InAppBrowserOptions);
// }
// });
// }
openBrowser(String url) {
this.browser = browser;
this.browser.openUrlRequest(urlRequest: URLRequest(url: WebUri.uri(Uri.parse(url))), options: _InAppBrowserOptions);
}
Future<String> generateURL(num amount, String orderDesc, String transactionID, String projId, String emailId, String paymentMethod, dynamic patientType, String patientName, dynamic patientID,
AuthenticatedUser authUser, bool isLiveCareAppo, var servID, var LiveServID,
[var appoDate, var appoNo, var clinicID, var doctorID, var patientData]) async {
// getDeviceToken();
String currentLanguageID = appState.isArabic() ? 'AR' : 'EN';
String form = isLiveCareAppo ? getLiveCareForm() : getForm();
form = form.replaceFirst("EMAIL_VALUE", emailId);
form = form.replaceFirst('AMOUNT_VALUE', amount.toString());
form = form.replaceFirst('ORDER_DESCRIPTION_VALUE', orderDesc);
form = form.replaceFirst('ORDER_ID_VALUE', transactionID);
form = form.replaceFirst('REQUEST_ID_VALUE', transactionID);
form = form.replaceFirst('PROJECT_ID_VALUE', projId);
form = form.replaceFirst('PAYMENT_OPTION_VALUE', paymentMethod);
form = form.replaceFirst('LANG_VALUE', currentLanguageID);
form = form.replaceFirst('PATIENT_OUT_SA', authUser.outSA == 0 ? false.toString() : true.toString());
form = form.replaceFirst('PATIENT_TYPE_ID', patientData == null ? patientType.toString() : "1");
Platform.isIOS
? form = form.replaceFirst('DEVICE_TOKEN', "${await Utils.getStringFromPrefs(CacheConst.pushToken)},${await Utils.getStringFromPrefs(CacheConst.apnsToken)}")
: form = form.replaceFirst('DEVICE_TOKEN', await Utils.getStringFromPrefs(CacheConst.pushToken) ?? "");
// form = form.replaceFirst('DEVICE_TOKEN', await AppSharedPreferences().getString(PUSH_TOKEN) + "," + await AppSharedPreferences().getString(ONESIGNAL_APNS_TOKEN));
// form = form.replaceFirst('DEVICE_TOKEN', await sharedPref.getString(PUSH_TOKEN));
form = form.replaceFirst('LATITUDE_VALUE', this.lat.toString());
form = form.replaceFirst('LONGITUDE_VALUE', this.long.toString());
// if (servID == "4")
// form = form.replaceFirst('SERVICE_URL_VALUE', MyInAppBrowser.PREAUTH_SERVICE_URL);
// else
form = form.replaceFirst('SERVICE_URL_VALUE', ApiConsts.SERVICE_URL);
if (servID != null) {
form = form.replaceFirst('SERV_ID', servID);
form = form.replaceFirst('LIVE_SERVICE_ID', LiveServID.toString());
} else {
form = form.replaceFirst('SERV_ID', "2");
form = form.replaceFirst('LIVE_SERVICE_ID', "2");
}
form = form.replaceFirst('CUSTNAME_VALUE', patientName);
form = form.replaceFirst('CUSTID_VALUE', patientID.toString());
if (isLiveCareAppo) {
form = form.replaceFirst('IS_SCHEDULE_VALUE', "true");
form = form.replaceFirst('APPOINTMENT_DATE_VALUE', appoDate);
form = form.replaceFirst('APPOINTMENT_NO_VALUE', appoNo.toString());
form = form.replaceFirst('DOCTOR_ID_VALUE', doctorID.toString());
form = form.replaceFirst('CLINIC_ID_VALUE', clinicID.toString());
}
var bytes = utf8.encode(form);
var base64Str = base64.encode(bytes);
return 'data:text/html;base64,' + base64Str;
}
Future<String> generateTamaraURL(num amount, String orderDesc, String transactionID, String projId, String emailId, String paymentMethod, dynamic patientType, String patientName, dynamic patientID,
AuthenticatedUser authUser, bool isLiveCareAppo, var servID, var LiveServID,
[var appoDate, var appoNo, var clinicID, var doctorID, var patientData, var installments]) async {
// getDeviceToken();
String currentLanguageID = appState.isArabic() ? 'AR' : 'EN';
String form = getTamaraForm();
form = form.replaceFirst("EMAIL_VALUE", emailId);
form = form.replaceFirst('AMOUNT_VALUE', amount.toString());
form = form.replaceFirst('ORDER_DESCRIPTION_VALUE', orderDesc);
form = form.replaceFirst('ORDER_ID_VALUE', transactionID);
form = form.replaceFirst('REQUEST_ID_VALUE', transactionID);
form = form.replaceFirst('PROJECT_ID_VALUE', projId);
form = form.replaceFirst('PAYMENT_OPTION_VALUE', paymentMethod);
form = form.replaceFirst('LANG_VALUE', currentLanguageID);
form = form.replaceFirst('SERVICE_URL_VALUE', "https://mdlaboratories.com/tamaralive/Home/Checkout");
form = form.replaceFirst('INSTALLMENTS_VALUE', installments);
form = form.replaceFirst('CUSTNATIONALID_VALUE', authUser.patientIdentificationNo!);
form = form.replaceFirst('CUSTMOBILE_VALUE', authUser.mobileNumber!);
form = form.replaceFirst('CUSTDOB_VALUE', DateUtil.getDayMonthYearDateFormatted(authUser.dateofBirthDataTime!));
form = form.replaceFirst('CURRENCY_VALUE', authUser.outSA == 0 ? "SAR" : "AED");
form = form.replaceFirst('COUNTRY_CODE_VALUE', authUser.outSA == 0 ? "966" : "971");
form = form.replaceFirst('CUSTNAME_VALUE', patientName);
form = form.replaceFirst('CUSTLASTNAME_VALUE', patientName);
form = form.replaceFirst('CUSTID_VALUE', patientID.toString());
var bytes = utf8.encode(form);
var base64Str = base64.encode(bytes);
return 'data:text/html;base64,' + base64Str;
}
String getForm() {
return '<html> ' +
'<head></head>' +
'<body>' +
'<form id="paymentForm" action="SERVICE_URL_VALUE" method="post">' +
'<input type="hidden" name="Amount" value="AMOUNT_VALUE">' +
'<input type="hidden" name="ProjID" value="PROJECT_ID_VALUE">' +
'<input type="hidden" name="Order_Desc" value="ORDER_DESCRIPTION_VALUE">' +
'<input type="hidden" name="OrderID" value="ORDER_ID_VALUE">' +
'<input type="hidden" name="PaymentOption" value="PAYMENT_OPTION_VALUE">' +
'<input type="hidden" name="Email" value="EMAIL_VALUE">' +
'<input type="hidden" name="ServID" value="SERV_ID" >' +
'<input type="hidden" name="ChannelID" value="2" >' +
'<input type="hidden" name="Lang" value="LANG_VALUE" >' +
'<input type="hidden" name="ReturnURL" value="" >' +
'<input type="hidden" name="CustName" value="CUSTNAME_VALUE" >' +
'<input type="hidden" name="PatientOutSA" value="PATIENT_OUT_SA" >' +
'<input type="hidden" name="PatientTypeID" value="PATIENT_TYPE_ID" >' +
'<input type="hidden" name="DeviceToken" value="DEVICE_TOKEN" >' +
'<input type="hidden" name="Longitude" value="LONGITUDE_VALUE" >' +
'<input type="hidden" name="Latitude" value="LATITUDE_VALUE" >' +
'<input type="hidden" name="Live_ServiceID" value="LIVE_SERVICE_ID" >' +
'<input type="hidden" name="CustID" value="CUSTID_VALUE" >' +
'<input type="hidden" name="ResponseContinueURL" value="http://hmg.com/Documents/success.html" >' +
'<input type="hidden" name="BackClickUrl" value="http://hmg.com/Documents/success.html" >' +
'</form>' +
'<script type="text/javascript"> document.getElementById("paymentForm").submit(); </script>' +
'</body>' +
'</html>';
}
String getTamaraForm() {
return '<html> ' +
'<head></head>' +
'<body>' +
'<form id="paymentForm" action="SERVICE_URL_VALUE" method="post">' +
'<input type="hidden" name="totalAmount" value="AMOUNT_VALUE">' +
'<input type="hidden" name="shippingAmount" value="0">' +
'<input type="hidden" name="taxAmount" value="0">' +
'<input type="hidden" name="discountAmount" value="0">' +
'<input type="hidden" name="PaymentType" value="PAY_BY_INSTALMENTS">' +
'<input type="hidden" name="Instalments" value="INSTALLMENTS_VALUE">' +
'<input type="hidden" name="ProjID" value="PROJECT_ID_VALUE">' +
'<input type="hidden" name="description" value="ORDER_DESCRIPTION_VALUE">' +
'<input type="hidden" name="OrderID" value="ORDER_ID_VALUE">' +
'<input type="hidden" name="Currency" value="CURRENCY_VALUE">' +
'<input type="hidden" name="CountryCode" value="COUNTRY_CODE_VALUE">' +
'<input type="hidden" name="Consumer.Email" value="EMAIL_VALUE">' +
'<input type="hidden" name="Lang" value="LANG_VALUE" >' +
'<input type="hidden" name="ReturnURL" value="https://mdlaboratories.com">' +
'<input type="hidden" name="Consumer.NationalId" value="CUSTNATIONALID_VALUE" >' +
'<input type="hidden" name="Consumer.PhoneNumber" value="CUSTMOBILE_VALUE" >' +
'<input type="hidden" name="Consumer.FirstName" value="CUSTNAME_VALUE" >' +
'<input type="hidden" name="Consumer.LastName" value="CUSTLASTNAME_VALUE" >' +
'<input type="hidden" name="Consumer.DateOfBirth" value="CUSTDOB_VALUE" >' +
'<input type="hidden" name="Consumer.IsFirstOrder" value="false" >' +
'<input type="hidden" name="address.Line1" value="">' +
'<input type="hidden" name="address.Line2" value="">' +
'<input type="hidden" name="address.City" value="Riyadh">' +
'<input type="hidden" name="address.CountryCode" value="SA">' +
'<input type="hidden" name="address.PostalCode" value="12626">' +
'<input type="hidden" name="address.Region" value="">'
'</form>' +
'<script type="text/javascript"> document.getElementById("paymentForm").submit(); </script>' +
'</body>' +
'</html>';
}
String getLiveCareForm() {
return '<html> ' +
'<head></head>' +
'<body>' +
'<form id="paymentForm" action="SERVICE_URL_VALUE" method="post">' +
'<input type="hidden" name="Amount" value="AMOUNT_VALUE">' +
'<input type="hidden" name="ProjID" value="PROJECT_ID_VALUE">' +
'<input type="hidden" name="IsSchedule" value="IS_SCHEDULE_VALUE">' +
'<input type="hidden" name="AppointmentDate" value="APPOINTMENT_DATE_VALUE">' +
'<input type="hidden" name="AppointmentNo" value="APPOINTMENT_NO_VALUE">' +
'<input type="hidden" name="DoctorID" value="DOCTOR_ID_VALUE">' +
'<input type="hidden" name="ClinicID" value="CLINIC_ID_VALUE">' +
'<input type="hidden" name="Order_Desc" value="ORDER_DESCRIPTION_VALUE">' +
'<input type="hidden" name="OrderID" value="ORDER_ID_VALUE">' +
'<input type="hidden" name="PaymentOption" value="PAYMENT_OPTION_VALUE">' +
'<input type="hidden" name="Email" value="EMAIL_VALUE">' +
'<input type="hidden" name="ServID" value="SERV_ID" >' +
'<input type="hidden" name="ChannelID" value="2" >' +
'<input type="hidden" name="Lang" value="LANG_VALUE" >' +
'<input type="hidden" name="ReturnURL" value="" >' +
'<input type="hidden" name="CustName" value="CUSTNAME_VALUE" >' +
'<input type="hidden" name="PatientOutSA" value="PATIENT_OUT_SA" >' +
'<input type="hidden" name="PatientTypeID" value="PATIENT_TYPE_ID" >' +
'<input type="hidden" name="DeviceToken" value="DEVICE_TOKEN" >' +
'<input type="hidden" name="Longitude" value="LONGITUDE_VALUE" >' +
'<input type="hidden" name="Latitude" value="LATITUDE_VALUE" >' +
'<input type="hidden" name="Live_ServiceID" value="LIVE_SERVICE_ID" >' +
'<input type="hidden" name="CustID" value="CUSTID_VALUE" >' +
'<input type="hidden" name="ResponseContinueURL" value="http://hmg.com/Documents/success.html" >' +
'<input type="hidden" name="BackClickUrl" value="http://hmg.com/Documents/success.html" >' +
'</form>' +
'<script type="text/javascript"> document.getElementById("paymentForm").submit(); </script>' +
'</body>' +
'</html>';
}
safariCallBack() {
print("Safari CallBack!!!");
}
}
class MyChromeSafariBrowser extends ChromeSafariBrowser {
final Function? onExitCallback;
final Function? onLoadStartCallback;
// AppoitmentAllHistoryResultList? appo;
// MyChromeSafariBrowser(browserFallback, {this.onExitCallback, this.onLoadStartCallback, this.appo});
MyChromeSafariBrowser(browserFallback, {this.onExitCallback, this.onLoadStartCallback});
@override
void onOpened() {
print("ChromeSafari browser opened");
}
@override
void onCompletedInitialLoad(bool? didLoadSuccessfully) {
print("ChromeSafari browser initial load completed");
onLoadStartCallback!("ApplePay");
}
@override
void onClosed() {
print("ChromeSafari browser closed");
MyInAppBrowser.isPaymentDone = true;
onExitCallback!();
}
}

@ -71,6 +71,8 @@ dependencies:
flutter_staggered_animations: ^1.1.1
smooth_corner: ^1.1.1
maps_launcher: ^3.0.0+1
amazon_payfort: ^1.1.4
network_info_plus: ^6.1.4
dev_dependencies:
flutter_test:

Loading…
Cancel
Save