welloo_sdk 0.0.53
welloo_sdk: ^0.0.53 copied to clipboard
Package de transaction Welloo
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:welloo_sdk/welloo_sdk.dart';
import 'package:welloo_sdk/src/shared/config/transaction_verification_config.dart';
import 'package:welloo_sdk/src/shared/services/logger_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Load environment variables
try {
await dotenv.load(fileName: '.env');
} catch (e) {
debugPrint('⚠️ .env file not found. Please create one from .env.example');
}
// Configure logger
LoggerService().configure(
minLevel: LogLevel.debug,
enabledInProduction: true,
);
// Initialize Welloo SDK
await WellooSdk.init();
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welloo SDK - Nouveau Système',
theme: ThemeData(
colorSchemeSeed: Colors.blue,
useMaterial3: true,
),
home: const DemoWello(),
);
}
}
class DemoWello extends StatefulWidget {
const DemoWello({super.key});
@override
State<DemoWello> createState() => _DemoWelloState();
}
class _DemoWelloState extends State<DemoWello> {
String? _lastTransactionRef;
final _sdk = WellooSdk();
// Configurations disponibles
TransactionVerificationConfig _currentConfig = TransactionVerificationConfig.waveConfig;
String _configName = 'Wave Config (2s, 150x)';
// Status en temps réel
String _currentStatus = 'Aucune transaction en cours';
String get _accessToken => dotenv.env['ACCESS_TOKEN'] ?? '';
String get _refreshToken => dotenv.env['REFRESH_TOKEN'] ?? '';
@override
void initState() {
super.initState();
_printWelcomeMessage();
}
void _printWelcomeMessage() {
print('\n${'=' * 60}');
print('🚀 WELLOO SDK - NOUVEAU SYSTÈME DE VÉRIFICATION');
print('=' * 60);
print('Configuration: $_configName');
print('Stratégie: ${_currentConfig.strategy.name}');
print('Polling: ${_currentConfig.pollingConfig.maxAttempts}x @ ${_currentConfig.pollingConfig.interval.inSeconds}s');
print('Deeplink: ${_currentConfig.deeplinkConfig.enabled ? "Activé" : "Désactivé"}');
print('Circuit Breaker: ${_currentConfig.enableCircuitBreaker ? "Activé" : "Désactivé"}');
print('Retry Policy: Max ${_currentConfig.maxRetries} tentatives');
print('=' * 60);
print('\n');
}
Future<void> _handleDeposit() async {
// Check if tokens are configured
if (_accessToken.isEmpty || _refreshToken.isEmpty) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Please configure ACCESS_TOKEN and REFRESH_TOKEN in .env file',
),
backgroundColor: Colors.red,
duration: Duration(seconds: 3),
),
);
return;
}
print('\n${'=' * 60}');
print('📦 INITIATION DÉPÔT');
print('=' * 60);
Navigator.of(context).push<TransactionResult>(
MaterialPageRoute(
builder: (_) => WellooDeposit(
packageName: 'com.example.welloo',
accessToken: _accessToken,
refreshToken: _refreshToken,
waitResponse: (response) {
_handleTransactionResponse(Map<String, dynamic>.from(response));
},
onError: (error) {
_handleTransactionError(Map<String, dynamic>.from(error));
},
),
),
);
}
void _handleTransactionResponse(Map<String, dynamic> response) {
print('\n✅ RÉPONSE TRANSACTION:');
print('Status: ${response['status']}');
print('Reference: ${response['reference_transaction']}');
print('Data: $response');
if (response['reference_transaction'] != null) {
setState(() {
_lastTransactionRef = response['reference_transaction'];
_currentStatus = 'Transaction ${response['status']}';
});
}
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Transaction ${response['status']}'),
backgroundColor: response['status'] == 'SUCCEEDED' ? Colors.green : Colors.orange,
),
);
}
void _handleTransactionError(Map<String, dynamic> error) {
print('\n❌ ERREUR TRANSACTION:');
print('Description: ${error['description']}');
print('Details: $error');
setState(() {
_currentStatus = 'Erreur: ${error['description']}';
});
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Erreur: ${error['description']}'),
backgroundColor: Colors.red,
),
);
}
Future<void> _checkTransactionStatus() async {
if (_lastTransactionRef == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('No transaction to check')),
);
return;
}
print('\n🔍 VÉRIFICATION MANUELLE: $_lastTransactionRef');
try {
final result = await _sdk.checkDepositStatus(
reference: _lastTransactionRef!,
);
if (!mounted) return;
if (result.isSuccess && result.data != null) {
final transaction = result.data!;
print('Status: ${transaction.status}');
print('Reference: ${transaction.reference}');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Status: ${transaction.status}\nReference: ${transaction.reference}',
),
backgroundColor:
transaction.status == 'success' ? Colors.green : Colors.orange,
),
);
} else {
print('❌ Error: ${result.error}');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error: ${result.error ?? "Unknown error"}'),
backgroundColor: Colors.red,
),
);
}
} catch (e) {
print('❌ Exception: $e');
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $e')),
);
}
}
void _changeConfiguration() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Choisir une Configuration'),
content: SizedBox(
width: double.maxFinite,
child: ListView(
shrinkWrap: true,
children: [
_buildConfigOption('Wave Config (2s, 150x)', TransactionVerificationConfig.waveConfig),
_buildConfigOption('Wello Config (3s, 60x)', TransactionVerificationConfig.welloConfig),
_buildConfigOption('Production (5s, 60x)', TransactionVerificationConfig.productionConfig),
_buildConfigOption('Development (1s, 30x)', TransactionVerificationConfig.developmentConfig),
_buildConfigOption('Polling Only', TransactionVerificationConfig.pollingOnlyConfig),
_buildConfigOption('Deeplink Only', TransactionVerificationConfig.deeplinkOnlyConfig),
],
),
),
),
);
}
Widget _buildConfigOption(String name, TransactionVerificationConfig config) {
return ListTile(
title: Text(name),
subtitle: Text(
'Stratégie: ${config.strategy.name}\n'
'Polling: ${config.pollingConfig.maxAttempts}x @ ${config.pollingConfig.interval.inSeconds}s',
),
selected: _configName == name,
onTap: () {
setState(() {
_configName = name;
_currentConfig = config;
});
Navigator.pop(context);
_printWelcomeMessage();
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Welloo SDK - Nouveau Système'),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: _changeConfiguration,
tooltip: 'Changer la configuration',
),
],
),
backgroundColor: Colors.white,
body: Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Configuration actuelle
Card(
color: Colors.blue[50],
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const Icon(Icons.settings, size: 40, color: Colors.blue),
const SizedBox(height: 8),
Text(
_configName,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 4),
Text(
'Stratégie: ${_currentConfig.strategy.name}',
style: TextStyle(fontSize: 12, color: Colors.grey[700]),
),
Text(
'Polling: ${_currentConfig.pollingConfig.maxAttempts}x @ ${_currentConfig.pollingConfig.interval.inSeconds}s',
style: TextStyle(fontSize: 12, color: Colors.grey[700]),
),
],
),
),
),
const SizedBox(height: 20),
// Status actuel
Card(
color: Colors.grey[50],
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
const Icon(Icons.info_outline, color: Colors.blue),
const SizedBox(width: 12),
Expanded(
child: Text(
_currentStatus,
style: const TextStyle(fontSize: 14),
),
),
],
),
),
),
const SizedBox(height: 20),
// Bouton principal
ElevatedButton.icon(
onPressed: _handleDeposit,
icon: const Icon(Icons.account_balance_wallet),
label: const Text("Initier un Dépôt"),
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 50),
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
),
const SizedBox(height: 20),
if (_lastTransactionRef != null) ...[
// Dernière transaction
Card(
color: Colors.orange[50],
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
Text(
'Dernière transaction:',
style: TextStyle(
fontSize: 11,
color: Colors.grey[600],
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
SelectableText(
_lastTransactionRef!,
style: TextStyle(
fontSize: 12,
color: Colors.grey[800],
fontFamily: 'monospace',
),
textAlign: TextAlign.center,
),
],
),
),
),
const SizedBox(height: 10),
// Vérification manuelle
ElevatedButton.icon(
onPressed: _checkTransactionStatus,
icon: const Icon(Icons.refresh),
label: const Text("Vérifier le Statut"),
style: ElevatedButton.styleFrom(
minimumSize: const Size(250, 50),
backgroundColor: Colors.orange,
foregroundColor: Colors.white,
),
),
const SizedBox(height: 8),
Text(
'Utilisez ce bouton si le deeplink ne fonctionne pas\nou pour vérifier manuellement',
style: TextStyle(
fontSize: 11,
color: Colors.grey[500],
fontStyle: FontStyle.italic,
),
textAlign: TextAlign.center,
),
],
const SizedBox(height: 30),
// Aide
Card(
color: Colors.green[50],
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
const Icon(Icons.help_outline, color: Colors.green, size: 30),
const SizedBox(height: 8),
Text(
'Nouveau Système de Vérification',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.green[900],
),
),
const SizedBox(height: 8),
Text(
'✓ 3 stratégies: Polling, Deeplink, Hybrid\n'
'✓ 8 configurations prédéfinies\n'
'✓ Circuit Breaker & Retry Policy\n'
'✓ Métriques & Events détaillés\n'
'✓ Logs structurés en console',
style: TextStyle(
fontSize: 11,
color: Colors.green[800],
),
textAlign: TextAlign.left,
),
],
),
),
),
],
),
),
),
),
);
}
}