PHP code example of bhaidar / laravel-checkeeper

1. Go to this page and download the library: Download bhaidar/laravel-checkeeper library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

bhaidar / laravel-checkeeper example snippets


return [
    // API authentication
    'api_key' => env('CHECKEEPER_API_KEY'),

    // API endpoint
    'base_url' => env('CHECKEEPER_BASE_URL', 'https://api.checkeeper.com/v3'),

    // HTTP timeout (seconds)
    'timeout' => 30,

    // Webhook configuration
    'webhooks' => [
        'enabled' => true,
        'secret' => env('CHECKEEPER_WEBHOOK_SECRET'),
        'route' => 'checkeeper/webhook',
        'middleware' => ['api'],
    ],

    // Queue configuration
    'queue' => [
        'enabled' => true,
        'connection' => env('CHECKEEPER_QUEUE_CONNECTION', 'default'),
        'queue' => env('CHECKEEPER_QUEUE_NAME', 'checkeeper'),
    ],
];

// 1. Create check data (DTO or array)
$checkData = new CheckData(...);

// 2. Optionally specify delivery method
$delivery = new DeliveryData(method: DeliveryMethod::UspsFirstClass);

// 3. Send to Checkeeper via Facade
$result = Checkeeper::checks()->create($checkData, $delivery);

// 4. Package handles HTTP request with retry logic
// 5. Returns typed CheckStatusData response
echo $result->id; // "check-abc123"

// 6. Webhooks notify you of status changes
// 7. Events fired for your listeners

use Bhaidar\Checkeeper\Facades\Checkeeper;

$result = Checkeeper::checks()->create([
    'bank' => [
        'routing' => '123456789',
        'account' => '987654321',
    ],
    'payer' => [
        'line1' => 'My Company Inc',
        'line2' => '123 Business St',
        'line3' => 'Suite 100',
        'line4' => 'New York, NY 10001',
    ],
    'payee' => [
        'line1' => 'Vendor Services LLC',
        'line2' => '456 Supplier Ave',
        'line3' => 'Los Angeles, CA 90210',
    ],
    'signer' => [
        'type' => 'text',
        'value' => 'Jane Smith',
    ],
    'amount' => 50000,              // $500.00 (amount in cents)
    'number' => 1001,
    'date' => '2024-02-29',
    'memo' => 'Invoice #12345',
    'nonce' => 'unique-id-12345',   // prevents duplicates
]);

// Result contains check ID and status
echo $result->id;            // "check-abc123"
echo $result->status->value; // "processing"

use Bhaidar\Checkeeper\Facades\Checkeeper;
use Bhaidar\Checkeeper\DataTransferObjects\CheckData;
use Bhaidar\Checkeeper\DataTransferObjects\BankData;
use Bhaidar\Checkeeper\DataTransferObjects\PayerData;
use Bhaidar\Checkeeper\DataTransferObjects\PayeeData;
use Bhaidar\Checkeeper\DataTransferObjects\SignerData;
use Bhaidar\Checkeeper\Enums\SignerType;
use Illuminate\Support\Str;

$checkData = new CheckData(
    bank: new BankData(
        routing: '123456789',
        account: '987654321'
    ),
    payer: new PayerData(
        line1: 'My Company Inc',
        line2: '123 Business St',
        line3: 'Suite 100',
        line4: 'New York, NY 10001'
    ),
    payee: new PayeeData(
        line1: 'Vendor Services LLC',
        line2: '456 Supplier Ave',
        line3: 'Los Angeles, CA 90210'
    ),
    signer: new SignerData(
        type: SignerType::Text,
        value: 'Jane Smith'
    ),
    amount: 50000,
    number: 1001,
    memo: 'Invoice #12345',
    nonce: 'payment-' . Str::uuid()
);

$result = Checkeeper::checks()->create($checkData);

use Illuminate\Support\Facades\Storage;

$payer = new PayerData(
    line1: 'My Company Inc',
    line2: '123 Business St',
    logo: base64_encode(Storage::get('company-logo.png'))
);

$signer = new SignerData(
    type: SignerType::Png,
    value: base64_encode(Storage::get('ceo-signature.png'))
);

