feat(wave-mock): simuler le paiement Wave en mode dev (épargne + cotisations)

En mode dev (URL contient 'mock' ou 'localhost', ou !AppConfig.isProd),
le paiement Wave est simulé directement sans ouvrir le navigateur :
- Dépôt épargne (depot_epargne_dialog.dart) : simulation 800ms + SnackBar succès
- Paiement cotisation (payment_dialog.dart) : même pattern

En mode prod : comportement inchangé (ouvre l'app Wave via launchUrl).

Pattern identique à wave_payment_page.dart (onboarding souscription)
appliqué à tous les flux Wave de l'application.
This commit is contained in:
dahoud
2026-04-16 19:29:26 +00:00
parent 18203f07b2
commit 1d20687a43
2 changed files with 47 additions and 2 deletions

View File

@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../shared/design_system/tokens/color_tokens.dart';
import '../../../../shared/design_system/tokens/app_colors.dart';
import '../../../../core/config/environment.dart';
import 'package:intl/intl.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:unionflow_mobile_apps/core/di/injection.dart';
@@ -445,9 +446,29 @@ class _PaymentDialogState extends State<PaymentDialog> {
numeroTelephone: phone,
);
final url = result.waveLaunchUrl.isNotEmpty ? result.waveLaunchUrl : result.redirectUrl;
if (url.isEmpty) {
throw Exception('URL Wave non reçue');
if (url.isEmpty) throw Exception('URL Wave non reçue');
// Mode dev/mock : simuler le paiement sans ouvrir le navigateur
final isMock = url.contains('mock') || url.contains('localhost') || !AppConfig.isProd;
if (isMock) {
await Future.delayed(const Duration(milliseconds: 800));
if (!mounted) return;
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(children: [
Icon(Icons.science_rounded, color: AppColors.onPrimary, size: 16),
const SizedBox(width: 8),
const Expanded(child: Text('Paiement simulé avec succès (mode dev)')),
]),
backgroundColor: AppColors.success,
),
);
context.read<ContributionsBloc>().add(const LoadContributions());
return;
}
// Mode prod : ouvrir Wave
final uri = Uri.parse(url);
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);

View File

@@ -4,6 +4,7 @@ import 'package:get_it/get_it.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:file_picker/file_picker.dart';
import '../../../../core/config/environment.dart';
import '../../../../core/constants/lcb_ft_constants.dart';
import '../../../../core/data/repositories/parametres_lcb_ft_repository.dart';
import '../../../../core/utils/error_formatter.dart';
@@ -159,6 +160,29 @@ class _DepotEpargneDialogState extends State<DepotEpargneDialog> {
);
final url = result.waveLaunchUrl.isNotEmpty ? result.waveLaunchUrl : result.redirectUrl;
if (url.isEmpty) throw Exception('URL Wave non reçue');
// Mode dev/mock : simuler le paiement au lieu d'ouvrir le navigateur
final isMock = url.contains('mock') || url.contains('localhost') || !AppConfig.isProd;
if (isMock) {
// Simulation : attendre 1s puis confirmer le succès
await Future.delayed(const Duration(milliseconds: 800));
if (!mounted) return;
Navigator.of(context).pop(true);
widget.onSuccess?.call();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Row(children: [
Icon(Icons.science_rounded, color: Colors.white, size: 16),
SizedBox(width: 8),
Expanded(child: Text('Dépôt simulé avec succès (mode dev)')),
]),
backgroundColor: AppColors.success,
),
);
return;
}
// Mode prod : ouvrir Wave
final uri = Uri.parse(url);
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);