move from embedded to redirect

This commit is contained in:
2025-11-26 14:58:16 +02:00
parent ab19958f71
commit 28312a4989
3 changed files with 146 additions and 3 deletions

View File

@@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:qpay/navbar.dart'; import 'package:qpay/navbar.dart';
import 'package:qpay/screens/confirm/confirm_screen.dart'; import 'package:qpay/screens/confirm/confirm_screen.dart';
import 'package:qpay/screens/gateway/gateway_redirect.dart';
import 'package:qpay/screens/gateway/gateway_screen.dart'; import 'package:qpay/screens/gateway/gateway_screen.dart';
import 'package:qpay/screens/integration/integration_screen.dart'; import 'package:qpay/screens/integration/integration_screen.dart';
import 'package:qpay/screens/onboarding/complete_screen.dart'; import 'package:qpay/screens/onboarding/complete_screen.dart';
@@ -83,7 +84,7 @@ class _MyAppState extends State<MyApp> {
themeMode: ThemeMode.light, // Force light mode regardless of OS setting themeMode: ThemeMode.light, // Force light mode regardless of OS setting
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
routerConfig: GoRouter( routerConfig: GoRouter(
initialLocation: '/', initialLocation: '/gateway-redirect',
routes: [ routes: [
ShellRoute( ShellRoute(
builder: (context, state, child) { builder: (context, state, child) {
@@ -119,6 +120,10 @@ class _MyAppState extends State<MyApp> {
path: '/gateway-web', path: '/gateway-web',
builder: (context, state) => const GatewayWebScreen(), builder: (context, state) => const GatewayWebScreen(),
), ),
GoRoute(
path: '/gateway-redirect',
builder: (context, state) => const GatewayRedirectScreen(),
),
GoRoute( GoRoute(
path: '/poll', path: '/poll',
builder: (context, state) => const PollScreen(), builder: (context, state) => const PollScreen(),

View File

@@ -85,14 +85,16 @@ class ConfirmController extends ChangeNotifier {
if (transactionController.model.selectedPaymentProcessor.authType == "WEB") { if (transactionController.model.selectedPaymentProcessor.authType == "WEB") {
if (context.mounted) { if (context.mounted) {
if(kIsWeb){ if(kIsWeb){
context.push('/gateway-web'); // the one we use here depends on when mpgs embedded bug will be fixed
// context.push('/gateway-web');
context.push('/gateway-redirect');
}else { }else {
context.push('/gateway'); context.push('/gateway');
} }
} }
} else { } else {
await pollTransaction(transactionController.model.receiptData?['id']); await pollTransaction(transactionController.model.receiptData?['id']);
context.push('/integration'); context.push('/poll');
} }
} else { } else {
model.status = response['status']; model.status = response['status'];

View File

@@ -0,0 +1,136 @@
import 'dart:js_interop';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:go_router/go_router.dart';
import 'package:qpay/interop.dart';
import 'package:qpay/models/responsive_policy.dart';
import 'package:qpay/screens/gateway/gateway_controller.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:web/web.dart' as web;
class GatewayRedirectScreen extends StatefulWidget {
const GatewayRedirectScreen({super.key});
@override
State<GatewayRedirectScreen> createState() => _GatewayRedirectScreenState();
}
class _GatewayRedirectScreenState extends State<GatewayRedirectScreen> {
late GatewayController controller;
late String url;
String? sessionID;
bool redirected = false;
bool integrationStarted = false;
@override
void initState() {
super.initState();
controller = GatewayController(context);
url = controller.transactionController.model.receiptData?['targetUrl'];
}
void updateRedirect(){
setState(() {
redirected = true;
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Complete your payment'),
leading: context.canPop()
? IconButton(
onPressed: () {
context.pop();
},
icon: const Icon(Icons.arrow_back),
)
: SizedBox.shrink(),
),
body: ListenableBuilder(
listenable: controller,
builder: (context, child) {
if (controller.model.status == 'SUCCESS') {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go('/integration');
});
}
return Container(
padding: EdgeInsets.all(50),
child: Center(
child: LayoutBuilder(
builder: (context, constraints) {
return SizedBox(
width: double.parse(constraints.maxWidth > ResponsivePolicy.md ?
ResponsivePolicy.md.toString() :
constraints.maxWidth.toString()),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 75),
Column(
children: [
Text(
'You are about to be redirected to an external gateway to complete your payment. '
'Once complete you can close the gateway tab and return to this one to check your '
'transaction status.',
style: TextStyle(fontSize: 20),
textAlign: TextAlign.center,
),
SizedBox(height: 50,),
Image.asset('assets/velocity-animation.gif', width: 150),
SizedBox(height: 50),
if(!redirected)
OutlinedButton(
child: Text('Redirect'),
onPressed: () async {
updateRedirect();
final Uri uri = Uri.parse(url);
if (!await launchUrl(
uri,
mode: LaunchMode.platformDefault, // Default behavior, usually opens in new tab on web
webOnlyWindowName: '_blank', // Specifically for web to open in a new tab
)) {
throw Exception('Could not launch $url');
}
},
),
if(redirected)
OutlinedButton(
child: Text('Check Status'),
onPressed: () {
context.go("/poll");
},
)
],
),
],
),
);
}
),
),
);
},
),
);
}
}