Android SDK

SDK Guide for Android

Demo project


SDK Android Installation / Usage

1- Add mavenCentral() under allprojects/repositories and buildscript/repositories in the project Gradle file.

2-Add the following dependency in the app Gradle file:

implementation 'com.myfatoorah:myfatoorah:2.2.17'

Add bellow line in the onCreate() method of your Application class:

// set up your My Fatoorah Merchant details
MFSDK.init("Put you Token API Key here", MFCountry.KUWAIT, MFEnvironment.TEST)
// set up your My Fatoorah Merchant details
MFSDK.INSTANCE.init("Put you Token API Key here", MFCountry.KUWAIT, MFEnvironment.TEST);

Add bellow code in the onCreate() method of your Activity:

// You can custom your action bar, but this is optional not required to set this line
MFSDK.setUpActionBar("MyFatoorah Payment", R.color.toolbar_title_color, R.color.toolbar_background_color, true)
// To hide action bar
// MFSDK.setUpActionBar(isShowToolBar = false)
// You can custom your action bar, but this is optional not required to set this line
 MFSDK.INSTANCE.setUpActionBar("MyFatoorah Payment", R.color.toolbar_title_color, R.color.toolbar_background_color, true);

📘

After Testing

Once your testing is finished, simply replace environment from TEST to LIVE and the API URL with the live, click here for more information.


Initiate/Execute Payment

As described earlier for the Gateway Integration, we are going to have the SDK integrated with the same steps to make a successful integration with the SDK.

🚧

Initiate Payment

As a good practice, you don't have to call the Initiate Payment function every time you need to execute payment, but you have to call it at least once to save the PaymentMethodId that you will need to call Execute Payment

// initiatePayment 

val request = MFInitiatePaymentRequest(0.100, MFCurrencyISO.KUWAIT_KWD)
MFSDK.initiatePayment(
    request,
    MFAPILanguage.EN
) { result: MFResult<MFInitiatePaymentResponse> ->
    when (result) {
        is Success ->
            Log.d(TAG, "Response: " + Gson().toJson(result.response))
        is Fail ->
            Log.d(TAG, "Fail: " + Gson().toJson(result.error))
    }
}
    

// executePayment 

val request = MFExecutePaymentRequest(1, 0.100)
MFSDK.executePayment(
    this,
    request,
    MFAPILanguage.EN,
    onInvoiceCreated = {
        Log.d(TAG, "invoiceId: $it")
    }
) { invoiceId: String, result: MFResult<MFGetPaymentStatusResponse> ->
    when (result) {
        is Success -> 
            Log.d(TAG, "Response: " + Gson().toJson(result.response))
        is Fail -> 
            Log.d(TAG, "Fail: " + Gson().toJson(result.error))
    }
}
// initiatePayment 

MFInitiatePaymentRequest request = new MFInitiatePaymentRequest(0.100, MFCurrencyISO.KUWAIT_KWD);
MFSDK.INSTANCE.initiatePayment(
    request,
    MFAPILanguage.EN,
    (MFResult<MFInitiatePaymentResponse> result) -> {
        if (result instanceof Success) {
            Log.d(TAG, "Response: " + new Gson().toJson(
                    ((Success<MFInitiatePaymentResponse>) result).getResponse()));
        } else if (result instanceof Fail) {
            Log.d(TAG, "Error: " + new Gson().toJson(((Fail) result).getError()));
        }

        return Unit.INSTANCE;
    });


// executePayment 

MFExecutePaymentRequest request = new MFExecutePaymentRequest(1, 0.100);
MFSDK.INSTANCE.executePayment(
        this,
        request,
        MFAPILanguage.EN,
        (String invoiceId) -> {
            Log.d(TAG, "invoiceId: " + invoiceId);
            return Unit.INSTANCE;
        },
        (String invoiceId, MFResult<MFGetPaymentStatusResponse> result) -> {
            if (result instanceof Success)
                Log.d(TAG, "Response: " + new Gson().toJson(((Success<MFGetPaymentStatusResponse>) result).getResponse()));
            else if (result instanceof Fail)
                Log.d(TAG, "Error: " + new Gson().toJson(((Fail) result).getError()));

            return Unit.INSTANCE;
        });

