PAYSTACK INTEGRATION WITH ANDROID USING ANDROID STUDIO

This article details Paystack integration with Android. Paystack is one of the Top Payment Gateways we have in Nigeria

The Paystack Android SDK allows businesses using Paystack to collect payments within their Android app.

The SDK shoulders the burden of PCI compliance, allowing your app to send card information directly to Paystack servers where they can process them. All your server needs to do is call Paystack to verify the status of the transaction. The SDK also validates card details client-side and provides an interface for collecting additional verification like card PIN and OTP.

Paystack supports Android back to version 16, which is the first SDK version that includes TLSv1.2 which is required by their servers. Native app support for user devices older than API 16 will not be available.

Paystack integration with Android

Installations

To install the library on Android Studio, add the following lines to your project’s build.gradle file.

dependencies {
implementation ‘co.paystack.android.design.widget:pinpad:1.0.1’
implementation ‘co.paystack.android:paystack:3.0.10’
}

Enable Permissions

To prepare for use, you must ensure that your app has internet permissions by making sure the uses-permission line below is present in the AndroidManifest.xml.

<uses-permission android:name=”android.permission.INTERNET” />

Set Your Public Key

Before you can charge a card with the PaystackSdk class, you need to set your public key. Your public key is available on the Paystack Dashboard.

Set your public key in your project’s AndroidManifest.xml by adding the following lines of code to the tag of your AndroidManifest.xml

<meta-data
android:name=”co.paystack.android.PublicKey”
android:value=”your public key obtained from: https://dashboard.paystack.co/#/settings/developer”/>

Initialize SDK

To use the Paystack Android SDK, you need to first initialize it using the PaystackSdk class.

public class PaymentActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_payment);
PaystackSdk.initialize(getApplicationContext());
}
}
view rawInitialize SDK hosted with ❤ by GitHub

Make sure to call this method in the onCreate method of your Fragment or Activity or Application

Collecting card information

Create a form that collects card information. You need to collect your customers’ card numbers, expiration dates and CVC. PaystackSDK has a Card class that allows you to collect and verify these Card information, here is a sample Android XML code that helps you collect card information

<?xml version=1.0 encoding=utf-8?>
<ScrollView xmlns:android=http://schemas.android.com/apk/res/android
android:layout_width=fill_parent
android:layout_height=fill_parent
android:background=@drawable/bg
android:fillViewport=true>
<LinearLayout
android:layout_width=match_parent
android:layout_height=match_parent
android:orientation=vertical
android:focusableInTouchMode=true
android:padding=16dp>
<ImageView
android:layout_width=wrap_content
android:layout_height=wrap_content
android:layout_gravity=center_horizontal
android:layout_marginBottom=20dp
android:scaleType=centerCrop
android:src=@drawable/logo />
<EditText
android:id=@+id/card_number
android:layout_width=match_parent
android:layout_height=wrap_content
android:layout_marginBottom=20dp
android:background=@drawable/edit_text
android:drawableLeft=@drawable/card
android:drawablePadding=5dp
android:hint=Card Number
android:inputType=number
android:padding=10dp
android:textColor=#fff
android:textColorHint=#D3D3D3 />
<LinearLayout
android:layout_width=match_parent
android:layout_height=wrap_content
android:orientation=horizontal>
<EditText
android:id=@+id/month
android:layout_width=0dp
android:layout_height=wrap_content
android:layout_marginRight=10dp
android:layout_marginBottom=20dp
android:layout_weight=1
android:background=@drawable/edit_text
android:drawableLeft=@drawable/date
android:drawablePadding=5dp
android:hint=Expiry Month
android:inputType=number
android:padding=10dp
android:textColor=#fff
android:textColorHint=#D3D3D3 />
<EditText
android:id=@+id/year
android:layout_width=0dp
android:layout_height=wrap_content
android:layout_marginBottom=20dp
android:layout_weight=1
android:background=@drawable/edit_text
android:drawableLeft=@drawable/date
android:drawablePadding=5dp
android:hint=Expiry Year
android:inputType=number
android:padding=10dp
android:textColor=#fff
android:textColorHint=#D3D3D3 />
</LinearLayout>
<EditText
android:id=@+id/cvc
android:layout_width=match_parent
android:layout_height=wrap_content
android:layout_marginBottom=20dp
android:background=@drawable/edit_text
android:drawableLeft=@drawable/card
android:drawablePadding=5dp
android:hint=CVV
android:inputType=number
android:padding=10dp
android:textColor=#fff
android:textColorHint=#D3D3D3 />
<Button
android:layout_width=match_parent
android:layout_height=wrap_content
android:onClick=pay
android:text=Make Payment
android:textColor=#FFFFFF />
</LinearLayout>
</ScrollView>

