Complyance Logo

Complyance Java SDK v3.0

Production ready Java SDK with Log on DocType support, automatic 320/32C classification, multi country compliance for KSA, Malaysia, and Belgium, and enterprise grade features. Built for real world e-invoice applications.

Feature Summary

  • 34 Types - Registered DocType support
  • 3 Countries - KSA, Malaysia, Belgium supported
  • 5 Overloads - Good Comply methods
  • v3.0 - Production ready

Installation

The automated setup will detect your operating system and provide the correct instructions.

macOS & Linux

  1. Install Java (JDK 11 or higher)

    brew install openjdk@11
  2. Set JAVA_HOME environment variable

    export JAVA_HOME=$(/usr/libexec/java_home -v 11)
  3. Verify installation

    java -version

Windows

  1. Download and install OpenJDK 11+
  2. Set JAVA_HOME environment variable
  3. Add Java to PATH

Manual Installation

Maven

Add the dependency to your pom.xml:

<dependency>
  <groupId>io.complyance</groupId>
  <artifactId>unify-sdk</artifactId>
  <version>3.0.0-beta</version>
</dependency>

Gradle

Add the dependency to your build.gradle:

implementation 'io.complyance:unify-sdk:3.0.0-beta'

Windows Installation

# Install Chocolatey (run as Administrator)
Set-ExecutionPolicy Bypass -Scope Process -Force
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

# Install OpenJDK 8 and Maven
choco install openjdk8 maven -y

# Verify installation
java -version
mvn -version

PowerShell Profile Configuration

# Edit PowerShell profile
notepad $PROFILE

# Add these lines to your PowerShell profile:
$env:JAVA_8_HOME = "C:\Program Files\OpenJDK\openjdk-8u402-b06"
$env:JAVA_HOME = $env:JAVA_8_HOME
$env:M2_HOME = "C:\Program Files\Apache\maven"
$env:PATH = "$env:JAVA_8_HOME\bin;$env:M2_HOME\bin;$env:PATH"

# Complyance SDK Environment Variables
$env:COMPLYANCE_API_BASE_URL = "http://127.0.0.1:4000"
$env:COMPLYANCE_JWT_TOKEN = "your-jwt-token-here"

# Convenient functions
function java8 { $env:JAVA_HOME = $env:JAVA_8_HOME; java -version }
function mvn8 { $env:JAVA_HOME = $env:JAVA_8_HOME; mvn @args }

Linux Installation

Ubuntu/Debian

sudo apt update && sudo apt install -y openjdk-8-jdk maven
export JAVA_8_HOME="/usr/lib/jvm/java-8-openjdk-amd64"
export JAVA_HOME="$JAVA_8_HOME"

CentOS/RHEL

sudo yum install java-1.8.0-openjdk-devel maven

Arch Linux

sudo pacman -S jre8-openjdk maven

One-command setup that automatically detects your OS and installs Java 8, Maven, and configures environment variables

macOS & Linux

# Download and run as Administrator:
setup-java8.sh

Windows

# Download and run as Administrator:
setup-java8.bat

The automated script detects your operating system and handles all dependencies, environment variables, and verification automatically.

Interactive Code Examples

Copy-paste ready examples demonstrating key SDK functionality

SDK Setup

// Maven Dependency
<dependency>
  <groupId>io.complyance</groupId>
  <artifactId>unify-sdk</artifactId>
  <version>3.0.0-beta</version>
</dependency>

// Gradle Dependency
implementation 'io.complyance:unify-sdk:3.0.0-beta'

// Basic SDK Configuration
public class BasicSetupExample {
    public static void main(String[] args) {
        SDKConfig config = new SDKConfig.Builder()
            .apiKey("your-api-key")
            .environment(Environment.SANDBOX)
            .appId("your-app-id")
            .defaultCountry("SA")
            .build();
        
        GETSUnifySDK.configure(config);
        System.out.println("SDK configured successfully!");
    }
}

