Java
The Paysafe Java SDK is designed to simplify integration with the Paysafe Payments API, providing a type-safe, convenient wrapper around the platform’s RESTful endpoints. It handles the foundational tasks required for secure and reliable API communication, including connection management, authentication, encryption, tokenization, data validation, and exception handling.
Paysafe’s server-side SDKs significantly streamline the integration process, reducing the development effort required to interact with the REST APIs. The Java SDK is fully compatible with package management tools like Gradle and Maven, enabling seamless inclusion in any Java-based project. Although integrating the SDK into your payment flows is optional, it offers numerous advantages:
- Comprehensive API coverage: The library encompasses the latest set of APIs, as outlined in our Developer Portal, ensuring compatibility with the most recent features and enhancements.
- Auto-generated models and request structures: The SDK provides pre-defined models and request parameter structures, mitigating the need for manual construction of API payloads and reducing the likelihood of errors.
- Intelligent request handling: The SDK includes built-in mechanisms for automatic request retries, improving resilience and reliability by mitigating transient failures and network-related issues.
- Advanced exception management: The SDK incorporates robust exception-handling mechanisms for API responses, simplifying error detection and recovery while ensuring seamless transaction processing
By leveraging the SDK, you can expedite integration, enhance maintainability, and focus on core business logic rather than low-level API interactions.
The following diagram shows where the SDKs fit into the Paysafe API integration flow:
Before you begin
Contact your business relationship manager or send an email to integrations@paysafe.com for your Merchant Portal credentials.
To obtain the Secret API key from the Merchant Portal:
- Log in to the Merchant Portal.
- Go to Developer > API Keys.
- For the Secret Key, you are required to authenticate once more.
- When the key is revealed, click the Copy icon to copy the API key.
- Your API key will have the format username:password, for example:
MerchantXYZ:B-tst1-0-51ed39e4-312d02345d3f123120881dff9bb4020a89e8ac44cdfdcecd702151182fdc952272661d290ab2e5849e31bb03deede9
Notes:
- Use the same API key for all payment methods.
- The API key is case-sensitive and sent using HTTP Basic Authentication
For more information, see Authentication.
Installation
Requirements
- Java 11 or later
Gradle users
Add this dependency to your project's build file:
implementation "com.paysafe.paymentsapi:sdk-java:1.0.0"
Maven users
Add this dependency to your project's POM:
<dependency>
<groupId>com.paysafe.paymentsapi</groupId>
<artifactId>sdk-java</artifactId>
<version>1.0.0</version>
</dependency>
Dependencies
The Paysafe Java SDK requires the following dependencies to work properly:
- Apache HttpClient - Http Client
- Jackson - Json serializer/ deserializer
Usage
PaysafeClient
The PaysafeClient class serves as the primary entry point for interacting with the Paysafe API. It provides access to various services and methods required to execute specific API requests.
The client can be configured to operate in either the LIVE or TEST environment, depending on your integration needs.
You can instantiate a PaysafeClient using either the provided constructor or the Java Builder Pattern, allowing for flexible and readable client configuration.
To create a PaysafeClient instance using constructor:
PaysafeClient paysafeClient = new PaysafeClient(apiKey, Environment.TEST);
This PaysafeClient instance will use the default client configuration (connect and response timeouts, automatic retries).
You can also instantiate PaysafeClient using the provided builder pattern. This enables additional API client configurations:
PaysafeClient paysafeClient = PaysafeClient.builder()
.apiKey(yourApiKey)
.environment(environement)
.automaticRetries(customRetries)
.connectTimeout(customConnectTimeout)
.responseTimeout(customResponseTimeout)
.sslContext(customSslContext)
.proxy(customProxy)
.build();
If some values are not provided in the builder call, default values will be used.
API Key
The Base64-encoded version of the secret API key is used to authenticate with the Payments API. For more information about obtaining your API Keys, see Before you begin.
Please keep your api key in a safe location, for example, load it from HashiCorp vault, Java Keystore, Kubernetes Secrets etc.
Environment
The environment is used to select the environment for tokenization. The accepted environments are PROD (Paysafe Production environment) and TEST (Paysafe Merchant Test or Sandbox environment).
Do not use real card numbers or other payment instrument details in the Merchant Test environment. Test/ Sandbox is not compliant with Payment Card Industry Data Security Standards (PCI-DSS) and does not protect cardholder/ payee information. Any upload of real cardholder data is strictly prohibited, as described in the Terms of Use.
Automatic retries
The client can be configured to automatically retry GET requests that have failed due to network problems or other unpredictable events. By default, such requests are retried three times, with a maximum of five retries allowed.
Connect and response timeouts
The client can be configured to use provided connect and response timeouts. Values must be provided in milliseconds. We recommend setting the value cautiously, as some requests may take longer to process.
Default values are:
- 30 seconds for connect timeout
- 60 seconds for response timeout
Proxy
PaysafeClient allows custom proxies to route all outgoing HTTP traffic through a corporate proxy server if required. A proxy object can be provided directly in builder:
Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress("localhost", 8443));
// Setup proxy credentials
PasswordAuthentication passwordAuthentication = new PasswordAuthentication("username", "password");
PaysafeClient paysafeClient = PaysafeClient.builder()
.apiKey(yourApiKey)
.environment(environement)
.proxy(customProxy)
.build();
Additionally, proxies can be automatically discerned from system level settings:
System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", "8443");
System.setProperty("http.proxyUser", "squid");
System.setProperty("http.proxyPassword", "ward");
SSLContext
The client also supports custom SSLContext. For example, custom SSLContext can be created as follows:
// Import the required classes
import com.paysafe.PaysafeClient;
import com.paysafe.enums.Environment;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.security.KeyStore;
// Initialize a KeyManagerFactory with the client KeyStore and password
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, clientKeyStorePassword);
// Create a TrustManagerFactory that trusts the CAs in our Trust KeyStore
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
//In case you want to use custom .pem file for SSL
X509ExtendedKeyManager keyManager = PemUtils.loadIdentityMaterial("certificate-chain.pem", "private-key.pem", "private-key-password".toCharArray());
X509ExtendedTrustManager trustManager = PemUtils.loadTrustMaterial("some-trusted-certificate.pem");
SSLFactory sslFactory = SSLFactory.builder()
.withIdentityMaterial(keyManager)
.withTrustMaterial(trustManager)
.build();
SSLContext sslContext = sslFactory.getSslContext();
This sslContext can be used in PaysafeClient builder:
PaysafeClient paysafeClient = PaysafeClient.builder()
.apiKey(yourApiKey)
.environment(environement)
.sslContext(sslContext)
.build();
Transaction flows
Check the status of the Payments API
As a first step, you can check the status of the Payments API by calling:
PaysafeClient paysafeClient = new PaysafeClient(apiKey, Environment.TEST);
paysafeClient.monitorService().verifyThatServiceIsAccessible();
assertEquals(ServiceStatus.READY, monitorResponse.getStatus());
Create a payment handle
The first step in creating a new transaction is to create a payment handle. A payment handle represents tokenized information about the payment method that you set up for a customer. Once the payment handle is created, you can include the paymentHandleToken in a new Payment, Standalone Credit, Original Credit, or Verification request.
To create a payment handle, please use a unique merchant reference number for each request.
Use the provided builder to create the payment handle request:
PaymentHandleRequest paymentHandleRequest = PaymentHandleRequest.builder()
.merchantRefNum(MERCHANT_REF_NUM)
.transactionType(TransactionType.PAYMENT)
.paymentType(PaymentType.CARD)
.amount(500)
.currencyCode(CurrencyCode.USD)
.threeDs(ThreeDs.builder()
.merchantUrl("https://api.qa.paysafe.com/checkout/v2/index.html#/desktop")
.deviceChannel("BROWSER")
.messageCategory("PAYMENT")
.transactionIntent(TransactionIntent.CHECK_ACCEPTANCE)
.authenticationPurpose(AuthenticationPurpose.PAYMENT_TRANSACTION)
.build())
.card(Card.builder()
.cardNum("4000000000001026")
.cardExpiry(CardExpiry.builder()
.month(10)
.year(2025)
.build())
.cvv("111")
.issuingCountry("US")
.build())
.accountId("1009688230")
.billingDetails(BillingDetails.builder()
.nickName("Home")
.street("Street name")
.city("City Name")
.state("AL")
.country("US")
.zip("94404")
.build())
.returnLinks(List.of(ReturnLink.builder()
.rel(ReturnLinkRel.DEFAULT)
.href("https://usgaminggamblig.com/payment/return/")
.method("GET")
.build()))
.build();
PaymentHandleRequest paymentHandleRequest = PaymentHandleRequest.builder()
.merchantRefNum(MERCHANT_REF_NUM)
.transactionType(TransactionType.PAYMENT)
.paymentType(PaymentType.SKRILL)
.amount(500)
.currencyCode(CurrencyCode.USD.toString())
.skrill(Skrill.builder()
.consumerId("greg_neteller@mailinator.com")
.emailSubject("Payout for XYZ")
.language("AT")
.logoUrl("http://www.paysafe.com/icon.jpg")
.detailDescription("Details 1 description")
.countryCode(CountryCode.DE)
.build())
.billingDetails(BillingDetails.builder()
.nickName("Home")
.street("Street name")
.city("City Name")
.state("AL")
.country("US")
.zip("94404")
.build())
.returnLinks(List.of(ReturnLink.builder()
.rel(ReturnLinkRel.DEFAULT)
.href("https://usgaminggamblig.com/payment/return/")
.method("GET")
.build()))
.build();
PaymentHandleRequest paymentHandleRequest = PaymentHandleRequest.builder()
.merchantRefNum(MERCHANT_REF_NUM)
.transactionType(TransactionType.PAYMENT)
.paymentType(PaymentType.PAYPAL)
.amount(500)
.currencyCode(CurrencyCode.USD)
.paypal(Paypal.builder()
.consumerId("saurabh.goyal@paypal.com")
.recipientDescription("My store description")
.language("AT")
.shippingPreference("GET_FROM_FILE")
.consumerMessage("My note to payer")
.orderDescription("My Order Description")
.recipientType(RecipientType.PAYPAL_ID)
.build())
.billingDetails(BillingDetails.builder()
.nickName("Home")
.street("Street name")
.city("City Name")
.state("AL")
.country("US")
.zip("94404")
.build())
.returnLinks(List.of(ReturnLink.builder()
.rel(ReturnLinkRel.DEFAULT)
.href("https://usgaminggamblig.com/payment/return/")
.method("GET")
.build()))
.build();
After which, you can call the corresponding method to create a payment handle:
try {
PaymentHandle paymentHandle = paysafeClient.paymentHandleService().createPaymentHandle(paymentHandleRequest);
}
catch (PaysafeSdkException e) {
log.error(e);
}
Process payments
To process a payment, you can create a payment request using the provided builder and submit it:
PaymentRequest paymentRequest = PaymentRequest.builder()
.merchantRefNum("YOUR_UNIQUE_MERCHANT_REF_NUMBER")
.amount(500)
.paymentHandleToken("SC2INoYvSe2MzQuB")
.currencyCode(USD)
.settleWithAuth(false)
.customerIp("172.0.0.1")
.currencyCode(USD)
.merchantDescriptor(MerchantDescriptor.builder()
.dynamicDescriptor("test")
.phone("1000000000")
.build())
.customerIp("172.0.0.1")
.build();
try {
Payment payment = paysafeClient.paymentService().processPayment(paymentRequest);
}
catch (PaysafeSdkException e) {
log.error(e);
}
If you want to authorize and settle the payment in a single request, use settleWithAuthset to true.
If you want to authorize and settle the payment separately, use settleWithAuthset to false.
The returned payment object will include an id, a unique identifier for the payment (whether settled or not). This id can be used to process settlements or refunds.
Process settlements
To process a settlement for a payment request created with settleWithAuth (false), you need to create a settlement request:
SettlementRequest request = SettlementRequest.builder()
.merchantRefNum("YOUR_UNIQUE_MERCHANT_REF_NUMBER")
.amount(500)
.build();
String paymentId = payment.getId();
try {
Settlement settlement = paysafeClient.settlementService().processSettlement(paymentId, request)
}
catch (PaysafeSdkException e) {
log.error(e);
}
Process refunds
To process a refund, you need to create a refund request:
RefundRequest refundRequest = RefundRequest.builder()
.merchantRefNum("YOUR_UNIQUE_MERCHANT_REF_NUMBER")
.amount(500)
.dupCheck(true)
.build();
If the payment was settled immediately, use:
String id = payment.getId();
If the payment was settled manually, by processing a settlement, use:
String id = settlement.getId();
Finally, execute the refund request:
try {
Refund refund = paysafeClient.refundService().processRefund(id, refundRequest);
}
catch (PaysafeSdkException e) {
log.error(e);
}
Using undocumented parameters
The Paysafe Java SDK is strongly typed and designed to support all officially released API fields. However, the Payments API may occasionally include new, undocumented, or experimental properties that are not part of the public API. These properties are typically in a testing phase and may take some time to be reflected in the SDKs.
To use such parameters in classes representing API payloads (for example PaymentHandleRequest), we have provided the additionalParameters field, which can be added one by one or as a complete map.
Request additional parameters
public Map<String, Object> getAdditionalParameters() {
return additionalParameters;
}
public void setAdditionalParameters(Map<String, Object> additionalParameters) {
this.additionalParameters = additionalParameters;
}
public void addAdditionalParameter(String key, Object value) {
if (additionalParameters == null) {
additionalParameters = new HashMap<>();
}
additionalParameters.put(key, value);
}
Usage
paymentHandleRequest.addAdditionalParameter("booleanParameter", true);
paymentHandleRequest.addAdditionalParameter("objectParameter",
Address.builder()
.city("London")
.country("United Kingdom")
.phone("+2139243")
.build()
);
Request customizations
Besides client-level customizations, the following values can also be customized at the request level:
- automaticRetries
- connectTimeout
- responseTimeout
- simulator header - used only in the TEST environment, for POST, PUT, PATCH, DELETE requests.
To customize a request, provide the RequestOptions object in method calls:
RequestOptions requestOptions = RequestOptions.builder()
.connectTimeout(90000)
.simulator(PaymentSimulator.INTERNAL)
.automaticRetries(3)
.connectionTimeout(10 * 1000) // In milliseconds
.readTimeout(20 * 1000) //In milliseconds
.build();
PaymentHandle paymentHandle = paymentHandleService.createPaymentHandle(paymentHandleRequest, requestOptions);
If one of the values is not provided (in this case, responseTimeout), the value from PaysafeClient will be used.
Exceptions
The Paysafe Java SDK encapsulates major API errors thrown by the Payments API, providing fine-grained control over exception handling. This abstraction simplifies error management, making it easier to identify, handle, and recover from API failures efficiently. By leveraging structured exception handling, you can navigate errors more effectively, ensuring smoother integration and enhanced application resilience.
Most exceptions in the SDK wrap Paysafe’s API Error object, as explained in the Payments API Reference, providing a standardized and consistent approach to error reporting and resolution.
The Correlation ID included in the exception can be shared with Paysafe for further debugging and issue investigation. This unique identifier allows our support and engineering teams to trace specific requests, analyze failures, and provide quicker resolutions, ensuring efficient troubleshooting and enhanced support responsiveness
All exceptions thrown by the PaysafeClient are subclasses of PaysafeSdkException.java. Specific HTTP response codes or situations are mapped to corresponding exceptions for clearer and more structured error handling:
Exception | Use case |
---|---|
InvalidCredentialsException | 401 HTTP Code |
InvalidRequestException | 400 HTTP Code |
UnauthorizedException | 403 HTTP Code |
RequestConflictException | 409 HTTP Code |
RequestDeclinedException | 402 HTTP Code |
APIException | 500+ HTTP Code |
APIConnectionException | Not able to connect to Paysafe APIs |
IllegalArgumentException | When any supplied argument is wrong |
PaysafeSdkException | Generic exception |
The following fields may be included in each exception, when available:
- internalCorrelationId - unique ID returned by the Payments API that can be provided to the Paysafe Support team as a reference for investigation.
- code - HTTP status code returned by the Payments API.
- error - contains details about the error, returned by the Payments API.
InvalidCredentialsException
Thrown when the Authentication credentials are wrong. Please revalidate the API key or contact Paysafe for the correct API key.
{
code = 401, // Http Status Code
correlationId ="9a59e6ba-5635-4d1d-8e4e-8c390bb0da34", // Paysafe API Request Correlation ID
error = PaysafeError {
code: 5279 //The error code. Also shown in the X-Application-Status-Code response header
message: "Invalid credentials"
details: ["The authentication credentials are invalid"]
}}
InvalidRequestException
Thrown when the request contains invalid fields, is missing required fields, or has an incorrect request state. Please reverify the API request parameters based on the Error Details provided.
{
code = 400, // Http Status Code
correlationId ="9a59e6ba-5635-4d1d-8e4e-8c390bb0da34", // Paysafe API Request Correlation ID
error = PaysafeError {
code: 5068 //The error code. Also shown in the X-Application-Status-Code response header
message: "Field error(s)"
details: ["Either you submitted a request that is missing a mandatory field or the value of a field does not match the format expected"]
fieldErrors: [{
field: "paymentHandle",
error: "Payment handle provided is not permitted for Payments because of its state"
}]
}}
UnauthorizedException
Thrown when the API cannot be accessed using the provided API key. Please reverify the API key or contact Paysafe support for assistance.
{
code = 403, // Http Status Code
correlationId ="9a59e6ba-5635-4d1d-8e4e-8c390bb0da34", // Paysafe API Request Correlation ID
error = PaysafeError {
code: 5270 //The error code. Also shown in the X-Application-Status-Code response header
message: "Unauthorized access"
details: ["The credentials provided with the request do not have permission to access the data requested"]
}}