Validate Card Values and Charge User

Using the functions: setCurrency, setPlan, setSubaccount, setTransactionCharge, setAmount, setEmail, setReference, setBearer, putMetadata, putCustomField, you can set up a fresh transaction direct from the SDK.

The following codes retrieve values from the form and proceed to call the charge function that will be shown later

public void pay(View view) {
int expiryMonth = 0;
int expiryYear = 0;
EditText etCardNumber = findViewById(R.id.card_number);
EditText etExpiryMonth = findViewById(R.id.month);
EditText etExpiryYear = findViewById(R.id.year);
EditText etCVC = findViewById(R.id.cvc);
String cardNumber = etCardNumber.getText().toString();
if(!etExpiryMonth.getText().toString().isEmpty()) {
expiryMonth = Integer.parseInt(etExpiryMonth.getText().toString());
}
if(!etExpiryMonth.getText().toString().isEmpty()) {
expiryYear = Integer.parseInt(etExpiryYear.getText().toString());
}
String cvv = etCVC.getText().toString();
Card card = new Card(cardNumber, expiryMonth, expiryYear, cvv);
if (card.isValid()) {
charge = new Charge();
charge.setCard(card);
dialog = new ProgressDialog(PaymentActivity.this);
dialog.setMessage(“Performing transaction… please wait”);
dialog.show();
charge.setAmount(1050);
charge.setEmail(email);
charge.setReference(“ChargedFromAndroid_” + Calendar.getInstance().getTimeInMillis());
try {
charge.putCustomField(“Charged From”, “Android SDK”);
} catch (JSONException e) {
e.printStackTrace();
}
chargeCard();\\Function to Charge user here
}
else {
Toast.makeText(PaymentActivity.this, “Invalid card details”, Toast.LENGTH_LONG).show();
}
}
private void dismissDialog() {
if ((dialog != null) && dialog.isShowing()) {
dialog.dismiss();
}
}

When an error occurs or transaction or concludes successfully, we will call the methods available in the callback you provided.

OnSuccess will be called once the charge succeeds here we call a function to verify the transaction on the server and perform the desired action you want on the server

beforeValidate is called every time the SDK needs to request user input. This function currently only allows the app know that the SDK is requesting further user input.OnError

onError is called if an error occurred during processing. Some Exception types that you should watch include
ExpiredAccessCodeException: This would be thrown if the access code has already been used to attempt a charge.
ChargeException: This would be thrown if the charge failed. It would hold the message from the server.

