edfapay_softpos_sdk 1.0.4
edfapay_softpos_sdk: ^1.0.4 copied to clipboard
Helps developers to easly integrate EdfaPay SoftPos to flutter mobile application with few simple steps.
Revamped Flutter Edfapay SoftPOS SDK #
Helps developers to easly integrate EdfaPay SoftPos to flutter mobile application with few simple steps.
Wiki & Documentation #
EdfaPay SoftPos SDK #
Important
Install edfapay-softpos-sdk #
- Add the dependency in to your project by running terminal command
pub addat project directory.
flutter pub add edfapay_softpos_sdk
- or add the dependency in to project
pubspec.yaml
dependencies:
edfapay_softpos_sdk: 1.0.0+1 # or specify 'any' to always look for the latest version
Important
Set Repository Access Credentials #
- Add below credentials properties to your project
./android/gradle.propertiesor~/.gradle/gradle.properties
PARTNER_REPO_USERNAME=edfapay-sdk-consumer
PARTNER_REPO_PASSWORD=Edfapay@123
Important
FlutterFragmentActivity #
- Change the android MainActivity super class from
FlutterActivitytoFlutterFragmentActivity - Path: At project directory:
./android/app/src/main/kotlin/app_package_tree/MainActivity.kt
Example
package com.edfapay.sample_app // your application package
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity: FlutterFragmentActivity()
Usage #
1: Imports #
- All files under package
package:edfapay_softpos_sdkyou need to import to your integration class.
import 'package:edfapay_softpos_sdk/edfapay_softpos_sdk.dart';
import 'package:edfapay_softpos_sdk/models/edfapay_credentials.dart';
import 'package:edfapay_softpos_sdk/enums/flow_type.dart';
import 'package:edfapay_softpos_sdk/enums/purchase_secondary_action.dart';
import 'package:edfapay_softpos_sdk/enums/presentation.dart';
import 'package:edfapay_softpos_sdk/models/txn_params.dart';
import 'package:edfapay_softpos_sdk/enums/env.dart';
import 'package:edfapay_softpos_sdk/helpers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
2: Setting Theme (Optional) #
2.1: Setting Colors and Logos
final logo = "base64 of image";
// final logo = await assetsBase64('path to image asset');
EdfaPayPlugin.theme()
.setPrimaryColor("#06E59F")
.setSecondaryColor("#000000")
.setPoweredByImage(logo)
.setHeaderImage(logo)
Tip
There is an helper method in SDK to convert image asset to base64
final logo = await assetsBase64('path to image asset');
2.2: Setting Presentation
- Presentation.FULLSCREEN
- Presentation.DIALOG_CENTER
- Presentation.DIALOG_TOP_FILL
- Presentation.DIALOG_BOTTOM_FILL
- Presentation.DIALOG_TOP_START
- Presentation.DIALOG_TOP_END
- Presentation.DIALOG_TOP_CENTER
- Presentation.DIALOG_BOTTOM_START
- Presentation.DIALOG_BOTTOM_END
- Presentation.DIALOG_BOTTOM_CENTER
Note: Properties of each presentation can be change from default to change User Experience
// Usage:
EdfaPayPlugin.theme()
.setPresentation(
Presentation.DIALOG_CENTER
.sizePercent(0.85) // aligned to screen smallest axis 0.20 to 1.0
.dismissOnBackPress(true)
.dismissOnTouchOutside(true)
.animateExit(true)
.animateEntry(true)
.dimBackground(true)
.dimAmount(1.0) // 0.0 to 1.0
.marginAll(0) // open number
.cornerRadius(20) // open number
.marginHorizontal(10) // open number
.marginVertical(10) // open number
.setPurchaseSecondaryAction(PurchaseSecondaryAction.none)
);
2.3: Secondary/Post Purchase Transaction Action
- PurchaseSecondaryAction.reverse
- PurchaseSecondaryAction.refund
- PurchaseSecondaryAction.none
// Usage:
EdfaPayPlugin.theme()
.setPresentation(
Presentation.DIALOG_CENTER
.setPurchaseSecondaryAction(PurchaseSecondaryAction.none)
);
2.4: Enable or disable PIN PAD shuffle at PIN Transaction
// Usage:
EdfaPayPlugin.theme()
.setPresentation(
Presentation.DIALOG_CENTER
.setShufflePinPad(true); // default false
);
3: Initialization #
3.1: Create Credentials
-
I will prompt for the credentials whether user Email/Password or Token
EdfaPayCredentials credentials = EdfaPayCredentials.withEmailPassword( environment: Env.DEVELOPMENT, email: null, password: null ); -
I will also prompt for the credentials whether user Email/Password or Token
EdfaPayCredentials credentials = EdfaPayCredentials.withInput( environment: Env.PRODUCTION, ); -
I will prompt for the credentials with prefilled user Email/Password
EdfaPayCredentials credentials = EdfaPayCredentials.withEmailPassword( environment: Env.DEVELOPMENT, email: "user@email.com", password: "Password@123" ); -
I will prompt for the credentials with prefilled user Email
EdfaPayCredentials credentials = EdfaPayCredentials.withEmail( environment: Env.DEVELOPMENT, email: "user@email.com", ); -
I will silently prepare and initialize the SDK with prefilled terminal Token
- This should be Terminal Token to behave as silent SDK initialization
EdfaPayCredentials credentials = EdfaPayCredentials.withToken( environment: Env.DEVELOPMENT, token: "****Terminal Token Should be Generated at Edfapay SoftPOS Portal****", );
3.2: Initialize with Created Credentials
- This function will begin initialization and configure your phone for transactions.
- Note: Make sure to catch the exception and observe the reason of failed initialization.
EdfaPayPlugin.initiate(credentials: credentials).then((value){ if(value.status == false){ // Handle initialization failed // inform the developer or user initializing failed // Developer should observe this and take necessary action // Note: If exception is not caught see the console for error through. }else{ // Allow user to start payment process in next step } }).catchError((e) { print('** Error Initializing SDK **'); print('>>> Exception'); print(' >>> ${e.toString()}'); if (e is PlatformException) { print(' >>> PlatformException <<<'); } else { print(' >>> SDK InitializationnError <<<'); } });
3.3: Enable start transaction from remote source [Optional]
- Make sure to open RemoteChannel after successful SDK initialization.
// Usage: Make sure to open RemoteChannel after initialize successful EdfaPayPlugin.RemoteChannel.LocalNetwork(8080, 3.0).open(); - Request from remote source:
# This command passing json to local IP and port of device running our SDK, via Netcat nc echo '{"id":"pay.1","data":{"fun":"purchase","flowType":"DETAIL","amount":"12.0"}}' | nc 192.168.100.70 8080 - Remote Source will receive response in json.
4: Purchase #
- FlowType.immediate
- It will close the Card Scanning Interface immediately after receive response from server.
- FlowType.status
- It will close the Card Scanning Interface at the status animation check/cross.
- FlowType.detail
- It will take the UI flow up to transaction detail screen and will completed by closing screen/ui.
Note: Observe the 4th isFlowCompleted parameter of onPaymentProcessComplete callback.
final params = TxnParams(
amount: "10.000",
transactionType: TransactionType.purchase,
orderId: "12340987" // Optional, If not provided the transactionId will be considered as orderId
);
EdfaPayPlugin.purchase(
params,
flowType: FlowType.detail,
onPaymentProcessComplete: (status, code, result, isFlowCompleted){
if(status){
print(' >>> [ Success ]');
print(' >>> [ ${jsonEncode(result)} ]');
}else{
print(' >>> [ Failed ]');
print(' >>> [ ${jsonEncode(result)} ]');
}
},
onServerTimeOut: (){
print('>>> Server Timeout');
print(' >>> The request timeout while performing transaction at backend');
},
onScanCardTimeOut: (){
print('>>> Scan Card Timeout');
print(' >>> The scan card timeout, no any card tap on device');
},
onCancelByUser: (){
print('>>> Canceled By User');
print(' >>> User have cancel the scanning/payment process on its own choice');
},
onError: (error){
print('>>> Exception');
print(' >>> "Scanning/Payment process through an exception, Check the logs');
print(' >>> ${error.toString()}');
}
);
Example #
Instruction to Run Example:
- Make sure to install below plugins to your sample flutter app
- Dont forget to apply Important marked configuration/change at the top in to your project
- Copy the below content and paste it to main.dart (make sure to replace all)
// ignore_for_file: avoid_print
import 'package:edfapay_softpos_sdk/edfapay_softpos_sdk.dart';
import 'package:edfapay_softpos_sdk/enums/flow_type.dart';
import 'package:edfapay_softpos_sdk/enums/presentation.dart';
import 'package:edfapay_softpos_sdk/enums/purchase_secondary_action.dart';
import 'package:edfapay_softpos_sdk/models/edfapay_credentials.dart';
import 'package:edfapay_softpos_sdk/models/txn_params.dart';
import 'package:edfapay_softpos_sdk/enums/env.dart';
import 'package:edfapay_softpos_sdk/helpers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/* add the plugin for below: (hexcolor: any) https://pub.dev/packages/hexcolor */
import 'package:hexcolor/hexcolor.dart';
// add the plugin for below: (fluttertoast: any) https://pub.dev/packages/fluttertoast
import 'package:fluttertoast/fluttertoast.dart';
const TERMINAL_TOKEN = "D08BE4C0FE041A155F0028C0FCD042087771DA505D54087EFC3A0FC1183213D6";
const logoPath = "assets/images/edfa_logo.png";
const amountToPay = "01.010";
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var _edfaPluginInitiated = false;
@override
void initState() {
super.initState();
// initiate();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Padding(
padding: const EdgeInsets.all(15),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 20),
Expanded(
flex: 2,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FractionallySizedBox(widthFactor: 0.3, child: Image.asset(logoPath)),
const SizedBox(height: 30),
const Text("SDK", style: TextStyle(fontSize: 65, fontWeight: FontWeight.w700), textAlign: TextAlign.center),
const SizedBox(height: 10),
const Text("v0.0.1", style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
],
),
),
const Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.all(10),
child: Text("You're on your way to enabling your Android App to allow your customers to pay in a very easy and simple way just click the payment button and tap your payment card on NFC enabled Android phone.",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.black45), textAlign: TextAlign.center),
),
),
if(!_edfaPluginInitiated)
ElevatedButton(onPressed: initiate, style: ButtonStyle(backgroundColor: MaterialStatePropertyAll(HexColor("06E59F"))), child: const Text("Initiate", style: TextStyle(color: Colors.black))),
if(_edfaPluginInitiated)
...[
ElevatedButton(onPressed: pay, style: ButtonStyle(backgroundColor: MaterialStatePropertyAll(HexColor("06E59F"))), child: const Text("Pay $amountToPay", style: TextStyle(color: Colors.black))),
ElevatedButton(onPressed: refund, style: ButtonStyle(backgroundColor: MaterialStatePropertyAll(HexColor("06E59F"))), child: const Text("Refund With RRN", style: TextStyle(color: Colors.black))),
ElevatedButton(onPressed: reconcile, style: ButtonStyle(backgroundColor: MaterialStatePropertyAll(HexColor("06E59F"))), child: const Text("Reconciliation", style: TextStyle(color: Colors.black))),
ElevatedButton(onPressed: txnHistory, style: ButtonStyle(backgroundColor: MaterialStatePropertyAll(HexColor("06E59F"))), child: const Text("Txn History $amountToPay", style: TextStyle(color: Colors.black))),
],
const Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Text("Click on button above to test the card processing with 10.00 SAR", style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400), textAlign: TextAlign.center),
),
],
),
),
),
);
}
initiate() async {
EdfaPayPlugin.enableLogs(true);
/*
EdfaPayCredentials credentials = EdfaPayCredentials.withEmailPassword(
environment: Env.DEVELOPMENT,
email: null,
password: null
);
EdfaPayCredentials credentials = EdfaPayCredentials.withEmailPassword(
environment: Env.DEVELOPMENT,
email: "user@mail.com",
password: "Password@123"
);
EdfaPayCredentials credentials = EdfaPayCredentials.withInput(
environment: Env.PRODUCTION,
);
EdfaPayCredentials credentials = EdfaPayCredentials.withEmail(
environment: Env.DEVELOPMENT,
email: "user@mail.com",
);
EdfaPayCredentials credentials = EdfaPayCredentials.withToken(
environment: Env.DEVELOPMENT,
token: TERMINAL_TOKEN,
);
*/
EdfaPayCredentials credentials = EdfaPayCredentials.withToken(
environment: Env.DEVELOPMENT,
token: TERMINAL_TOKEN,
);
setTheme();
EdfaPayPlugin.initiate(credentials: credentials).then((value) {
if(value.status == true){
EdfaPayPlugin.RemoteChannel.LocalNetwork(8080, 3.0).open();
}
setState(() {
_edfaPluginInitiated = value.status;
});
}).catchError((e) {
if (e is PlatformException) {
toast(e.message ?? e.code);
} else {
toast("Error Initializing SDK: ${e.toString()}");
}
});
}
setTheme() async {
final logo = await assetsBase64(logoPath);
final presentation = Presentation.DIALOG_CENTER
.sizePercent(0.85)
.dismissOnTouchOutside(true)
.dimBackground(true)
.dimAmount(1.0)
.marginAll(0)
.animateEntry(true)
.animateExit(true)
.cornerRadius(20)
.dismissOnBackPress(true)
.marginHorizontal(10)
.marginVertical(10)
.setPurchaseSecondaryAction(PurchaseSecondaryAction.reverse)
.setShufflePinPad();
EdfaPayPlugin.theme()
.setButtonBackgroundColor("#06E59F")
.setButtonTextColor("#000000")
.setHeaderImage(logo)
.setPoweredByImage(logo)
.setPresentation(presentation);
}
pay() async {
if (!_edfaPluginInitiated) {
toast("Edfapay plugin not initialized.");
return;
}
final params = TxnParams.purchase(
amount: amountToPay,
orderId: "12340987"
);
EdfaPayPlugin.enableLogs(true);
EdfaPayPlugin.purchase(params, flowType: FlowType.detail, onPaymentProcessComplete: (status, code, result, isFlowCompleted) {
toast("Card Payment Process Completed");
print('>>> Payment Process Complete');
}, onServerTimeOut: () {
toast("Server Request Timeout");
print('>>> Server Timeout');
print(' >>> The request timeout while performing transaction at backend');
}, onScanCardTimeOut: () {
toast("Card Scan Timeout");
print('>>> Scan Card Timeout');
print(' >>> The scan card timeout, no any card tap on device');
}, onCancelByUser: () {
toast("Cancel By User");
print('>>> Canceled By User');
print(' >>> User have cancel the scanning/payment process on its own choice');
}, onError: (Exception error) {
toast(error.toString());
print('>>> Exception');
print(' >>> "Scanning/Payment process through an exception, Check the logs');
print(' >>> ${error.toString()}');
});
}
refund() async {
if (!_edfaPluginInitiated) {
toast("Edfapay plugin not initialized.");
return;
}
final params = TxnParams.refundWithRrn(
amount: amountToPay,
transactionDate: DateTime(2025, 08, 26),
rrn: null,
);
EdfaPayPlugin.enableLogs(true);
EdfaPayPlugin.refund(params, onPaymentProcessComplete: (status, code, result, isFlowCompleted) {
toast("Card Payment Process Completed");
print('>>> Payment Process Complete');
}, onServerTimeOut: () {
toast("Server Request Timeout");
print('>>> Server Timeout');
print(' >>> The request timeout while performing transaction at backend');
}, onScanCardTimeOut: () {
toast("Card Scan Timeout");
print('>>> Scan Card Timeout');
print(' >>> The scan card timeout, no any card tap on device');
}, onCancelByUser: () {
toast("Cancel By User");
print('>>> Canceled By User');
print(' >>> User have cancel the scanning/payment process on its own choice');
}, onError: (Exception error) {
toast(error.toString());
print('>>> Exceptio¬n');
print(' >>> "Scanning/Payment process through an exception, Check the logs');
print(' >>> ${error.toString()}');
});
}
reconcile() async {
if (!_edfaPluginInitiated) {
toast("Edfapay plugin not initialized.");
return;
}
EdfaPayPlugin.reconcile(
onSuccess: (response){
toast("Success reconcile");
},
onError: (error){
print('>>> Exception');
print(' >>> "Scanning/Payment process through an exception, Check the logs');
print(' >>> ${error.toString()}');
}
);
}
txnHistory() async {
if (!_edfaPluginInitiated) {
toast("Edfapay plugin not initialized.");
return;
}
EdfaPayPlugin.txnHistory(
onSuccess: (response){
toast("Success txnHistory");
},
onError: (error){
print('>>> Exception');
print(' >>> "Scanning/Payment process through an exception, Check the logs');
print(' >>> ${error.toString()}');
}
);
}
toast(String text) {
Fluttertoast.showToast(msg: text);
}
}
License #
MIT