- Overview
- Features
- Installation
- Quick Start
- API Reference
- Usage Examples
- Real-time Transaction Monitoring
- Banking Integration
- Error Handling
- Best Practices
- Java vs Kotlin
- Testing
- Contributing
- Support
- License
SofizPay SDK is a comprehensive Java/Kotlin library for secure payment processing with real-time transaction monitoring, banking integration, and advanced payment management capabilities.
Key Benefits:
- ๐ Secure payment processing
- โก Real-time transaction monitoring with callbacks
- ๐ฏ Simple, intuitive API for both Java and Kotlin
- ๐ฆ Banking transaction support
- ๐ Comprehensive transaction history and search
- ๐ Advanced signature verification
- ๐ Testnet and Production environment support
- โ Send Payments: Secure payment transfers with memo support
- โ Transaction History: Retrieve and filter transaction records with pagination
- โ Balance Checking: Real-time balance queries
- โ Transaction Search: Find transactions by memo, hash, or account
- โ Real-time Streams: Live transaction monitoring with customizable callbacks
- โ Banking Transactions: Create bank transactions for deposits
- โ Account Management: Create new accounts and manage payment credentials
- โ Signature Verification: RSA signature validation for secure communications
- โ Error Handling: Robust error management and detailed reporting
- โ Kotlin Support: Modern Kotlin implementation with data classes and coroutines-ready
dependencies {
implementation 'io.github.kenandarabeh:sofizpay-sdk-java:1.0.5-SNAPSHOT'
}dependencies {
implementation("io.github.kenandarabeh:sofizpay-sdk-java:1.0.5-SNAPSHOT")
}<dependency>
<groupId>io.github.kenandarabeh</groupId>
<artifactId>sofizpay-sdk-java</artifactId>
<version>1.0.5-SNAPSHOT</version>
</dependency>git clone https://github.com/kenandarabeh/sofizpay-sdk-java.git
cd sofizpay-sdk-java
./gradlew buildimport com.sofizpay.sdk.SofizPayStellarSDK;
public class QuickStart {
public static void main(String[] args) {
// Initialize SDK (testnet by default)
try (SofizPayStellarSDK sdk = new SofizPayStellarSDK(true)) {
// Create payment data
SofizPayStellarSDK.PaymentData paymentData = new SofizPayStellarSDK.PaymentData();
paymentData.secret = "YOUR_SECRET_KEY";
paymentData.destination = "DESTINATION_ADDRESS";
paymentData.amount = "10.0";
paymentData.memo = "Payment for services";
// Send payment
SofizPayStellarSDK.PaymentResult result = sdk.submit(paymentData);
if (result.success) {
System.out.println("โ
Payment successful! TX: " + result.transactionId);
} else {
System.out.println("โ Payment failed: " + result.message);
}
}
}
}import com.sofizpay.sdk.SofizPayStellarSDK
fun main() {
// Initialize SDK (testnet by default)
SofizPayStellarSDK(isTestnet = true).use { sdk ->
// Create payment data
val paymentData = SofizPayStellarSDK.PaymentData(
secret = "YOUR_SECRET_KEY",
destination = "DESTINATION_ADDRESS",
amount = "10.0",
memo = "Payment for services"
)
// Send payment
val result = sdk.submit(paymentData)
if (result.success) {
println("โ
Payment successful! TX: ${result.transactionId}")
} else {
println("โ Payment failed: ${result.message}")
}
}
}Send payments with memo support.
Java:
PaymentData paymentData = new PaymentData();
paymentData.secret = "SECRET_KEY";
paymentData.destination = "DESTINATION_ADDRESS";
paymentData.amount = "10.0";
paymentData.memo = "Payment memo";
PaymentResult result = sdk.submit(paymentData);Kotlin:
val paymentData = PaymentData(
secret = "SECRET_KEY",
destination = "DESTINATION_ADDRESS",
amount = "10.0",
memo = "Payment memo"
)
val result = sdk.submit(paymentData)Get account balance.
BalanceResult balance = sdk.getBalance("ACCOUNT_ADDRESS");
System.out.println("Balance: " + balance.balance);Extract public key from secret key.
PublicKeyResult result = sdk.getPublicKey("SECRET_KEY");
String publicKey = result.publicKey;Get paginated transaction history for an account.
TransactionHistoryResult result = sdk.getTransactions("ACCOUNT_ID", 50);
for (TransactionInfo tx : result.transactions) {
System.out.println("TX: " + tx.hash + " Amount: " + tx.amount);
}Find transactions containing specific memo text.
SearchTransactionsResult result = sdk.searchTransactionsByMemo("ACCOUNT_ID", "invoice-123", 10);Retrieve specific transaction by hash.
TransactionByHashResult result = sdk.getTransactionByHash("TRANSACTION_HASH");
if (result.found) {
TransactionInfo tx = result.transaction;
System.out.println("Found transaction: " + tx.amount);
}Generate a new account keypair.
AccountCreationResult result = sdk.createAccount();
System.out.println("Account ID: " + result.accountId);
System.out.println("Secret Key: " + result.secretKey);Fund account with testnet funds (testnet only).
FundResult result = sdk.fundAccountFromFaucet("ACCOUNT_ID");
if (result.success) {
System.out.println("Account funded successfully");
}Create bank transactions for deposits.
CIBTransactionData cibData = new CIBTransactionData();
cibData.account = "YOUR_SECRET_KEY";
cibData.amount = "150";
cibData.full_name = "Ahmed";
cibData.phone = "+213*********";
cibData.email = "ahmed@sofizpay.com";
cibData.memo = "Payment";
cibData.return_url = "https://yoursite.com/payment-success";
cibData.redirect = true;
CIBTransactionResult result = sdk.makeCIBTransaction(cibData);Verify RSA signatures for secure communication.
boolean isValid = sdk.verifySignature("message", "base64_signature");
if (isValid) {
System.out.println("Signature is valid");
}Monitor transactions in real-time with customizable callbacks.
// Define callback
TransactionCallback callback = new TransactionCallback() {
@Override
public void onNewTransaction(TransactionInfo transaction) {
System.out.println("New transaction: " + transaction.type +
" Amount: " + transaction.amount);
if ("received".equals(transaction.type)) {
handleIncomingPayment(transaction);
}
}
};
// Start monitoring
StreamResult streamResult = sdk.startTransactionStream("ACCOUNT_ID", callback);
// Check status
StreamStatusResult status = sdk.getStreamStatus("ACCOUNT_ID");
System.out.println("Stream active: " + status.active);
// Stop monitoring
StreamResult stopResult = sdk.stopTransactionStream("ACCOUNT_ID");// Start monitoring with lambda
val streamResult = sdk.startTransactionStream("ACCOUNT_ID") { transaction ->
println("New transaction: ${transaction.type} Amount: ${transaction.amount}")
if (transaction.type == "received") {
handleIncomingPayment(transaction)
}
}
// Check status
val status = sdk.getStreamStatus("ACCOUNT_ID")
println("Stream active: ${status.active}")
// Stop monitoring
val stopResult = sdk.stopTransactionStream("ACCOUNT_ID")Complete banking integration for payment processing.
public class PaymentProcessor {
private final SofizPayStellarSDK sdk;
public PaymentProcessor() {
this.sdk = new SofizPayStellarSDK(false); // Production
}
public void processDeposit(String account, String amount, String fullName, String phone, String email) {
CIBTransactionData cibData = new CIBTransactionData();
cibData.account = account;
cibData.amount = amount;
cibData.full_name = fullName;
cibData.phone = phone;
cibData.email = email;
cibData.memo = "Payment deposit";
cibData.return_url = "https://yoursite.com/payment-success";
cibData.redirect = true;
CIBTransactionResult result = sdk.makeCIBTransaction(cibData);
if (result.success) {
System.out.println("Transaction successful");
Map<String, Object> responseData = result.data;
// Process response data
} else {
System.err.println("Transaction failed: " + result.message);
}
}
public void close() {
sdk.close();
}
}public class PaymentSystem {
private final SofizPayStellarSDK sdk;
public PaymentSystem() {
this.sdk = new SofizPayStellarSDK(true); // Testnet
}
public void processPayment(String secretKey, String destination,
String amount, String memo) {
try {
// Check balance first
String accountId = sdk.getPublicKey(secretKey).publicKey;
BalanceResult balance = sdk.getBalance(accountId);
System.out.println("Current balance: " + balance.balance);
// Create payment
PaymentData paymentData = new PaymentData();
paymentData.secret = secretKey;
paymentData.destination = destination;
paymentData.amount = amount;
paymentData.memo = memo;
// Submit payment
PaymentResult result = sdk.submit(paymentData);
if (result.success) {
System.out.println("โ
Payment successful!");
System.out.println("Transaction ID: " + result.transactionId);
// Start monitoring for confirmation
startPaymentMonitoring(accountId, result.transactionId);
} else {
System.err.println("โ Payment failed: " + result.message);
}
} catch (Exception e) {
System.err.println("Error processing payment: " + e.getMessage());
}
}
private void startPaymentMonitoring(String accountId, String expectedTxId) {
TransactionCallback callback = new TransactionCallback() {
@Override
public void onNewTransaction(TransactionInfo transaction) {
if (expectedTxId.equals(transaction.hash)) {
System.out.println("โ
Payment confirmed!");
sdk.stopTransactionStream(accountId);
}
}
};
sdk.startTransactionStream(accountId, callback);
}
public void close() {
sdk.close();
}
}class ECommercePaymentProcessor(private val isTestnet: Boolean = true) : AutoCloseable {
private val sdk = SofizPayStellarSDK(isTestnet)
suspend fun processOrder(order: Order): PaymentResult {
return try {
// Validate order
if (order.amount <= 0) {
return PaymentResult(false, "Invalid amount", null)
}
// Create payment
val paymentData = SofizPayStellarSDK.PaymentData(
secret = order.customerSecretKey,
destination = getCompanyAddress(),
amount = order.amount.toString(),
memo = "Order #${order.id}"
)
// Submit payment
val result = sdk.submit(paymentData)
if (result.success) {
// Log successful payment
logPayment(order.id, result.transactionId!!)
// Start monitoring for confirmation
startOrderMonitoring(order)
}
result
} catch (e: Exception) {
PaymentResult(false, "Payment processing error: ${e.message}", null)
}
}
private fun startOrderMonitoring(order: Order) {
val companyAccountId = getCompanyAddress()
sdk.startTransactionStream(companyAccountId) { transaction ->
if (transaction.memo == "Order #${order.id}" && transaction.type == "received") {
println("โ
Order ${order.id} payment confirmed!")
fulfillOrder(order)
sdk.stopTransactionStream(companyAccountId)
}
}
}
private fun getCompanyAddress(): String = "COMPANY_ADDRESS"
private fun logPayment(orderId: String, txId: String) { /* Log to database */ }
private fun fulfillOrder(order: Order) { /* Fulfill order */ }
override fun close() = sdk.close()
}
data class Order(
val id: String,
val customerSecretKey: String,
val amount: Double,
val items: List<String>
)public class TransactionAnalytics {
private final SofizPayStellarSDK sdk;
public TransactionAnalytics() {
this.sdk = new SofizPayStellarSDK(false); // Production
}
public void generateReport(String accountId, int days) {
try {
// Get recent transactions
TransactionHistoryResult result = sdk.getTransactions(accountId, 200);
double totalReceived = 0;
double totalSent = 0;
int receivedCount = 0;
int sentCount = 0;
for (TransactionInfo tx : result.transactions) {
if ("received".equals(tx.type)) {
totalReceived += Double.parseDouble(tx.amount);
receivedCount++;
} else if ("sent".equals(tx.type)) {
totalSent += Double.parseDouble(tx.amount);
sentCount++;
}
}
System.out.println("=== Transaction Report ===");
System.out.println("Total Received: " + totalReceived + " (" + receivedCount + " transactions)");
System.out.println("Total Sent: " + totalSent + " (" + sentCount + " transactions)");
System.out.println("Net Flow: " + (totalReceived - totalSent));
} catch (Exception e) {
System.err.println("Error generating report: " + e.getMessage());
}
}
public void close() {
sdk.close();
}
}All methods return structured response objects with consistent error handling:
// Java
PaymentResult result = sdk.submit(paymentData);
if (result.success) {
System.out.println("Success: " + result.transactionId);
} else {
System.err.println("Error: " + result.message);
}// Kotlin
val result = sdk.submit(paymentData)
if (result.success) {
println("Success: ${result.transactionId}")
} else {
println("Error: ${result.message}")
}"Secret key is required.""Destination address is required.""Amount is required.""Bad request: Invalid destination address""Network error: Connection timeout""Insufficient balance for transaction"
try (SofizPayStellarSDK sdk = new SofizPayStellarSDK()) {
// SDK operations
} catch (Exception e) {
System.err.println("SDK error: " + e.getMessage());
e.printStackTrace();
}// โ
Store secret keys securely
String secretKey = System.getenv("SECRET_KEY"); // From environment
// โ Never hardcode secret keys in source code
// โ
Validate inputs
if (amount == null || amount.isEmpty()) {
throw new IllegalArgumentException("Amount is required");
}
// โ
Use try-with-resources for automatic cleanup
try (SofizPayStellarSDK sdk = new SofizPayStellarSDK()) {
// Use SDK
} // Automatically closed// โ
Reuse SDK instances
private static final SofizPayStellarSDK sdk = new SofizPayStellarSDK();
// โ
Use reasonable limits for transaction queries
TransactionHistoryResult result = sdk.getTransactions(accountId, 50); // Not 1000+
// โ
Stop streams when no longer needed
sdk.stopTransactionStream(accountId);// โ
Always check success status
if (result.success) {
// Process successful result
} else {
// Handle error gracefully
logError("Payment failed", result.message);
}
// โ
Implement retry logic for network operations
public PaymentResult submitWithRetry(PaymentData data, int maxRetries) {
for (int i = 0; i < maxRetries; i++) {
PaymentResult result = sdk.submit(data);
if (result.success || !isRetryableError(result.message)) {
return result;
}
try {
Thread.sleep(1000 * (i + 1)); // Exponential backoff
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
return new PaymentResult(false, "Max retries exceeded", null);
}This SDK provides both Java and Kotlin implementations with identical functionality:
- Familiar Syntax: Traditional Java patterns
- Enterprise Ready: Mature ecosystem
- Explicit Types: Clear type declarations
- Wide Adoption: Large developer community
- Concise Syntax: Less boilerplate code
- Null Safety: Compile-time null checks
- Data Classes: Built-in equals/hashCode/toString
- Lambda Support: Modern functional programming
You can easily migrate from Java to Kotlin implementation:
// Java
PaymentData data = new PaymentData();
data.secret = "SECRET";
data.destination = "DEST";
data.amount = "10.0";// Kotlin
val data = PaymentData(
secret = "SECRET",
destination = "DEST",
amount = "10.0"
)./gradlew test./gradlew integrationTest@Test
public void testPaymentSubmission() {
SofizPayStellarSDK sdk = new SofizPayStellarSDK(true); // Testnet
// Create test account
AccountCreationResult account = sdk.createAccount();
// Fund account
FundResult fundResult = sdk.fundAccountFromFaucet(account.accountId);
assertTrue(fundResult.success);
// Test payment
PaymentData paymentData = new PaymentData();
paymentData.secret = account.secretKey;
paymentData.destination = "DESTINATION_ADDRESS";
paymentData.amount = "1.0";
paymentData.memo = "Test payment";
PaymentResult result = sdk.submit(paymentData);
assertTrue(result.success);
assertNotNull(result.transactionId);
sdk.close();
}We welcome contributions! Here's how to get started:
# Clone repository
git clone https://github.com/kenandarabeh/sofizpay-sdk-java.git
cd sofizpay-sdk-java
# Build project
./gradlew build
# Run tests
./gradlew test
# Run examples
./gradlew runJavaExample
./gradlew runKotlinExample- Fork the repository
- Create feature branch:
git checkout -b feature/amazing-feature - Write tests for new functionality
- Ensure all tests pass:
./gradlew test - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow Java/Kotlin conventions
- Add Javadoc/KDoc for public methods
- Include unit tests for new features
- Use meaningful variable names
- Handle errors gracefully
- ๐ Documentation
- ๐ Report Issues
- ๐ฌ Discussions
- โญ Star the Project
- ๐ง Email Support
- Check the documentation above
- Search existing issues on GitHub
- Join our community discussions
- Contact support for enterprise needs
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License
Copyright (c) 2025 SofizPay
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
- Open Source Community - For continuous improvement and feedback
- Java/Kotlin Ecosystem - For providing robust development tools
- OkHttp - Reliable HTTP client for network operations
- Gson - JSON serialization and deserialization
- Gradle - Build automation and dependency management
- JetBrains - Kotlin language development
- WebSocket Streams - Real-time WebSocket transaction monitoring
- Multi-signature Support - Advanced security with multiple signatures
- Advanced Analytics - Built-in transaction analytics and reporting
- Spring Boot Integration - Auto-configuration for Spring applications
- Reactive Streams - RxJava/Reactor support for reactive applications
- Mobile SDK - Android and iOS native SDKs
- v1.0.5-SNAPSHOT - Latest development version with enhanced features
- v1.0.0 - Initial release with core payment functionality
- v1.0.0-kotlin - Kotlin implementation with modern language features
Start building with SofizPay SDK today!
GitHub โข Maven Central โข Support โข Contact
Made with โค๏ธ by the SofizPay Team