private void chargeCard() {
transaction = null;
PaystackSdk.chargeCard(PaymentActivity.this, charge, new Paystack.TransactionCallback() {
// This is called only after transaction is successful
@Override
public void onSuccess(Transaction transaction) {
dismissDialog();
PaymentActivity.this.transaction = transaction;
Toast.makeText(PaymentActivity.this, transaction.getReference(), Toast.LENGTH_LONG).show();
new verifyOnServer().execute(transaction.getReference());
}
// This is called only before requesting OTP
// Save reference so you may send to server if
// error occurs with OTP
// No need to dismiss dialog
@Override
public void beforeValidate(Transaction transaction) {
PaymentActivity.this.transaction = transaction;
Toast.makeText(PaymentActivity.this, transaction.getReference(), Toast.LENGTH_LONG).show();
}
@Override
public void onError(Throwable error, Transaction transaction) {
// If an access code has expired, simply ask your server for a new one
// and restart the charge instead of displaying error
PaymentActivity.this.transaction = transaction;
if (error instanceof ExpiredAccessCodeException) {
PaymentActivity.this.chargeCard();
return;
}
dismissDialog();
if (transaction.getReference() != null) {
Toast.makeText(PaymentActivity.this, transaction.getReference() + ” concluded with error: ” + error.getMessage(), Toast.LENGTH_LONG).show();
new verifyOnServer().execute(transaction.getReference());
} else {
Toast.makeText(PaymentActivity.this, error.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
private class verifyOnServer extends AsyncTask<String, Void, String> {
private String reference;
private String error;
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result != null) {
Toast.makeText(PaymentActivity.this, String.format(“Gateway response: %s”, result), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(PaymentActivity.this, String.format(“There was a problem verifying %s on the backend: %s “, this.reference, error), Toast.LENGTH_LONG).show();
dismissDialog();
}
}
@Override
protected String doInBackground(String… reference) {
try {
this.reference = reference[0];
String json = String.format(“{\”reference\”:\”%s\”}”, this.reference);
String url1 = “https://www.serverdomain.com/app/verify.php?details=” + json;
URL url = new URL(url1);
BufferedReader in = new BufferedReader(
new InputStreamReader(
url.openStream()));
String inputLine;
inputLine = in.readLine();
in.close();
return inputLine;
} catch (Exception e) {
error = e.getClass().getSimpleName() + “: ” + e.getMessage();
}
return null;
}
}
view rawCharge Card hosted with ❤ by GitHub

Send the reference to your backend and verify by calling our REST API. An authorization will be returned which will let you know if its code is reusable. You can learn more about our verify call here

Below is a sample code on how you can achieve that using php

<?php
$details = $_GET[“details”];
$obj = json_decode($details);
$reference = $obj -> {“reference”};
$result = array();
//The parameter after verify/ is the transaction reference to be verified
$url = ‘https://api.paystack.co/transaction/verify/$reference’;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt(
$ch, CURLOPT_HTTPHEADER, [
‘Authorization: Bearer SECRET_KEY’]
);
$request = curl_exec($ch);
curl_close($ch);
if ($request) {
$result = json_decode($request, true);
// print_r($result);
if($result){
if($result[‘data’]){
//something came in
if($result[‘data’][‘status’] == ‘success’){
// the transaction was successful, you can deliver value
/*
@ also remember that if this was a card transaction, you can store the
@ card authorization to enable you charge the customer subsequently.
@ The card authorization is in:
@ $result[‘data’][‘authorization’][‘authorization_code’];
@ PS: Store the authorization with this email address used for this transaction.
@ The authorization will only work with this particular email.
@ If the user changes his email on your system, it will be unusable
*/
echo “Transaction was successful”;
}else{
// the transaction was not successful, do not deliver value’
// print_r($result); //uncomment this line to inspect the result, to check why it failed.
echo “Transaction was not successful: Last gateway response was: “.$result[‘data’][‘gateway_response’];
}
}else{
echo $result[‘message’];
}
}else{
//print_r($result);
die(“Something went wrong while trying to convert the request variable to json. Uncomment the print_r command to see what is in the result variable.”);
}
}else{
//var_dump($request);
die(“Something went wrong while executing curl. Uncomment the var_dump line above this line to see what the issue is. Please check your CURL command to make sure everything is ok”);
}
view rawVerify hosted with ❤ by GitHub

Do you have any questions on Paystack integration with Android or need help, place a comment below

Sharing is caring!

Leave a Comment

Your email address will not be published. Required fields are marked *

Open chat
Henry from VIS Nigeria
Hello 👋 Welcome to VIS Nigeria
Can we help you?
Let's have a WhatsApp chat!