Skip to main content

Java SDK

The Papi Java SDK (papi-api-client) provides a typed client for the Papi payment API. It handles HTTP communication, serialization, and model classes so you can focus on your business logic.


Installation

The SDK is hosted on the Ibonia package repository. Add the repository and the dependency to your project.

Maven

<repositories>
<repository>
<id>ibonia-repo-group</id>
<url>https://package-repository.ibonia.com/repository/ibonia-mvn-group</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>com.ibonia.papi</groupId>
<artifactId>papi-api-client</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>

Gradle

repositories {
maven { url 'https://package-repository.ibonia.com/repository/ibonia-mvn-group' }
}

dependencies {
implementation 'com.ibonia.papi:papi-api-client:1.0.2'
}

Core classes

ClassPackageDescription
ApiClientcom.ibonia.papi.apiclientBase HTTP client. Instantiate once and share.
PaymentLinksApicom.ibonia.papi.apiclient.apiMethods for creating payment links.
PaymentLinkRequestcom.ibonia.papi.apiclient.modelRequest body for creating a payment link.
PaymentLinkResponsecom.ibonia.papi.apiclient.modelResponse returned after a payment link is created.
PaymentResponsecom.ibonia.papi.apiclient.modelPayload sent by Papi to your notification endpoint.

Usage

1
Initialize the client

Create one ApiClient instance (it is thread-safe) and pass it to PaymentLinksApi. In a Spring application, do this in the constructor so the API instance is ready when your bean is created.

import com.ibonia.papi.apiclient.ApiClient;
import com.ibonia.papi.apiclient.api.PaymentLinksApi;

ApiClient apiClient = new ApiClient();
PaymentLinksApi paymentLinksApi = new PaymentLinksApi(apiClient);
2
Build a payment link request

Construct a PaymentLinkRequest using the fluent builder. The fields amount, description, clientName, reference, and notificationUrl are required.

import com.ibonia.papi.apiclient.model.PaymentLinkRequest;
import java.net.URI;

PaymentLinkRequest request = new PaymentLinkRequest()
.amount(15000.0)
.description("Payment for Order #123")
.clientName("John Doe")
.reference("ORDER-123")
.payerEmail("john.doe@example.com")
.payerPhone("+261340000000")
.notificationUrl(new URI("https://yourapp.com/api/payment-notifications"))
.validDuration(60); // link expires after 60 minutes
3
Create the payment link

Call createPaymentLink with your API key (from the dashboard) and the request. The method returns a wrapper — call .getData() to get the actual PaymentLinkResponse.

import com.ibonia.papi.apiclient.model.PaymentLinkResponse;

PaymentLinkResponse response = paymentLinksApi
.createPaymentLink("YOUR_API_KEY", request)
.getData();

String paymentUrl = response.getPaymentLink(); // redirect the user here
String notifToken = response.getNotificationToken(); // store this for verification

Redirect the customer to paymentUrl. After the payment, Papi will call your notificationUrl with the result.

4
Handle the payment notification

Expose a POST endpoint that accepts a PaymentResponse body. Papi calls this endpoint after every payment attempt.

import com.ibonia.papi.apiclient.model.PaymentResponse;

@PostMapping("/api/payment-notifications")
public ResponseEntity<?> handleNotification(
@RequestBody @Valid PaymentResponse notification) {

// Verify authenticity before doing anything else
boolean tokenMatches = notifToken.equals(notification.getNotificationToken());
boolean refMatches = "ORDER-123".equals(notification.getMerchantPaymentReference());

if (!tokenMatches || !refMatches) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}

switch (notification.getPaymentStatus()) {
case SUCCESS -> handleSuccess(notification);
case FAILED -> handleFailure(notification);
case PENDING -> handlePending(notification);
}

return ResponseEntity.ok().build();
}

PaymentLinkRequest fields

FieldTypeRequiredDescription
amountdoublePayment amount (minimum 300 MGA).
clientNameStringCustomer's full name.
referenceStringYour unique identifier for this payment.
descriptionStringShort payment description (max 255 chars).
notificationUrlURIEndpoint that receives payment status notifications.
payerEmailStringCustomer's email address.
payerPhoneStringCustomer's phone number.
successUrlURIRedirect URL after a successful payment.
failureUrlURIRedirect URL after a failed payment.
validDurationintLink validity in minutes (default: 1).
providerStringLock to one provider: MVOLA, ARTEL_MONEY, ORANGE_MONEY, BRED.
isTestModebooleantrue to flag the transaction as a test in the dashboard.
testReasonStringReason displayed in the dashboard when test mode is on.

PaymentResponse fields

FieldGetterDescription
paymentStatusgetPaymentStatus()SUCCESS, FAILED, or PENDING.
paymentMethodgetPaymentMethod()Provider used: MVOLA, ARTEL_MONEY, ORANGE_MONEY, BRED.
currencygetCurrency()Always MGA.
amountgetAmount()Amount paid.
feegetFee()Transaction fee deducted.
clientNamegetClientName()Customer's name.
descriptiongetDescription()Payment description.
merchantPaymentReferencegetMerchantPaymentReference()Internal reference from the payment provider.
notificationTokengetNotificationToken()Token from the original payment link response — use to verify authenticity.
paymentReferencegetPaymentReference()Your reference from the original request.
payerEmailgetPayerEmail()Customer email (if provided).
payerPhonegetPayerPhone()Customer phone (if provided).

Full example (Spring Boot)

The example below shows a complete Spring Boot service that creates a payment link and handles the callback notification — the same pattern used in production.

import com.ibonia.papi.apiclient.ApiClient;
import com.ibonia.papi.apiclient.api.PaymentLinksApi;
import com.ibonia.papi.apiclient.model.PaymentLinkRequest;
import com.ibonia.papi.apiclient.model.PaymentLinkResponse;
import com.ibonia.papi.apiclient.model.PaymentResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URI;

@Service
public class PaymentService {

private final PaymentLinksApi paymentLinksApi;

@Value("${app.domain}")
private String appDomain;

public PaymentService() {
this.paymentLinksApi = new PaymentLinksApi(new ApiClient());
}

public String createPaymentLink(String apiKey, double amount,
String reference, String customerName,
String email, String phone) throws Exception {
PaymentLinkRequest request = new PaymentLinkRequest()
.amount(amount)
.description("Payment " + reference)
.clientName(customerName)
.reference(reference)
.payerEmail(email)
.payerPhone(phone)
.notificationUrl(new URI(appDomain + "/api/payment-notifications"))
.validDuration(60);

PaymentLinkResponse response = paymentLinksApi
.createPaymentLink(apiKey, request)
.getData();

// Persist response.getNotificationToken() alongside the order reference
// so you can verify it when the notification arrives.

return response.getPaymentLink();
}

public void handleNotification(PaymentResponse notification) {
String storedToken = lookupNotificationToken(
notification.getMerchantPaymentReference());

if (!storedToken.equals(notification.getNotificationToken())) {
throw new SecurityException("Notification token mismatch");
}

if (notification.getPaymentStatus() == PaymentResponse.PaymentStatusEnum.SUCCESS) {
confirmOrder(notification.getMerchantPaymentReference());
}
}

// ... lookupNotificationToken and confirmOrder implementations
}