Direct Payment/Tokenization

As we have explained earlier in the [Direct Payment] integration and how it works, it also has the same scenario for the SDK implementation, you have to know the following steps to understand how it works:

  • Get the payment method that allows Direct Payment by calling initiatePayment to get paymentMethodId
  • Collect card info from user MFCardInfo(cardNumber: "51234500000000081", cardExpiryMonth: "05", cardExpiryYear: "21", cardSecurityCode: "100", saveToken: false)
  • If you want to save your credit card info and get a token for next payment you have to set saveToken: true and you will get the token in the response read more in Tokenization
  • If you want to execute a payment through a saved token you have use MFCardInfo(cardToken: "put your token here")
  • Now you are ready to execute the payment, please check the following sample code
val request = MFExecutePaymentRequest(2, 0.100)

// val mfCardInfo = MFCardInfo("Your token here")
val mfCardInfo = MFCardInfo("5123450000000008", "09", "21", "100", true)

MFSDK.executeDirectPayment(
    this,
    request,
    mfCardInfo,
    MFAPILanguage.EN,
    onInvoiceCreated = {
        Log.d(TAG, "invoiceId: $it")
    }
) { invoiceId: String, result: MFResult<MFDirectPaymentResponse> ->
    when (result) {
        is Success ->
            Log.d(TAG, "Response: " + Gson().toJson(result.response))
        is Fail ->
            Log.d(TAG, "Fail: " + Gson().toJson(result.error))
    }
}
MFExecutePaymentRequest request = new MFExecutePaymentRequest(2, 0.100);

// MFCardInfo mfCardInfo = new MFCardInfo("Your token here");
MFCardInfo mfCardInfo = new MFCardInfo("5123450000000008", "09", "21", "100", false);

MFSDK.INSTANCE.executeDirectPayment(
        this,
        request,
        mfCardInfo,
        MFAPILanguage.EN,
        (String invoiceId) -> {
            Log.d(TAG, "invoiceId: " + invoiceId);
            return Unit.INSTANCE;
        },
        (String invoiceId, MFResult<MFDirectPaymentResponse> result) -> {
            if (result instanceof Success) 
                Log.d(TAG, "Response: " + new Gson().toJson(((Success<MFDirectPaymentResponse>) result).getResponse()));
            else if (result instanceof Fail) 
                Log.d(TAG, "Error: " + new Gson().toJson(((Fail) result).getError()));

            return Unit.INSTANCE;
        });

Send Payment

We have explained in the Send Payment section earlier, the different usage cases for it and how it works, here we are going to embed some sample code for calling it through the SDK on the different platforms

val request = MFSendPaymentRequest(0.100, "Customer name", MFNotificationOption.LINK)
MFSDK.sendPayment(request, MFAPILanguage.EN) { result: MFResult<MFSendPaymentResponse> ->
    when(result){
        is MFResult.Success ->
            Log.d(TAG, "Response: " + Gson().toJson(result.response))
        is MFResult.Fail ->
            Log.d(TAG, "Fail: " + Gson().toJson(result.error))
    }
}
MFSendPaymentRequest request = new MFSendPaymentRequest(0.100, "Customer name", MFNotificationOption.LINK);
MFSDK.INSTANCE.sendPayment(request, MFAPILanguage.EN, (MFResult<MFSendPaymentResponse> result) -> {
        if (result instanceof MFResult.Success)
            Log.d(TAG, "Response: " + new Gson().toJson(((MFResult.Success<MFSendPaymentResponse>) result).getResponse()));
        else if (result instanceof MFResult.Fail)
            Log.d(TAG, "Error: " + new Gson().toJson(((MFResult.Fail) result).getError()));

        return Unit.INSTANCE;
    });

Payment Inquiry

