INFRA: Set Up Project.

This commit is contained in:
2025-11-28 11:10:49 +05:00
commit c798279f7d
609 changed files with 77436 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
import 'dart:async';
import 'package:customer/constant/constant.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:webview_flutter/webview_flutter.dart';
class MercadoPagoScreen extends StatefulWidget {
final String initialURl;
const MercadoPagoScreen({super.key, required this.initialURl});
@override
State<MercadoPagoScreen> createState() => _MercadoPagoScreenState();
}
class _MercadoPagoScreenState extends State<MercadoPagoScreen> {
WebViewController controller = WebViewController();
@override
void initState() {
initController();
super.initState();
}
void initController() {
controller =
WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {},
onPageStarted: (String url) {},
onWebResourceError: (WebResourceError error) {},
onNavigationRequest: (NavigationRequest navigation) async {
debugPrint("--->2 ${navigation.url}");
if (navigation.url.contains("${Constant.globalUrl}payment/success")) {
Get.back(result: true);
}
if (navigation.url.contains("${Constant.globalUrl}payment/failure") || navigation.url.contains("${Constant.globalUrl}payment/pending")) {
Get.back(result: false);
}
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse(widget.initialURl));
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
_showMyDialog();
return false;
},
child: Scaffold(
appBar: AppBar(
title: Text("Payment".tr),
centerTitle: false,
leading: GestureDetector(
onTap: () {
_showMyDialog();
},
child: const Icon(Icons.arrow_back),
),
),
body: WebViewWidget(controller: controller),
),
);
}
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text('Cancel Payment'.tr),
content: SingleChildScrollView(child: Text("Cancel Payment?".tr)),
actions: <Widget>[
TextButton(
child: Text('Cancel'.tr, style: const TextStyle(color: Colors.red)),
onPressed: () {
Navigator.of(context).pop();
Get.back(result: false);
},
),
TextButton(
child: Text('Continue'.tr, style: const TextStyle(color: Colors.green)),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}

View File

@@ -0,0 +1,107 @@
// ignore_for_file: file_names
import 'dart:developer';
import 'package:customer/models/payment_model/pay_fast_model.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:webview_flutter/webview_flutter.dart';
class PayFastScreen extends StatefulWidget {
final String htmlData;
final PayFastModel payFastSettingData;
const PayFastScreen({super.key, required this.htmlData, required this.payFastSettingData});
@override
State<PayFastScreen> createState() => _PayFastScreenState();
}
class _PayFastScreenState extends State<PayFastScreen> {
WebViewController controller = WebViewController();
@override
void initState() {
initController();
super.initState();
}
void initController() {
controller =
WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
// Update loading bar.
},
onWebResourceError: (WebResourceError error) {},
onNavigationRequest: (NavigationRequest navigation) async {
if (kDebugMode) {
log("--->2 $navigation");
}
if (navigation.url == widget.payFastSettingData.returnUrl) {
Get.back(result: true);
} else if (navigation.url == widget.payFastSettingData.notifyUrl) {
Get.back(result: false);
} else if (navigation.url == widget.payFastSettingData.cancelUrl) {
_showMyDialog();
}
return NavigationDecision.navigate;
},
),
)
..loadHtmlString((widget.htmlData));
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
_showMyDialog();
return false;
},
child: Scaffold(
appBar: AppBar(
leading: GestureDetector(
onTap: () {
_showMyDialog();
},
child: const Icon(Icons.arrow_back),
),
),
body: WebViewWidget(controller: controller),
),
);
}
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Cancel Payment'),
content: SingleChildScrollView(child: Text("Cancel Payment?".tr)),
actions: <Widget>[
TextButton(
child: Text('Exit'.tr, style: TextStyle(color: Colors.red)),
onPressed: () {
Get.back();
Get.back(result: false);
},
),
TextButton(
child: Text('Continue Payment'.tr, style: TextStyle(color: Colors.green)),
onPressed: () {
Get.back();
},
),
],
);
},
);
}
}

View File

@@ -0,0 +1,85 @@
// To parse this JSON data, do
//
// final razorPayFailedModel = razorPayFailedModelFromJson(jsonString);
import 'dart:convert';
RazorPayFailedModel razorPayFailedModelFromJson(String str) => RazorPayFailedModel.fromJson(json.decode(str));
String razorPayFailedModelToJson(RazorPayFailedModel data) => json.encode(data.toJson());
class RazorPayFailedModel {
RazorPayFailedModel({
required this.error,
required this.httpStatusCode,
});
Error error;
int httpStatusCode;
factory RazorPayFailedModel.fromJson(Map<String, dynamic>? json) => RazorPayFailedModel(
error: Error.fromJson(json!["error"]),
httpStatusCode: json["http_status_code"],
);
Map<String, dynamic> toJson() => {
"error": error.toJson(),
"http_status_code": httpStatusCode,
};
}
class Error {
Error({
required this.code,
required this.description,
required this.source,
required this.step,
required this.reason,
required this.metadata,
});
String code;
String description;
String source;
String step;
String reason;
Metadata metadata;
factory Error.fromJson(Map<String, dynamic> json) => Error(
code: json["code"] ?? '',
description: json["description"] ?? "",
source: json["source"] ?? "",
step: json["step"] ?? "",
reason: json["reason"] ?? "",
metadata: Metadata.fromJson(json["metadata"]),
);
Map<String, dynamic> toJson() => {
"code": code,
"description": description,
"source": source,
"step": step,
"reason": reason,
"metadata": metadata.toJson(),
};
}
class Metadata {
Metadata({
required this.paymentId,
required this.orderId,
});
String paymentId;
String orderId;
factory Metadata.fromJson(Map<String, dynamic> json) => Metadata(
paymentId: json["payment_id"] ?? "",
orderId: json["order_id"] ?? "",
);
Map<String, dynamic> toJson() => {
"payment_id": paymentId,
"order_id": orderId,
};
}

