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

flutter pub add edfapay_softpos_sdk

or add the dependency in project pubspec.yaml

dependencies:
edfapay_softpos_sdk: 1.0.0+1 # or specify 'any' to always look for the latest version

Important

FlutterFragmentActivity

  • Change the android MainActivity super class from FlutterActivity to FlutterFragmentActivity
  • ./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

import 'package:edfapay_softpos_sdk/edfapay_softpos_sdk.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';

2: Initialization

2.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****",
    );
    

2.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 == 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) {
      
        if (e is PlatformException) {
            toast(e.message ?? e.code);
        } else {
            toast("Error Initializing SDK: ${e.toString()}");
        }
      
    });
    

3: Setting Theme (Optional)

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');

4: Pay


final params = TxnParams(
    amount: "10.000",
    transactionType: TransactionType.purchase,
    orderId: "12340987" // Optional, If not provided the transactionId will be considered as orderId
);

EdfaPayPlugin.pay(
    params,
    onPaymentProcessComplete: (status, code, result, isProcessComplete){
      
        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:

// ignore_for_file: avoid_print
import 'package:edfapay_softpos_sdk/edfapay_softpos_sdk.dart';
import 'package:edfapay_softpos_sdk/enums/env.dart';
import 'package:edfapay_softpos_sdk/helpers.dart';
import 'package:edfapay_softpos_sdk/models/txn_params.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:edfapay_softpos_sdk/models/edfapay_credentials.dart';
import 'helper_methods.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 = "1C55275E0D3E7E527881B05FB2C22C2247FE477223B5B116E12D9A151A17FD68";
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,
    );
    */

    /* Above are all possible ways to create credentials*/
    EdfaPayCredentials credentials = EdfaPayCredentials.withEmailPassword(
        environment: Env.DEVELOPMENT,
        email: null,
        password: null
    );

    setTheme();
    EdfaPayPlugin.initiate(credentials: credentials).then((value) {
      setState(() {
        _edfaPluginInitiated = value.status;
      });

    }).catchError((e) {
      if (e is PlatformException) {
        toast(e.message ?? e.code);
      } else {
        toast("Error Initializing SDK");
      }
    });
  }

  setTheme() async {
    final logo = await assetsBase64(logoPath);
    EdfaPayPlugin.theme()
        .setButtonBackgroundColor("#06E59F")
        .setButtonTextColor("#000000")
        .setHeaderImage(logo)
        .setPoweredByImage(logo);
  }

  pay() async {
    if (!_edfaPluginInitiated) {
      toast("Edfapay plugin not initialized.");
      return;
    }

    final params = TxnParams.purchase(
        amount: amountToPay,
        orderId: "12340987"
    );

    EdfaPayPlugin.enableLogs(true);
    EdfaPayPlugin.pay(params, onPaymentProcessComplete: (status, code, result, isProcessComplete) {
      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, isProcessComplete) {
      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