Skip to content

AS2aaS/php-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AS2aaS PHP Client

A comprehensive PHP client library for AS2aaS (AS2 as a Service), designed to simplify AS2 messaging integration for business applications. This library abstracts the complexity of AS2 protocol implementation, enabling developers to integrate secure B2B messaging with just a few lines of code.

Latest Version Software License Build Status Total Downloads

Overview

AS2aaS provides a cloud-based AS2 messaging service that handles the complex technical requirements of AS2 protocol implementation. This PHP client library offers a clean, intuitive API for integrating AS2 messaging capabilities into your business applications.

Key Use Cases:

  • Healthcare and pharmaceutical supply chain (DSCSA compliance)
  • Retail and manufacturing EDI transactions
  • Financial services secure document exchange
  • Any B2B integration requiring AS2 protocol compliance

Installation

Install the package via Composer:

composer require as2aas/php-client

Laravel Installation

For Laravel applications, the service provider is automatically registered via package discovery. Publish the configuration file:

php artisan vendor:publish --tag=as2aas-config

Add your API key to your .env file:

AS2AAS_API_KEY=pk_live_your_api_key
AS2AAS_TIMEOUT=30000
AS2AAS_RETRIES=3

Quick Start

<?php

use AS2aaS\Client;

// Initialize the client (environment auto-detected from API key)
$as2 = new Client('pk_live_your_api_key'); // Production environment
// $as2 = new Client('pk_test_your_api_key'); // Test environment

// Get a trading partner
$partner = $as2->partners()->getByAs2Id('MCKESSON');

// Send a message
$message = $as2->messages()->send(
    $partner, 
    file_get_contents('purchase-order.edi'),
    'Purchase Order #PO-2024-001'
);

echo "Message sent! Status: " . $message->getStatus();

Laravel Quick Start

// Using Facade
use AS2aaS\Laravel\Facades\AS2;

$partner = AS2::partners()->getByAs2Id('MCKESSON');
$message = AS2::messages()->send($partner, $content, 'Purchase Order');

// Using Dependency Injection
use AS2aaS\Client;

class OrderController extends Controller
{
    public function sendOrder(Client $as2)
    {
        $partner = $as2->partners()->getByAs2Id('MCKESSON');
        $message = $as2->messages()->send($partner, $ediContent, 'Purchase Order');
        
        return response()->json(['message_id' => $message->getId()]);
    }
}

Features

  • Simple API: Send AS2 messages with minimal code complexity
  • Laravel Ready: First-class Laravel integration with service provider and facades
  • Enterprise Architecture: Account-based multi-tenant support
  • Master Partner Management: Centralized partner configuration with inheritance
  • Automatic Security: Built-in signing, encryption, and compression handling
  • Real-time Notifications: Webhook integration for message status updates
  • Comprehensive Error Handling: Detailed exception management with retry logic
  • Content Detection: Automatic EDI, XML, and JSON content type recognition

Configuration

Environment Variables

Configure your API key using environment variables:

AS2AAS_API_KEY=pk_live_your_api_key

Advanced Configuration

use AS2aaS\Client;

$as2 = new Client([
    'apiKey' => 'pk_live_your_api_key',
    'timeout' => 30000,
    'retries' => 3,
    'defaultMdnMode' => 'async',
    'defaultSigning' => true,
    'defaultEncryption' => true,
]);

// API endpoint: https://api.as2aas.com/v1
// Test vs Live environment auto-detected by API from your key type

Global Configuration

Client::configure([
    'timeout' => 45000,
    'retries' => 5,
    'defaultMdnMode' => 'sync',
]);

Core Usage Examples

Partner Management

// List all partners
$partners = $as2->partners()->list();

// Search for specific partners
$partners = $as2->partners()->list(['search' => 'McKesson']);

// Get partner by AS2 ID
$partner = $as2->partners()->getByAs2Id('MCKESSON');

// Get partner by name (supports partial matching)
$partner = $as2->partners()->getByName('McKesson Corporation');

// Create new partner
$partner = $as2->partners()->create([
    'name' => 'Regional Supplier',
    'as2_id' => 'REGIONAL-001',
    'url' => 'https://supplier.example.com/as2'
    // Uses sensible defaults: sign=true, encrypt=true, mdn_mode='async'
]);