We have explain the main usage for the Payment Inquiry function, that will enable your application to get the full details about a certain invoice / payment. You can use this function within your application on the different platforms as well. Here we are explaining some samples of its usage through the SDK.

val request = MFGetPaymentStatusRequest("12345", MFKeyType.INVOICE_ID)
MFSDK.getPaymentStatus(request, "en", object: MFCallback<MFGetPaymentStatusResponse>{
    override fun onResponse(isSuccess: Boolean, response: MFGetPaymentStatusResponse?, error: MFError?) {
        if(isSuccess)
            Log.d(TAG, "Response: " + Gson().toJson(response))
        else
            Log.d(TAG, "Error: " + Gson().toJson(error))
    }
})
MFGetPaymentStatusRequest request = new MFGetPaymentStatusRequest("12345", MFKeyType.INVOICE_ID);
MFSDK.INSTANCE.getPaymentStatus(request, "en", new MFCallback<MFGetPaymentStatusResponse>() {
    @Override
    public void onResponse(boolean isSuccess, @Nullable MFGetPaymentStatusResponse response, @Nullable MFError error) {
        if (isSuccess)
            Log.d(TAG, "Response: " + new Gson().toJson(response));
        else
            Log.d(TAG, "Error: " + new Gson().toJson(error));
    }
});

Android Embedded Payment Usage

Step 1:

Add MFPaymentCardView in your xml layout like the following:

<com.myfatoorah.sdk.views.embeddedpayment.MFPaymentCardView
   android:id="@+id/mfPaymentView"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

Note: you could custom a lot of properties of the payment card view like the following:

<com.myfatoorah.sdk.views.embeddedpayment.MFPaymentCardView
   android:id="@+id/mfPaymentView"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   app:inputColor="@color/paymentCardViewTextColor"
   app:labelColor="@color/paymentCardViewLabelColor"
   app:errorColor="@color/paymentCardViewValidateTextColor"
   app:cardHolderNameHint="cardHolderNameHint"
   app:cardNumberHint="cardNumberHint"
   app:expiryDateHint="expiryDateHint"
   app:cvvHint="cvvHint"
   app:showLabels="false"
   app:cardHolderNameLabel="cardHolderNameLabel"
   app:cardNumberLabel="cardNumberLabel"
   app:expiryDateLabel="expiryDateLabel"
   app:cvvLabel="cvvLabel"/>

(Alternative Option) You could custom a lot of properties of the payment card view in code behind like the following:

mfPaymentView.cardStyle = MFCardViewStyle(
    hideCardIcons = false,
    direction = "ltr",
    cardHeight = 230,
    input = MFCardViewInput(
        color = getColorFromRes(R.color.cardview_input_text_color),
        fontSize = 13f,
        fontFamily = MFFontFamily.Tahoma,
        inputHeight = 32f,
        inputMargin = 0f,
        borderColor = getColorFromRes(R.color.cardview_input_border_color),
        borderWidth = 2f,
        borderRadius = 8f,
        boxShadow = MFBoxShadow(10, 10, 5, 0, getColorFromRes(R.color.cardview_input_boxshadow_color)),
        placeHolder = MFCardViewPlaceHolder(
            holderName = "Name On Card test",
            cardNumber = "Number test",
            expiryDate = "MM / YY",
            securityCode = "CVV test"
        )
    ),
    label = MFCardViewLabel(
        display = true,
        color = getColorFromRes(R.color.cardview_label_text_color),
        fontSize = 13f,
        fontFamily = MFFontFamily.CourierNew,
        fontWeight = MFFontWeight.Bold,
        text = MFCardViewText(
            holderName = "Card Holder Name test",
            cardNumber = "Card Number test",
            expiryDate = "Expiry Date test",
            securityCode = "Security Code test"
        )
    ),
    error = MFCardViewError(
        borderColor = getColorFromRes(R.color.cardview_error_border_color),
        borderRadius = 8f,
        boxShadow = MFBoxShadow(10, 10, 5, 0, getColorFromRes(R.color.cardview_error_boxshadow_color))
    )
)
MFCardViewInput cardViewInput = new MFCardViewInput(
        getColorFromRes(R.color.cardview_input_text_color),
        13f,
        MFFontFamily.Tahoma,
        32f,
        0f,
        getColorFromRes(R.color.cardview_input_border_color),
        2f,
        8f,
        new MFBoxShadow(10, 10, 5, 0, getColorFromRes(R.color.cardview_input_boxshadow_color)),
        new MFCardViewPlaceHolder("Name On Card test", "Number test", "MM / YY", "CVV test")
);
MFCardViewLabel cardViewLabel = new MFCardViewLabel(
        true,
        getColorFromRes(R.color.cardview_label_text_color),
        13f,
        MFFontFamily.CourierNew,
        MFFontWeight.Bold,
        new MFCardViewText("Card Holder Name test", "Card Number test", "Expiry Date test", "Security Code test")
);
MFCardViewError cardViewError = new MFCardViewError(
        getColorFromRes(R.color.cardview_error_border_color),
        8f,
        new MFBoxShadow(10, 10, 5, 0, getColorFromRes(R.color.cardview_error_boxshadow_color))
);
MFCardViewStyle cardViewStyle =
        new MFCardViewStyle(false, "ltr", 230, cardViewInput, cardViewLabel, cardViewError);
