sunmi_mtb 1.0.1
sunmi_mtb: ^1.0.1 copied to clipboard
A Flutter plugin for MineSec SoftPOS (MSA) payment integration on Android. Supports checking installation, warm-up, activation, and sale transactions.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:sunmi_mtb/sunmi_mtb.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sunmi MTB Example',
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true),
home: const MsaDemoPage(),
);
}
}
class MsaDemoPage extends StatefulWidget {
const MsaDemoPage({super.key});
@override
State<MsaDemoPage> createState() => _MsaDemoPageState();
}
class _MsaDemoPageState extends State<MsaDemoPage> {
// ─── Configuration ──────────────────────────────────────────────
final _msa = SunmiMtb();
final _amountController = TextEditingController(text: '0.00');
String _status = 'Ready';
// ─── Actions ────────────────────────────────────────────────────
Future<void> _checkInstalled() async {
_setStatus('Checking...');
final installed = await _msa.isInstalled();
_setStatus(installed ? '✅ MineSec App is Installed!' : '❌ MineSec App is NOT Installed.');
}
Future<void> _warmUp() async {
_setStatus('Warming up...');
final result = await _msa.warmUp();
_setStatus('WarmUp Result:\n$result');
}
Future<void> _activate() async {
_setStatus('Activating...');
// Replace with a real activation code from your backend
final result = await _msa.activate('845903741039');
_setStatus('Activation Result:\n$result');
}
Future<void> _sale() async {
_setStatus('Initiating Sale...');
final result = await _msa.saleTransaction(amount: _amountController.text);
if (result == null) {
_setStatus('Transaction returned no result.');
return;
}
if (result.isError) {
_setStatus(
'❌ Transaction Failed\n'
'Code: ${result.rspCode}\n'
'Message: ${result.rspMsg}',
);
return;
}
_setStatus(
'${result.isApproved ? "✅ Payment Approved!" : "⚠️ Status: ${result.tranStatus}"}\n'
'─────────────────────\n'
'Transaction ID: ${result.tranId ?? 'N/A'}\n'
'Approval Code: ${result.approvalCode ?? 'N/A'}\n'
'Amount: ${result.totalAmount ?? 'N/A'}\n'
'Payment Method: ${result.paymentMethod ?? 'N/A'}\n'
'Card: ${result.maskedAccount ?? 'N/A'}\n'
'Entry Mode: ${result.entryMode ?? 'N/A'}\n'
'RRN: ${result.rrn ?? 'N/A'}\n'
'Trace: ${result.trace ?? 'N/A'}\n'
'Merchant: ${result.mchName ?? 'N/A'}\n'
'TID: ${result.acqTid ?? 'N/A'}\n'
'MID: ${result.acqMid ?? 'N/A'}\n'
'POS Msg ID: ${result.posMessageId ?? 'N/A'}\n'
'Time: ${result.createdAt ?? 'N/A'}',
);
}
void _setStatus(String status) {
setState(() => _status = status);
}
// ─── UI ─────────────────────────────────────────────────────────
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('MineSec SoftPOS Demo'), backgroundColor: Theme.of(context).colorScheme.inversePrimary),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Status display
Text('Status:', style: Theme.of(context).textTheme.titleMedium),
Container(
margin: const EdgeInsets.symmetric(vertical: 8),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(color: Colors.grey.shade200, borderRadius: BorderRadius.circular(8)),
child: SelectableText(_status, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13)),
),
const SizedBox(height: 20),
// Action buttons
ElevatedButton(onPressed: _checkInstalled, child: const Text('Check MSA App Installed')),
const SizedBox(height: 10),
ElevatedButton(onPressed: _warmUp, child: const Text('Warm Up SoftPOS')),
const SizedBox(height: 10),
ElevatedButton(onPressed: _activate, child: const Text('Activate POS (Sample Code)')),
const SizedBox(height: 20),
// Amount input
TextField(
controller: _amountController,
decoration: const InputDecoration(labelText: 'Sale Amount', border: OutlineInputBorder()),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
const SizedBox(height: 10),
ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.deepPurple, foregroundColor: Colors.white),
onPressed: _sale,
child: const Text('Initiate Sale Transaction'),
),
],
),
),
);
}
}