// Test partner connectivity
$result = $as2->partners()->test($partner);
if ($result['success']) {
    echo 'Partner connectivity verified';
}

Message Operations

// Send message with content
$message = $as2->messages()->send(
    $partner,
    $ediContent,
    'Invoice #12345'
);

// Send file directly
$message = $as2->messages()->sendFile(
    $partner,
    './purchase-order.edi',
    'Purchase Order #PO-2024-001'
);

// Send with advanced options
$message = $as2->messages()->send($partner, $content, 'Urgent Order', [
    'priority' => 'high',
    'compress' => true,
    'metadata' => ['orderId' => 'PO-2024-001', 'department' => 'procurement']
]);

// Send batch messages
$results = $as2->messages()->sendBatch([
    [
        'partner' => 'MCKESSON',
        'content' => file_get_contents('order1.edi'),
        'subject' => 'Order #1'
    ],
    [
        'partner' => 'CARDINAL',
        'content' => file_get_contents('order2.edi'),
        'subject' => 'Order #2'
    ]
]);

// List messages
$recent = $as2->messages()->list(['limit' => 10]);
$failed = $as2->messages()->list(['status' => 'failed']);
$fromPartner = $as2->messages()->list(['partner' => 'MCKESSON']);

// Get message payload
$content = $as2->messages()->getPayload('msg_000001');

// Wait for delivery confirmation
try {
    $delivered = $as2->messages()->waitForDelivery($message->getId(), 60000);
    echo 'Message delivered successfully';
} catch (Exception $e) {
    echo 'Message delivery failed or timed out';
}

// Validate content before sending
$result = $as2->messages()->validate($ediContent);
if ($result['valid']) {
    echo "Valid {$result['format']} document";
}

// Send test message
$testResult = $as2->messages()->sendTest($partner, [
    'messageType' => 'sample_edi',
    'encrypt' => true,
    'sign' => true
]);

Certificate Management

// Upload certificate
$cert = $as2->certificates()->upload([
    'name' => 'My Company Identity',
    'file' => './certificates/identity.pem',
    'type' => 'identity'
]);

// List certificates
$certs = $as2->certificates()->list();
$expiring = $as2->certificates()->list(['expiringWithin' => 30]);

// Generate identity certificate
$cert = $as2->certificates()->generateIdentity([
    'commonName' => 'My Company AS2',
    'organization' => 'My Company Inc',
    'country' => 'US',
    'email' => 'admin@mycompany.com'
]);

// Download certificate
$files = $as2->certificates()->download('cert_000001');

Webhook Event Handling

// Verify webhook signature (in your webhook handler)
$isValid = $as2->webhooks()->verifySignature($payload, $signature, $secret);

// Handle webhook events
$as2->webhooks()->handleEvent($eventData, [
    'message.delivered' => function($data) {
        echo "Message {$data['id']} delivered to {$data['partner']['name']}";
    },
    'message.failed' => function($data) {
        echo "Message {$data['id']} failed: {$data['error']['message']}";
    }
]);

Enterprise Features and Tenant Management

// Account management (account-level operations)
$account = $as2->accounts()->get();
$tenants = $as2->accounts()->listTenants();

// Create tenant
$tenant = $as2->accounts()->createTenant([
    'name' => 'European Operations',
    'slug' => 'europe'
]);

// Tenant Switching - Method 1: Client-level switching
$as2->setTenant('1'); // Set tenant context
$partners = $as2->partners()->list(); // Now scoped to this tenant
$messages = $as2->messages()->list(); // Also scoped to this tenant

// Tenant Switching - Method 2: Tenants module switching  
$as2->tenants()->switch('1'); // Also updates client context
$partners = $as2->partners()->list(); // Scoped to switched tenant

// Check current tenant
$currentTenantId = $as2->getCurrentTenant();

// Clear tenant context (for account-level operations)
$as2->setTenant(null);
$allTenants = $as2->accounts()->listTenants(); // Works without tenant context

// Tenant-specific API keys (automatically scoped)
$tenantClient = new Client('tk_live_your_tenant_key'); // Pre-scoped to tenant
$partners = $tenantClient->partners()->list(); // No switching needed