View File

@@ -0,0 +1,77 @@
// To parse this JSON data, do
//
// final createRazorPayOrderModel = createRazorPayOrderModelFromJson(jsonString);
import 'dart:convert';
CreateRazorPayOrderModel createRazorPayOrderModelFromJson(String str) => CreateRazorPayOrderModel.fromJson(json.decode(str));
String createRazorPayOrderModelToJson(CreateRazorPayOrderModel data) => json.encode(data.toJson());
class CreateRazorPayOrderModel {
CreateRazorPayOrderModel({
required this.id,
required this.entity,
required this.amount,
required this.amountPaid,
required this.amountDue,
required this.currency,
required this.receipt,
required this.offerId,
required this.status,
required this.attempts,
required this.notes,
required this.createdAt,
});
String id;
String entity;
int amount;
int amountPaid;
int amountDue;
String currency;
String receipt;
dynamic offerId;
String status;
int attempts;
Notes notes;
int createdAt;
factory CreateRazorPayOrderModel.fromJson(Map<String, dynamic> json) => CreateRazorPayOrderModel(
id: json["id"],
entity: json["entity"],
amount: json["amount"],
amountPaid: json["amount_paid"],
amountDue: json["amount_due"],
currency: json["currency"],
receipt: json["receipt"] ?? "",
offerId: json["offer_id"],
status: json["status"],
attempts: json["attempts"],
notes: Notes.fromJson(json["notes"]),
createdAt: json["created_at"],
);
Map<String, dynamic> toJson() => {
"id": id,
"entity": entity,
"amount": amount,
"amount_paid": amountPaid,
"amount_due": amountDue,
"currency": currency,
"receipt": receipt,
"offer_id": offerId,
"status": status,
"attempts": attempts,
"notes": notes.toJson(),
"created_at": createdAt,
};
}
class Notes {
Notes();
factory Notes.fromJson(Map<String, dynamic> json) => Notes();
Map<String, dynamic> toJson() => {};
}

View File

@@ -0,0 +1,203 @@
// To parse this JSON data, do
//
// final getPaymentTxtTokenModel = getPaymentTxtTokenModelFromJson(jsonString);
import 'dart:convert';
GetPaymentTxtTokenModel getPaymentTxtTokenModelFromJson(String str) => GetPaymentTxtTokenModel.fromJson(json.decode(str));
String getPaymentTxtTokenModelToJson(GetPaymentTxtTokenModel data) => json.encode(data.toJson());
class GetPaymentTxtTokenModel {
GetPaymentTxtTokenModel({
required this.head,
required this.body,
});
Head head;
Body body;
factory GetPaymentTxtTokenModel.fromJson(Map<String, dynamic> json) =>
GetPaymentTxtTokenModel(
head: Head.fromJson(json["head"] ?? {}),
body: Body.fromJson(json["body"] ?? {}),
);
Map<String, dynamic> toJson() => {
"head": head.toJson(),
"body": body.toJson(),
};
}
class Body {
Body({
required this.resultInfo,
this.txnToken,
this.isPromoCodeValid,
this.authenticated,
});
ResultInfo resultInfo;
String? txnToken;
bool? isPromoCodeValid;
bool? authenticated;
factory Body.fromJson(Map<String, dynamic> json) => Body(
resultInfo: ResultInfo.fromJson(json["resultInfo"] ?? {}),
txnToken: json["txnToken"],
isPromoCodeValid: json["isPromoCodeValid"],
authenticated: json["authenticated"],
);
Map<String, dynamic> toJson() => {
"resultInfo": resultInfo.toJson(),
"txnToken": txnToken,
"isPromoCodeValid": isPromoCodeValid,
"authenticated": authenticated,
};
}
class ResultInfo {
ResultInfo({
this.resultStatus,
this.resultCode,
this.resultMsg,
});
String? resultStatus;
String? resultCode;
String? resultMsg;
factory ResultInfo.fromJson(Map<String, dynamic> json) => ResultInfo(
resultStatus: json["resultStatus"],
resultCode: json["resultCode"],
resultMsg: json["resultMsg"],
);
Map<String, dynamic> toJson() => {
"resultStatus": resultStatus,
"resultCode": resultCode,
"resultMsg": resultMsg,
};
}
class Head {
Head({
this.responseTimestamp,
this.version,
this.signature,
});
String? responseTimestamp;
String? version;
String? signature;
factory Head.fromJson(Map<String, dynamic> json) => Head(
responseTimestamp: json["responseTimestamp"],
version: json["version"],
signature: json["signature"],
);
Map<String, dynamic> toJson() => {
"responseTimestamp": responseTimestamp,
"version": version,
"signature": signature,
};
}
// class GetPaymentTxtTokenModel {
// GetPaymentTxtTokenModel({
// required this.head,
// required this.body,
// });
//
// Head head;
// Body body;
//
// factory GetPaymentTxtTokenModel.fromJson(Map<String, dynamic> json) => GetPaymentTxtTokenModel(
// head: Head.fromJson(json["head"]),
// body: Body.fromJson(json["body"]),
// );
//
// Map<String, dynamic> toJson() => {
// "head": head.toJson(),
// "body": body.toJson(),
// };
// }
//
// class Body {
// Body({
// required this.resultInfo,
// required this.txnToken,
// required this.isPromoCodeValid,
// required this.authenticated,
// });
//
// ResultInfo resultInfo;
// String txnToken;
// bool isPromoCodeValid;
// bool authenticated;
//
// factory Body.fromJson(Map<String, dynamic> json) => Body(
// resultInfo: ResultInfo.fromJson(json["resultInfo"]),
// txnToken: json["txnToken"],
// isPromoCodeValid: json["isPromoCodeValid"],
// authenticated: json["authenticated"],
// );
//
// Map<String, dynamic> toJson() => {
// "resultInfo": resultInfo.toJson(),
// "txnToken": txnToken,
// "isPromoCodeValid": isPromoCodeValid,
// "authenticated": authenticated,
// };
// }
//
// class ResultInfo {
// ResultInfo({
// required this.resultStatus,
// required this.resultCode,
// required this.resultMsg,
// });
//
// String resultStatus;
// String resultCode;
// String resultMsg;
//
// factory ResultInfo.fromJson(Map<String, dynamic> json) => ResultInfo(
// resultStatus: json["resultStatus"],
// resultCode: json["resultCode"],
// resultMsg: json["resultMsg"],
// );
//
// Map<String, dynamic> toJson() => {
// "resultStatus": resultStatus,
// "resultCode": resultCode,
// "resultMsg": resultMsg,
// };
// }
//
// class Head {
// Head({
// required this.responseTimestamp,
// required this.version,
// required this.signature,
// });
//
// String responseTimestamp;
// String version;
// String signature;
//
// factory Head.fromJson(Map<String, dynamic> json) => Head(
// responseTimestamp: json["responseTimestamp"],
// version: json["version"],
// signature: json["signature"],
// );
//
// Map<String, dynamic> toJson() => {
// "responseTimestamp": responseTimestamp,
// "version": version,
// "signature": signature,
// };
// }