mfPaymentView.setCardStyle(cardViewStyle);

Step 2:

You need to call initiateSession() function to create session. You need to do this for each payment separately. Session is valid for only one payment. and inside it's success state, call load() function and pass it the session response, to load the payment card view on the screen, like the following:

Note: If you want to use saved card option with embedded payment, send the parameter customerIdentifier in the MFInitiateSessionRequest with a unique value for each customer. This value cannot be used for more than one Customer. Check commented lines in the following code.

// val request = MFInitiateSessionRequest(customerIdentifier = "12345")
// MFSDK.initiateSession(request)

MFSDK.initiateSession {
    when (it) {
        is MFResult.Success -> {
            mfPaymentView.load(
                it.response,
                onCardBinChanged = { bin ->
                    Log.d(TAG, "bin: $bin")
                }
            )
        }
        is MFResult.Fail -> {
            Log.d(TAG, "Fail: " + Gson().toJson(it.error))
        }
    }
}
// MFInitiateSessionRequest request = new MFInitiateSessionRequest("12332212");
// MFSDK.INSTANCE.initiateSession(request, (MFResult<MFInitiateSessionResponse> result) -> {

MFSDK.INSTANCE.initiateSession(null, (MFResult<MFInitiateSessionResponse> result) -> {
    if (result instanceof MFResult.Success) {
        mfPaymentView.load(
                ((Success<MFInitiateSessionResponse>) result).getResponse(),
                (String bin) -> {
                    Log.d(TAG, "bin: " + bin);
                    return Unit.INSTANCE;
                });
    }
    if (result instanceof MFResult.Fail) {
        Log.d(TAG, "Fail: " + new Gson().toJson(((Fail) result).getError()));
    }

    return Unit.INSTANCE;
});

Note: The initiateSession() function should called after MFSDK.init() function (that we mentioned above).

Step 3:

Finally, you need to handle your Pay button to call the pay() function, copy the below code to your pay event handler section:

val request = MFExecutePaymentRequest(0.100)

