Complyance PHP SDK
Production-ready PHP SDK with intelligent document type support, automatic compliance validations, and multi-country e-invoicing capabilities for UAE, KSA, and Malaysia. Designed with enterprise-grade features and modern PHP architecture for real-world e-invoice applications.
Feature Summary
- Multi-Country Support - UAE,KSA,Malaysia
- PSR-7 Compatible - Modern HTTP message interfaces
- PHP 8.0+ - Modern PHP features and type hints
- Composer - Easy dependency management
Installation
Composer
composer require io.complyance/unify-sdkQuick Start
SDK Setup & Configuration
You must configure the SDK once at the start of your application.
use ComplyanceSDK\GETSUnifySDK;
use ComplyanceSDK\Models\SDKConfig;
use ComplyanceSDK\Models\Source;
use ComplyanceSDK\Enums\SourceType;
use ComplyanceSDK\Enums\Environment;
// 1. Define your source info (Your App Name and Version)
$sources = [new Source('App name', 'Version', SourceType::fromString(SourceType::FIRST_PARTY))];
// 2. Set up configuration
// Change Environment::SANDBOX to Environment::PRODUCTION when going live
$config = new SDKConfig(
'YOUR_API_KEY_HERE',
Environment::from(Environment::SANDBOX),
$sources
);
// 3. Initialize the SDK
GETSUnifySDK::configure($config);The "Purpose" Workflow
The integration requires a specific two-stage process to ensure your document data correctly translates to regulatory standards.
Step 1: MAPPING (Setup & Template Creation)
Set the Purpose to "MAPPING" to push your raw data to the Complyance platform. This stage is used for initial field discovery and visualization.
- In Code: Submit your payload with
Purpose::from('MAPPING'). - In Portal: Locate the uploaded payload, complete the field mapping, and save it as a successful Template.
- Final Step: Register and bind your unique
sourceNameandsourceVersionto this template on the portal.
Step 2: INVOICING (Production Submission)
After your template is successfully bound to your source identifiers, change the Purpose to "INVOICING".
- Action: The system now recognizes your
sourceName/sourceVersionand applies the saved template logic to transform, validate, and officially submit the document to the tax authority. - Requirement: You must use the exact same Source identifiers registered during the Mapping phase.
How to change the Purpose in code:
use ComplyanceSDK\Enums\Purpose;
// 1. Initial Phase: Field Analysis & Template Binding
$currentPurpose = Purpose::from('MAPPING');
// 2. Final Phase: Official Submission using the bound template
// $currentPurpose = Purpose::from('INVOICING');Why this structure is important:
- MAPPING is the "Discovery" phase where you build the blueprint.
- The Portal is where you finalize the logic and connect it to your
sourceName. - INVOICING is the "Execution" phase where the SDK performs the actual heavy lifting using that blueprint.
Building the UAE Payload
$payload = [
'invoice_data' => [
'document_number' => 'INV-' . date('YmdHis'),
'document_id' => '{UNIQUE_ID}',
'document_type' => 'tax_invoice',
'invoice_date' => getDynamicDate(0),
'invoice_time' => '00:00:00Z',
'currency_code' => '{CURRENCY_CODE}',
'tax_currency_code' => '{CURRENCY_CODE}',
'due_date' => getDynamicDate(30),
'period_start_date' => getDynamicDate(-30),
'period_end_date' => getDynamicDate(0),
'period_frequency' => '{FREQUENCY}', // e.g., MONTHLY
'exchange_rate' => '{EXCHANGE_RATE}',
'line_extension_amount' => '{LINE_EXTENSION_AMOUNT}',
'tax_exclusive_amount' => '{TAX_EXCLUSIVE_AMOUNT}',
'total_tax_amount' => '{TOTAL_TAX_AMOUNT}',
'total_amount' => '{TOTAL_AMOUNT}',
'total_allowances' => '{TOTAL_ALLOWANCES}',
'total_charges' => '{TOTAL_CHARGES}',
'prepaid_amount' => '{PREPAID_AMOUNT}',
'amount_due' => '{AMOUNT_DUE}',
'rounding_amount' => '{ROUNDING_AMOUNT}',
'original_reference_id' => '{ORIGINAL_REFERENCE_ID}',
'credit_note_reason' => '{CREDIT_NOTE_REASON}'
],
'seller_info' => [
'seller_name' => '{SELLER_NAME}',
'seller_trade_name' => '{SELLER_TRADE_NAME}',
'seller_party_id' => '{SELLER_PARTY_ID}',
'vat_number_type' => '{VAT_NUMBER_TYPE}',
'vat_number' => '{VAT_NUMBER}',
'tax_scheme' => '{TAX_SCHEME}',
'registration_number' => '{REGISTRATION_NUMBER}',
'registration_type' => '{REGISTRATION_TYPE}',
'registration_scheme' => '{REGISTRATION_SCHEME}',
'authority_name' => '{AUTHORITY_NAME}',
'peppol_id' => '{PEPPOL_ID}',
'seller_email' => '{SELLER_EMAIL}',
'seller_phone' => '{SELLER_PHONE}',
'seller_contact_name' => '{SELLER_CONTACT_NAME}',
'street_name' => '{STREET_NAME}',
'additional_address' => '{ADDITIONAL_ADDRESS}',
'building_number' => '{BUILDING_NUMBER}',
'city_name' => '{CITY}',
'state_province' => '{STATE}',
'postal_code' => '{POSTAL_CODE}',
'country_code' => '{COUNTRY_CODE}'
],
'buyer_info' => [
'buyer_name' => '{BUYER_NAME}',
'buyer_trade_name' => '{BUYER_TRADE_NAME}',
'buyer_party_id' => '{BUYER_PARTY_ID}',
'buyer_vat_type' => '{BUYER_VAT_TYPE}',
'buyer_vat_number' => '{BUYER_VAT_NUMBER}',
'buyer_tax_scheme' => '{BUYER_TAX_SCHEME}',
'buyer_registration_number' => '{BUYER_REGISTRATION_NUMBER}',
'buyer_registration_type' => '{BUYER_REGISTRATION_TYPE}',
'buyer_registration_scheme' => '{BUYER_REGISTRATION_SCHEME}',
'buyer_authority_name' => '{BUYER_AUTHORITY_NAME}',
'buyer_peppol_id' => '{BUYER_PEPPOL_ID}',
'buyer_email' => '{BUYER_EMAIL}',
'buyer_phone' => '{BUYER_PHONE}',
'buyer_contact_name' => '{BUYER_CONTACT_NAME}',
'buyer_street_name' => '{BUYER_STREET_NAME}',
'buyer_additional_address' => '{BUYER_ADDITIONAL_ADDRESS}',
'buyer_building_number' => '{BUYER_BUILDING_NUMBER}',
'buyer_city' => '{BUYER_CITY}',
'buyer_state_province' => '{BUYER_STATE}',
'buyer_postal_code' => '{BUYER_POSTAL_CODE}',
'buyer_country' => '{BUYER_COUNTRY_CODE}'
],
'line_items' => [
[
'line_id' => '{LINE_ID}',
'item_name' => '{ITEM_NAME}',
'item_description' => '{ITEM_DESCRIPTION}',
'quantity' => '{QUANTITY}',
'unit_code' => '{UNIT_CODE}',
'unit_price' => '{UNIT_PRICE}',
'net_price' => '{NET_PRICE}',
'gross_price' => '{GROSS_PRICE}',
'line_taxable_value' => '{LINE_TAXABLE_VALUE}',
'tax_category' => '{TAX_CATEGORY}',
'tax_rate' => '{TAX_RATE}',
'tax_amount' => '{TAX_AMOUNT}',
'line_total' => '{LINE_TOTAL}',
'item_type' => '{ITEM_TYPE}', // e.g., GOODS or SERVICE
'country_of_origin' => '{COUNTRY_OF_ORIGIN}',
'classification_code' => '{CLASSIFICATION_CODE}',
'classification_scheme' => '{CLASSIFICATION_SCHEME}',
'seller_item_code' => '{SELLER_ITEM_CODE}',
'buyer_item_code' => '{BUYER_ITEM_CODE}',
'batch_number' => '{BATCH_NUMBER}'
]
],
'extensions' => [
'unique_identifier' => '{UNIQUE_ID}',
'invoiced_object_id' => '{INVOICED_OBJECT_ID}',
'taxpoint_date' => getDynamicDate(0),
'total_amount_including_tax' => '{TOTAL_AMOUNT_INCLUDING_TAX}',
'authority_name' => '{AUTHORITY_NAME}',
'buyer_authority_name' => '{BUYER_AUTHORITY_NAME}',
'business_process_type' => '{BUSINESS_PROCESS_TYPE}',
'specification_identifier' => '{SPECIFICATION_IDENTIFIER}'
],
'payment_info' => [
'payment_id' => '{PAYMENT_ID}',
'payment_means_code' => '{PAYMENT_MEANS_CODE}',
'payment_means_text' => '{PAYMENT_MEANS_TEXT}',
'remittance_info' => '{REMITTANCE_INFO}',
'account_id' => '{ACCOUNT_ID}',
'account_name' => '{ACCOUNT_NAME}',
'bank_id' => '{BANK_ID}'
],
'payment_terms' => [
[
'instructions_id' => '{TERM_ID}',
'note' => '{PAYMENT_NOTE}',
'amount' => '{TERM_AMOUNT}',
'due_date' => getDynamicDate(30)
]
],
'supporting_documents' => [
[
'type' => '{DOCUMENT_TYPE}',
'id' => '{DOCUMENT_ID}'
]
],
'additional_data' => [
'delivery_date' => getDynamicDate(0),
'order_reference' => '{ORDER_REFERENCE}',
'source_system' => '{SOURCE_SYSTEM}'
]
];Complete Implementation Example
<?php
require 'vendor/autoload.php';
use ComplyanceSDK\GETSUnifySDK;
use ComplyanceSDK\Models\SDKConfig;
use ComplyanceSDK\Models\Source;
use ComplyanceSDK\Enums\SourceType;
use ComplyanceSDK\Enums\Environment;
use ComplyanceSDK\Enums\LogicalDocType;
use ComplyanceSDK\Enums\Country;
use ComplyanceSDK\Enums\Operation;
use ComplyanceSDK\Enums\Mode;
use ComplyanceSDK\Enums\Purpose;
// -------------------
// STEP 1: CONFIGURE SDK
// -------------------
$sourceName = 'your-source-name';
$sourceVersion = 'your_source_version';
$sources = [
new Source($sourceName, $sourceVersion, SourceType::fromString(SourceType::FIRST_PARTY))
];
$config = new SDKConfig(
'YOUR_API_KEY_HERE', // Replace with your API key
Environment::from(Environment::SANDBOX), // Change to PRODUCTION when going live
$sources
);
GETSUnifySDK::configure($config);
echo "✅ SDK Configured Successfully\n\n";
// -------------------
// STEP 2: BUILD PAYLOAD
// -------------------
$documentId = bin2hex(random_bytes(16));
$payload = [
'invoice_data' => [
'document_number' => 'INV-' . date('YmdHis'),
'document_id' => '{UNIQUE_ID}',
'document_type' => 'tax_invoice',
'invoice_date' => getDynamicDate(0),
'invoice_time' => '00:00:00Z',
'currency_code' => '{CURRENCY_CODE}',
'tax_currency_code' => '{CURRENCY_CODE}',
'due_date' => getDynamicDate(30),
'period_start_date' => getDynamicDate(-30),
'period_end_date' => getDynamicDate(0),
'period_frequency' => '{FREQUENCY}', // e.g., MONTHLY
'exchange_rate' => '{EXCHANGE_RATE}',
'line_extension_amount' => '{LINE_EXTENSION_AMOUNT}',
'tax_exclusive_amount' => '{TAX_EXCLUSIVE_AMOUNT}',
'total_tax_amount' => '{TOTAL_TAX_AMOUNT}',
'total_amount' => '{TOTAL_AMOUNT}',
'total_allowances' => '{TOTAL_ALLOWANCES}',
'total_charges' => '{TOTAL_CHARGES}',
'prepaid_amount' => '{PREPAID_AMOUNT}',
'amount_due' => '{AMOUNT_DUE}',
'rounding_amount' => '{ROUNDING_AMOUNT}',
'original_reference_id' => '{ORIGINAL_REFERENCE_ID}',
'credit_note_reason' => '{CREDIT_NOTE_REASON}'
],
'seller_info' => [
'seller_name' => '{SELLER_NAME}',
'seller_trade_name' => '{SELLER_TRADE_NAME}',
'seller_party_id' => '{SELLER_PARTY_ID}',
'vat_number_type' => '{VAT_NUMBER_TYPE}',
'vat_number' => '{VAT_NUMBER}',
'tax_scheme' => '{TAX_SCHEME}',
'registration_number' => '{REGISTRATION_NUMBER}',
'registration_type' => '{REGISTRATION_TYPE}',
'registration_scheme' => '{REGISTRATION_SCHEME}',
'authority_name' => '{AUTHORITY_NAME}',
'peppol_id' => '{PEPPOL_ID}',
'seller_email' => '{SELLER_EMAIL}',
'seller_phone' => '{SELLER_PHONE}',
'seller_contact_name' => '{SELLER_CONTACT_NAME}',
'street_name' => '{STREET_NAME}',
'additional_address' => '{ADDITIONAL_ADDRESS}',
'building_number' => '{BUILDING_NUMBER}',
'city_name' => '{CITY}',
'state_province' => '{STATE}',
'postal_code' => '{POSTAL_CODE}',
'country_code' => '{COUNTRY_CODE}'
],
'buyer_info' => [
'buyer_name' => '{BUYER_NAME}',
'buyer_trade_name' => '{BUYER_TRADE_NAME}',
'buyer_party_id' => '{BUYER_PARTY_ID}',
'buyer_vat_type' => '{BUYER_VAT_TYPE}',
'buyer_vat_number' => '{BUYER_VAT_NUMBER}',
'buyer_tax_scheme' => '{BUYER_TAX_SCHEME}',
'buyer_registration_number' => '{BUYER_REGISTRATION_NUMBER}',
'buyer_registration_type' => '{BUYER_REGISTRATION_TYPE}',
'buyer_registration_scheme' => '{BUYER_REGISTRATION_SCHEME}',
'buyer_authority_name' => '{BUYER_AUTHORITY_NAME}',
'buyer_peppol_id' => '{BUYER_PEPPOL_ID}',
'buyer_email' => '{BUYER_EMAIL}',
'buyer_phone' => '{BUYER_PHONE}',
'buyer_contact_name' => '{BUYER_CONTACT_NAME}',
'buyer_street_name' => '{BUYER_STREET_NAME}',
'buyer_additional_address' => '{BUYER_ADDITIONAL_ADDRESS}',
'buyer_building_number' => '{BUYER_BUILDING_NUMBER}',
'buyer_city' => '{BUYER_CITY}',
'buyer_state_province' => '{BUYER_STATE}',
'buyer_postal_code' => '{BUYER_POSTAL_CODE}',
'buyer_country' => '{BUYER_COUNTRY_CODE}'
],
'line_items' => [
[
'line_id' => '{LINE_ID}',
'item_name' => '{ITEM_NAME}',
'item_description' => '{ITEM_DESCRIPTION}',
'quantity' => '{QUANTITY}',
'unit_code' => '{UNIT_CODE}',
'unit_price' => '{UNIT_PRICE}',
'net_price' => '{NET_PRICE}',
'gross_price' => '{GROSS_PRICE}',
'line_taxable_value' => '{LINE_TAXABLE_VALUE}',
'tax_category' => '{TAX_CATEGORY}',
'tax_rate' => '{TAX_RATE}',
'tax_amount' => '{TAX_AMOUNT}',
'line_total' => '{LINE_TOTAL}',
'item_type' => '{ITEM_TYPE}', // e.g., GOODS or SERVICE
'country_of_origin' => '{COUNTRY_OF_ORIGIN}',
'classification_code' => '{CLASSIFICATION_CODE}',
'classification_scheme' => '{CLASSIFICATION_SCHEME}',
'seller_item_code' => '{SELLER_ITEM_CODE}',
'buyer_item_code' => '{BUYER_ITEM_CODE}',
'batch_number' => '{BATCH_NUMBER}'
]
],
'extensions' => [
'unique_identifier' => '{UNIQUE_ID}',
'invoiced_object_id' => '{INVOICED_OBJECT_ID}',
'taxpoint_date' => getDynamicDate(0),
'total_amount_including_tax' => '{TOTAL_AMOUNT_INCLUDING_TAX}',
'authority_name' => '{AUTHORITY_NAME}',
'buyer_authority_name' => '{BUYER_AUTHORITY_NAME}',
'business_process_type' => '{BUSINESS_PROCESS_TYPE}',
'specification_identifier' => '{SPECIFICATION_IDENTIFIER}'
],
'payment_info' => [
'payment_id' => '{PAYMENT_ID}',
'payment_means_code' => '{PAYMENT_MEANS_CODE}',
'payment_means_text' => '{PAYMENT_MEANS_TEXT}',
'remittance_info' => '{REMITTANCE_INFO}',
'account_id' => '{ACCOUNT_ID}',
'account_name' => '{ACCOUNT_NAME}',
'bank_id' => '{BANK_ID}'
],
'payment_terms' => [
[
'instructions_id' => '{TERM_ID}',
'note' => '{PAYMENT_NOTE}',
'amount' => '{TERM_AMOUNT}',
'due_date' => getDynamicDate(30)
]
],
'supporting_documents' => [
[
'type' => '{DOCUMENT_TYPE}',
'id' => '{DOCUMENT_ID}'
]
],
'additional_data' => [
'delivery_date' => getDynamicDate(0),
'order_reference' => '{ORDER_REFERENCE}',
'source_system' => '{SOURCE_SYSTEM}'
]
];
// -------------------
// STEP 3: SEND REQUEST
// -------------------
try {
echo "🔄 Sending invoice with Purpose = MAPPING...\n";
$response = GETSUnifySDK::pushToUnify(
$sourceName,
$sourceVersion,
LogicalDocType::from(LogicalDocType::TAX_INVOICE),
Country::from(Country::YOUR_COUNTRY_CODE), // Replace with your country enum
Operation::from(Operation::SINGLE),
Mode::from(Mode::DOCUMENTS),
Purpose::from(Purpose::MAPPING),
$payload
);
print_r($response);
} catch (\Exception $e) {
echo "❌ Error: " . $e->getMessage() . "\n";
}
// -------------------
// STEP 4: CHANGE PURPOSE TO INVOICE & SUBMIT
// -------------------
try {
echo "🚀 Submitting invoice with Purpose = INVOICING...\n";
$invoiceResponse = GETSUnifySDK::pushToUnify(
$sourceName,
$sourceVersion,
LogicalDocType::from(LogicalDocType::TAX_INVOICE),
Country::from(Country::YOUR_COUNTRY_CODE),
Operation::from(Operation::SINGLE),
Mode::from(Mode::DOCUMENTS),
Purpose::from(Purpose::INVOICING),
$payload
);
print_r($invoiceResponse);
echo "✅ Invoice submitted successfully\n";
} catch (\Exception $e) {
echo "❌ Error during INVOICING submission: " . $e->getMessage() . "\n";
}Running the PHP Script
After completing the SDK configuration and invoice submission steps, execute the PHP file from your terminal.
Step 1: Open Terminal
Navigate to your project directory:
cd /path/to/your/projectStep 2: Run the Script
Use the following command format to execute your PHP file:
php your_file_name.phpReplace your_file_name with the name of your PHP script.
Step 3: Verify Execution
-
After running the command, the terminal will display:
-
SDK configuration status
-
Mapping response
-
Invoice submission response
-
Or validation/error messages (if any)
Sample Reference File
If you prefer to start with a ready-to-use template, we have provided a complete reference implementation that aligns with the required compliance standards.
Download the full class file: UAETaxInvoiceTest.php
Support
- Contact: Contact Complyance for E-Invoicing - Complyance has helped over 1000+ organizations simplify global e-invoicing. Let us help you understand how Complyance can work for you.