flutter_payment_plugin 1.0.15
flutter_payment_plugin: ^1.0.15 copied to clipboard
A Flutter plugin for Omniware Payment Gateway integration.
example/lib/main.dart
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:math';
import 'dart:async';
import 'dart:convert';
import 'package:flutter_payment_plugin/flutter_payment_plugin.dart';
import 'hash_generator.dart';
final scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
final _plugin = FlutterPaymentPlugin();
final _hasher = HashGenerator();
StreamSubscription<String>? _logSub;
// ====== Defaults (prefilled) ======
final _baseUrlCtl = TextEditingController(
text: 'https://pgbiz.omniware.in',
);
// Merchant creds
final _apiKeyCtl = TextEditingController(
text: 'fb6bca86-b429-4abf-a42f-824bdd29022e',
);
final _saltCtl = TextEditingController(
text: '80c67bfdf027da08de88ab5ba903fecafaab8f6d',
);
// Payment fields
final _orderIdCtl = TextEditingController();
final _amountCtl = TextEditingController(text: '2');
final _nameCtl = TextEditingController(text: 'Tester Sharma');
final _phoneCtl = TextEditingController(text: '9876543210');
final _emailCtl = TextEditingController(
text: 'tester@example.com',
);
final _returnUrlCtl = TextEditingController(
text: 'https://pgbiz.omniware.in/tnpv2/return_page.php',
);
final _descCtl = TextEditingController(
text: 'Payment Short Description',
);
final _currencyCtl = TextEditingController(text: 'INR');
final _countryCtl = TextEditingController(text: 'IND');
final _cityCtl = TextEditingController(text: 'Bangalore');
final _stateCtl = TextEditingController(text: 'Karnataka');
final _addr1Ctl = TextEditingController(text: 'ad1');
final _addr2Ctl = TextEditingController(text: 'ad2');
final _zipCtl = TextEditingController(text: '560001');
final _enableAutoRefundCtl = TextEditingController(text: 'n');
// UDF fields
final _udf1Ctl = TextEditingController(text: 'ud1');
final _udf2Ctl = TextEditingController(text: 'udf2');
final _udf3Ctl = TextEditingController(text: 'udf3');
final _udf4Ctl = TextEditingController(text: 'udf4');
final _udf5Ctl = TextEditingController(text: 'udf5');
String _mode = 'LIVE';
String _hash = '';
String _lastStatusTitle = '';
String _lastResponseJson = '';
@override
void initState() {
super.initState();
_initPlatformVersion();
_orderIdCtl.text = _generateOrderId();
if (kIsWeb) {
final origin = Uri.base.origin;
if (origin.isNotEmpty) {
_returnUrlCtl.text = '$origin/payment_return.html';
}
}
_logSub = FlutterPaymentPlugin.logLines.listen((s) {
debugPrint(s);
});
}
Future<void> _initPlatformVersion() async {
String pv;
try {
pv = await _plugin.getPlatformVersion() ??
'Unknown platform version';
} on PlatformException {
pv = 'Failed to get platform version.';
}
if (!mounted) return;
setState(() {
_platformVersion = pv;
});
}
@override
void dispose() {
_logSub?.cancel();
super.dispose();
}
String _generateOrderId() {
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const numbers = '0123456789';
final r = Random();
final letter = letters[r.nextInt(letters.length)];
final digits = List.generate(
3,
(_) => numbers[r.nextInt(numbers.length)],
).join();
return '$letter$digits';
}
void _regenOrderId() {
setState(() {
_orderIdCtl.text = _generateOrderId();
});
}
void _generateHash() {
final camel = <String, String>{
'mode': _mode,
'amount': _amountCtl.text,
'name': _nameCtl.text,
'phone': _phoneCtl.text,
'email': _emailCtl.text,
'returnURL': _returnUrlCtl.text,
'description': _descCtl.text,
'currency': _currencyCtl.text,
'country': _countryCtl.text,
'city': _cityCtl.text,
'state': _stateCtl.text,
'addressLine1': _addr1Ctl.text,
'addressLine2': _addr2Ctl.text,
'zipCode': _zipCtl.text,
'enable_auto_refund': _enableAutoRefundCtl.text,
'orderID': _orderIdCtl.text,
'udf1': _udf1Ctl.text,
'udf2': _udf2Ctl.text,
'udf3': _udf3Ctl.text,
'udf4': _udf4Ctl.text,
'udf5': _udf5Ctl.text,
};
final hash = _hasher.generateHash(
salt: _saltCtl.text.trim(),
apiKey: _apiKeyCtl.text.trim(),
camelCaseInputs: camel,
);
setState(() {
_hash = hash;
});
}
Future<void> _startPayment() async {
if (_baseUrlCtl.text.trim().isEmpty ||
_apiKeyCtl.text.trim().isEmpty ||
_saltCtl.text.trim().isEmpty) {
_toast('Base URL, API Key and SALT are required');
return;
}
if (_hash.isEmpty) {
_generateHash();
if (_hash.isEmpty) {
_toast('Could not generate hash');
return;
}
}
final params = <String, String>{
'api_key': _apiKeyCtl.text.trim(),
'order_id': _orderIdCtl.text.trim(),
'salt': _saltCtl.text.trim(),
'hash': _hash,
'mode': _mode,
'amount': _amountCtl.text.trim(),
'name': _nameCtl.text.trim(),
'phone': _phoneCtl.text.trim(),
'email': _emailCtl.text.trim(),
'return_url': _returnUrlCtl.text.trim(),
'description': _descCtl.text.trim(),
'currency': _currencyCtl.text.trim(),
'country': _countryCtl.text.trim(),
'city': _cityCtl.text.trim(),
'state': _stateCtl.text.trim(),
'address_line_1': _addr1Ctl.text.trim(),
'address_line_2': _addr2Ctl.text.trim(),
'zip_code': _zipCtl.text.trim(),
'udf1': _udf1Ctl.text.trim(),
'udf2': _udf2Ctl.text.trim(),
'udf3': _udf3Ctl.text.trim(),
'udf4': _udf4Ctl.text.trim(),
'udf5': _udf5Ctl.text.trim(),
'enable_auto_refund': _enableAutoRefundCtl.text.trim(),
};
try {
final result = await FlutterPaymentPlugin.openPayment(
url: _baseUrlCtl.text.trim(),
params: params,
title: 'Payment',
);
final message = result.cancelled
? 'Payment cancelled'
: (result.success
? 'Payment success'
: 'Payment finished with response');
final pretty = _prettyJson(result.data);
if (!mounted) return;
setState(() {
_lastStatusTitle = message;
_lastResponseJson = pretty;
});
} on PlatformException catch (e) {
if (!mounted) return;
_toast(
'Failed to open Payment WebView: ${e.message}',
);
}
}
String _prettyJson(String? s) {
if (s == null || s.isEmpty) return '';
try {
final obj = jsonDecode(s);
return const JsonEncoder.withIndent(' ').convert(obj);
} catch (_) {
return s;
}
}
void _toast(String msg) {
final sm = scaffoldMessengerKey.currentState;
sm?.clearSnackBars();
sm?.showSnackBar(
SnackBar(content: Text(msg)),
);
}
Widget _field(
String label,
TextEditingController ctl, {
TextInputType? type,
bool readOnly = false,
}) {
return TextField(
controller: ctl,
readOnly: readOnly,
keyboardType: type,
decoration: InputDecoration(
labelText: label,
border: const OutlineInputBorder(),
),
);
}
@override
Widget build(BuildContext context) {
final pad = const SizedBox(height: 12);
return MaterialApp(
scaffoldMessengerKey: scaffoldMessengerKey,
home: Scaffold(
appBar: AppBar(
title: const Text(
'Omniware Payment Playground',
),
),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Text(
'Running on: $_platformVersion • Plugin: ${FlutterPaymentPlugin.version}',
),
if (kIsWeb) ...[
pad,
const Text(
'Web: allow popups, use Return URL '
'…/payment_return.html, then Generate Hash before paying.',
style: TextStyle(fontSize: 12, color: Colors.deepOrange),
),
],
pad,
_field('Base URL', _baseUrlCtl),
pad,
_field('API Key', _apiKeyCtl),
pad,
_field('SALT', _saltCtl),
pad,
Row(
children: [
Expanded(
child: _field(
'Order ID',
_orderIdCtl,
),
),
const SizedBox(width: 12),
ElevatedButton(
onPressed: _regenOrderId,
child: const Text(
'Generate Order ID',
),
),
],
),
pad,
Row(
children: [
Expanded(
child: InputDecorator(
decoration:
const InputDecoration(
labelText: 'Mode',
border:
OutlineInputBorder(),
),
child:
DropdownButtonHideUnderline(
child:
DropdownButton<String>(
isExpanded: true,
value: _mode,
items: const [
DropdownMenuItem(
value: 'LIVE',
child: Text('LIVE'),
),
DropdownMenuItem(
value: 'TEST',
child: Text('TEST'),
),
],
onChanged: (v) {
setState(() {
_mode = v ?? 'LIVE';
});
},
),
),
),
),
const SizedBox(width: 12),
Expanded(
child: _field(
'Amount',
_amountCtl,
type:
TextInputType.number,
),
),
],
),
pad,
_field('Name', _nameCtl),
pad,
Row(
children: [
Expanded(
child: _field(
'Phone',
_phoneCtl,
type:
TextInputType.phone,
),
),
const SizedBox(width: 12),
Expanded(
child: _field(
'Email',
_emailCtl,
type:
TextInputType.emailAddress,
),
),
],
),
pad,
_field(
'Return URL',
_returnUrlCtl,
type: TextInputType.url,
),
pad,
_field(
'Description',
_descCtl,
),
pad,
Row(
children: [
Expanded(
child: _field(
'Currency',
_currencyCtl,
),
),
const SizedBox(width: 12),
Expanded(
child: _field(
'Country',
_countryCtl,
),
),
],
),
pad,
Row(
children: [
Expanded(
child: _field(
'City',
_cityCtl,
),
),
const SizedBox(width: 12),
Expanded(
child: _field(
'State',
_stateCtl,
),
),
],
),
pad,
Row(
children: [
Expanded(
child: _field(
'Address Line 1',
_addr1Ctl,
),
),
const SizedBox(width: 12),
Expanded(
child: _field(
'Address Line 2',
_addr2Ctl,
),
),
],
),
pad,
Row(
children: [
Expanded(
child: _field(
'ZIP Code',
_zipCtl,
),
),
const SizedBox(width: 12),
Expanded(
child: _field(
'Enable Auto Refund (y/n)',
_enableAutoRefundCtl,
),
),
],
),
pad,
Row(
children: [
Expanded(
child: _field(
'UDF1',
_udf1Ctl,
),
),
const SizedBox(width: 12),
Expanded(
child: _field(
'UDF2',
_udf2Ctl,
),
),
],
),
pad,
Row(
children: [
Expanded(
child: _field(
'UDF3',
_udf3Ctl,
),
),
const SizedBox(width: 12),
Expanded(
child: _field(
'UDF4',
_udf4Ctl,
),
),
],
),
pad,
_field(
'UDF5',
_udf5Ctl,
),
pad,
Row(
children: [
Expanded(
child: _field(
'Generated Hash',
TextEditingController(
text: _hash,
),
readOnly: true,
),
),
const SizedBox(width: 12),
ElevatedButton(
onPressed: _generateHash,
child: const Text(
'Generate Hash',
),
),
],
),
pad,
ElevatedButton(
onPressed: _startPayment,
style:
ElevatedButton.styleFrom(
padding:
const EdgeInsets.symmetric(
vertical: 14,
),
),
child: const Text(
'Start Payment',
),
),
const SizedBox(height: 24),
if (_lastStatusTitle.isNotEmpty ||
_lastResponseJson.isNotEmpty) ...[
Text(
_lastStatusTitle,
style: Theme.of(context)
.textTheme
.titleMedium,
),
const SizedBox(height: 8),
Container(
padding:
const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.black87,
borderRadius:
BorderRadius.circular(8),
),
child: SelectableText(
_lastResponseJson,
style: const TextStyle(
fontFamily: 'monospace',
color: Colors.white,
),
),
),
const SizedBox(height: 24),
],
],
),
),
),
),
);
}
}