Airpay Flutter Package Integration Doc
Airpay Flutter Package Integration Doc
7
DATE – 21/12/2023
ABSTRACT
DISCLAIMER
This documentation shall only be used for evaluating the planned services designated herein and may
contain information that is privileged, confidential, Proprietary, or otherwise protected from disclosure.
As a result, this document or content thereof shall not be disclosed, used, or duplicated, in whole or in
part, for any purpose other than the Scope of Work assigned by airpay Payment Services to your
company ("Recipient"). Upon completion of service or termination of service, the Recipient shall return
all materials, including, without limiting the generality of the foregoing, all originals, copies,
reproductions, and summaries of confidential information. Any unauthorized use or disclosure by the
directors, officers, or employees of the Recipient shall be deemed to be unauthorized use or disclosure
by the Recipient and the Recipient shall indemnify and hold harmless the airpay Payment Services from
and against all damages, losses, costs, and expenses incurred because of such breach. airpay payment
services may seek injunctive relief restraining the unauthorized disclosure or use of confidential
information in addition to any other legal or equitable remedy otherwise available.
VERSION HISTORY
TABLE OF CONTENTS
ABSTRACT ...................................................................................................................................................... 2
Disclaimer...................................................................................................................................................... 3
Version History .............................................................................................................................................. 4
INITIAL CONFIGURATION -............................................................................................................................. 6
REQUEST PARAMETER TO CALL AIRPAY PACKAGE – ...................................................................................... 7
Request – .................................................................................................................................................. 7
PRIVATEKEY LOGIC – .................................................................................................................................. 9
CHECKSUM LOGIC – ................................................................................................................................ 10
RESPONSE MESSAGE - ................................................................................................................................. 10
Code Response ........................................................................................................................................ 10
RESPONSE FROM THE PAYMENT GATEWAY............................................................................................. 14
MANIFEST CHANGES - ................................................................................................................................. 14
pubspecs.yaml CHANGES - .......................................................................................................................... 14
SUMMARY – ................................................................................................................................................ 16
FOR SUPPORT – ........................................................................................................................................... 16
REQUEST AND RESPONSE PARAMETER TABLE ............................................................................................ 17
Request Parameter: - .......................................................................................................................... 17
Response Parameters .......................................................................................................................... 20
Sample code for reference – ....................................................................................................................... 22
INITIAL CONFIGURATION -
Add airpay_package as a dependency in your pubspec.yaml file. You can now include an
airpayPackage in your project.
Depend on it -
With Dart:
$ dart pub add airpay_package
With Flutter:
$ flutter pub add airpay_package
This will add a line like this to your package's pubspec.yaml (and run an implicit dart
pub get):
dependencies:
airpay_flutter_package: ^2.0.7
Alternatively, your editor might support dart pub get or flutter pub get. Check
the docs for your editor to learn more.
Import it :
import 'package:airpay_package/airpay_package.dart';
Just make sure that your activity has set windowSoftInputMode to adjustResize in
AndroidManifest.xml
<application>
<activity android:windowSoftInputMode=“adjustResize”>
</activity>
</application >
REQUEST –
sb_frequency: subscription_frequency.text,
sb_amount: subscription_amount.text,
sb_isrecurring: "1",
sb_recurringcount: subscription_rec_count.text,
sb_retryattempts: subRetryValue,
sb_maxamount: subscription_max_amount.text
);
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => new AirPay(
user: user,
closure: (status, response) => {onComplete(status, response)}),
),
);
}
PRIVATEKEY LOGIC –
CHECKSUM LOGIC –
var siindexvar =
'${subscription_date.text}${subscription_frequency.text}${dropdownValue.toString()}${subscription_am
ount.text}${"1"}${subscription_rec_count.text}${subRetryValue.toString()}';
if(txn_subtype.text.toString() == "12"){
siindexvar = siindexvar;
}else{
siindexvar = "";
}
var setAllStr =
'${email.text}${fname.text}${lname.text}${fullAddress.text}${city.text}${state.text}${country.text}${amo
unt.text.toString()}${orderId.text.toString()}${siindexvar.toString()}$formattedDate';
// checksum
var sAllData = utf8.encode('$sKey@$setAllStr');
var checksum = sha256.convert(sAllData);
RESPONSE MESSAGE -
CODE RESPONSE
onComplete method:
onComplete(status, response) {
print(resp);
Navigator.pop(context);
if (txtStsMsg == '') {
customer_fvpa = ":$customer_vpa";
var sParam =
'${transid}:${apTransactionID}:${amount}:${transtatus}:${message}:${merchantid}:${username}$custom
er_fvpa';
if(checkSumResult.toString() == secureHash.toString()){
Fluttertoast.showToast(
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.white24,
textColor: Colors.white,
fontSize: 16.0
);
}else{
Fluttertoast.showToast(
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.white24,
textColor: Colors.white,
fontSize: 16.0
);
AwesomeDialog(
context: context,
dialogType: DialogType.NO_HEADER,
headerAnimationLoop: true,
animType: AnimType.BOTTOMSLIDE,
//title: "AirPay",
txtStsMsg)
.show();
MANIFEST CHANGES -
In the AndroidManifest.xml file located at android/app/src/main you need to add this permission inside
the manifest tag and also need to add xmlns:tools value -
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.airpay_example">
And need to add Meta-data tag inside the application tag value -
For reference shared code below –
<meta-data
android:name="flutterEmbedding"
android:value="2" />
PUBSPECS.YAML CHANGES -
name: airpay_example
description: A new Flutter project.
# The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as
CFBundleVersion.
# Read more about iOS versioning at
#
https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference
/Articles/CoreFoundationKeys.html
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
airpay_flutter_package: ^2.0.7
#airpay_flutter_package:
# path: ../
# git:
# url:
# ref: main
dev_dependencies:
flutter_test:
sdk: flutter
SUMMARY –
Flutter is intended to provide an example to Merchant for integrating merchant Payment Solution.
For a summary of features, please see the Airpay_Flutter_SDK_Integration.pdf file.
FOR SUPPORT –
Day/Week/Month/Year/Adhoc
sb_frequency Numeric 1-999 Subscription frequency (length 1-999, required for
enabling subscription)
sb_amount Numeric 1-6 .2 Subscription amount (length 1-6 .2, required for
enabling subscription)
sb_isrecurring Numeric 1 Is subscription recurring (length 1, required for
enabling subscription)
sb_recurringcount Numeric 1-999 Subscription Recurring Count (length 1-999, required
for enabling subscription and Is Subscription Recurring
is Yes , if recurring count is 999 than subscription is set
as never ending end date its apply only for enach
transaction)
sb_retryattempts Numeric 1 Subscription retry attempts (length 1, required for
enabling subscription)
sb_maxamount Numeric 1-6 .2 Maximum amount can charge, and greater than or
equal to the amount (Not required)
RESPONSE PARAMETERS
import 'package:airpay_flutter_package/airpay_package.dart';
import 'package:airpay_flutter_package/screens/airpay_home_new.dart';
import 'package:awesome_dialog/awesome_dialog.dart';
import 'package:email_validator/email_validator.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:intl/intl.dart';
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:crc32_checksum/crc32_checksum.dart';
@override
_HomeState createState() => _HomeState(isSandbox: isSandbox);
}
r'[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-
\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{1FAB0}-
\u{1FAB6}\u{1FAC0}-\u{1FAC2}\u{1FAD0}-\u{1FAD9}\u{1FADA}-\u{1FADB}\u{1FADC}-
\u{1FADD}\u{1FAE0}-\u{1FAE1}\u{1FAE2}-\u{1FAE3}\u{1FAE4}-\u{1FAE5}\u{1FAE6}-\u{1FAE7}\u{1FAE8}-
\u{1FAE9}\u{1FAEA}-\u{1FAEB}]',
unicode: true,
);
final RegExp regex = RegExp(r'[^a-zA-Z]');
final RegExp email_regex = RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$');
_HomeState({required this.isSandbox});
void _showAddress() {
setState(() {
isVisible = !isVisible;
});
}
void _showSubscription() {
setState(() {
isSubVisible = !isSubVisible;
});
}
@override
void initState() {
super.initState();
dropdownValue = "D";
subRetryValue = "0"; //Default value set as 0
fname.text = "";
lname.text = "";
email.text = "";
phone.text = "";
fullAddress.text = "";
pincode.text = "";
orderId.text = "";
amount.text = "";
city.text = "";
state.text = "";
country.text = "";
}
onComplete(status, response) {
//(!TextUtils.isEmpty(transaction.getChMode()) &&
transaction.getChMode().equalsIgnoreCase("upi")){
if(!chmode.toString().isEmpty && chmode.toString() == "upi" ){
customer_vpa = resp['CUSTOMERVPA'] ?? "";
customer_fvpa = ":$customer_vpa";
}
var merchantid = ""; //Please enter Merchant Id
var sParam =
'${transid}:${apTransactionID}:${amount}:${transtatus}:${message}:${merchantid}:${username}$custom
er_fvpa';
if(checkSumResult.toString() == secureHash.toString()){
Fluttertoast.showToast(
msg: "Securehash matched",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.white24,
textColor: Colors.white,
fontSize: 16.0
);
}else{
Fluttertoast.showToast(
msg: "Securehash mis-matched",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.white24,
textColor: Colors.white,
fontSize: 16.0
);
}
AwesomeDialog(
context: context,
dialogType: DialogType.NO_HEADER,
headerAnimationLoop: true,
animType: AnimType.BOTTOMSLIDE,
//title: "AirPay",
desc: 'Transaction Status: ' +
txtSts +
'\nTransaction Status Message: ' +
txtStsMsg)
.show();
}
void ValidateFields() {
var msg = '';
if (fname.text.length < 2) {
msg = 'Enter first name';
} else if (RegExp(r"^[a-zA-Z0-9]+$").hasMatch(fname.text) == false) {
msg = 'Enter a valid first name';
} else if (lname.text.isEmpty) {
msg = 'Enter last name';
} else if (RegExp(r"^[a-zA-Z0-9]+$").hasMatch(lname.text) == false) {
msg = 'Enter a valid last name';
} else if (email.text.isEmpty && phone.text.isEmpty) {
msg = 'Enter an email ID or phone number';
} else if (email.text.isNotEmpty &&
RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9._`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(email.text) ==
false) {
msg = "Please enter a valid email";
} else if (phone.text.isNotEmpty && phone.text.length < 10) {
msg = 'Enter a valid phone number';
} else if (orderId.text.isEmpty) {
msg = 'Enter order ID';
} else if (amount.text.isEmpty) {
msg = 'Enter an amount to proceed';
} else if (amount.text == '0') {
msg = 'Enter valid amount to proceed';
}
else if(txn_subtype.text == "12" && subscription_date.text.toString().isEmpty){
msg = 'Enter valid Subscription Next Run Date';
}
else if(txn_subtype.text == "12" && subscription_frequency.text.toString().isEmpty){
msg = 'Enter valid Subscription Frequency';
}
else if(txn_subtype.text == "12" && subscription_max_amount.text.toString().isEmpty){
msg = 'Enter valid Subscription Max Amount';
}
else if(txn_subtype.text == "12" && subscription_amount.text.toString().isEmpty){
msg = 'Enter valid Subscription Amount';
}
else if(txn_subtype.text == "12" && subscription_rec_count.text.toString().isEmpty){
msg = 'Enter valid Subscription Recurring Count';
}
if (msg.isNotEmpty) {
AwesomeDialog(
context: context,
dialogType: DialogType.NO_HEADER,
headerAnimationLoop: true,
animType: AnimType.BOTTOMSLIDE,
btnOkOnPress: () {},
btnOkColor: Colors.red,
desc: msg)
.show();
return;
}
//Testing Credentails
String domainPath =
''; // Please enter same input as successurl
String successURL =
''; // Please enter successurl
String failedURL =
''; // Please enter same input as successurl
var setAllStr =
'${email.text}${fname.text}${lname.text}${fullAddress.text}${city.text}${state.text}${country.text}${amo
unt.text
.toString()}${orderId.text
.toString()}${siindexvar.toString()}$formattedDate';
sb_nextrundate: subscription_date.text,
sb_period: dropdownValue.toString(),
sb_frequency: subscription_frequency.text,
sb_amount: subscription_amount.text,
sb_isrecurring: "1",
sb_recurringcount: subscription_rec_count.text,
sb_retryattempts: subRetryValue,
sb_maxamount: subscription_max_amount.text
);
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => new AirPay(
user: user,
closure: (status, response) => {onComplete(status, response)}),
),
);
}
setState(() {
selectedDate = picked;
final formattedDate = DateFormat('dd/MM/yyyy').format(selectedDate.toLocal());
//subscription_date.text = selectedDate.toLocal().toString().split(' ')[0];
subscription_date.text = formattedDate;
});
}
}
@override
Widget build(BuildContext context) {
String newValue = "";
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Image.asset(
'assets/airpays.png',
height: 40,
color: Colors.white,
width: 200,
),
backgroundColor: Colors.blue[900],
),
backgroundColor: Colors.grey[400],
body: SafeArea(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
margin: EdgeInsets.fromLTRB(8.0, 8, 8.0, 4),
color: Colors.white,
child: Padding(
padding: const EdgeInsets.fromLTRB(12.0, 2.0, 12.0, 15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Personal Information',
style: TextStyle(
fontSize: 20.0,
color: Colors.blue[900],
fontWeight: FontWeight.bold),
),
SizedBox(
height: 15.0,
),
Row(
children: [
Expanded(
child: Text(
'First Name *',
style: TextStyle(
fontSize: 18.0, color: Colors.blue[900]),
)),
SizedBox(
width: 10.0,
),
Expanded(
child: Text(
'Last Name *',
style: TextStyle(
fontSize: 18.0, color: Colors.blue[900]),
),
),
],
),
Row(
children: [
Expanded(
child: TextFormField(
inputFormatters: [
// FilteringTextInputFormatter.allow(RegExp(r'^[a-zA-Z0-9]+$')),
FilteringTextInputFormatter.deny(_emojiRegex),
FilteringTextInputFormatter.deny(regex),
new LengthLimitingTextInputFormatter(18),
],
keyboardType: TextInputType.name,
decoration: InputDecoration(
hintText: 'First Name',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey, fontSize: 15.0),
),
controller: fname,
)),
SizedBox(
width: 10.0,
),
Expanded(
child: TextFormField(
inputFormatters: [
FilteringTextInputFormatter.deny(_emojiRegex),
FilteringTextInputFormatter.deny(regex),
// FilteringTextInputFormatter.allow(RegExp(r'^[a-zA-Z0-9]+$')),
new LengthLimitingTextInputFormatter(18),
],
keyboardType: TextInputType.name,
decoration: InputDecoration(
hintText: 'Last Name',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey, fontSize: 15.0),
),
controller: lname,
),
),
],
),
SizedBox(
height: 8.0,
),
Container(
child: TextFormField(
validator: (value) => EmailValidator.validate(value!)
? null
: "Please enter a valid email",
inputFormatters: [
FilteringTextInputFormatter.deny(_emojiRegex),
// FilteringTextInputFormatter.allow(RegExp(r'^[a-zA-Z0-9]+$')),
],
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'Email Id',
// contentPadding: EdgeInsets.all(2.0),
hintStyle:
TextStyle(color: Colors.grey, fontSize: 15.0),
),
controller: email,
),
),
SizedBox(
height: 8.0,
),
Container(
child: TextFormField(
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.deny(_emojiRegex),
new LengthLimitingTextInputFormatter(
10), // for mobile
FilteringTextInputFormatter.digitsOnly
], // Only numbers can be entered
decoration: InputDecoration(
hintText: 'Phone',
// contentPadding: EdgeInsets.all(2.0),
hintStyle:
TextStyle(color: Colors.grey, fontSize: 15.0),
),
controller: phone,
),
),
SizedBox(
height: 15.0,
),
],
),
),
),
Visibility(
visible: true,
child: Card(
margin: EdgeInsets.fromLTRB(8.0, 8, 8.0, 4),
color: Colors.white,
child: Padding(
padding: EdgeInsets.fromLTRB(8.0, 8, 8.0, 4),
child: Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'Address',
style: TextStyle(
color: Colors.blue[900],
fontSize: 20.0,
fontWeight: FontWeight.bold),
),
IconButton(
onPressed: () {
_showAddress();
},
icon: isVisible
? Icon(Icons.arrow_drop_up)
: Icon(Icons.arrow_drop_down),
color: Colors.black,
)
],
),
Visibility(
visible: isVisible,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Container(
child: TextFormField(
inputFormatters: <TextInputFormatter>[
// FilteringTextInputFormatter.allow(RegExp(r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
FilteringTextInputFormatter.deny(_emojiRegex),
new LengthLimitingTextInputFormatter(
254),
],
keyboardType: TextInputType.text,
decoration: InputDecoration(
hintText: 'Full Address',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: fullAddress,
),
),
SizedBox(
height: 8.0,
),
Container(
child: TextFormField(
inputFormatters: <TextInputFormatter>[
// FilteringTextInputFormatter.allow(RegExp(r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
FilteringTextInputFormatter.deny(_emojiRegex),
new LengthLimitingTextInputFormatter(
18),
],
keyboardType: TextInputType.text,
decoration: InputDecoration(
hintText: 'City Name',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: city,
),
),
SizedBox(
height: 8.0,
),
Row(
children: [
Expanded(
child: Text(
'State Name',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue[900]),
)),
SizedBox(
width: 8.0,
),
Expanded(
child: Text(
'Country Name',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue[900]),
),
),
],
),
Row(
children: [
Expanded(
child: TextFormField(
inputFormatters: <TextInputFormatter>[
// FilteringTextInputFormatter.allow(RegExp(r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
FilteringTextInputFormatter.deny(_emojiRegex),
new LengthLimitingTextInputFormatter(
18),
],
keyboardType: TextInputType.name,
decoration: InputDecoration(
hintText: 'State',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: state,
)),
SizedBox(
width: 10.0,
),
Expanded(
child: TextFormField(
inputFormatters: <
TextInputFormatter>[
// FilteringTextInputFormatter.allow(RegExp(r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
FilteringTextInputFormatter.deny(_emojiRegex),
new LengthLimitingTextInputFormatter(
18),
],
keyboardType: TextInputType.name,
decoration: InputDecoration(
hintText: 'Country ',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: country,
),
),
],
),
SizedBox(
height: 8.0,
),
Container(
child: TextFormField(
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.deny(_emojiRegex),
FilteringTextInputFormatter
.digitsOnly,
new LengthLimitingTextInputFormatter(
8),
],
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'PinCode',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: pincode,
),
),
SizedBox(
height: 15.0,
),
],
),
),
//Subscription Child
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'Subscription',
style: TextStyle(
color: Colors.blue[900],
fontSize: 20.0,
fontWeight: FontWeight.bold),
),
IconButton(
onPressed: () {
_showSubscription();
},
icon: isSubVisible
? Icon(Icons.arrow_drop_up)
: Icon(Icons.arrow_drop_down),
color: Colors.black,
)
],
),
Visibility(
visible: isSubVisible,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Container(
child: TextFormField(
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.deny(_emojiRegex),
FilteringTextInputFormatter
.digitsOnly,
new LengthLimitingTextInputFormatter(
2),
],
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Txn Subtype',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: txn_subtype,
),
),
SizedBox(
height: 15.0,
),
Text(
'Subscription Next Run Date',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue[900]),
),
SizedBox(
height: 10.0,
),
Container(
child: TextFormField(
inputFormatters: <TextInputFormatter>[
// FilteringTextInputFormatter.allow(RegExp(r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
FilteringTextInputFormatter.deny(_emojiRegex),
new LengthLimitingTextInputFormatter(
254),
],
keyboardType: TextInputType.text,
decoration: InputDecoration(
hintText: 'Subscription Next Run Date',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: subscription_date,
onTap: () => _selectDate(context),
),
),
SizedBox(
height: 10.0,
),
Text(
'Period',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue[900]),
),
SizedBox(
height: 10.0,
),
DropdownMenu<String>(
initialSelection: subscription_period.first,
onSelected: (String ? value){
setState(() {
dropdownValue = value!;
if(dropdownValue =="Day"){
dropdownValue = "D";
}else if(dropdownValue =="Week"){
dropdownValue = "W";
});
},
dropdownMenuEntries:
subscription_period.map<DropdownMenuEntry<String>>((String value) {
return DropdownMenuEntry<String>(value: value, label: value);
}).toList(),
),
SizedBox(
height: 10.0,
),
Row(
children: [
Expanded(
child: Text(
'Frequency',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue[900]),
)),
SizedBox(
height: 10.0,
),
Expanded(
child: Text(
'Max Amount',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue[900]),
),
),
],
),
Row(
children: [
Expanded(
child: TextFormField(
inputFormatters: <TextInputFormatter>[
// FilteringTextInputFormatter.allow(RegExp(r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
FilteringTextInputFormatter.deny(_emojiRegex),
new LengthLimitingTextInputFormatter(
18),
],
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Frequency',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: subscription_frequency,
)),
SizedBox(
width: 10.0,
),
Expanded(
child: TextFormField(
inputFormatters: <
TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
FilteringTextInputFormatter.deny(_emojiRegex),
new LengthLimitingTextInputFormatter(
18),
],
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Max Amount ',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: subscription_max_amount,
),
),
],
),
SizedBox(
height: 10.0,
),
Row(
children: [
Expanded(
child: Text(
'Subcription Amount',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue[900]),
)),
SizedBox(
height: 10.0,
),
Expanded(
child: Text(
'Recurring Count',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue[900]),
),
),
],
),
Row(
children: [
Expanded(
child: TextFormField(
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
FilteringTextInputFormatter.deny(_emojiRegex),
new LengthLimitingTextInputFormatter(
18),
],
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Subscription Amount',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: subscription_amount,
)),
SizedBox(
height: 10.0,
),
Expanded(
child: TextFormField(
inputFormatters: <
TextInputFormatter>[
new LengthLimitingTextInputFormatter(3),
// FilteringTextInputFormatter.allow(RegExp(r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
FilteringTextInputFormatter.deny(_emojiRegex),
FilteringTextInputFormatter.digitsOnly,
new LengthLimitingTextInputFormatter(
18),
],
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Recurring Count',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 15.0),
),
controller: subscription_rec_count,
),
),
],
),
SizedBox(
height: 10.0,
),
Text(
'Retry Attempts:',
style: TextStyle(
fontSize: 18.0,
color: Colors.blue[900]),
),
SizedBox(
height: 10.0,
),
DropdownMenu<String>(
initialSelection: subscription_retry.first,
onSelected: (String ? value){
setState(() {
subRetryValue = value!;
if(subRetryValue == "No"){
subRetryValue = "0";
}else {
subRetryValue = "1";
}
});
},
dropdownMenuEntries:
subscription_retry.map<DropdownMenuEntry<String>>((String value) {
return DropdownMenuEntry<String>(value: value, label: value);
}).toList(),
),
SizedBox(
height: 10.0,
),
],
),
),
],
)),
)),
Card(
margin: EdgeInsets.all(8.0),
color: Colors.white,
child: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Transaction Information',
style: TextStyle(
fontSize: 20.0,
color: Colors.blue[900],
fontWeight: FontWeight.bold),
),
SizedBox(
height: 15.0,
),
Row(
children: [
Expanded(
child: Text(
'Order Id *',
style: TextStyle(
fontSize: 18.0, color: Colors.blue[900]),
)),
SizedBox(
width: 8.0,
),
Expanded(
child: Text(
'Amount *',
style: TextStyle(
fontSize: 18.0, color: Colors.blue[900]),
),
),
],
),
Row(
children: [
Expanded(
child: TextFormField(
inputFormatters: [
new LengthLimitingTextInputFormatter(20),
FilteringTextInputFormatter.deny(_emojiRegex),
FilteringTextInputFormatter.allow(
RegExp(r'([a-zA-Z0-9])')),
],
keyboardType: TextInputType.name,
decoration: InputDecoration(
hintText: 'Order Id',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey, fontSize: 15.0),
),
controller: orderId,
)),
SizedBox(
width: 8.0,
),
Expanded(
child: TextFormField(
inputFormatters: [
FilteringTextInputFormatter.deny(_emojiRegex),
FilteringTextInputFormatter.allow(RegExp(
r'(^[0-9]{0,7}(?:\.[0-9]{0,2})?)')),
],
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Amount',
// contentPadding: EdgeInsets.all(2.0),
hintStyle: TextStyle(
color: Colors.grey, fontSize: 15.0),
),
controller: amount,
),
),
],
),
SizedBox(
height: 15.0,
),
],
),
),
),
Container(
margin: EdgeInsets.all(8.0),
child: ElevatedButton(
// padding: EdgeInsets.fromLTRB(2.0, 11.0, 2.0, 11.0),
onPressed: () {
ValidateFields();
},
// color: Colors.blue[900],
child: Text(
'NEXT',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
Container(
margin: EdgeInsets.all(8.0),
child: ElevatedButton(
// padding: EdgeInsets.fromLTRB(2.0, 11.0, 2.0, 11.0),
onPressed: () {
Navigator.pop(context);
},
// color: Colors.blue[900],
child: Text(
'BACK',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
)
],
),
),
));
}