View File

@@ -0,0 +1,115 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:webview_flutter/webview_flutter.dart';
class MidtransScreen extends StatefulWidget {
final String initialURl;
const MidtransScreen({super.key, required this.initialURl});
@override
State<MidtransScreen> createState() => _MidtransScreenState();
}
class _MidtransScreenState extends State<MidtransScreen> {
WebViewController controller = WebViewController();
bool isLoading = true;
@override
void initState() {
controller.clearCache();
initController();
super.initState();
}
void initController() {
controller =
WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: ((url) {
setState(() {
isLoading = false;
});
}),
onNavigationRequest: (NavigationRequest navigation) async {
log("Midtrans :: ${navigation.url}");
if (Platform.isIOS) {
if (navigation.url.contains('/success')) {
Get.back(result: true);
} else if (navigation.url.contains('/failed')) {
Get.back(result: false);
}
} else {
String? orderId = Uri.parse(navigation.url).queryParameters['merchant_order_id'];
if (orderId != null) {
Get.back(result: true);
} else {
Get.back(result: false);
}
}
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse(widget.initialURl));
}
@override
Widget build(BuildContext context) {
// ignore: deprecated_member_use
return WillPopScope(
onWillPop: () async {
_showMyDialog();
return false;
},
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
centerTitle: false,
leading: GestureDetector(
onTap: () {
_showMyDialog();
},
child: const Icon(Icons.arrow_back, color: Colors.white),
),
),
body: Stack(alignment: Alignment.center, children: [WebViewWidget(controller: controller), Visibility(visible: isLoading, child: const Center(child: CircularProgressIndicator()))]),
),
);
}
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text('Cancel Payment'.tr),
content: SingleChildScrollView(child: Text("Cancel Payment?".tr)),
actions: <Widget>[
TextButton(
child: Text('Cancel'.tr, style: const TextStyle(color: Colors.red)),
onPressed: () {
Get.back(result: false);
Get.back(result: false);
},
),
TextButton(
child: Text('Continue'.tr, style: const TextStyle(color: Colors.green)),
onPressed: () {
Get.back(result: false);
},
),
],
);
},
);
}
}

View File

