Sunday, August 16, 2020

Flutter - Fatora payment gateway

Online money transaction is a fundamental feature of every e-commerce platform that's become a part of our daily lives. An online payment gateway is a tunnel that connects user bank account to the platform where you can transfer your money.

A payment gateway is a software that authorizes you to perform an online transaction through different payment modes like net banking, credit card, debit card, UPI, or the many online wallets that are available these days. A payment gateway plays the role of a third party that securely transfers your money from the bank account to the merchant’s payment account.

 

In this post, we going create a Flutter application to perform payment gateway by using Rest API of Fatora payment gateway. In this demo, user will enter amount and customer email id to complete the transaction. We will use a test API key to perform the whole process in test mode. The final output will look like below:

 




fatora payment gateway?

The Fatora is a smart payment gateway that enables merchants to sell their services quickly and simply through an online application. The Fatora gateway provides robust features for processing online payments:

1. Easy integration with rest API.
2. High level of data transfer security.
3. Creating, recording and speeding up the process of creating invoices.
4. Give startups more securing and necessary time to develop their business.
5. Ensuring the rights providers by collect the price of their services and sales directly.
6. Supporting entrepreneurs and freelancers ( designers, developers, content writers) receiving their money easily and quickly.


You have to perform following steps to use services of Fatora payment gateway:

1. If you are new to Fatora gateway, you have to subscribe at the beginning.
2. To subscribe, you have to send the following information to Maktapp support.
    1. Commercial registration.
    2. A scan copy of a personal identification.
    3. Application name.
    Application type (website or mobile application).
3. API key of thw Firebase Cloud Messaging (in case mobile application), Fatora gateway will send push notifications after the end of processing payments.
4. URL of success and failure page of your application to redirect clients to these URL after the end of processing payments.

After completation of above steps, Fatora
support will send you an API KEY, which is provide to merchant to consume the Fatora rest API. In this demo, we going to use a test API key E4B73FEE-F492-4607-A38D-852B0EBC91C9. So, the whole procress will work in the test mode of Fatora payment gateway.

Creating a new project

1. Create a new Flutter project from File ⇒ New Flutter Project with your development IDE.
2. Add the plugin dio webview_flutter and uuid as a dependency in the pubspec.yaml file. Once you do that, you need to run flutter packages.
3. Now start editing main.dart class as you can see, we have implemented our theme.

import 'package:flutter/material.dart';
import 'package:flutter_fatora_payment_gaetway/pay.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: const Color(0xFF02BB9F),
primaryColorDark: const Color(0xFF167F67),
accentColor: const Color(0xFF167F67),
),
home: MyHomePage(title: 'Flutter Fatora Payment Gateway'),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

String paymentID="";
String orderId="";
String transaction="";

final _teAmount = TextEditingController();
final _teEmail = TextEditingController();

void _pay() {
if (_teAmount.text.isNotEmpty && _teEmail.text.isNotEmpty) {
final result = Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => Pay(
_teAmount.text.trim(),
_teEmail.text.trim(),
"E4B73FEE-F492-4607-A38D-852B0EBC91C9")));
result.then((result) {
transactionResult(result);
});
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
widget.title,
style: TextStyle(color: Colors.white),
),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: getFormUI(),
),
));
}

Widget getFormUI() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
TextFormField(
controller: _teAmount,
decoration: InputDecoration(hintText: 'Amount'),
keyboardType: TextInputType.phone,
maxLength: 10,
),
TextFormField(
controller: _teEmail,
decoration: InputDecoration(hintText: 'Email'),
maxLength: 32,
),
SizedBox(height: 15.0),
RaisedButton(
onPressed: _pay,
child: Text('Pay'),
),
SizedBox(height: 40.0),
Align(
alignment: Alignment.centerLeft,
child: Text(paymentID),
),
Align(
alignment: Alignment.centerLeft,
child: Text(orderId),
),
Align(
alignment: Alignment.centerLeft,
child: Text(transaction),
),
],
);
}

Widget buttonMedium(String buttonLabel, EdgeInsets margin, Color bgColor,
Color textColor, double textSize) {
var loginBtn = Container(
margin: margin,
padding: EdgeInsets.all(10.0),
alignment: FractionalOffset.center,
decoration: BoxDecoration(
color: bgColor,
borderRadius: BorderRadius.all(const Radius.circular(60.0)),
),
child: Text(
buttonLabel,
style: TextStyle(
color: textColor, fontSize: textSize, fontWeight: FontWeight.bold),
),
);
return loginBtn;
}

void transactionResult(String result) {
_teAmount.text = "";
_teEmail.text = "";

setState(() {
var transactionDetail = result.split(" ");

paymentID="Payment Id: "+transactionDetail[0];
orderId="OrderId: "+transactionDetail[1];
transaction="Transaction Id: "+transactionDetail[2];
});

}
}

the getFormUI() method will display input box for amount, email id and a pay button to perform transaction. The transactionResult() method will display result of Fatora transaction.



