Introduction
Welcome to the Fena online payment guide. Before we dive into integration, let us explain how this system works.
How Fena online payments works
The Fena Online Payment system consists of three main parts
- A webpage that initiates a request to Fena to make a payment.
- A page on your webserver that Fena to notify you when a payment has been made.
- A webpage that confirms the above payment and passes the customer on to the next phase of your application, such as your ‘order confirmation’ or 'Thank You' page.
Parts 1 and 3 can be accessed by customers on your website/app. Part 2 is only visible to Fena. This diagram illustrates the interaction between your customer, Fena and your application.
Installation
Fena Java Payment SDK can be installed via maven.
Add the following under dependencies in your pom.xml:
<dependency>
<groupId>com.faizpay</groupId>
<artifactId>payment-sdk</artifactId>
<version>0.3</version>
</dependency>
Quick Start
Before we start make sure you have Fena SDK installed. To install SDK please check our installation guide
Create a Token and Redirect to Fena
Create the connection object:
import com.faizpay.payment.sdk.Connection;
import com.faizpay.payment.sdk.ErrorHandler;
//Parameters: (TerminalId ,TerminalSecret)
Connection connection = new Connection("315f2c07-fd16-4462-86d2-05b0b18d5b39","6a8dfd42-d585-424b-b8e8-b523242661d9");
// check if the connection object has been created without errors:
ErrorHandler error = connection.isValid();
if (error instanceof ErrorHandler) {
System.out.println(error);
}
Make sure to use your own 'terminalId' and 'terminalSecret' values.
Create the payment object: order ID = 1 amount = 2.00
import com.faizpay.payment.sdk.Payment;
import com.faizpay.payment.sdk.ErrorHandler;
Payment payment = new Payment(connection, "1", "2.00");
// check if the payment object has been created without errors:
ErrorHandler error = payment.isValid();
if (error instanceof ErrorHandler) {
System.out.println(error);
}
Make sure to set the 'orderId' to your internal (persisted) order ID (for tracking completion).
Then finally call the process on the payment object. This will return the redirect url as a string.
String url = payment.process();
Setup Webhook / Notification Endpoint
- Create a connection object
- Create a NotificationHandler object
- Get your Order ID from token
- Fetch the order detail from database
- Validate requested payment matches with Token
- Update your database with payment completed
import com.faizpay.payment.sdk.Connection;
//Parameters: (TerminalId ,TerminalSecret)
Connection connection = new Connection("315f2c07-fd16-4462-86d2-05b0b18d5b39","6a8dfd42-d585-424b-b8e8-b523242661d9");
Make sure to use your own 'terminalId' and 'terminalSecret' values.
import com.faizpay.payment.sdk.NotificationHandler;
import com.faizpay.payment.sdk.ErrorHandler;
NotificationHandler notificationHandler = new NotificationHandler(connection, tokenFromPostRequest);
ErrorHandler error = notificationHandler.isValid();
if (error instanceof ErrorHandler) {
System.out.println(error);
return;
}
Fena calls the webhook or notification endpoint with post request of encoded as "application/x-www-form-urlencoded" with token in key called "token".
// get the order id
String orderId = notificationHandler.getOrderID();
// fetch the order from your database
Object data = searchYourDatabase(orderId);
// if order is not found in system
if (checkIfEntryFound(data)) {
System.out.println("Invalid Token - " + tokenFromPostRequest);
return;
}
// validate if the requested payment matches with token
if (notificationHandler.validateAmount(data["amount"])) {
System.out.println("Invalid Amount - " + tokenFromPostRequest);
return;
}
// all checks are passed - update the database to mark payment complete
Setup Redirect Page
User will be redirected back to your redirect endpoint with your Order ID in query as "order" And Payment Status in query as "status" as query parameter.
You can read more about Redirect pages in our Redirect Handling section.
Connection
Our SDK uses a connection object for most of the requests. To create a new connection object, you simply need to do the following:
terminal ID = 8afa74ae-6ef9-48bb-93b2-9fe8be53db50
terminal Secret = 55d7d5ed-be22-4321-bb3f-aec8524d8be2
import com.faizpay.payment.sdk.Connection;
import com.faizpay.payment.sdk.ErrorHandler;
Connection connection = new Connection("315f2c07-fd16-4462-86d2-05b0b18d5b39", "6a8dfd42-d585-424b-b8e8-b523242661d9");
Make sure to use your own 'terminalId' and 'terminalSecret' values.
Input Arguments
Argument | Required | Description |
---|---|---|
Terminal Id | Yes | Terminal ID of terminal. Must be UUID 4. |
Terminal Secret | Yes | Terminal Secret of terminal. Must be UUID 4. |
We recommend you validate your object. This can be done by calling isValid
method on object.
ErrorHandler error = connection.isValid();
if (error instanceof ErrorHandler) {
System.out.println(error);
}
If valid arguments are given, error object will be null otherwise it will be object of ErrorHandler
.
Return Object
Operation | Class Object |
---|---|
Success | null |
Error | ErrorHandler Code 1 |
Error | ErrorHandler Code 2 |
Payment
To create a new payment, you simply do the following:
Order ID = 1
Amount = 2.00
import com.faizpay.payment.sdk.Payment;
import com.faizpay.payment.sdk.ErrorHandler;
Payment payment = new Payment(connection, "1", "2.00");
Make sure your orderId is unique. If the payment for the given orderId has completed before for your terminal user will be redirected to your redirect endpoint without executing the payment. This is setup to avoid the duplicate payment.
Input Arguments
Argument | Required | Description |
---|---|---|
Connection | Yes | Connection object. |
Order Id | Yes | Your Order ID. Must not be empty and cannot be more than 255 characters. |
Amount | Yes | Amount requested must be in 2 decimal places, string and greater than 0.00. |
We recommend you should validate your object. This can be done by calling isValid
method on object.
ErrorHandler error = payment.isValid();
if (error instanceof ErrorHandler) {
System.out.println(error);
}
If valid arguments are given, error object will be null otherwise it will be object of ErrorHandler
.
Return Object
Operation | Class Object |
---|---|
Success | null |
Error | ErrorHandler Code 3 |
Error | ErrorHandler Code 4 |
Error | ErrorHandler Code 5 |
Error | ErrorHandler Code 6 |
Payment Process
To return the redirect url after a payment, call Process
on the Payment object.
String url = payment.process();
Provider
If you want to predefine the account provider or force the customer to pay from a certain account use the Provider object. To create a new Provider, do the following:
provider ID = ob-lloyds-personal
sort code = 123456
account number = 12345678
Full list of supported provider ids can be found using this endpoint
https://app.fena.co/api/providers
import com.faizpay.payment.sdk.Provider;
import com.faizpay.payment.sdk.ErrorHandler;
Provider provider = new Provider(
"ob-lloyds-personal",
"123456",
"12345678"
);
Input Arguments
Argument | Required | Description |
---|---|---|
Provider ID | Yes | Must be a value of provider given by Fena. |
Sort Code | *No | Must be 6 digits and numeric. Cannot empty if Account Number is given. |
Account Number | *No | Must be 8 digits and numeric. Cannot empty if Sort Code is given. |
We recommend you should validate your object. This can be done by calling isValid
method on object.
ErrorHandler error = provider.isValid();
if(error instanceof ErrorHandler){
System.out.println(error);
}
If valid arguments are given, error object will be null otherwise it will be object of ErrorHandler
.
Return Object
Operation | Class Object |
---|---|
Success | null |
Error | ErrorHandler Code 7 |
Error | ErrorHandler Code 8 |
Error | ErrorHandler Code 9 |
Error | ErrorHandler Code 10 |
User
If you want to send the customers details to Fena. You can set customer detail using User object. To Create a new User, do the following:
email = john.doe@test.com
firstName = John
lastName = Doe
contactNumber = 07000845953
import com.faizpay.payment.sdk.User;
import com.faizpay.payment.sdk.ErrorHandler;
User user = new User(
"john.doe@test.com",
"John",
"Doe",
"07000845953"
);
Input Arguments
Argument | Required | Description |
---|---|---|
Yes | Must be valid email. Can be empty. Must not be more than 255 characters. | |
First Name | Yes | Can be empty. Must not be more than 255 characters. |
Last Name | Yes | Can be empty. Must not be more than 255 characters. |
Contact Number | Yes | Can be empty. Must not be more than 255 characters. |
We recommend you should validate your object. This can be done by calling isValid
method on object.
ErrorHandler error = user.isValid();
if (error instanceof ErrorHandler) {
System.out.println(error);
}
If valid arguments are given, error object will be null otherwise it will be object of ErrorHandler
.
Return Object
Operation | Class Object |
---|---|
Success | null |
Error | ErrorHandler Code 12 |
Error | ErrorHandler Code 13 |
Error | ErrorHandler Code 14 |
Error | ErrorHandler Code 15 |
Notification Handling
Fena calls the webhook or notification endpoint with post request of encoded as "application/x-www-form-urlencoded" with token in key called "token".
Fena will only make a notification request if the payment is successful.
Only one request will be made per your unique order id. This is to prevent duplicated payments.
To handle the webhook or notification of payment, create a NotificationHandler
object .
import com.faizpay.payment.sdk.NotificationHandler;
import com.faizpay.payment.sdk.ErrorHandler;
NotificationHandler notificationHandler = new NotificationHandler(
connection, tokenFromPostRequest
);
Input Arguments
Argument | Required | Description |
---|---|---|
Connection | Yes | Connection object. |
token | Yes | Token sent by Fena. Fena post token with key of "token". |
ErrorHandler error = notificationHandler.isValid();
if (error instanceof ErrorHandler) {
System.out.println(error);
}
We recommend you should validate your object. This can be done by calling isValid
method on object.
Return Object
Operation | Class Object |
---|---|
Success | null |
Error | ErrorHandler Code 16 |
Error | ErrorHandler Code 17 |
Error | ErrorHandler Code 18 |
NotificationHandler Functions
Once the NotificationHandler objected is created you can call the following functions.
Operation | Argument | Class Object |
---|---|---|
getOrderID | get the order id set in the payment object | |
getRequestedAmount | get the requested amount | |
getNetAmount | get the net amount paid | |
getId | get the Fena transaction id | |
getTerminal | get the terminal id | |
validateAmount | amountRequested | return true or false by validating amount requested in token matches your amountRequested in database |
We recommend 'amount' to be validated using "validateAmount" to make sure user has paid the requested amount.
Redirect Handling
On payment completion, or rejection, the user will be redirected to "Redirect Endpoint" configured in terminal settings along with two query parameters:
- order
- status
Your Order ID as "order"
Payment Status as "status"
Example:
https://www.test.com/thankyou?order=aa-bb-cc&status=executed
Status Description
Status | Description |
---|---|
executed | Payment has been successfully processed |
rejected | Payment has been rejected by the account provider |
Errors
Errors in the SDK are handled via the ErrorHandler
object.
error.getCode();
error.getMessage();
error object has 2 methods
The SDK uses the following error codes:
Error Code | Meaning |
---|---|
1 | Invalid Terminal ID - Should be valid UUID4 |
2 | Invalid Terminal Secret - Should be valid UUID4 |
3 | Order ID cannot be empty |
4 | Amount cannot be empty or less than 0.01 |
5 | Number must be 2 decimal places |
6 | Order ID cannot be greater than 255 characters |
7 | Invalid Sort Code |
8 | Invalid Account Number |
9 | Provider ID must be set to set sort code and account number |
10 | Sort Code and account both must be set |
11 | Invalid email is given |
12 | First name: needs to be less than 255 |
13 | Last name: needs to be less than 255 |
14 | Contact Number: needs to be less than 255 |
15 | Email: needs to be less than 255 |
16 | Unable to decode the token - Invalid / Expire token given |
17 | Token content missing data |
18 | Token terminal mismatch |