@@ -0,0 +1,339 @@
// ignore_for_file: must_be_immutable
import 'dart:async';
import 'dart:convert';
import 'package:customer/models/payment_model/orange_money.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:webview_flutter/webview_flutter.dart';
class OrangeMoneyScreen extends StatefulWidget {
String initialURl;
OrangeMoney orangePay;
String accessToken = '';
String payToken = '';
String orderId = '';
String amount = '';
OrangeMoneyScreen({super.key, required this.initialURl, required this.orangePay, required this.accessToken, required this.payToken, required this.orderId, required this.amount});
@override
State<OrangeMoneyScreen> createState() => _OrangeMoneyScreenState();
}
class _OrangeMoneyScreenState extends State<OrangeMoneyScreen> {
WebViewController controller = WebViewController();
bool isLoading = true;
Timer? timer;
@override
void initState() {
controller.clearCache();
initController();
startTransactionPolling();
super.initState();
}
// 🔹 Poll Orange API every 3 seconds to check status
void startTransactionPolling() {
timer = Timer.periodic(const Duration(seconds: 3), (Timer t) async {
if (!mounted) return;
String status = await transactionStatus(accessToken: widget.accessToken, amount: widget.amount, orderId: widget.orderId, payToken: widget.payToken);
if (status == 'SUCCESS') {
timer?.cancel();
debugPrint('✅ Payment successful for Order ID: ${widget.orderId}');
Get.back(result: true);
} else if (status == 'FAILED' || status == 'CANCELLED') {
timer?.cancel();
debugPrint('❌ Payment failed or cancelled.');
Get.back(result: false);
}
});
}
void initController() {
controller =
WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: (url) {
setState(() {
isLoading = false;
});
},
),
)
..loadRequest(Uri.parse(widget.initialURl));
}
Future<String> transactionStatus({required String orderId, required String amount, required String payToken, required String accessToken}) async {
String apiUrl = widget.orangePay.isSandbox == true ? 'https://api.orange.com/orange-money-webpay/dev/v1/transactionstatus' : 'https://api.orange.com/orange-money-webpay/cm/v1/transactionstatus';
Map<String, String> requestBody = {"order_id": orderId, "amount": amount, "pay_token": payToken};
try {
var response = await http.post(
Uri.parse(apiUrl),
headers: {'Authorization': 'Bearer $accessToken', 'Content-Type': 'application/json', 'Accept': 'application/json'},
body: json.encode(requestBody),
);
if (response.statusCode == 201) {
Map<String, dynamic> responseData = jsonDecode(response.body);
debugPrint('🔍 Transaction Status: ${responseData['status']}');
return responseData['status'];
} else {
return '';
}
} catch (e) {
debugPrint('⚠️ Transaction check error: $e');
return '';
}
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
_showCancelDialog();
return false;
},
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
leading: IconButton(icon: const Icon(Icons.arrow_back, color: Colors.white), onPressed: _showCancelDialog),
title: Text('Orange Money Payment'.tr),
),
body: isLoading ? const Center(child: CircularProgressIndicator()) : WebViewWidget(controller: controller),
),
);
}
Future<void> _showCancelDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Cancel Payment'.tr),
content: Text('Are you sure you want to cancel this payment?'.tr),
actions: [
TextButton(child: Text('No', style: TextStyle(color: Colors.green)), onPressed: () => Get.back()),
TextButton(
child: Text('Yes'.tr, style: TextStyle(color: Colors.red)),
onPressed: () {
timer?.cancel();
Get.back(); // close dialog
Get.back(result: false); // close WebView and mark as failed
},
),
],
);
},
);
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
}
// // ignore_for_file: must_be_immutable
//
// import 'dart:async';
// import 'dart:convert';
// import 'package:customer/models/payment_model/orange_money.dart';
// import 'package:flutter/material.dart';
// import 'package:get/get.dart';
// import 'package:http/http.dart' as http;
// import 'package:webview_flutter/webview_flutter.dart';
//
// class OrangeMoneyScreen extends StatefulWidget {
// String initialURl;
// OrangeMoney orangePay;
// String accessToken = '';
// String payToken = '';
// String orderId = '';
// String amount = '';
//
// OrangeMoneyScreen({
// super.key,
// required this.initialURl,
// required this.orangePay,
// required this.accessToken,
// required this.payToken,
// required this.orderId,
// required this.amount,
// });
//
// @override
// State<OrangeMoneyScreen> createState() => _OrangeMoneyScreenState();
// }
//
// class _OrangeMoneyScreenState extends State<OrangeMoneyScreen> {
// WebViewController controller = WebViewController();
// bool isLoading = true;
//
// @override
// void initState() {
// controller.clearCache();
// initController();
// callTransaction();
// super.initState();
// }
//
// Timer? timer;
//
// void callTransaction() {
// timer = Timer.periodic(const Duration(seconds: 3), (Timer t) {
// if (mounted) {
// transactionstatus(accessToken: widget.accessToken, amount: widget.amount, orderId: widget.orderId, payToken: widget.payToken).then((value) {
// if (value == 'SUCCESS') {
// if (timer != null) {
// timer!.cancel();
// }
// Get.back(result: true);
// } else if (value == 'FAILED') {
// if (timer != null) {
// timer!.cancel();
// }
// Get.back(result: false);
// }
// });
// }
// });
// }
//
// void initController() {
// controller = WebViewController()
// ..setJavaScriptMode(JavaScriptMode.unrestricted)
// ..setBackgroundColor(const Color(0x00000000))
// ..setNavigationDelegate(
// NavigationDelegate(
// onPageFinished: ((url) {
// setState(() {
// isLoading = false;
// });
// }),
// onNavigationRequest: (NavigationRequest navigation) async {
// return NavigationDecision.navigate;
// },
// ),
// )
// ..loadRequest(Uri.parse(widget.initialURl));
// }
//
// Future transactionstatus({
// required String orderId,
// required String amount,
// required String payToken,
// required String accessToken,
// }) async {
// String apiUrl = widget.orangePay.isSandbox == true
// ? 'https://api.orange.com/orange-money-webpay/dev/v1/transactionstatus'
// : 'https://api.orange.com/orange-money-webpay/cm/v1/transactionstatus';
// Map<String, String> requestBody = {
// "order_id": orderId,
// "amount": amount, // "OUV",
// "pay_token": payToken
// };
//
// var response = await http.post(Uri.parse(apiUrl),
// headers: <String, String>{
// 'Authorization': 'Bearer $accessToken',
// 'Content-Type': 'application/json',
// 'Accept': 'application/json',
// },
// body: json.encode(requestBody));
//
// // Handle the response
// if (response.statusCode == 201) {
// Map<String, dynamic> responseData = jsonDecode(response.body);
// return responseData['status'];
// } else {
// return '';
// }
// }
//
// @override
// Widget build(BuildContext context) {
// // ignore: deprecated_member_use
// return WillPopScope(
// onWillPop: () async {
// _showMyDialog();
// return false;
// },
// child: Scaffold(
// appBar: AppBar(
// backgroundColor: Colors.black,
// centerTitle: false,
// leading: GestureDetector(
// onTap: () {
// _showMyDialog();
// },
// child: const Icon(
// Icons.arrow_back,
// color: Colors.white,
// ),
// )),
// body: isLoading
// ? const Center(
// child: CircularProgressIndicator(),
// )
// : WebViewWidget(controller: controller),
// ),
// );
// }
//
// Future<void> _showMyDialog() async {
// return showDialog<void>(
// context: context,
// barrierDismissible: true, // user must tap button!
// builder: (BuildContext context) {
// return AlertDialog(
// title: Text('Cancel Payment'.tr),
// content: SingleChildScrollView(
// child: Text("cancelPayment?".tr),
// ),
// actions: <Widget>[
// TextButton(
// child: Text(
// 'Cancel'.tr,
// style: const TextStyle(color: Colors.red),
// ),
// onPressed: () {
// Get.back(result: false);
// Get.back(result: false);
// },
// ),
// TextButton(
// child: Text(
// 'Continue'.tr,
// style: const TextStyle(color: Colors.green),
// ),
// onPressed: () {
// Get.back(result: false);
// },
// ),
// ],
// );
// },
// );
// }
//
// @override
// void dispose() {
// if (timer != null) {
// timer!.cancel();
// }
// // TODO: implement dispose
// super.dispose();
// }
// }