Production Invoice

/**
 * ProductionInvoiceExample - Real-world invoice processing with LogicalDocType
 * 
 * This example demonstrates:
 * - Using LogicalDocType.TAX_INVOICE for B2B invoicing
 * - Proper SDK configuration and error handling
 * - Complete invoice payload structure
 * - Production-ready implementation patterns
 */
public class ProductionInvoiceExample {
    public static void main(String[] args) {
        System.out.println("=== šŸ¢ Production Invoice Processing ===");
        
        try {
            // Configure SDK for production use
            Source source = new Source("my-company", "1.0");
            SDKConfig config = new SDKConfig(
                "your-production-api-key",
                Environment.SANDBOX,  // Use SANDBOX for testing, PRODUCTION for live
                Arrays.asList(source)
            );
            GETSUnifySDK.configure(config);

            // Create invoice payload
            Map<String, Object> payload = createInvoicePayload();
            
            // Submit invoice using LogicalDocType
            UnifyResponse response = GETSUnifySDK.pushToUnify(
                "my-company",                  // Source name
                "1.0",                         // Source version
                LogicalDocType.TAX_INVOICE,    // Logical document type
                Country.SA,                    // Country
                Operation.SINGLE,              // Operation
                Mode.DOCUMENTS,                // Mode
                Purpose.INVOICING,             // Purpose
                payload                        // Invoice data
            );

            handleResponse(response);

        } catch (SDKException e) {
            System.err.println("āŒ SDK Error: " + e.getMessage());
            if (e.getError() != null) {
                System.err.println("   Error Code: " + e.getError().getCode());
            }
        } catch (Exception e) {
            System.err.println("āŒ Unexpected error: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * Create production invoice payload
     */
    private static Map<String, Object> createInvoicePayload() {
        Map<String, Object> payload = new HashMap<>();

        // Invoice Data
        Map<String, Object> invoiceData = new HashMap<>();
        invoiceData.put("invoice_number", "INV-2024-001");
        invoiceData.put("invoice_date", "2024-01-15");
        invoiceData.put("invoice_time", "14:30:00");
        invoiceData.put("currency_code", "SAR");
        invoiceData.put("total_amount", 1150.00);
        invoiceData.put("total_payable_amount", 1150.00);
        invoiceData.put("tax_exclusive_amount", 1000.00);
        invoiceData.put("line_extension_amount", 1000.00);
        invoiceData.put("total_tax_amount", 150.00);
        payload.put("invoice_data", invoiceData);

        // Seller Info
        Map<String, Object> sellerInfo = new HashMap<>();
        sellerInfo.put("company_name", "Tech Solutions LLC");
        sellerInfo.put("vat_registration", "310123456700003");
        sellerInfo.put("tax_scheme", "VAT");
        sellerInfo.put("street_address", "King Fahd Road");
        sellerInfo.put("building_number", "1234");
        sellerInfo.put("district_name", "Al Olaya");
        sellerInfo.put("city_name", "Riyadh");
        sellerInfo.put("postal_code", "11564");
        sellerInfo.put("country_code", "SA");
        sellerInfo.put("phone", "+966501234567");
        sellerInfo.put("email", "contact@techsolutions.sa");
        payload.put("seller_info", sellerInfo);

        // Buyer Info
        Map<String, Object> buyerInfo = new HashMap<>();
        buyerInfo.put("buyer_name", "Customer Corp");
        buyerInfo.put("buyer_vat", "310987654300003");
        buyerInfo.put("buyer_address", "Business District");
        buyerInfo.put("buyer_building", "4567");
        buyerInfo.put("buyer_district", "Al Malaz");
        buyerInfo.put("buyer_city", "Riyadh");
        buyerInfo.put("buyer_postal", "11564");
        buyerInfo.put("buyer_country", "SA");
        payload.put("buyer_info", buyerInfo);

        // Line Items
        List<Map<String, Object>> lineItems = new ArrayList<>();
        Map<String, Object> item1 = new HashMap<>();
        item1.put("item_id", "ITEM001");
        item1.put("item_name", "Consulting Services");
        item1.put("quantity", "1");
        item1.put("unit_code", "PCE");
        item1.put("unit_price", "1000.00");
        item1.put("tax_amount", "150.00");
        item1.put("tax_category", "S");
        item1.put("tax_rate", "15");
        lineItems.add(item1);
        payload.put("line_items", lineItems);

        return payload;
    }

    /**
     * Handle SDK response with complete structure
     */
    private static void handleResponse(UnifyResponse response) {
        if (response == null) {
            System.err.println("āŒ No response received");
            return;
        }
        
        if (response.isSuccess()) {
            System.out.println("Invoice submitted successfully!");
            System.out.println("   šŸ“„ Status: " + response.getStatus());
            
            if (response.getData() != null) {
                // Show submission details
                if (response.getData().getSubmission() != null) {
                    System.out.println("   šŸ†” Submission ID: " + response.getData().getSubmission().getSubmissionId());
                    System.out.println("   šŸš€ Submission Status: " + response.getData().getSubmission().getStatus());
                    
                    if (response.getData().getSubmission().getResponse() != null) {
                        System.out.println("   šŸ“‹ UUID: " + response.getData().getSubmission().getResponse().getUuid());
                        System.out.println("   šŸ”— Hash: " + response.getData().getSubmission().getResponse().getHash());
                    }
                }
                
                // Show logical document type info
                if (response.getData().getLogicalDocumentType() != null) {
                    System.out.println("   šŸŽÆ Document Type: " + response.getData().getLogicalDocumentType().getOriginalType());
                    if (response.getData().getLogicalDocumentType().getMetaConfig() != null) {
                        System.out.println("   šŸ“Š Meta Config: " + response.getData().getLogicalDocumentType().getMetaConfig().toString());
                    }
                }
                
                // Show processing info
                if (response.getData().getProcessing() != null) {
                    System.out.println("   ā±ļø Processing Time: " + response.getData().getProcessing().getTotalProcessingTime() + "ms");
                }
            }
        } else {
            System.err.println("āŒ Invoice submission failed:");
            if (response.getError() != null) {
                System.err.println("   Error Code: " + response.getError().getCode());
                System.err.println("   Message: " + response.getError().getMessage());
                if (response.getError().getSuggestion() != null) {
                    System.err.println("   Suggestion: " + response.getError().getSuggestion());
                }
                if (response.getError().isRetryable()) {
                    System.err.println("   šŸ”„ Retryable: Yes");
                }
            } else {
                System.err.println("   Message: " + response.getMessage());
            }
        }
    }
}

Document Types

/**
 * DocumentTypesExample - Demonstrates different LogicalDocType options
 * 
 * This example shows how to use various LogicalDocType enum values:
 * - B2B Types: TAX_INVOICE, TAX_INVOICE_CREDIT_NOTE, TAX_INVOICE_DEBIT_NOTE
 * - B2C Types: SIMPLIFIED_TAX_INVOICE, SIMPLIFIED_TAX_INVOICE_CREDIT_NOTE
 * - Special Types: Export, Prepayment, Third Party, Self-Billed, Nominal Supply
 */
public class DocumentTypesExample {
    public static void main(String[] args) {
        System.out.println("=== šŸ“‹ Document Types Example ===");
        
        try {
            // Configure SDK
            Source source = new Source("my-app", "1.0");
            SDKConfig config = new SDKConfig(
                "your-api-key",
                Environment.SANDBOX, 
                Arrays.asList(source)
            );
            GETSUnifySDK.configure(config);

            // Create sample payload
            Map<String, Object> payload = createSamplePayload();

            // Example 1: B2B Tax Invoice
            System.out.println("\n=== šŸ¢ B2B Tax Invoice ===");
            submitDocument(payload, LogicalDocType.TAX_INVOICE, "B2B Tax Invoice");

            // Example 2: B2C Simplified Tax Invoice  
            System.out.println("\n=== šŸ›’ B2C Simplified Tax Invoice ===");
            submitDocument(payload, LogicalDocType.SIMPLIFIED_TAX_INVOICE, "B2C Simplified Tax Invoice");

            // Example 3: Credit Note
            System.out.println("\n=== šŸ“ Credit Note ===");
            submitDocument(payload, LogicalDocType.TAX_INVOICE_CREDIT_NOTE, "B2B Credit Note");

            // Example 4: Export Invoice
            System.out.println("\n=== šŸŒ Export Invoice ===");
            submitDocument(payload, LogicalDocType.TAX_INVOICE_EXPORT_INVOICE, "B2B Export Invoice");

            System.out.println("\nšŸŽ‰ All document type examples completed!");

        } catch (SDKException e) {
            System.err.println("āŒ SDK Error: " + e.getMessage());
        } catch (Exception e) {
            System.err.println("āŒ Unexpected error: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private static Map<String, Object> createSamplePayload() {
        Map<String, Object> payload = new HashMap<>();

        // Invoice Data
        Map<String, Object> invoiceData = new HashMap<>();
        invoiceData.put("invoice_number", "INV-2024-001");
        invoiceData.put("invoice_date", "2024-01-15");
        invoiceData.put("currency_code", "SAR");
        invoiceData.put("total_amount", 1150.00);
        invoiceData.put("tax_exclusive_amount", 1000.00);
        invoiceData.put("total_tax_amount", 150.00);
        payload.put("invoice_data", invoiceData);

        // Seller Info
        Map<String, Object> sellerInfo = new HashMap<>();
        sellerInfo.put("company_name", "Tech Solutions LLC");
        sellerInfo.put("vat_registration", "310123456700003");
        sellerInfo.put("street_address", "King Fahd Road");
        sellerInfo.put("city_name", "Riyadh");
        sellerInfo.put("country_code", "SA");
        payload.put("seller_info", sellerInfo);

        // Buyer Info
        Map<String, Object> buyerInfo = new HashMap<>();
        buyerInfo.put("buyer_name", "Customer Corp");
        buyerInfo.put("buyer_vat", "310987654300003");
        buyerInfo.put("buyer_city", "Riyadh");
        buyerInfo.put("buyer_country", "SA");
        payload.put("buyer_info", buyerInfo);

        // Line Items
        List<Map<String, Object>> lineItems = new ArrayList<>();
        Map<String, Object> item1 = new HashMap<>();
        item1.put("item_id", "ITEM001");
        item1.put("item_name", "Consulting Services");
        item1.put("quantity", "1");
        item1.put("unit_price", "1000.00");
        item1.put("tax_amount", "150.00");
        item1.put("tax_rate", "15");
        lineItems.add(item1);
        payload.put("line_items", lineItems);

        return payload;
    }

    private static void submitDocument(Map<String, Object> payload, LogicalDocType logicalType, String description) {
        try {
            System.out.println("   šŸ“‹ Document Type: " + logicalType.name());
            System.out.println("   šŸŽÆ Description: " + description);

            UnifyResponse response = GETSUnifySDK.pushToUnify(
                "my-app",                      // Source name
                "1.0",                         // Source version
                logicalType,                   // Logical document type
                Country.SA,                    // Country
                Operation.SINGLE,              // Operation
                Mode.DOCUMENTS,                // Mode
                Purpose.INVOICING,             // Purpose
                payload                        // Payload
            );

            if (response.isSuccess()) {
                System.out.println("   " + description + " submitted successfully!");
                System.out.println("   šŸ“„ Status: " + response.getStatus());
                
                if (response.getData() != null) {
                    if (response.getData().getSubmission() != null) {
                        System.out.println("   šŸ†” Submission ID: " + response.getData().getSubmission().getSubmissionId());
                        System.out.println("   šŸš€ Status: " + response.getData().getSubmission().getStatus());
                    }
                    
                    if (response.getData().getLogicalDocumentType() != null) {
                        System.out.println("   šŸŽÆ Original Type: " + response.getData().getLogicalDocumentType().getOriginalType());
                    }
                    
                    if (response.getData().getProcessing() != null) {
                        System.out.println("   ā±ļø Processing Time: " + response.getData().getProcessing().getTotalProcessingTime() + "ms");
                    }
                }
            } else {
                System.out.println("   āŒ " + description + " failed:");
                if (response.getError() != null) {
                    System.out.println("   Error Code: " + response.getError().getCode());
                    System.out.println("   Message: " + response.getError().getMessage());
                } else {
                    System.out.println("   Message: " + response.getMessage());
                }
            }

        } catch (SDKException e) {
            System.err.println("   āŒ " + description + " SDK Error: " + e.getMessage());
        } catch (Exception e) {
            System.err.println("   āŒ " + description + " failed: " + e.getMessage());
        }
    }
}

Primary Method: pushToUnify()

// Full control with LogicalDocType
UnifyResponse response = GETSUnifySDK.pushToUnify(
    String sourceName,           // Source identifier
    String sourceVersion,        // Source version  
    LogicalDocType logicalType,  // Document type (TAX_INVOICE, etc.)
    Country country,             // Target country (SA, MY, BE)
    Operation operation,         // SINGLE
    Mode mode,                   // DOCUMENTS
    Purpose purpose,             // INVOICING or MAPPING
    Map<String, Object> payload, // Business data
    List<Destination> destinations // Optional: auto-generated if null
);

API Usage Types

Basic SDK Usage

// Configure SDK
SDKConfig config = new SDKConfig.Builder()
    .apiKey("your-api-key")
    .environment(Environment.SANDBOX)
    .appId("your-app-id")
    .defaultCountry("SA")
    .build();

GETSUnifySDK.configure(config);

// Create invoice payload
Map<String, Object> payload = createInvoicePayload();

// Submit invoice
UnifyResponse response = GETSUnifySDK.pushToUnify(
    "your-app-id",
    LogicalDocType.TAX_INVOICE,
    Country.SA,
    Operation.SINGLE,
    Mode.DOCUMENTS,
    Purpose.INVOICING,
    payload
);

// Handle response
if (response.isSuccess()) {
    System.out.println("Invoice submitted successfully!");
} else {
    System.err.println("Error: " + response.getErrorMessage());
}

Response Structures

Success Response Structure

{
  "status": "success",
  "message": "Document processed successfully",
  "data": {
    "submission": {
      "submissionId": "sub_123456789",
      "status": "processed",
      "response": {
        "uuid": "uuid-123456789",
        "hash": "hash-123456789"
      }
    },
    "logicalDocumentType": {
      "originalType": "TAX_INVOICE",
      "metaConfig": {
        "isB2B": true,
        "country": "SA"
      }
    },
    "processing": {
      "totalProcessingTime": 150
    }
  }
}

Error Response Structure

{
  "status": "error",
  "message": "Document processing failed",
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid document structure",
    "suggestion": "Check required fields",
    "retryable": true
  }
}

Key Features and Payload Structure

Key Features

  • 34 LogicalDocTypes - Complete document type support
  • Automatic B2B/B2C Classification - Smart document type detection
  • Multi-country compliance - SA, MY, BE, and more
  • Enterprise-grade features - Production ready

Payload Structure

  • invoice_data - Core invoice information
  • seller_info - Seller/supplier details
  • buyer_info - Buyer/customer details
  • line_items - Invoice line items
  • tax_summary - Tax calculations
  • additional_data - Extra fields

LogicalDocTypes (34 Types)

B2B Document Types (22)

  • TAX_INVOICE - Standard B2B tax invoice
  • TAX_INVOICE_CREDIT_NOTE - B2B credit note
  • TAX_INVOICE_DEBIT_NOTE - B2B debit note
  • TAX_INVOICE_EXPORT_INVOICE - Export invoice
  • TAX_INVOICE_PREPAYMENT - Prepayment invoice
  • TAX_INVOICE_PREPAYMENT_ADJUSTED - Adjusted prepayment
  • TAX_INVOICE_EXPORT_CREDIT_NOTE - Export credit note
  • TAX_INVOICE_EXPORT_DEBIT_NOTE - Export debit note
  • TAX_INVOICE_THIRD_PARTY_INVOICE - Third-party invoice
  • TAX_INVOICE_SELF_BILLED_INVOICE - Self-billed invoice
  • TAX_INVOICE_NOMINAL_SUPPLY_INVOICE - Nominal supply invoice
  • TAX_INVOICE_SUMMARY_INVOICE - Summary invoice
  • INVOICE - Standard business invoice
  • CREDIT_NOTE - Credit note for adjustments
  • DEBIT_NOTE - Debit note for charges
  • RECEIPT - Payment confirmation
  • EXPORT_INVOICE - Export invoice
  • EXPORT_CREDIT_NOTE - Export credit note
  • EXPORT_THIRD_PARTY_INVOICE - Export third-party invoice
  • THIRD_PARTY_INVOICE - Third-party invoice
  • SELF_BILLED_INVOICE - Self-billed invoice
  • NOMINAL_SUPPLY_INVOICE - Nominal supply invoice

B2C Document Types (12)

  • SIMPLIFIED_TAX_INVOICE - Simplified tax invoice
  • SIMPLIFIED_TAX_INVOICE_CREDIT_NOTE - Simplified credit note
  • SIMPLIFIED_TAX_INVOICE_DEBIT_NOTE - Simplified debit note
  • SIMPLIFIED_TAX_INVOICE_PREPAYMENT - Simplified prepayment
  • SIMPLIFIED_TAX_INVOICE_PREPAYMENT_ADJUSTED - Simplified adjusted prepayment
  • SIMPLIFIED_TAX_INVOICE_EXPORT_INVOICE - Simplified export invoice
  • SIMPLIFIED_TAX_INVOICE_EXPORT_CREDIT_NOTE - Simplified export credit note
  • SIMPLIFIED_TAX_INVOICE_EXPORT_DEBIT_NOTE - Simplified export debit note
  • SIMPLIFIED_TAX_INVOICE_THIRD_PARTY_INVOICE - Simplified third-party invoice
  • SIMPLIFIED_TAX_INVOICE_SELF_BILLED_INVOICE - Simplified self-billed invoice
  • SIMPLIFIED_TAX_INVOICE_NOMINAL_SUPPLY_INVOICE - Simplified nominal supply invoice
  • SIMPLIFIED_TAX_INVOICE_SUMMARY_INVOICE - Simplified summary invoice

Automatic Configuration

The SDK automatically configures itself based on LogicalDocType and country:

  • Validation Rules - Country-specific validation
  • Country-specific compliance - ZATCA, LHDN requirements
  • B2B/B2C Classification - Automatic detection
  • Required Payload Fields - Dynamic field requirements
  • Tax Calculation - Country-specific tax rules
  • Error Handling - Comprehensive error management

Common SDK Capabilities

Core Features

  • Automatic document type classification - Smart detection
  • Multi-country compliance - Global support
  • Pre-submission validation - Catch errors early
  • Dynamic payload transformation - Flexible data handling
  • Real-time processing and feedback - Immediate results

Integration Features

  • Easy to use Java SDK with REST API - Simple integration
  • Comprehensive error handling and logging - Production ready
  • Enterprise-grade security and scalability - Business grade
  • Flexible deployment options - Cloud, on-premise
  • Extensible for custom requirements - Customizable

Next Steps