use Bhaidar\Checkeeper\DataTransferObjects\DeliveryData;
use Bhaidar\Checkeeper\DataTransferObjects\AddressData;
use Bhaidar\Checkeeper\Enums\DeliveryMethod;

// First class mail
$delivery = new DeliveryData(
    method: DeliveryMethod::UspsFirstClass
);

$result = Checkeeper::checks()->create($checkData, $delivery);

// Priority mail
$delivery = new DeliveryData(
    method: DeliveryMethod::UspsPriority
);

$result = Checkeeper::checks()->create($checkData, $delivery);

// Overnight shipping (bundled to one address)
$delivery = new DeliveryData(
    method: DeliveryMethod::UpsNextDay,
    bundleAddress: new AddressData(
        name: 'John Doe',
        line1: '789 Main St',
        city: 'Chicago',
        state: 'IL',
        zip: '60601',
        country: 'US',
        phone: '555-123-4567'
    )
);

$result = Checkeeper::checks()->create($checkData, $delivery);

// PDF return (no mailing, get PDF to print yourself)
$delivery = new DeliveryData(
    method: DeliveryMethod::Pdf
);

$result = Checkeeper::checks()->create($checkData, $delivery);

$result = Checkeeper::checks()->create($checkData);

$checks = [
    [
        'bank' => ['routing' => '123456789', 'account' => '111111'],
        'payer' => ['line1' => 'My Company'],
        'payee' => ['line1' => 'Vendor A'],
        'signer' => ['type' => 'text', 'value' => 'Jane Smith'],
        'amount' => 25000,
        'number' => 1001,
        'nonce' => 'check-001',
    ],
    [
        'bank' => ['routing' => '123456789', 'account' => '111111'],
        'payer' => ['line1' => 'My Company'],
        'payee' => ['line1' => 'Vendor B'],
        'signer' => ['type' => 'text', 'value' => 'Jane Smith'],
        'amount' => 35000,
        'number' => 1002,
        'nonce' => 'check-002',
    ],
];

// Without delivery (uses team default)
$result = Checkeeper::checks()->createBulk($checks);

// With delivery
$delivery = new DeliveryData(method: DeliveryMethod::UspsPriority);
$result = Checkeeper::checks()->createBulk($checks, $delivery);

// Result contains:
echo "Created: " . count($result['checks']); // New checks
echo "Duplicates: " . count($result['existing']); // Checks with duplicate nonce
echo "Total credits: " . $result['total_credits']; // Cost in credits

$checksData = [
    new CheckData(/* ... */),
    new CheckData(/* ... */),
    new CheckData(/* ... */),
];

$delivery = new DeliveryData(method: DeliveryMethod::UspsFirstClass);
$result = Checkeeper::checks()->createBulk($checksData, $delivery);

use Bhaidar\Checkeeper\Jobs\CreateCheckJob;

// Dispatch to queue
CreateCheckJob::dispatch($checkData);

// With delay
CreateCheckJob::dispatch($checkData)->delay(now()->addMinutes(5));

// On specific queue
CreateCheckJob::dispatch($checkData)->onQueue('payments');

// With callback URL (for your own tracking)
CreateCheckJob::dispatch($checkData, callbackUrl: 'https://yourapp.com/check-created');

// app/Providers/EventServiceProvider.php

use Bhaidar\Checkeeper\Events\CheckCreated;
use App\Listeners\NotifyAccountingOfCheckCreation;

protected $listen = [
    CheckCreated::class => [
        NotifyAccountingOfCheckCreation::class,
    ],
];

$checks = Checkeeper::checks()->list();

foreach ($checks as $check) {
    echo "{$check->id}: {$check->status->value}\n";
}

use Bhaidar\Checkeeper\Enums\CheckStatus;

$checks = Checkeeper::checks()
    ->filter()
    ->whereEquals('status', CheckStatus::Delivered->value)
    ->whereGreaterThan('amount', 10000)
    ->whereBetween('date', '2024-01-01', '2024-12-31')
    ->whereContains('memo', 'Invoice')
    ->sortBy('created', 'desc')
    ->get();

// Equality
->whereEquals('field', 'value')
->whereNotEquals('field', 'value')