// Master Partner Inheritance Flow (7 Steps)

// Step 1: Create master partner (account-level)
$masterPartner = $as2->accounts()->masterPartners()->create([
    'name' => 'ACME Corporation',
    'as2_id' => 'ACME-CORP-001',
    'url' => 'https://acme.example.com/as2',
    'mdn_mode' => 'async',
    'sign' => true,
    'encrypt' => true,
    'compress' => false
]);

// Step 2: List master partners
$masterPartners = $as2->accounts()->masterPartners()->list();

// Step 3: Check inheritance status
$status = $as2->accounts()->masterPartners()->getInheritanceStatus($masterPartner->getId());

// Step 4: Inherit to tenants
$as2->accounts()->masterPartners()->inherit($masterPartner->getId(), [
    'tenant_ids' => ['1', '2', '3'],
    'override_settings' => [
        'url' => 'https://tenant-specific.acme.com/as2',
        'mdn_mode' => 'sync'
    ]
]);

// Step 5: View tenant partners (inherited + specific)
$as2->setTenant('1');
$tenantPartners = $as2->partners()->list(); // Shows both inherited and tenant-specific

// Step 6: Remove inheritance (optional)
$as2->accounts()->masterPartners()->removeInheritance($masterPartner->getId(), ['2', '3']);

// Step 7: Update master partner (propagates to inherited)
$as2->accounts()->masterPartners()->update($masterPartner->getId(), [
    'name' => 'ACME Corporation (Updated)',
    'url' => 'https://new-acme.example.com/as2'
]);

// Billing (account-level operations)
$usage = $as2->billing()->getUsage();
$transactions = $as2->billing()->getTransactions();

Tenant Context Rules

  • Account-level modules (accounts, tenants, billing): No X-Tenant-ID header needed
  • Tenant-scoped modules (partners, messages, certificates, webhooks): Require X-Tenant-ID header
  • Automatic header management: Client automatically adds header based on current tenant context
  • Default behavior:
    • Account keys (pk_*): Defaults to first tenant if no tenant set
    • Tenant keys (tk_*): Automatically scoped to their specific tenant

Master Partner Inheritance Flow

The complete 7-step inheritance process:

  1. Create Master Partner: Account-level partner creation
  2. List Master Partners: View all master partners with inheritance stats
  3. Check Inheritance Status: See which tenants inherit which partners
  4. Inherit to Tenants: Bulk or individual inheritance with custom settings
  5. View Tenant Partners: Combined view of inherited + tenant-specific partners
  6. Remove Inheritance: Selective removal from specific tenants
  7. Update Master Partner: Changes automatically propagate to inherited partners

Benefits:

  • Centralized Management: Create once, inherit everywhere
  • Tenant Customization: Override settings per tenant (URL, MDN mode, etc.)
  • Automatic Sync: Master partner changes propagate automatically
  • Selective Control: Choose which tenants inherit which partners
  • Audit Trail: Track all inheritance relationships and changes

Testing

Unit Testing with Mock Client

For unit testing your application without making actual API calls, use the built-in mock client:

use AS2aaS\Client;

// Create mock client (no API calls)
$mockAs2 = Client::createMock();

// Mock client has same interface as real client
$partner = $mockAs2->partners()->create([
    'name' => 'Test Partner',
    'as2_id' => 'TEST-PARTNER',
    'url' => 'https://test.example.com/as2'
]);

$message = $mockAs2->messages()->send($partner, 'test content', 'Test Subject');
echo $message->getStatus(); // 'delivered' (simulated)

// Access mock data for assertions
$mockData = $mockAs2->getMockData();
$this->assertCount(1, $mockData->partners);

Integration Testing with Test Environment

For integration testing against the AS2aaS test environment:

// Use test environment with test API key (API auto-detects from key)
$as2 = new Client('pk_test_your_key');

// Or use the createTest helper for clarity
$as2 = Client::createTest('pk_test_your_key');

// Sandbox operations for testing
$info = $as2->sandbox()->getInfo();
$samples = $as2->sandbox()->getSample('edi-850');

