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/ */
// 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);
$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,
],
];
$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