// Comparison
->whereLessThan('amount', 10000)
->whereLessThanOrEqual('amount', 10000)
->whereGreaterThan('amount', 10000)
->whereGreaterThanOrEqual('amount', 10000)

// Lists
->whereIn('status', ['delivered', 'printed'])
->whereNotIn('status', ['cancelled'])

// Text search
->whereContains('memo', 'Invoice')

// Ranges
->whereBetween('date', '2024-01-01', '2024-12-31')

// Sorting
->sortBy('created', 'desc')
->sortBy('amount', 'asc')

$checks = Checkeeper::checks()->list([
    'filters[status][$eq]' => 'delivered',
    'filters[amount][$gt]' => 10000,
    'sort' => 'created:desc',
]);

$status = Checkeeper::checks()->status('check-abc123');

echo $status->id;              // "check-abc123"
echo $status->status->value;   // "delivered"
echo $status->created;         // "2024-02-29 10:00:00"
echo $status->updated;         // "2024-03-02 14:30:00"
echo $status->trackingUrl;     // "https://tools.usps.com/..."

$events = Checkeeper::checks()->tracking('check-abc123');

foreach ($events as $event) {
    echo "{$event->event}: {$event->eventDate}\n";
    if ($event->location) {
        echo "  Location: {$event->location->city}, {$event->location->state}\n";
    }
}

$cancelled = Checkeeper::checks()->cancel('check-abc123');

if ($cancelled) {
    echo "Check cancelled successfully";
}

use Illuminate\Support\Facades\Storage;

// Get JPG image
$imageData = Checkeeper::checks()->image('check-abc123', 'jpg');
Storage::put('checks/check-abc123.jpg', $imageData);

// Get PDF
$pdfData = Checkeeper::checks()->image('check-abc123', 'pdf');
Storage::put('checks/check-abc123.pdf', $pdfData);

// Download in controller
public function download($checkId)
{
    $pdfData = Checkeeper::checks()->image($checkId, 'pdf');

    return response()->streamDownload(function () use ($pdfData) {
        echo $pdfData;
    }, "check-{$checkId}.pdf");
}

$voucherData = Checkeeper::checks()->voucherImage('check-abc123');
Storage::put('vouchers/voucher-abc123.jpg', $voucherData);

use Bhaidar\Checkeeper\Events\WebhookReceived;
use Bhaidar\Checkeeper\Events\CheckCreated;
use Bhaidar\Checkeeper\Events\CheckCancelled;

protected $listen = [
    WebhookReceived::class => [
        LogWebhookActivity::class,
        ProcessCheckStatusUpdate::class,
    ],

    CheckCreated::class => [
        SendCheckCreatedNotification::class,
        UpdateInvoiceStatus::class,
    ],

    CheckCancelled::class => [
        RefundPayment::class,
        NotifyAccounting::class,
    ],
];

namespace App\Listeners;

use Bhaidar\Checkeeper\Events\WebhookReceived;
use App\Models\Invoice;

class MarkInvoiceAsPaid
{
    public function handle(WebhookReceived $event): void
    {
        $payload = $event->payload;

        if ($payload['event'] !== 'check.delivered') {
            return;
        }

        $invoice = Invoice::where('check_id', $payload['check_id'])->first();

        if (! $invoice) {
            return;
        }

        $invoice->update([
            'status' => 'paid',
            'paid_at' => $payload['delivered_at'],
        ]);

        $invoice->customer->notify(new CheckDeliveredNotification($invoice));
    }
}

namespace App\Listeners;

use Bhaidar\Checkeeper\Events\WebhookReceived;
use Illuminate\Support\Facades\Log;

class LogWebhookActivity
{
    public function handle(WebhookReceived $event): void
    {
        Log::info('Checkeeper webhook received', [
            'event' => $event->payload['event'] ?? 'unknown',
            'check_id' => $event->payload['check_id'] ?? null,
            'received_at' => $event->receivedAt,
        ]);
    }
}

// config/checkeeper.php
'webhooks' => [
    'enabled' => false,
],

$info = Checkeeper::team()->info();

echo $info['name'];
echo $info['credits'];

$templates = Checkeeper::templates()->list();

foreach ($templates as $template) {
    echo "{$template['id']}: {$template['name']}\n";
}