mfPaymentView.pay(
    this,
    request,
    MFAPILanguage.EN,
    onInvoiceCreated = {
        Log.d(TAG, "invoiceId: $it")
    }
) { invoiceId: String, result: MFResult<MFGetPaymentStatusResponse> ->
    when (result) {
        is MFResult.Success -> {
            Log.d(TAG, "Response: " + Gson().toJson(result.response))
        }
        is MFResult.Fail -> {
            Log.d(TAG, "Fail: " + Gson().toJson(result.error))
        }
    }
    Log.d(TAG, "invoiceId: $invoiceId")
}
MFExecutePaymentRequest request = new MFExecutePaymentRequest(0.100);

        mfPaymentView.pay(
                this,
                request,
                MFAPILanguage.EN,
                (String invoiceId) -> {
                    Log.d(TAG, "invoiceId: " + invoiceId);
                    return Unit.INSTANCE;
                },
                (String invoiceId, MFResult<MFGetPaymentStatusResponse> result) -> {
                    if (result instanceof MFResult.Success) {
                        Log.d(TAG, "Response: " + new Gson().toJson(((Success<MFGetPaymentStatusResponse>) result).getResponse()));
                    }
                    else if (result instanceof MFResult.Fail) {
                        String error = new Gson().toJson(((Fail) result).getError());
                        Log.d(TAG, "Fail: " + error);
                    }

                    Log.d(TAG, "invoiceId:" + invoiceId);

                    return Unit.INSTANCE;
                });

(Alternative Option) You can validate the session first and complete the payment if the session is valid

val request = MFExecutePaymentRequest(0.100)
mfPaymentView.validate { result: MFResult<String> ->
    when (result) {
        is MFResult.Success -> {
            Log.d(TAG, "Response: " + Gson().toJson(result.response))
            mfPaymentView.pay(
                this,
                request,
                MFAPILanguage.EN,
                onInvoiceCreated = { Log.d(TAG, "invoiceId: $it") })
            { invoiceId: String, result: MFResult<MFGetPaymentStatusResponse> ->
                when (result) {
                    is MFResult.Success -> {
                        Log.d(TAG, "Response: " + Gson().toJson(result.response))
                    }
                    is MFResult.Fail -> {
                        Log.d(TAG, "Fail: " + Gson().toJson(result.error))
                    }
                }
            }
        }
        is MFResult.Fail -> Log.d(TAG, "Fail: " + Gson().toJson(result.error))
    }
}
MFExecutePaymentRequest request = new MFExecutePaymentRequest(0.100);
mfPaymentView.validate((MFResult<String> resultValidate) -> {
    if (resultValidate instanceof MFResult.Success) {
        Log.d(TAG, "Response: " + new Gson().toJson(((Success<String>) resultValidate).getResponse()));
        mfPaymentView.pay(
                this,
                request,
                MFAPILanguage.EN,
                (String invoiceId) -> {
                    Log.d(TAG, "invoiceId: " + invoiceId);
                    return Unit.INSTANCE;
                },
                (String invoiceId, MFResult<MFGetPaymentStatusResponse> resultPay) -> {
                    if (resultPay instanceof MFResult.Success) {
                        Log.d(TAG, "Response: " + new Gson().toJson(((Success<MFGetPaymentStatusResponse>) resultPay).getResponse()));
                    } else if (resultPay instanceof MFResult.Fail) {
                        Log.d(TAG, "Fail: " + new Gson().toJson(((Fail) resultPay).getError()));
                    }
                    return Unit.INSTANCE;
                });
    } else if (resultValidate instanceof MFResult.Fail) {
        Log.d(TAG, "Fail: " + new Gson().toJson(((Fail) resultValidate).getError()));
    }
    return Unit.INSTANCE;
});

Read Card with NFC (Optional)

Add the following code if you want to add the feature of a reading card with NFC.

override fun onResume() {
    super.onResume()
    mfPaymentView.enableCardNFC(this)
}

public override fun onPause() {
    super.onPause()
    mfPaymentView.disableCardNFC(this)
}

public override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    mfPaymentView.readCard(intent)
}
@Override
protected void onResume() {
    super.onResume();
    mfPaymentView.enableCardNFC(this);
}

@Override
protected void onPause() {
    super.onPause();
    mfPaymentView.disableCardNFC(this);
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    mfPaymentView.readCard(intent);
}

Add the following attribute in your .xml file if you want to show animated NFC icon in the front of the embedded payment view.

<com.myfatoorah.sdk.views.embeddedpayment.MFPaymentCardView
    ...
    app:showNFCReadCardIcon="true"/>