Skip to main content

PHP Examples

Complete PHP examples for integrating with the LuxCore API using cURL.

LuxCore Client Class

<?php

class LuxCoreClient
{
    private const BASE_URL = 'https://api.lux-core.io/api/v1';
    private string $apiKey;

    public function __construct(?string $apiKey = null)
    {
        $this->apiKey = $apiKey ?? getenv('LUXCORE_API_KEY');
        if (!$this->apiKey) {
            throw new InvalidArgumentException('API key is required');
        }
    }

    private function request(string $method, string $path, ?array $data = null, ?array $params = null): array
    {
        $url = self::BASE_URL . $path;
        
        if ($params) {
            $url .= '?' . http_build_query($params);
        }

        $ch = curl_init();
        
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'X-API-Key: ' . $this->apiKey,
                'Content-Type: application/json',
            ],
        ]);

        switch (strtoupper($method)) {
            case 'POST':
                curl_setopt($ch, CURLOPT_POST, true);
                if ($data) {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
                }
                break;
            case 'PUT':
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
                if ($data) {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
                }
                break;
            case 'DELETE':
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
                break;
        }

        $response = curl_exec($ch);
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $decoded = json_decode($response, true);

        if ($statusCode >= 400) {
            throw new LuxCoreException(
                $decoded['message'] ?? 'Unknown error',
                $statusCode,
                $decoded['error'] ?? null
            );
        }

        return $decoded;
    }

    // Payments
    public function createPayment(array $data): array
    {
        return $this->request('POST', '/payments', $data);
    }

    public function getPayment(string $paymentId): array
    {
        return $this->request('GET', "/payments/{$paymentId}");
    }

    public function listPayments(array $filters = []): array
    {
        return $this->request('GET', '/payments', null, $filters);
    }

    public function cancelPayment(string $paymentId): array
    {
        return $this->request('POST', "/payments/{$paymentId}/cancel");
    }

    // Balance
    public function getBalance(?string $currency = null): array
    {
        $params = $currency ? ['currency' => $currency] : [];
        return $this->request('GET', '/balance', null, $params);
    }

    public function getAllBalances(): array
    {
        return $this->request('GET', '/balance/all');
    }

    // Webhooks
    public function createWebhook(array $data): array
    {
        return $this->request('POST', '/webhooks', $data);
    }

    public function listWebhooks(): array
    {
        return $this->request('GET', '/webhooks');
    }

    public function deleteWebhook(string $webhookId): void
    {
        $this->request('DELETE', "/webhooks/{$webhookId}");
    }

    // Static webhook verification
    public static function verifyWebhookSignature(
        array $payload,
        string $signature,
        int $timestamp,
        string $secret
    ): bool {
        // Check timestamp (reject if older than 5 minutes)
        $currentTime = time();
        if (abs($currentTime - $timestamp) > 300) {
            throw new InvalidArgumentException('Webhook timestamp too old');
        }

        // Calculate expected signature
        $payloadString = json_encode($payload, JSON_UNESCAPED_SLASHES);
        $payloadToSign = "{$timestamp}.{$payloadString}";
        $expectedSignature = 'sha256=' . hash_hmac('sha256', $payloadToSign, $secret);

        // Compare signatures (timing-safe)
        if (!hash_equals($signature, $expectedSignature)) {
            throw new InvalidArgumentException('Invalid webhook signature');
        }

        return true;
    }
}

class LuxCoreException extends Exception
{
    private ?string $errorCode;

    public function __construct(string $message, int $statusCode, ?string $errorCode = null)
    {
        parent::__construct($message, $statusCode);
        $this->errorCode = $errorCode;
    }

    public function getErrorCode(): ?string
    {
        return $this->errorCode;
    }

    public function getStatusCode(): int
    {
        return $this->getCode();
    }
}

Usage Examples

Create a Deposit Payment

<?php
require_once 'LuxCoreClient.php';

$client = new LuxCoreClient();

try {
    $payment = $client->createPayment([
        'amount' => 100000, // $1,000.00 MXN (in centavos)
        'currency' => 'MXN',
        'method' => 'spei',
        'type' => 'deposit',
        'merchant_reference' => 'order_' . time(),
        'customer' => [
            'name' => 'Juan Perez',
            'email' => 'juan@example.com',
            'phone' => '+525551234567',
        ],
        'metadata' => [
            'order_id' => '12345',
            'source' => 'web',
        ],
    ]);

    echo "Payment created: {$payment['transaction_id']}\n";
    echo "Status: {$payment['status']}\n";

    if (isset($payment['instructions'])) {
        echo "Bank: {$payment['instructions']['bank_name']}\n";
        echo "CLABE: {$payment['instructions']['account_number']}\n";
        echo "Reference: {$payment['instructions']['reference']}\n";
    }
} catch (LuxCoreException $e) {
    echo "Error ({$e->getStatusCode()}): {$e->getMessage()}\n";
}

