Java SDK
GitHub Repository: sunbay-nexus-sdk-java
Official SUNBAY Nexus Java SDK, providing complete payment integration capabilities for Java 8+ applications.
Features
- ✅ Clean and intuitive API design
- ✅ Builder pattern for request construction
- ✅ Support for Java 8+
- ✅ Automatic authentication
- ✅ Automatic retry for GET requests
- ✅ Comprehensive exception handling
- ✅ Minimal dependencies
Installation
Maven
<dependency>
<groupId>com.sunmi</groupId>
<artifactId>sunbay-nexus-sdk-java</artifactId>
<version>1.0.8</version>
</dependency>Quick Start
1. Initialize Client
NexusClient is thread-safe and can be reused in multi-threaded environments. There are two usage patterns:
Pattern 1: Singleton Pattern (Recommended for Production)
// Create once, reuse globally
NexusClient client = new NexusClient.Builder()
.apiKey("{YOUR_API_KEY}")
.baseUrl("https://open.sunbay.us")
.build();
// Use client throughout the application
// Remember to call client.close() when shutting downPattern 2: try-with-resources (For Temporary Use)
// Client implements AutoCloseable, can use try-with-resources
try (NexusClient client = new NexusClient.Builder()
.apiKey("{YOUR_API_KEY}")
.baseUrl("https://open.sunbay.us")
.build()) {
// Use client
SaleResponse response = client.sale(request);
// Client automatically closes when exiting try block
}2. Create Payment Transaction
import com.sunmi.sunbay.nexus.NexusClient;
import com.sunmi.sunbay.nexus.exception.SUNBAYBusinessException;
import com.sunmi.sunbay.nexus.exception.SUNBAYNetworkException;
import com.sunmi.sunbay.nexus.model.common.SaleAmount;
import com.sunmi.sunbay.nexus.model.request.SaleRequest;
import com.sunmi.sunbay.nexus.model.response.SaleResponse;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
// Assume client is already initialized (singleton or try-with-resources)
// NexusClient client = ... (from step 1)
// Set expiration time (optional)
ZonedDateTime expireTime = ZonedDateTime.now().plusMinutes(10);
String timeExpire = expireTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX"));
// Build amount using Builder pattern
// Note: All amount fields use Integer type, in smallest currency unit (cents)
// Example: 100.00 USD = 10000 cents
SaleAmount amount = SaleAmount.builder()
.orderAmount(10000) // 100.00 USD, in cents
.priceCurrency("USD")
.build();
// Build payment request using Builder pattern
SaleRequest request = SaleRequest.builder()
.appId("app_123456")
.merchantId("mch_789012")
.referenceOrderId("ORDER20231119001")
.transactionRequestId("PAY_REQ_" + System.currentTimeMillis())
.amount(amount)
.description("Product purchase")
.terminalSn("T1234567890")
.timeExpire(timeExpire)
.build();
// Execute transaction
try {
SaleResponse response = client.sale(request);
// If no exception is thrown, transaction is successful
System.out.println("Transaction ID: " + response.getTransactionId());
} catch (SUNBAYNetworkException e) {
System.err.println("Network Error: " + e.getMessage());
} catch (SUNBAYBusinessException e) {
System.err.println("API Error: " + e.getCode() + " - " + e.getMessage());
}API Methods
All request classes support the Builder pattern for convenient object construction.
Transaction APIs
sale(SaleRequest)- Payment transactionauth(AuthRequest)- Pre-authorizationforcedAuth(ForcedAuthRequest)- Forced authorizationincrementalAuth(IncrementalAuthRequest)- Incremental authorizationpostAuth(PostAuthRequest)- Post-authorization completionrefund(RefundRequest)- RefundvoidTransaction(VoidRequest)- Void transactionabort(AbortRequest)- Abort transactiontipAdjust(TipAdjustRequest)- Tip adjustment
Example: Pre-authorization
AuthRequest request = AuthRequest.builder()
.appId("app_123456")
.merchantId("mch_789012")
.referenceOrderId("AUTH" + System.currentTimeMillis())
.transactionRequestId("PAY_REQ_" + System.currentTimeMillis())
.amount(AuthAmount.builder()
.orderAmount(20000) // 200.00 USD, in cents
.priceCurrency("USD")
.build())
.description("Hotel reservation")
.terminalSn("T1234567890")
.build();
AuthResponse response = client.auth(request);Query APIs
query(QueryRequest)- Query transaction
Example: Query Transaction
QueryRequest request = QueryRequest.builder()
.appId("app_123456")
.merchantId("mch_789012")
.transactionId("TXN20231119001")
.build();
QueryResponse response = client.query(request);Settlement APIs
batchClose(BatchCloseRequest)- Batch settlement
Example: Batch Settlement
BatchCloseRequest request = BatchCloseRequest.builder()
.appId("app_123456")
.merchantId("mch_789012")
.transactionRequestId("BATCH_CLOSE_" + System.currentTimeMillis())
.terminalSn("T1234567890")
.description("End of day settlement")
.build();
BatchCloseResponse response = client.batchClose(request);Exception Handling
The SDK throws two types of exceptions:
SUNBAYNetworkException: Network-related errors (connection timeout, network errors, etc.)SUNBAYBusinessException: Business logic errors (parameter validation, API business errors, etc.)
Always catch SUNBAYNetworkException first, then SUNBAYBusinessException
// Build request using Builder pattern
SaleRequest request = SaleRequest.builder()
.appId("app_123456")
.merchantId("mch_789012")
.referenceOrderId("ORDER20231119001")
.transactionRequestId("PAY_REQ_" + System.currentTimeMillis())
.amount(SaleAmount.builder()
.orderAmount(10000) // 100.00 USD, in cents
.priceCurrency("USD")
.build())
.description("Product purchase")
.terminalSn("T1234567890")
.build();
try {
SaleResponse response = client.sale(request);
// If no exception is thrown, transaction is successful
// Use response object here
} catch (SUNBAYNetworkException e) {
// Network exception (e.g., connection timeout, network error)
System.err.println("Network Error: " + e.getMessage());
if (e.isRetryable()) {
// Can retry
}
} catch (SUNBAYBusinessException e) {
// Business exception (e.g., insufficient funds, parameter error)
System.err.println("API Error: " + e.getCode() + " - " + e.getMessage());
if (e.getTraceId() != null) {
System.err.println("Trace ID: " + e.getTraceId());
}
}Configuration Options
NexusClient client = new NexusClient.Builder()
.apiKey("sk_test_xxx")
.baseUrl("https://open.sunbay.us") // Default: https://open.sunbay.us
.connectTimeout(30000) // Default: 30000ms (30 seconds)
.readTimeout(60000) // Default: 60000ms (60 seconds)
.maxRetries(3) // Default: 3 times (GET request retry)
.maxTotal(200) // Default: 200 (max connections in pool)
.maxPerRoute(20) // Default: 20 (max connections per route)
.build();Connection Pool Configuration
The SDK uses Apache HttpClient’s connection pool to efficiently manage HTTP connections. You can configure:
-
maxTotal: Maximum total connections across all routes in the pool (default: 200)
- This is the total number of connections that can be open simultaneously across all hosts/routes
- Example: If you have 10 different API endpoints, the total connections across all endpoints cannot exceed this value
-
maxPerRoute: Maximum connections per route/host (default: 20)
- This is the maximum number of connections that can be open for a single host/route
- A route is typically defined by protocol (http/https), host, and port
- Example: For
https://open.sunbay.us, you can have at most 20 concurrent connections
Example:
- If
maxTotal = 200andmaxPerRoute = 20 - You can have at most 20 connections to
https://open.sunbay.us(limited by maxPerRoute) - But if connecting to multiple hosts, the total connections across all hosts cannot exceed 200 (limited by maxTotal)
These settings help optimize performance in high-concurrency scenarios.
System Requirements
- Java 8 or higher
- Apache HttpClient 4.5.14
- Jackson 2.18.2
Related Links
License
MIT License