$checkData = new CheckData(
    // ... other fields
    templateId: 'template-123'
);

use Bhaidar\Checkeeper\Events\CheckCreated;

class SendCheckCreatedEmail
{
    public function handle(CheckCreated $event): void
    {
        $check = $event->check;       // CheckStatusData
        $metadata = $event->metadata;  // array

        Mail::to($recipient)->send(new CheckCreatedMail($check));
    }
}

use Bhaidar\Checkeeper\Events\CheckCancelled;

class RefundCancelledCheck
{
    public function handle(CheckCancelled $event): void
    {
        $checkId = $event->checkId;

        Refund::create(['check_id' => $checkId]);
    }
}

use Bhaidar\Checkeeper\Events\WebhookReceived;

class ProcessWebhookPayload
{
    public function handle(WebhookReceived $event): void
    {
        $payload = $event->payload;       // array
        $signature = $event->signature;   // string
        $receivedAt = $event->receivedAt; // string (ISO 8601)

        match ($payload['event']) {
            'check.printed' => $this->handlePrinted($payload),
            'check.mailed' => $this->handleMailed($payload),
            'check.delivered' => $this->handleDelivered($payload),
            default => null,
        };
    }
}

use Bhaidar\Checkeeper\Exceptions\AuthenticationException;
use Bhaidar\Checkeeper\Exceptions\ValidationException;
use Bhaidar\Checkeeper\Exceptions\NotFoundException;
use Bhaidar\Checkeeper\Exceptions\CheckkeeperException;

try {
    $result = Checkeeper::checks()->create($checkData);
} catch (AuthenticationException $e) {
    // Invalid API key (401/403)
    Log::error('Checkeeper auth failed', ['error' => $e->getMessage()]);

} catch (ValidationException $e) {
    // Invalid check data (422)
    return back()->withErrors($e->errors);

} catch (NotFoundException $e) {
    // Check not found (404)
    abort(404, 'Check not found');

} catch (CheckkeeperException $e) {
    // Other API errors
    Log::error('Checkeeper error', [
        'status' => $e->statusCode,
        'message' => $e->getMessage(),
        'errors' => $e->errors,
    ]);
}

use Bhaidar\Checkeeper\Facades\Checkeeper;
use Bhaidar\Checkeeper\DataTransferObjects\CheckData;
use Bhaidar\Checkeeper\DataTransferObjects\BankData;
use Bhaidar\Checkeeper\DataTransferObjects\PayerData;
use Bhaidar\Checkeeper\DataTransferObjects\PayeeData;
use Bhaidar\Checkeeper\DataTransferObjects\SignerData;
use Bhaidar\Checkeeper\DataTransferObjects\DeliveryData;
use Bhaidar\Checkeeper\Enums\SignerType;
use Bhaidar\Checkeeper\Enums\DeliveryMethod;
use Bhaidar\Checkeeper\Events\WebhookReceived;
use Bhaidar\Checkeeper\Jobs\CreateCheckJob;

// Step 1: Create payment record
$payment = Payment::create([
    'invoice_id' => $invoice->id,
    'vendor_id' => $vendor->id,
    'amount' => 50000, // $500.00
    'status' => 'pending',
]);

// Step 2: Prepare check data
$checkData = new CheckData(
    bank: new BankData(
        routing: config('company.bank_routing'),
        account: config('company.bank_account')
    ),
    payer: new PayerData(
        line1: config('company.name'),
        line2: config('company.address'),
        logo: base64_encode(Storage::get('company-logo.png'))
    ),
    payee: new PayeeData(
        line1: $vendor->name,
        line2: $vendor->address
    ),
    signer: new SignerData(
        type: SignerType::Png,
        value: base64_encode(Storage::get('ceo-signature.png'))
    ),
    amount: $payment->amount,
    number: $payment->check_number,
    memo: "Invoice #{$invoice->number}",
    nonce: "payment-{$payment->id}"
);

// Step 3: Create check with delivery method
$delivery = new DeliveryData(method: DeliveryMethod::UspsFirstClass);
$result = Checkeeper::checks()->create($checkData, $delivery);

$payment->update([
    'check_id' => $result->id,
    'status' => 'sent_to_printer',
]);

// Or queue it for async processing
CreateCheckJob::dispatch($checkData);

// Step 4: Listen for webhook events
// app/Listeners/UpdatePaymentStatus.php
class UpdatePaymentStatus
{
    public function handle(WebhookReceived $event): void
    {
        $payload = $event->payload;
        $checkId = $payload['check_id'];

        $payment = Payment::where('check_id', $checkId)->first();

        if (! $payment) {
            return;
        }

        match ($payload['event']) {
            'check.printed' => $payment->update(['status' => 'printed']),
            'check.mailed' => $payment->update(['status' => 'mailed']),
            'check.delivered' => $payment->update([
                'status' => 'delivered',
                'delivered_at' => $payload['delivered_at'],
            ]),
            'check.returned' => $payment->update(['status' => 'returned']),
            default => null,
        };

        $payment->vendor->notify(new CheckStatusUpdated($payment));
    }
}

// Step 5: Display status to user
// resources/views/payments/show.blade.php

use Bhaidar\Checkeeper\Facades\Checkeeper;
use Illuminate\Support\Facades\Http;

test('can create vendor payment', function () {
    Http::fake([
        'api.checkeeper.com/*' => Http::response([
            'data' => [
                'checks' => [
                    ['id' => 'check-123', 'status' => 'processing']
                ],
                'total_credits' => 1,
            ],
        ], 201),
    ]);

    $vendor = Vendor::factory()->create();
    $invoice = Invoice::factory()->create(['vendor_id' => $vendor->id]);

    $payment = Payment::create([
        'invoice_id' => $invoice->id,
        'vendor_id' => $vendor->id,
        'amount' => 50000,
    ]);

    CreateCheckJob::dispatchSync($checkData);

    expect($payment->fresh())
        ->check_id->toBe('check-123')
        ->status->toBe('sent_to_printer');
});

test('updates payment status on webhook', function () {
    $payment = Payment::factory()->create(['check_id' => 'check-123']);

    $payload = json_encode([
        'event' => 'check.delivered',
        'check_id' => 'check-123',
        'delivered_at' => now()->toIso8601String(),
    ]);

    $signature = hash_hmac('sha256', $payload, config('checkeeper.webhooks.secret'));

    $this->postJson('/checkeeper/webhook', json_decode($payload, true), [
        'X-Checkeeper-Signature' => $signature,
    ])->assertOk();

    expect($payment->fresh()->status)->toBe('delivered');
});

// List checks (returns Collection of CheckStatusData)
Checkeeper::checks()->list(array $filters = []): Collection

// Create single check (delivery is separate from check data)
Checkeeper::checks()->create(CheckData|array $data, ?DeliveryData $delivery = null): CheckStatusData

// Create multiple checks (delivery applies to all checks)
Checkeeper::checks()->createBulk(array $checks, ?DeliveryData $delivery = null): array

// Get check status
Checkeeper::checks()->status(string $id): CheckStatusData

// Get tracking events
Checkeeper::checks()->tracking(string $id): Collection

// Cancel check
Checkeeper::checks()->cancel(string $id): bool

// Get check image (jpg or pdf)
Checkeeper::checks()->image(string $id, string $type = 'jpg'): string

// Add attachment
Checkeeper::checks()->attachment(string $id, string $file): bool

// Get voucher image
Checkeeper::checks()->voucherImage(string $id): string

// Fluent filter builder
Checkeeper::checks()->filter(): CheckFilterBuilder

Checkeeper::team()->info(): array

Checkeeper::templates()->list(): Collection
bash
php artisan vendor:publish --tag=checkeeper-config
blade
<div class="payment-status">
    <h3>Payment #{{ $payment->id }}</h3>

    <div class="status-badge {{ $payment->status }}">
        {{ ucfirst($payment->status) }}
    </div>

    @if($payment->check_id)
        <div class="tracking">
            <h4>Tracking</h4>
            @foreach($tracking as $event)
                <div class="event">
                    <span>{{ $event->event }}</span>
                    <span>{{ $event->eventDate }}</span>
                    <span>{{ $event->location->city ?? '' }}</span>
                </div>
            @endforeach
        </div>

        <a href="{{ route('payments.download', $payment) }}" class="btn">
            Download Check Image
        </a>
    @endif
</div>