Create a Withdrawal (Payout)

<?php
$payout = $client->createPayment([
    'amount' => 50000,
    'currency' => 'MXN',
    'method' => 'spei',
    'type' => 'withdrawal',
    'merchant_reference' => 'payout_' . time(),
    'customer' => [
        'name' => 'Finance Team',
        'email' => 'finance@company.com',
    ],
    'payout' => [
        'recipient_name' => 'Maria Garcia',
        'bank_account' => '012345678901234567',
        'bank_code' => '002',
        'reference' => 'PAYOUT-001',
    ],
]);

echo "Payout created: {$payout['transaction_id']}\n";

List Payments

<?php
$result = $client->listPayments([
    'status' => 'completed',
    'limit' => 20,
    'created_at_from' => '2025-01-01T00:00:00Z',
]);

echo "Found {$result['total']} payments\n";

foreach ($result['data'] as $payment) {
    echo "{$payment['transaction_id']}: {$payment['amount']} {$payment['currency']}\n";
}

Webhook Handler

<?php
require_once 'LuxCoreClient.php';

// Get webhook secret from environment
$webhookSecret = getenv('LUXCORE_WEBHOOK_SECRET');

// Get headers and payload
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = (int)($_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? 0);
$payload = json_decode(file_get_contents('php://input'), true);

try {
    // Verify signature
    LuxCoreClient::verifyWebhookSignature(
        $payload,
        $signature,
        $timestamp,
        $webhookSecret
    );

    // Process event
    $event = $payload['event'];
    $payment = $payload['payment'];

    switch ($event) {
        case 'payment.completed':
            // Handle completed payment
            error_log("Payment {$payment['id']} completed!");
            // Update database, send confirmation, etc.
            updateOrderStatus($payment['merchant_reference'], 'paid');
            break;

        case 'payment.failed':
            // Handle failed payment
            error_log("Payment {$payment['id']} failed: {$payment['failure_reason']}");
            updateOrderStatus($payment['merchant_reference'], 'failed');
            break;

        case 'payout.completed':
            // Handle completed payout
            error_log("Payout {$payment['id']} completed!");
            break;

        default:
            error_log("Unhandled event: {$event}");
    }

    // Return success
    http_response_code(200);
    echo json_encode(['received' => true]);

} catch (InvalidArgumentException $e) {
    http_response_code(400);
    echo json_encode(['error' => $e->getMessage()]);
}

function updateOrderStatus(string $reference, string $status): void
{
    // Your database update logic here
}

Laravel Integration

<?php
// app/Services/LuxCoreService.php

namespace App\Services;

use Illuminate\Support\Facades\Http;

class LuxCoreService
{
    private string $apiKey;
    private string $baseUrl = 'https://api.lux-core.io/api/v1';

    public function __construct()
    {
        $this->apiKey = config('services.luxcore.api_key');
    }

    public function createPayment(array $data): array
    {
        $response = Http::withHeaders([
            'X-API-Key' => $this->apiKey,
        ])->post("{$this->baseUrl}/payments", $data);

        if ($response->failed()) {
            throw new \Exception($response->json('message'));
        }

        return $response->json();
    }

    public function getPayment(string $paymentId): array
    {
        $response = Http::withHeaders([
            'X-API-Key' => $this->apiKey,
        ])->get("{$this->baseUrl}/payments/{$paymentId}");

        return $response->json();
    }
}
<?php
// routes/api.php

use Illuminate\Http\Request;

Route::post('/webhooks/luxcore', function (Request $request) {
    $signature = $request->header('X-Webhook-Signature');
    $timestamp = (int) $request->header('X-Webhook-Timestamp');
    $payload = $request->all();

    // Verify signature
    try {
        \App\Services\LuxCoreClient::verifyWebhookSignature(
            $payload,
            $signature,
            $timestamp,
            config('services.luxcore.webhook_secret')
        );
    } catch (\Exception $e) {
        return response()->json(['error' => $e->getMessage()], 400);
    }

    // Dispatch job to process webhook asynchronously
    \App\Jobs\ProcessLuxCoreWebhook::dispatch($payload);

    return response()->json(['received' => true]);
});

Error Handling

<?php
try {
    $payment = $client->createPayment($data);
} catch (LuxCoreException $e) {
    switch ($e->getStatusCode()) {
        case 401:
            // Invalid API key
            log_error('Invalid LuxCore API key');
            break;
        case 400:
            // Validation error
            log_error("Validation error: {$e->getMessage()}");
            break;
        case 429:
            // Rate limited
            sleep(60);
            // Retry...
            break;
        case 500:
        case 503:
            // Server error - retry with backoff
            sleep(5);
            // Retry...
            break;
        default:
            log_error("API error ({$e->getStatusCode()}): {$e->getMessage()}");
    }
}