dunopay_flutter 1.1.1
dunopay_flutter: ^1.1.1 copied to clipboard
DunoPay payment widget for Flutter — accept Mobile Money payments (MTN, MOOV, Wave, Orange…) across West Africa with a native payment sheet.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:dunopay_flutter/dunopay_flutter.dart';
void main() => runApp(const ExampleApp());
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title : 'DunoPay Example',
theme : ThemeData(
colorSchemeSeed: const Color(0xFF7B2FBE),
useMaterial3 : true,
),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String _status = '—';
// ── DunoPay instance (reusable) ──────────────────────────────────────────
final _dunopay = DunoPay(
publicKey: 'pk_sandbox_VOTRE_CLE_ICI',
mode : DunoPayMode.sandbox,
theme : const DunoPayTheme(
primaryColor: Color(0xFF7B2FBE),
),
);
// ── Open payment sheet ───────────────────────────────────────────────────
Future<void> _pay() async {
await _dunopay.collect(
context : context,
amount : 5000,
currency : 'XOF',
description: 'Commande #42 — Boutique Test',
// Pre-fill customer info to skip the form step
customer: const DunoPayCustomer(
firstname: 'Jean',
lastname : 'Dupont',
phone : '0196789966',
email : 'jean@example.com',
),
onSuccess: (result) => setState(() =>
_status = '✅ ${result.reference} — ${result.amount} ${result.currency}'),
onError : (err) => setState(() => _status = '❌ $err'),
onCancel : () => setState(() => _status = 'Annulé'),
);
}
// ── Without pre-filled customer (shows customer info step) ───────────────
Future<void> _payAnonymous() async {
await _dunopay.collect(
context : context,
amount : 2500,
currency : 'XOF',
description: 'Abonnement mensuel',
// no customer → sheet shows form step first
onSuccess: (result) => setState(() =>
_status = '✅ ${result.reference} — ${result.amount} ${result.currency}'),
onError : (err) => setState(() => _status = '❌ $err'),
onCancel : () => setState(() => _status = 'Annulé'),
);
}
@override
Widget build(BuildContext context) {
const purple = Color(0xFF7B2FBE);
return Scaffold(
backgroundColor: const Color(0xFFF9FAFB),
appBar: AppBar(
title : const Text('DunoPay Example'),
backgroundColor : purple,
foregroundColor : Colors.white,
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child : Column(
mainAxisSize: MainAxisSize.min,
children: [
// Status
Container(
padding : const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration : BoxDecoration(
color : Colors.white,
borderRadius: BorderRadius.circular(12),
border : Border.all(color: const Color(0xFFE5E7EB)),
),
child: Text(
_status,
style : const TextStyle(fontSize: 13, color: Color(0xFF374151)),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 32),
// Pay with pre-filled customer
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _pay,
style : ElevatedButton.styleFrom(
backgroundColor: purple,
foregroundColor: Colors.white,
shape : RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
padding : const EdgeInsets.symmetric(vertical: 16),
elevation : 0,
),
child: const Text(
'Payer 5 000 XOF',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
),
const SizedBox(height: 12),
// Pay anonymous (shows customer form)
SizedBox(
width: double.infinity,
child: OutlinedButton(
onPressed: _payAnonymous,
style : OutlinedButton.styleFrom(
foregroundColor: purple,
side : const BorderSide(color: Color(0xFF7B2FBE)),
shape : RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
padding : const EdgeInsets.symmetric(vertical: 16),
),
child: const Text(
'Payer 2 500 XOF (sans client)',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
),
],
),
),
),
);
}
}