4.
After that, create class pay.dart to handle Fatora rest API request and it's response. In this class, we'll call getFatoraUrl() method first to get a Fatora interface web url to complete request transaction.

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_fatora_payment_gaetway/ProgressHud.dart';
import 'package:uuid/uuid.dart';
import 'package:webview_flutter/webview_flutter.dart';

class Pay extends StatefulWidget {

final String title;
String packagePrice;
String userEmail;
String fatoraKey;

Pay(this.packagePrice, this.userEmail, this.fatoraKey, {Key key, this.title})
: super(key: key);

@override
_PayState createState() => _PayState(packagePrice,userEmail,fatoraKey);
}

class _PayState extends State<Pay> {
String packagePrice;
String userEmail;
String fatoraKey;

_PayState(this.packagePrice, this.userEmail,this.fatoraKey);

bool _isLoading = true;
WebViewController controller;
static var uri = "https://maktapp.credit/v3/";
String baseURl = "https://maktapp.credit";

static BaseOptions options = BaseOptions(
baseUrl: uri,
responseType: ResponseType.plain,
connectTimeout: 30000,
receiveTimeout: 30000,
validateStatus: (code) {
if (code >= 200) {
return true;
} else {
return false;
}
});

static Dio dio = Dio(options);



@override
void initState() {
super.initState();
getFatoraUrl();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Fatora Payment Gateway",style: TextStyle(color:Colors.white),),
),
body: ProgressHUD(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Stack(
children: <Widget>[
WebView(
initialUrl: baseURl,
javascriptMode: JavascriptMode.unrestricted,
onPageFinished: pageFinishedLoading,
onWebViewCreated: (WebViewController webViewController) {
controller = webViewController;
}),
],
),
),
inAsyncCall: _isLoading,
opacity: 0.0,
),

);
}

void pageFinishedLoading(String url) {
setState(() {
_isLoading = false;
if (url.contains("SuccessPayment")) {

var transactionResponse = url.split('paymentID=')[1].split("&orderId=");
var paymentID = transactionResponse[0];
var orderId = transactionResponse[1].split("&transactionid=")[0];
var transactionId = transactionResponse[1].split("&transactionid=")[1];
Navigator.pop(context, paymentID+" "+orderId+" "+transactionId);

} else if (url.contains("Declined")) {
setState(() {
baseURl = url;
controller.loadUrl(baseURl);
_isLoading = true;
});
}
});
}

Future<dynamic> getFatoraUrl() async {
try {
var response = await dio.post('AddTransaction', data: {
"token": fatoraKey,
"orderId": Uuid().v1(),
"amount": packagePrice,
"customerEmail": userEmail,
"lang": "en"
});
if (response.statusCode == 200 || response.statusCode == 201) {
var responseJson = json.decode(response.data);

setState(() {
baseURl = responseJson["result"];
controller.loadUrl(baseURl);
_isLoading = true;
});

return responseJson;
} else
print(">>Error: " + response.statusCode.toString());
} on DioError catch (exception) {
if (exception == null ||
exception.toString().contains('SocketException')) {
print(">>Error: " + "Network Error");
} else if (exception.type == DioErrorType.RECEIVE_TIMEOUT ||
exception.type == DioErrorType.CONNECT_TIMEOUT) {
print(">>Error: " +
"Could'nt connect, please ensure you have a stable network.");
} else {
return null;
}
}
}
}

after that, when user enter detail and tap on the pay button. The pageFinishedLoading() automatically detact response of transaction success and fail. If transaction success, you can see the transaction detail below of the screen.

5. The ProgressHud.dart class will display loader for the pay.dart screen.

library modal_progress_hud;
import 'package:flutter/material.dart';

class ProgressHUD extends StatelessWidget {

final Widget child;
final bool inAsyncCall;
final double opacity;
final Color color;
final Animation<Color> valueColor;

ProgressHUD({
Key key,
@required this.child,
@required this.inAsyncCall,
this.opacity = 0.3,
this.color = Colors.black45,
this.valueColor,
}) : super(key: key);

@override
Widget build(BuildContext context) {
List<Widget> widgetList = new List<Widget>();
widgetList.add(child);
if (inAsyncCall) {
final modal = new Stack(
children: [
new Opacity(
opacity: opacity,
child: ModalBarrier(dismissible: false, color: color),
),
new Center(
child: new CircularProgressIndicator(
valueColor: valueColor,
),
),
],
);
widgetList.add(modal);
}
return Stack(
children: widgetList,
);
}
}


If you have followed the above post carefully. You will be able to do transaction with Fatora payment gateway as shown above. But if you are facing any problem to implement the rest API and you have any quires, please feel free to ask it from comment section below.

Share:

Get it on Google Play

React Native - Start Development with Typescript

React Native is a popular framework for building mobile apps for both Android and iOS. It allows developers to write JavaScript code that ca...