View File

@@ -0,0 +1,125 @@
import 'dart:async';
import 'package:customer/payment/paystack/paystack_url_genrater.dart';
import 'package:customer/themes/app_them_data.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:webview_flutter/webview_flutter.dart';
class PayStackScreen extends StatefulWidget {
final String initialURl;
final String reference;
final String amount;
final String secretKey;
final String callBackUrl;
const PayStackScreen({super.key, required this.initialURl, required this.reference, required this.amount, required this.secretKey, required this.callBackUrl});
@override
State<PayStackScreen> createState() => _PayStackScreenState();
}
class _PayStackScreenState extends State<PayStackScreen> {
WebViewController controller = WebViewController();
@override
void initState() {
initController();
super.initState();
}
void initController() {
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
// Update loading bar.
},
onPageStarted: (String url) {},
onPageFinished: (String url) {},
onWebResourceError: (WebResourceError error) {},
onNavigationRequest: (NavigationRequest navigation) async {
debugPrint("--->2${navigation.url}");
debugPrint("--->2" "${widget.callBackUrl}?trxref=${widget.reference}&reference=${widget.reference}");
if (navigation.url == 'https://foodieweb.siswebapp.com/success?trxref=${widget.reference}&reference=${widget.reference}' ||
navigation.url == '${widget.callBackUrl}?trxref=${widget.reference}&reference=${widget.reference}') {
final isDone = await PayStackURLGen.verifyTransaction(secretKey: widget.secretKey, reference: widget.reference, amount: widget.amount);
Get.back(result: isDone);
}
if ((navigation.url == '${widget.callBackUrl}?trxref=${widget.reference}&reference=${widget.reference}') ||
(navigation.url == "https://hello.pstk.xyz/callback") ||
(navigation.url == 'https://standard.paystack.co/close') ||
(navigation.url == 'https://talazo.app/login')) {
final isDone = await PayStackURLGen.verifyTransaction(secretKey: widget.secretKey, reference: widget.reference, amount: widget.amount);
Get.back(result: isDone);
}
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse(widget.initialURl));
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
_showMyDialog();
return false;
},
child: Scaffold(
appBar: AppBar(
backgroundColor: AppThemeData.grey50,
title: Text("Payment".tr),
centerTitle: false,
leading: GestureDetector(
onTap: () {
_showMyDialog();
},
child: const Icon(
Icons.arrow_back,
),
)),
body: WebViewWidget(controller: controller),
),
);
}
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Cancel Payment'),
content: const SingleChildScrollView(
child: Text("cancelPayment?"),
),
actions: <Widget>[
TextButton(
child: const Text(
'Cancel',
style: TextStyle(color: Colors.red),
),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop(false);
},
),
TextButton(
child: const Text(
'Continue',
style: TextStyle(color: Colors.green),
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}

View File

@@ -0,0 +1,57 @@
// To parse this JSON data, do
//
// final payStackUrlModel = payStackUrlModelFromJson(jsonString);
import 'dart:convert';
PayStackUrlModel payStackUrlModelFromJson(String str) => PayStackUrlModel.fromJson(json.decode(str));
String payStackUrlModelToJson(PayStackUrlModel data) => json.encode(data.toJson());
class PayStackUrlModel {
PayStackUrlModel({
required this.status,
required this.message,
required this.data,
});
bool status;
String message;
Data data;
factory PayStackUrlModel.fromJson(Map<String, dynamic> json) => PayStackUrlModel(
status: json["status"],
message: json["message"],
data: Data.fromJson(json["data"]),
);
Map<String, dynamic> toJson() => {
"status": status,
"message": message,
"data": data.toJson(),
};
}
class Data {
Data({
required this.authorizationUrl,
required this.accessCode,
required this.reference,
});
String authorizationUrl;
String accessCode;
String reference;
factory Data.fromJson(Map<String, dynamic> json) => Data(
authorizationUrl: json["authorization_url"],
accessCode: json["access_code"],
reference: json["reference"],
);
Map<String, dynamic> toJson() => {
"authorization_url": authorizationUrl,
"access_code": accessCode,
"reference": reference,
};
}

View File

@@ -0,0 +1,75 @@
import 'dart:convert';
import 'package:customer/models/payment_model/pay_fast_model.dart';
import 'package:customer/models/user_model.dart';
import 'package:customer/payment/paystack/pay_stack_url_model.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
class PayStackURLGen {
static Future payStackURLGen({required String amount, required String secretKey, required String currency, required UserModel userModel}) async {
const url = "https://api.paystack.co/transaction/initialize";
final response = await http.post(Uri.parse(url), body: {
"email": userModel.email,
"amount": amount,
"currency": currency,
}, headers: {
"Authorization": "Bearer $secretKey",
});
debugPrint(response.body);
final data = jsonDecode(response.body);
if (!data["status"]) {
return null;
}
return PayStackUrlModel.fromJson(data);
}
static Future<bool> verifyTransaction({
required String reference,
required String secretKey,
required String amount,
}) async {
debugPrint("we Enter payment Settle");
debugPrint(reference);
final url = "https://api.paystack.co/transaction/verify/$reference";
var response = await http.get(Uri.parse(url), headers: {
"Authorization": "Bearer $secretKey",
});
debugPrint(response.body);
final data = jsonDecode(response.body);
if (data["status"] == true) {
if (data["message"] == "Verification successful") {}
}
return data["status"];
//PayPalClientSettleModel.fromJson(data);
}
static Future<String> getPayHTML({required String amount, required PayFastModel payFastSettingData, required UserModel userModel}) async {
String newUrl = 'https://${payFastSettingData.isSandbox == false ? "www" : "sandbox"}.payfast.co.za/eng/process';
Map body = {
'merchant_id': payFastSettingData.merchantId,
'merchant_key': payFastSettingData.merchantKey,
'amount': amount,
'item_name': "goRide online payment",
'return_url': payFastSettingData.returnUrl,
'cancel_url': payFastSettingData.cancelUrl,
'notify_url': payFastSettingData.notifyUrl,
'name_first': userModel.firstName,
'name_last': userModel.lastName,
'email_address': userModel.email,
};
final response = await http.post(
Uri.parse(newUrl),
body: body,
);
debugPrint(response.body);
return response.body;
}
}

View File

@@ -0,0 +1,38 @@
import 'dart:convert';
import 'package:customer/models/payment_model/razorpay_model.dart';
import 'package:customer/payment/createRazorPayOrderModel.dart';
import 'package:http/http.dart' as http;
import '../constant/constant.dart';
class RazorPayController {
Future<CreateRazorPayOrderModel?> createOrderRazorPay({required double amount, required RazorPayModel? razorpayModel}) async {
final String orderId = DateTime.now().millisecondsSinceEpoch.toString();
RazorPayModel razorPayData = razorpayModel!;
print(razorPayData.razorpayKey);
print("we Enter In");
const url = "${Constant.globalUrl}payments/razorpay/createorder";
print(orderId);
final response = await http.post(
Uri.parse(url),
body: {
"amount": (amount.round() * 100).toString(),
"receipt_id": orderId,
"currency": "INR",
"razorpaykey": razorPayData.razorpayKey,
"razorPaySecret": razorPayData.razorpaySecret,
"isSandBoxEnabled": razorPayData.isSandboxEnabled.toString(),
},
);
if (response.statusCode == 500) {
return null;
} else {
final data = jsonDecode(response.body);
print(data);
return CreateRazorPayOrderModel.fromJson(data);
}
}
}

View File

@@ -0,0 +1,61 @@
// To parse this JSON data, do
//
// final stripePayFailedModel = stripePayFailedModelFromJson(jsonString);
import 'dart:convert';
StripePayFailedModel stripePayFailedModelFromJson(String str) => StripePayFailedModel.fromJson(json.decode(str));
String stripePayFailedModelToJson(StripePayFailedModel data) => json.encode(data.toJson());
class StripePayFailedModel {
StripePayFailedModel({
required this.error,
});
Error error;
factory StripePayFailedModel.fromJson(Map<String, dynamic> json) => StripePayFailedModel(
error: Error.fromJson(json["error"]),
);
Map<String, dynamic> toJson() => {
"error": error.toJson(),
};
}
class Error {
Error({
required this.code,
required this.localizedMessage,
required this.message,
required this.stripeErrorCode,
required this.declineCode,
required this.type,
});
String code;
String localizedMessage;
String message;
dynamic stripeErrorCode;
dynamic declineCode;
dynamic type;
factory Error.fromJson(Map<String, dynamic> json) => Error(
code: json["code"],
localizedMessage: json["localizedMessage"],
message: json["message"],
stripeErrorCode: json["stripeErrorCode"],
declineCode: json["declineCode"],
type: json["type"],
);
Map<String, dynamic> toJson() => {
"code": code,
"localizedMessage": localizedMessage,
"message": message,
"stripeErrorCode": stripeErrorCode,
"declineCode": declineCode,
"type": type,
};
}

View File

@@ -0,0 +1,257 @@
class XenditModel {
String? id;
String? externalId;
String? userId;
String? status;
String? merchantName;
String? merchantProfilePictureUrl;
int? amount;
String? payerEmail;
String? description;
String? expiryDate;
String? invoiceUrl;
List<AvailableBanks>? availableBanks;
List<AvailableRetailOutlets>? availableRetailOutlets;
List<AvailableEwallets>? availableEwallets;
List<AvailableQrCodes>? availableQrCodes;
List<AvailableDirectDebits>? availableDirectDebits;
List<AvailablePaylaters>? availablePaylaters;
bool? shouldExcludeCreditCard;
bool? shouldSendEmail;
String? created;
String? updated;
String? currency;
Null metadata;
XenditModel(
{this.id,
this.externalId,
this.userId,
this.status,
this.merchantName,
this.merchantProfilePictureUrl,
this.amount,
this.payerEmail,
this.description,
this.expiryDate,
this.invoiceUrl,
this.availableBanks,
this.availableRetailOutlets,
this.availableEwallets,
this.availableQrCodes,
this.availableDirectDebits,
this.availablePaylaters,
this.shouldExcludeCreditCard,
this.shouldSendEmail,
this.created,
this.updated,
this.currency,
this.metadata});
XenditModel.fromJson(Map<String, dynamic> json) {
id = json['id'];
externalId = json['external_id'];
userId = json['user_id'];
status = json['status'];
merchantName = json['merchant_name'];
merchantProfilePictureUrl = json['merchant_profile_picture_url'];
amount = json['amount'];
payerEmail = json['payer_email'];
description = json['description'];
expiryDate = json['expiry_date'];
invoiceUrl = json['invoice_url'];
if (json['available_banks'] != null) {
availableBanks = <AvailableBanks>[];
json['available_banks'].forEach((v) {
availableBanks!.add(AvailableBanks.fromJson(v));
});
}
if (json['available_retail_outlets'] != null) {
availableRetailOutlets = <AvailableRetailOutlets>[];
json['available_retail_outlets'].forEach((v) {
availableRetailOutlets!.add(AvailableRetailOutlets.fromJson(v));
});
}
if (json['available_ewallets'] != null) {
availableEwallets = <AvailableEwallets>[];
json['available_ewallets'].forEach((v) {
availableEwallets!.add(AvailableEwallets.fromJson(v));
});
}
if (json['available_qr_codes'] != null) {
availableQrCodes = <AvailableQrCodes>[];
json['available_qr_codes'].forEach((v) {
availableQrCodes!.add(AvailableQrCodes.fromJson(v));
});
}
if (json['available_direct_debits'] != null) {
availableDirectDebits = <AvailableDirectDebits>[];
json['available_direct_debits'].forEach((v) {
availableDirectDebits!.add(AvailableDirectDebits.fromJson(v));
});
}
if (json['available_paylaters'] != null) {
availablePaylaters = <AvailablePaylaters>[];
json['available_paylaters'].forEach((v) {
availablePaylaters!.add(AvailablePaylaters.fromJson(v));
});
}
shouldExcludeCreditCard = json['should_exclude_credit_card'];
shouldSendEmail = json['should_send_email'];
created = json['created'];
updated = json['updated'];
currency = json['currency'];
metadata = json['metadata'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['external_id'] = externalId;
data['user_id'] = userId;
data['status'] = status;
data['merchant_name'] = merchantName;
data['merchant_profile_picture_url'] = merchantProfilePictureUrl;
data['amount'] = amount;
data['payer_email'] = payerEmail;
data['description'] = description;
data['expiry_date'] = expiryDate;
data['invoice_url'] = invoiceUrl;
if (availableBanks != null) {
data['available_banks'] = availableBanks!.map((v) => v.toJson()).toList();
}
if (availableRetailOutlets != null) {
data['available_retail_outlets'] = availableRetailOutlets!.map((v) => v.toJson()).toList();
}
if (availableEwallets != null) {
data['available_ewallets'] = availableEwallets!.map((v) => v.toJson()).toList();
}
if (availableQrCodes != null) {
data['available_qr_codes'] = availableQrCodes!.map((v) => v.toJson()).toList();
}
if (availableDirectDebits != null) {
data['available_direct_debits'] = availableDirectDebits!.map((v) => v.toJson()).toList();
}
if (availablePaylaters != null) {
data['available_paylaters'] = availablePaylaters!.map((v) => v.toJson()).toList();
}
data['should_exclude_credit_card'] = shouldExcludeCreditCard;
data['should_send_email'] = shouldSendEmail;
data['created'] = created;
data['updated'] = updated;
data['currency'] = currency;
data['metadata'] = metadata;
return data;
}
}
class AvailableBanks {
String? bankCode;
String? collectionType;
int? transferAmount;
String? bankBranch;
String? accountHolderName;
int? identityAmount;
AvailableBanks({this.bankCode, this.collectionType, this.transferAmount, this.bankBranch, this.accountHolderName, this.identityAmount});
AvailableBanks.fromJson(Map<String, dynamic> json) {
bankCode = json['bank_code'];
collectionType = json['collection_type'];
transferAmount = json['transfer_amount'];
bankBranch = json['bank_branch'];
accountHolderName = json['account_holder_name'];
identityAmount = json['identity_amount'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['bank_code'] = bankCode;
data['collection_type'] = collectionType;
data['transfer_amount'] = transferAmount;
data['bank_branch'] = bankBranch;
data['account_holder_name'] = accountHolderName;
data['identity_amount'] = identityAmount;
return data;
}
}
class AvailableRetailOutlets {
String? retailOutletName;
AvailableRetailOutlets({this.retailOutletName});
AvailableRetailOutlets.fromJson(Map<String, dynamic> json) {
retailOutletName = json['retail_outlet_name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['retail_outlet_name'] = retailOutletName;
return data;
}
}
class AvailableEwallets {
String? ewalletType;
AvailableEwallets({this.ewalletType});
AvailableEwallets.fromJson(Map<String, dynamic> json) {
ewalletType = json['ewallet_type'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['ewallet_type'] = ewalletType;
return data;
}
}
class AvailableQrCodes {
String? qrCodeType;
AvailableQrCodes({this.qrCodeType});
AvailableQrCodes.fromJson(Map<String, dynamic> json) {
qrCodeType = json['qr_code_type'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['qr_code_type'] = qrCodeType;
return data;
}
}
class AvailableDirectDebits {
String? directDebitType;
AvailableDirectDebits({this.directDebitType});
AvailableDirectDebits.fromJson(Map<String, dynamic> json) {
directDebitType = json['direct_debit_type'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['direct_debit_type'] = directDebitType;
return data;
}
}
class AvailablePaylaters {
String? paylaterType;
AvailablePaylaters({this.paylaterType});
AvailablePaylaters.fromJson(Map<String, dynamic> json) {
paylaterType = json['paylater_type'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['paylater_type'] = paylaterType;
return data;
}
}

View File

@@ -0,0 +1,161 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:customer/payment/xenditModel.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:webview_flutter/webview_flutter.dart';
class XenditScreen extends StatefulWidget {
final String initialURl;
final String transId;
final String apiKey;
const XenditScreen({super.key, required this.initialURl, required this.transId, required this.apiKey});
@override
State<XenditScreen> createState() => _XenditScreenState();
}
class _XenditScreenState extends State<XenditScreen> {
WebViewController controller = WebViewController();
bool isLoading = true;
@override
void initState() {
controller.clearCache();
initController();
callTransaction();
super.initState();
}
void callTransaction() {
Timer? timer;
timer = Timer.periodic(const Duration(seconds: 4), (Timer t) async {
if (!mounted) {
timer?.cancel();
return;
}
await Future.delayed(const Duration(seconds: 5)).then((v) async {
final value = await checkStatus(paymentId: widget.transId);
if (!mounted) {
timer?.cancel();
return;
}
if (value.status == 'PAID' || value.status == 'SETTLED') {
timer?.cancel();
Get.back(result: true);
} else if (value.status == 'FAILED') {
timer?.cancel();
Get.back(result: false);
}
});
});
}
@override
void dispose() {
super.dispose();
}
void initController() {
controller =
WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: ((url) {
setState(() {
isLoading = false;
});
}),
onNavigationRequest: (NavigationRequest navigation) async {
log("URL :: ${navigation.url}");
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse(widget.initialURl));
}
@override
Widget build(BuildContext context) {
// ignore: deprecated_member_use
return WillPopScope(
onWillPop: () async {
_showMyDialog();
return false;
},
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
centerTitle: false,
leading: GestureDetector(
onTap: () {
_showMyDialog();
},
child: const Icon(Icons.arrow_back, color: Colors.white),
),
),
body: Stack(alignment: Alignment.center, children: [WebViewWidget(controller: controller), Visibility(visible: isLoading, child: const Center(child: CircularProgressIndicator()))]),
),
);
}
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text('Cancel Payment'.tr),
content: SingleChildScrollView(child: Text("Cancel Payment?".tr)),
actions: <Widget>[
TextButton(
child: Text('Cancel'.tr, style: const TextStyle(color: Colors.red)),
onPressed: () {
Navigator.of(context).pop(false);
Navigator.of(context).pop(false);
},
),
TextButton(
child: Text('Continue'.tr, style: const TextStyle(color: Colors.green)),
onPressed: () {
Navigator.of(context).pop(false);
},
),
],
);
},
);
}
Future<XenditModel> checkStatus({required String paymentId}) async {
// API endpoint
var url = Uri.parse('https://api.xendit.co/v2/invoices/$paymentId');
// Headers
var headers = {'Content-Type': 'application/json', 'Authorization': generateBasicAuthHeader(widget.apiKey.toString())};
// Making the POST request
var response = await http.get(url, headers: headers);
// Checking the response status
if (response.statusCode == 200) {
XenditModel model = XenditModel.fromJson(jsonDecode(response.body));
return model;
} else {
return XenditModel();
}
}
String generateBasicAuthHeader(String apiKey) {
String credentials = '$apiKey:';
String base64Encoded = base64Encode(utf8.encode(credentials));
return 'Basic $base64Encoded';
}
}