How to integrate Rave Pay Flutterwave in Android Studio (Including App Demo Source Code)
In this article, we will learn to integrate Rave Pay by FlutterWave Payment Gatway in our android app using android studio. Rave Pay is the most popular payment gateway in south africa and its supports a number of payment methods that users can use to send money. we have explained everything in a very simple way so you can understand it easily we also have provided the complete source code of the sample app you can download it from the link given at the end of this post.
The Flutterwave payment gateway is a popular payment gateway used especially in South Africa. In this tutorial am going to show you how to integrate the Rave Pay flutterwave in android studio. It is a very easy way to make and accept payments locally and globally. I will also be explaining full in detail every part of the code. The app demo source code will also be provided in this tutorial.
Just like other payment gateways before you integrate the Rave Pay flutterwave payment in your android app you need to first have a developer account. This means that you should go to the dashboard flutterwave website to create your own developer account which you will be using to receive payments in your app. After creating your developer account you will get your own publicKey and encryptionKey to accept real payments.
Payment methods currently supported by the Rave Pay Flutterwave
- CARDS
- USSD
- MPESA
- GH MOBILE MONEY
- UG MOBILE MONEY
- ZM MOBILE MONEY
- RWANDA MOBILE MONEY
- FRANC MOBILE MONEY
- US ACH
- UK BANK
- SA BANK
- NIGERIA BANK ACCOUNT
- NIGERIA BANK TRANSFER
- BARTER MOBILE WALLET
As you can see from the above list it supports different types of payment methods.
The Rave Pay Flutterwave is basically having two SDKs for Android
Default Drop-in UI
In the default drop-in UI, the design of the payment layout is in the default mode. This is just a simple UI and it is easy to use. In this tutorial, I used the default drop-in UI SDK so as to test the flutterwave payment which will be a much easier thing for me to do right now.
Custom SDK
In the custom SDK you can choose to change the UI style and some other designs on how the card payment method will look like. This is to say you can make can your own custom changes I the UI design. But this will be a bit complex; for now, we will not be using it since am just trying to show you how to integrate Rave Pay Flutterwave in the android application using android studio.
Minimum Android SDK Version
The minimum supported android SDK version that is supported is 15
Steps on How to Integrate the Rave Pay Flutterwave Payment in Android Studio
Open your app build.gradle file and the following dependency
implementation 'com.github.flutterwave.rave-android:rave_android:2.1.37'
///dependencies {
implementation 'com.github.flutterwave.rave-android:rave_android:2.1.37'
}///
The next thing to do is open your root-level build.gradle file and add the following maven URL
maven { url 'https://jitpack.io' }
///allprojects {
repositories {
maven { url 'https://jitpack.io' }
google()
jcenter()
}
}///
Designing the UI (activity_main.xml file)
Since am just trying to integrate the flutterwave payment and to see how it works, then the app design is not going to be that complex. Instead, the product price and some other values will be fixed. That is to say, we are to be using static values, not dynamic values. For instance the price of the products.
The XML layouts for the activity and the successful payment dialog are given in the source code.
activity_main.xml code
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/parent_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginTop="10dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="none"
android:scrollingCache="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginEnd="18dp"
app:cardBackgroundColor="@android:color/white"
app:cardCornerRadius="20dp"
app:cardElevation="2dp"
app:cardUseCompatPadding="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
app:layout_constraintEnd_toStartOf="@+id/imageView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Fresh Tomato 1KG"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NGN 20"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="@color/lightGreen"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="8dp"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="18dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:tint="@color/greyQuantityColor"
app:srcCompat="@drawable/ic_remove" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/space_15_dp"
android:layout_marginRight="@dimen/space_15_dp"
android:gravity="center_vertical"
android:text="1"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="@color/greyQuantityColor"
app:fontFamily="sans-serif-medium" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="@dimen/space_35_dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:tint="@color/greyQuantityColor"
app:srcCompat="@drawable/ic_add" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/imageView"
android:layout_width="120dp"
android:layout_height="120dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/tomato" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginEnd="18dp"
app:cardBackgroundColor="@android:color/white"
app:cardCornerRadius="20dp"
app:cardElevation="2dp"
app:cardUseCompatPadding="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
app:layout_constraintEnd_toStartOf="@+id/imageView1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView12"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Fresh Carrot 1KG"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NGN 10"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="@color/lightGreen"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView12" />
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="8dp"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView4">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="18dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:tint="@color/greyQuantityColor"
app:srcCompat="@drawable/ic_remove" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/space_15_dp"
android:layout_marginRight="@dimen/space_15_dp"
android:gravity="center_vertical"
android:text="1"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="@color/greyQuantityColor"
app:fontFamily="sans-serif-medium" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="@dimen/space_35_dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:tint="@color/greyQuantityColor"
app:srcCompat="@drawable/ic_add" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/imageView1"
android:layout_width="120dp"
android:layout_height="120dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/carrot" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginEnd="18dp"
app:cardBackgroundColor="@android:color/white"
app:cardCornerRadius="20dp"
app:cardElevation="2dp"
app:cardUseCompatPadding="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
app:layout_constraintEnd_toStartOf="@+id/imageView2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView10"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Fresh cauliflower 1KG"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NGN 18"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="@color/lightGreen"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView10" />
<LinearLayout
android:id="@+id/linearLayou3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="8dp"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView6">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="18dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:tint="@color/greyQuantityColor"
app:srcCompat="@drawable/ic_remove" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/space_15_dp"
android:layout_marginRight="@dimen/space_15_dp"
android:gravity="center_vertical"
android:text="1"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="@color/greyQuantityColor"
app:fontFamily="sans-serif-medium" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="@dimen/space_35_dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:tint="@color/greyQuantityColor"
app:srcCompat="@drawable/ic_add" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/imageView2"
android:layout_width="120dp"
android:layout_height="120dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/cauliflower" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/space_10_dp"
android:paddingBottom="@dimen/space_18_dp"
android:paddingLeft="@dimen/space_20_dp"
android:paddingRight="@dimen/space_20_dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/space_10_dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total Amount"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="@color/grey_80"
/>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="@+id/finalAmmount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NGN 48"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/lightgreen400"
android:textStyle="bold" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/greybtns" />
<androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/space_18_dp"
android:background="@drawable/round_btn"
android:paddingLeft="@dimen/space_20_dp"
android:paddingRight="@dimen/space_20_dp"
android:text="Pay With Rave Pay"
android:onClick="startRazor"
android:textColor="@android:color/white" />
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
How to get your PublicKey and EncryptionKey
All you have to do is log on to your flutterwave dashboard. and now click on settings and then select APIs. In the APIs section, you will see your PublicKey and Encryption Key. If you are already logged in to your flutterwave dashboard then simply click on this link you will directly land on the APIs page. Keep in mind that you have to provide some documents when requesting a Ravepay flutterwave live mode PublicKey & EncryptionKey.
The MainActivity.java class (Source Code)
package com.example.ravepay.flutterwave;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatButton;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
import com.flutterwave.raveandroid.RavePayActivity;
import com.flutterwave.raveandroid.RaveUiManager;
import com.flutterwave.raveandroid.rave_java_commons.RaveConstants;
import org.json.JSONObject;
import java.math.BigDecimal;
import java.util.UUID;
public class MainActivity extends AppCompatActivity{
ProgressDialog progressDialog;
TextView finalAmmount;
private String email ="[email protected]";
private String currency ="NGN";
private String fName ="Avdesh";
private String lName ="Yadav";
private String publicKey ="FLWPUBK_TEST-57a4ff84df663ccdafd25f94af471b95-X";
private String encryptionKey ="FLWSECK_TEST1577be908e6c";
private static final String TAG = "RAVI_PAYMENTS";
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Please Wait..");
progressDialog.setCancelable(false);
finalAmmount = findViewById(R.id.finalAmmount);
}
public void startRazor(View view) {
progressDialog.show();
final Activity activity = this;
UUID uuid = UUID.randomUUID();
new RaveUiManager(MainActivity.this).setAmount(round( Integer.parseInt(finalAmmount.getText().toString().substring(4)), 2))
.setCurrency(currency)
.setEmail(email)
.setfName(fName)
.setlName(lName)
.setPublicKey(publicKey)
.setEncryptionKey(encryptionKey)
.setTxRef(uuid.toString()) // unique order id
.setPhoneNumber(phoneNumber, true)
.acceptAccountPayments(true)
.acceptCardPayments(true)
.acceptMpesaPayments(true)
.acceptAchPayments(true)
.acceptGHMobileMoneyPayments(false)
.acceptUgMobileMoneyPayments(false)
.acceptZmMobileMoneyPayments(false)
.acceptRwfMobileMoneyPayments(false)
.acceptSaBankPayments(false)
.acceptUkPayments(false)
.acceptBankTransferPayments(true)
acceptBankTransferPayments(true, duration, frequency)
.acceptUssdPayments(true)
.acceptBarterPayments(false)
.acceptFrancMobileMoneyPayments(false,null)
.allowSaveCardFeature(true)
.onStagingEnv(true)
//.setMeta(List<Meta>)
//.withTheme(styleId) // Sets the theme of the UI.
.isPreAuth(false)
.shouldDisplayFee(true)
.showStagingLabel(true)
.initialize();
}
public static float round(float d, int decimalPlace) {
BigDecimal bd = new BigDecimal(Float.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.floatValue();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
progressDialog.dismiss();
if (requestCode == RaveConstants.RAVE_REQUEST_CODE && data != null) {
String message = data.getStringExtra("response");
if (resultCode == RavePayActivity.RESULT_SUCCESS) {
Log.d(TAG, "onActivityResult: " + "SUCCESS " + message);
Toast.makeText(this, "SUCCESS " + message, Toast.LENGTH_SHORT).show();
}
else if (resultCode == RavePayActivity.RESULT_ERROR) {
Log.d(TAG, "onActivityResult: " + "ERROR " + message);
Toast.makeText(this, "ERROR " + message, Toast.LENGTH_SHORT).show();
}
else if (resultCode == RavePayActivity.RESULT_CANCELLED) {
Log.d(TAG, "onActivityResult: " + "CANCELLED " + message);
Toast.makeText(this, "CANCELLED " , Toast.LENGTH_SHORT).show();
}
}
else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void showCustomDialog() {
final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // before
dialog.setContentView(R.layout.payment_success_dialog);
dialog.setCancelable(true);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
((AppCompatButton) dialog.findViewById(R.id.bt_close)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
// finish();
}
});
dialog.show();
dialog.getWindow().setAttributes(lp);
}
}
The MainActivity.java class (Code Explanation)
The first thing to do is to initialize the progressDialog in the main activity onCreate Method. The progress dialog will load once the buy button is pressed.
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Please Wait..");
progressDialog.setCancelable(false);///
//progressDialog.show(); this will be added inside the onclick method///
Next you create a Random ID to be used in transaction reference
UUID uuid = UUID.randomUUID();
The next thing you should do is to initialize the Rave Pay Fluitterwave SDK and add all the required methods.
new RaveUiManager(MainActivity.class)
.setAmount(round( Integer.parseInt(finalAmmount.getText().toString().substring(1)), 2))
///The amount to be paid///
.setCurrency(currency)
///The country currency, here we are using NGN///
.setEmail(email)
///The user email///
.setfName(fName)
///The user first name///
.setlName(lName)
///The user last name///
.setNarration(narration)
///This is a custom description added by the merchant. For Bank Transfer payments, For Bank Transfer payments, this becomes the account name of the account to be paid into///
.setPublicKey(publicKey)
///Your publicKey from flutterwave dashboard///
.setEncryptionKey(encryptionKey)
///Your encryptionKey from flutterwave dashboard///
.setTxRef(uuid.toString())
/// unique order id///
.setPhoneNumber(phoneNumber, true)
// /this sets the customer's phone number. This functions is also overloaded to allow you specify whether the customer can edit their phone number as such: setPhoneNumber(phoneNumber,false). When set to false, the user will not be able to change the number you set here///
.acceptAccountPayments(true)
/ // Set to true if you want to accept payments via bank accounts, else set to false///
.acceptCardPayments(true) // Set to true if you want to accept payments via cards, else set to false
.acceptMpesaPayments(true)
/ //Set to true if you want to accept Mpesa payments, else set to false . For this option to work, you should set your country to KE and your currency to KES///
.acceptAchPayments(true)
/ //accept the AchPayment method///
.acceptGHMobileMoneyPayments(false)
///Set to true if you want to accept Ghana mobile money payments, else set to false. For this option to work, you should set your country to GH and your currency to GHS///
.acceptUgMobileMoneyPayments(false)
/ //Set to true if you want to accept Uganda mobile money payments, else set to false. For this option to work, you should set your country to UG and your currency to UGX///
.acceptZmMobileMoneyPayments(false)
///Set to true if you want to accept Zambia mobile money payments, else set to false. For this option to work, you should set your country to NG and your currency to ZMW. MTN is the only available network at the moment///
.acceptRwfMobileMoneyPayments(false)
/ // Set to true if you want to accept Rwanda mobile money payments, else set to false. For this option to work, you should set your country to NG and your currency to RWF///
.acceptSaBankPayments(false)
//Set to true if you want to accept South African direct bank account payments, else set to false . For this option to work, you should set your country to ZA and your currency to ZAR///
.acceptUkPayments(false)
/ // Set to true if you want to accept UK Bank Account payments, else set to false. For this option to work, you should set your country to NG, set currency to GBP, set accountbank String, set accountname String, set accountnumber String, set is_uk_bank_charge2 true, set payment_type account. Please use your live credentials for this///
.acceptBankTransferPayments(true)
/// set to true if you want to accept payments via bank transfer from your customers, else set to false. This option is currently only available for Nigerian Naira.///
Note: By default, the account numbers generated are dynamic. This method has been overloaded for more options as shown below:
///To generate static (permanent) accounts instead, pass in true as a second parameter. E.g acceptBankTransferPayments(true, true)
To generate accounts that expire at a certain date, or after a certain number of payments, pass in integer values for duration and frequency as such:
acceptBankTransferPayments(true, duration, frequency)///
.acceptUssdPayments(true)
///accept the USSD payment method///
.acceptBarterPayments(false)
///Set to true if you want to accept payments via Barter from your customers, else set to false///
.acceptFrancMobileMoneyPayments(false,null)
/// set to true if you want to accept Francophone mobile money payments, else set to false. For this option to work, you should set your country to NG and your currency to XOF for West African CFA franc like Ivory Coast OR XAF for Central African CFA franc like Cameroon . See more details///
.allowSaveCardFeature(true)
///Set to true if you want to give the user the option to save their cards for future transactions. This option helps them avoid retyping their card details for every transaction///
.onStagingEnv(true)
///Set to true if you want your transactions to run in the staging environment otherwise set to false. Defaults to false///
///.setMeta(List<Meta>) //Pass in any other custom data you wish to pass. It takes in a List of Meta objects///
/// .withTheme(styleId) // Sets the theme of the UI///
.isPreAuth(false)
/ //Set to true to preauthorise the transaction amount///
/// .setSubAccounts(List<SubAccount>)
Pass in a List of SubAccount,if you want to split transaction fee with other people. Subaccounts are your vendors' accounts that you want to settle per transaction. To initialize a SubAccount class, do SubAccount(String subAccountId,String transactionSplitRatio) or SubAccount(String subAccountId, String transactionSplitRatio,String transactionChargeType, String transactionCharge) to also charge the subaccount a fee///
.shouldDisplayFee(true)
/// Set to false to not display a dialog for confirming total amount(including charge fee) that Rave will charge. By default this is set to true///
.showStagingLabel(true)
/ //Set to false to not display a staging label when in staging environment. By default this is set to true///
.initialize();
The amount rounding method for the product amount this method will convert price to double like 100 will be like 100.00 if we will pass decimalPlace 2
public static float round(float d, int decimalPlace) {
BigDecimal bd = new BigDecimal(Float.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.floatValue();
}
Creating the onActivityResult method to toast a success message or an error if any occur
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
progressDialog.dismiss(); // first we dismiss the progressbar
if (requestCode == RaveConstants.RAVE_REQUEST_CODE && data != null) {
String message = data.getStringExtra("response"); // its json response send by RavePay Flutter Wave SDK
if (resultCode == RavePayActivity.RESULT_SUCCESS) {
// Payment successfully paid by user the this code will run
showCustomDialog();
Log.d(TAG, "onActivityResult: " + "SUCCESS " + message);
Toast.makeText(this, "SUCCESS " + message, Toast.LENGTH_SHORT).show();
}
else if (resultCode == RavePayActivity.RESULT_ERROR) {
// this code will run if there is any error during transaction
Log.d(TAG, "onActivityResult: " + "ERROR " + message);
Toast.makeText(this, "ERROR " + message, Toast.LENGTH_SHORT).show();
}
else if (resultCode == RavePayActivity.RESULT_CANCELLED) {
Log.d(TAG, "onActivityResult: " + "CANCELLED " + message);
// in this case if user had not paid and click on back button without payment then this will call there message will be null because we will not recieve any response
Toast.makeText(this, "CANCELLED " + message, Toast.LENGTH_SHORT).show();
}
}
else {
super.onActivityResult(requestCode, resultCode, data);
}
}
The last step is to create a showCustomDialog method
private void showCustomDialog() {
final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // before
dialog.setContentView(R.layout.payment_success_dialog);
dialog.setCancelable(true);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
((AppCompatButton) dialog.findViewById(R.id.bt_close)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
// finish();
}
});
dialog.show();
dialog.getWindow().setAttributes(lp);
}///
we called this method inside onActivityResult method so now we have created it. This method will pop up a dialog telling that the transaction carried out has been successfully completed.
Sample Success Response
{"status":"success","message":"Tx Fetched","data":{"id":2472426,"txRef":"dcdfd0c7-43ab-465d-b33a-e4fd639ea8a7","orderRef":"URF_1631217605000_440835","flwRef":"FLW-MOCK-d29dd2d2bae79ce16cf52d223e2e36ba","redirectUrl":"https://rave-webhook.herokuapp.com/receivepayment","device_fingerprint":"e6d457f2e6c2f379","settlement_token":null,"cycle":"one-time","amount":48,"charged_amount":48,"appfee":0.68,"merchantfee":0,"merchantbearsfee":1,"chargeResponseCode":"00","raveRef":"RV316312176050003C565FDC61","chargeResponseMessage":"Please enter the OTP sent to your mobile number 080****** and email te**@rave**.com","authModelUsed":"PIN","currency":"NGN","IP":"52.209.154.143","narration":"CARD Transaction ","status":"successful","modalauditid":"ba76633754026b7d47cb2f044d00ecd7","vbvrespmessage":"successful","authurl":"N/A","vbvrespcode":"00","acctvalrespmsg":null,"acctvalrespcode":null,"paymentType":"card","paymentPlan":null,"paymentPage":null,"paymentId":"11413","fraud_status":"ok","charge_type":"normal","is_live":0,"retry_attempt":null,"getpaidBatchId":null,"createdAt":"2021-09-09T20:00:05.000Z","updatedAt":"2021-09-09T20:00:15.000Z","deletedAt":null,"customerId":1388453,"AccountId":859156,"customer.id":1388453,"customer.phone":null,"customer.fullName":"Avdesh Yadav","customer.customertoken":null,"customer.email":"[email protected]","customer.createdAt":"2021-09-09T20:00:05.000Z","customer.updatedAt":"2021-09-09T20:00:05.000Z","customer.deletedAt":null,"customer.AccountId":859156,"meta":[],"flwMeta":{}}}
Sample Error Response Send By RavePay SDK
// sample error response
{"status":"error","message":"Please provide one of tx ref or flw ref","data":null}
// sample error response
Conclusion
In this tutorial, I have fully explained how to integrate Rave Pay Flutterwave in android applications using android studio. And I believe you can now integrate this payment gateway into your android app. Like I have explained earlier you can see that the flutterwave has different payments methods which the app users can choose to make their payments in a very easy and simple way if you have any questions or query please ask us in the comment section we will be glad to help you Happy Coding!.
Files ( Login Required )
What's Your Reaction?