// Send test messages to verify partner setup
$testResult = $as2->messages()->sendTest($partner, [
    'messageType' => 'sample_edi'
]);

Laravel Testing

// In your Laravel tests
use AS2aaS\Client;
use AS2aaS\Testing\MockClient;

class OrderTest extends TestCase
{
    public function test_can_send_order()
    {
        // Bind mock client
        $this->app->singleton(Client::class, function () {
            return Client::createMock();
        });

        // Your test code
        $response = $this->post('/orders/send', ['partner_id' => 'MCKESSON']);
        $response->assertStatus(200);
    }
}

Utility Functions

// Validate EDI
$result = $as2->utils()->validateEDI($ediContent);

// Detect content type
$contentType = $as2->utils()->detectContentType($content, 'invoice.edi');

// Format file size
echo $as2->utils()->formatFileSize(1048576); // "1.0 MB"

// Generate AS2 ID
$as2Id = $as2->utils()->generateAs2Id('Acme Corporation'); // "ACME-CORP-AS2"

Laravel Integration

Installation

The service provider is automatically registered. Publish the configuration:

php artisan vendor:publish --tag=as2aas-config

Configuration

Add to your .env file:

AS2AAS_API_KEY=pk_live_your_api_key
AS2AAS_TIMEOUT=30000
AS2AAS_RETRIES=3
AS2AAS_DEFAULT_MDN_MODE=async

Usage in Laravel

// Using dependency injection
use AS2aaS\Client;

class OrderController extends Controller
{
    public function sendOrder(Client $as2)
    {
        $partner = $as2->partners()->getByAs2Id('MCKESSON');
        $message = $as2->messages()->send($partner, $ediContent, 'Purchase Order');
        
        return response()->json(['message_id' => $message->getId()]);
    }
}

// Using facade
use AS2aaS\Laravel\Facades\AS2;

$partner = AS2::partners()->getByAs2Id('MCKESSON');
$message = AS2::messages()->send($partner, $content, $subject);

// Using service container
$as2 = app('as2aas');
$partners = $as2->partners()->list();

Webhook Handling in Laravel

// routes/web.php
Route::post('/webhooks/as2', [WebhookController::class, 'handle']);

// WebhookController.php
use AS2aaS\Laravel\Facades\AS2;

class WebhookController extends Controller
{
    public function handle(Request $request)
    {
        $signature = $request->header('X-Signature');
        $payload = $request->getContent();
        
        if (!AS2::webhooks()->verifySignature($payload, $signature, config('as2aas.webhooks.secret'))) {
            abort(401, 'Invalid signature');
        }
        
        $event = json_decode($payload, true);
        
        AS2::webhooks()->handleEvent($event, [
            'message.delivered' => function($data) {
                // Update order status
                Order::where('as2_message_id', $data['id'])->update(['status' => 'delivered']);
            },
            'message.failed' => function($data) {
                // Send notification
                Mail::to('admin@company.com')->send(new MessageFailedMail($data));
            }
        ]);
        
        return response('OK');
    }
}

Error Handling

The client provides comprehensive error handling with specific exception types:

use AS2aaS\Exceptions\AS2AuthenticationError;
use AS2aaS\Exceptions\AS2ValidationError;
use AS2aaS\Exceptions\AS2NetworkError;
use AS2aaS\Exceptions\AS2PartnerError;
use AS2aaS\Exceptions\AS2RateLimitError;

try {
    $message = $as2->messages()->send($partner, $content, $subject);
} catch (AS2PartnerError $e) {
    echo 'Partner issue: ' . $e->getMessage();
} catch (AS2RateLimitError $e) {
    echo 'Rate limited, retry in: ' . $e->getRetryAfter() . ' seconds';
} catch (AS2ValidationError $e) {
    echo 'Validation errors: ' . json_encode($e->getValidationErrors());
} catch (AS2NetworkError $e) {
    if ($e->isRetryable()) {
        echo 'Retryable network error';
    }
} catch (AS2AuthenticationError $e) {
    echo 'Authentication failed: ' . $e->getMessage();
}

Multi-Tenant Architecture

AS2aaS supports enterprise multi-tenant architectures where you can manage multiple business entities or customers within a single account:

Account and Tenant Management

// Account-level operations
$account = $as2->accounts()->get();
$tenants = $as2->accounts()->listTenants();

// Create new tenant for a customer
$tenant = $as2->accounts()->createTenant([
    'name' => 'East Coast Division',
    'slug' => 'east-coast'
]);

// Switch tenant context for operations
$as2->setTenant($tenant->getId());

// All subsequent operations are scoped to this tenant
$partners = $as2->partners()->list();
$messages = $as2->messages()->list();

Master Partner Inheritance

Create master partners at the account level and inherit them to specific tenants:

// Create master partner (account-level)
$masterPartner = $as2->accounts()->masterPartners()->create([
    'name' => 'McKesson Corporation',
    'as2_id' => 'MCKESSON',
    'url' => 'https://as2.mckesson.com/receive'
]);

// Inherit to specific tenants with custom settings
$as2->accounts()->masterPartners()->inherit($masterPartner->getId(), [
    'tenant_ids' => ['1', '2'],
    'override_settings' => [
        'url' => 'https://tenant-specific.mckesson.com/as2',
        'mdn_mode' => 'sync'
    ]
]);

// View inherited partners from tenant perspective
$as2->setTenant('1');
$tenantPartners = $as2->partners()->list(); // Shows inherited + tenant-specific

Industry-Specific Integration

Healthcare and Pharmaceutical (DSCSA)

The client is designed to support Drug Supply Chain Security Act (DSCSA) compliance requirements:

// Create trading account for pharmacy chain
$tenant = $as2->accounts()->createTenant([
    'name' => 'Regional Pharmacy Chain'
]);

// Set up major pharmaceutical partners
$mckesson = $as2->accounts()->masterPartners()->create([
    'name' => 'McKesson Pharmaceutical',
    'as2_id' => 'MCKESSON-PHARMA',
    'url' => 'https://as2.mckesson.com/dscsa'
]);

// Inherit to trading account
$as2->accounts()->masterPartners()->inherit($mckesson->getId(), [
    'tenant_ids' => [$tenant->getId()]
]);

// Send DSCSA transaction
$as2->setTenant($tenant->getId());
$dscsaData = json_encode([
    'transaction_type' => 'T3_VERIFICATION_REQUEST',
    'ndc' => '12345-678-90',
    'serial_number' => 'SN789012345'
]);

$message = $as2->messages()->send($partner, $dscsaData, 'T3 Verification Request');

Testing

Run the test suite:

composer test

Run with coverage:

composer test-coverage

Run static analysis:

composer analyse

Check code style:

composer cs-check

API Reference

Client Initialization

  • new Client(string $apiKey) - Initialize with API key
  • new Client(array $config) - Initialize with configuration array
  • Client::createTest(string $apiKey) - Create test environment client
  • Client::configure(array $config) - Set global configuration

Core Modules

  • partners() - Partner management and lookup
  • messages() - Message sending and receiving
  • certificates() - Certificate upload and management
  • accounts() - Account-level operations (enterprise)
  • tenants() - Tenant management and context switching
  • webhooks() - Webhook event handling
  • billing() - Subscription and usage management
  • sandbox() - Testing and development utilities
  • partnerships() - Advanced partner onboarding
  • utils() - Helper functions and content detection

Requirements

  • PHP 8.0 or higher
  • Guzzle HTTP client 7.0+
  • OpenSSL extension for certificate operations
  • JSON extension for API communication

Contributing

Please see CONTRIBUTING for details on our code of conduct and the process for submitting pull requests.

Security

If you discover any security-related issues, please email security@as2aas.com instead of using the issue tracker.

License

The MIT License (MIT). Please see License File for more information.

Support

About AS2aaS

AS2aaS is a cloud-based AS2 messaging service that eliminates the complexity of implementing and maintaining AS2 infrastructure. Our platform handles the technical requirements of AS2 protocol compliance while providing a simple, developer-friendly API for integration.

Perfect for businesses requiring secure B2B document exchange, including healthcare organizations needing DSCSA compliance, retail companies managing EDI transactions, and any enterprise requiring AS2 protocol support.

About

PHP client for AS2aaS

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages