1. Go to this page and download the library: Download salehye/invoicing 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/ */
salehye / invoicing example snippets
use Salehye\Invoicing\Traits\HasInvoices;
class Customer extends Model
{
use HasInvoices;
}
// Check if overdue (Unpaid + past due_at, or Overdue status)
$invoice->isOverdue(); // bool
// Mark as overdue (via command)
php artisan invoicing:mark-overdue
// Overdue invoices can transition to: Paid or Canceled
$invoice->status->canTransitionTo(InvoiceStatus::Paid); // true
$invoice->status->canTransitionTo(InvoiceStatus::Canceled); // true
'overdue_threshold_days' => 0, // 0 = immediately overdue after due_at
'overdue_threshold_days' => 3, // 3 days grace period
$invoice->isDraft(); // status === Draft
$invoice->isUnpaid(); // status === Unpaid
$invoice->isPaid(); // status === Paid
$invoice->isCanceled(); // status === Canceled
$invoice->isRefunded(); // status === Refunded
$invoice->isOverdue(); // status === Overdue OR (Unpaid + past due_at)
$invoice->totalPaid(); // sum of successful payments
$invoice->remainingBalance(); // total - totalPaid (min 0)
$invoice->isFullyPaid(); // true if remainingBalance <= 0
$invoice->hasLines(); // true if invoice has line items
$invoice->lineCount(); // number of line items
$invoice->lines; // HasMany relationship
$invoice->payments; // HasMany relationship
$invoice->billable; // MorphTo relationship (nullable)
$invoice->user; // BelongsTo User (nullable)
Invoice::forTenant('tenant-1')->get(); // filter by tenant
Invoice::forUser(1)->get(); // filter by user
Invoice::status(InvoiceStatus::Paid)->get(); // filter by status
$processor = app(PaymentProcessor::class);
$payment = $processor->recordPayment(
invoice: $invoice,
gateway: 'manual',
amount: 500.00,
transactionId: 'TXN-001',
userId: auth()->id(), // optional
);
// Amount validation: must be > 0 and ≤ remainingBalance()
// Throws InvalidPaymentAmountException on violation
$processor->markAsSuccess($payment);
// Fires PaymentSucceeded event
// Auto-marks invoice as paid if fully paid
$processor->markAsFailed($payment);
// Fires PaymentFailed event
use Salehye\Invoicing\Services\GatewayManager;
app(GatewayManager::class)->register('paypal', \App\Gateways\PayPalGateway::class);
use Salehye\Invoicing\Contracts\PaymentGateway;
use Salehye\Invoicing\Contracts\WebhookEvent;
use Salehye\Invoicing\Models\Invoice;
class PayPalGateway implements PaymentGateway
{
public function createCheckout(Invoice $invoice, string $returnUrl, string $cancelUrl): array
{
return ['checkout_url' => 'https://paypal.com/pay/...'];
}
public function handleWebhook(array $payload): ?WebhookEvent
{
return null;
}
public function getPaymentStatus(string $transactionId): string
{
return 'success';
}
public function refund(Invoice $invoice, ?float $amount = null): bool
{
return true;
}
}
class SendInvoicePaidNotification
{
public function handle(InvoicePaid $event): void
{
$invoice = $event->invoice; // readonly — cannot be modified
Mail::to($invoice->billable)->send(new InvoicePaidMail($invoice));
}
}
// Just use it directly — no manual registration ller::class, 'download'])
->middleware('invoice.paid:invoice');
// The parameter name is configurable: 'invoice.paid:invoice_id'
class Customer extends Model
{
use HasInvoices;
}
// Available methods
$customer->invoices(); // MorphMany — all invoices
$customer->draftInvoices(); // MorphMany — status = Draft
$customer->unpaidInvoices(); // MorphMany — status = Unpaid
$customer->paidInvoices(); // MorphMany — status = Paid
$customer->canceledInvoices(); // MorphMany — status = Canceled
$customer->overdueInvoices(); // MorphMany — Overdue OR unpaid + past due_at
$customer->refundedinvoices(); // MorphMany — status = Refunded
$customer->totalInvoiceBalance(); // float — sum of unpaid totals
$customer->totalPaidAmount(); // float — sum of paid totals
// Invoice with user
$invoice = Invoicing::create([
'billable' => $customer,
'title' => 'Order Invoice',
'user_id' => auth()->id(),
'items' => [...],
]);
$invoice->user; // BelongsTo → configured User model
// Payment with user
$payment = $processor->recordPayment($invoice, 'stripe', 100, userId: auth()->id());
$payment->user; // BelongsTo → configured User model
// Bank transfer inherits user_id from invoice
$payment = $processor->initiateBankTransfer($invoice);
// payment.user_id = invoice.user_id
// Override with explicit user
$payment = $processor->initiateBankTransfer($invoice, null, null, $otherUserId);
use Salehye\Invoicing\Contracts\TaxCalculator;
class SaudiVatCalculator implements TaxCalculator
{
public function calculate(float $subtotal, ?array $metadata = null): float
{
return round($subtotal * 0.15, 2);
}
}
// Register in a service provider
app()->singleton(TaxCalculator::class, SaudiVatCalculator::class);
use Salehye\Invoicing\Contracts\DiscountCalculator;
class CouponDiscountCalculator implements DiscountCalculator
{
public function calculate(float $subtotal, ?array $metadata = null): float
{
$coupon = $metadata['coupon'] ?? null;
return $coupon ? $coupon->applyTo($subtotal) : 0;
}
}
app()->singleton(DiscountCalculator::class, CouponDiscountCalculator::class);