PHP code example of ideacrafters / eloquent-payable
1. Go to this page and download the library: Download ideacrafters/eloquent-payable 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/ */
ideacrafters / eloquent-payable example snippets
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Ideacrafters\EloquentPayable\Traits\Payable;
use Ideacrafters\EloquentPayable\Contracts\Payable as PayableContract;
use Ideacrafters\EloquentPayable\Contracts\Payer;
class Invoice extends Model implements PayableContract
{
use Payable;
protected $fillable = ['total_amount', 'client_id', 'title', 'description', 'currency', 'status'];
public function getPayableAmount(?Payer $payer = null): float
{
return $this->total_amount;
}
public function isPayableBy(Payer $payer): bool
{
return $this->client_id === $payer->getKey();
}
public function getPayableTitle(): string
{
return $this->title ?: "Invoice #{$this->id}";
}
public function getPayableDescription(): ?string
{
return $this->description;
}
public function getPayableCurrency(): string
{
return $this->currency ?: 'USD';
}
public function getPayableMetadata(): array
{
return [
'invoice_id' => $this->id,
'client_id' => $this->client_id,
'status' => $this->status,
];
}
public function
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Ideacrafters\EloquentPayable\Traits\HasPayments;
use Ideacrafters\EloquentPayable\Contracts\Payer;
class User extends Authenticatable implements Payer
{
use HasPayments;
public function getKey()
{
return $this->getKey();
}
public function getMorphClass()
{
return static::class;
}
public function getEmail(): ?string
{
return $this->email;
}
public function getName(): ?string
{
return $this->name;
}
public function canMakePayments(): bool
{
return $this->email_verified_at !== null;
}
public function getPreferredCurrency(): ?string
{
return $this->preferred_currency ?? 'USD';
}
public function getBillingAddress(): ?array
{
return $this->billing_address;
}
public function getShippingAddress(): ?array
{
return $this->shipping_address;
}
public function getTaxId(): ?string
{
return $this->tax_id;
}
public function getPhoneNumber(): ?string
{
return $this->phone;
}
public function getLocale(): ?string
{
return $this->locale ?? 'en';
}
public function getTimezone(): ?string
{
return $this->timezone ?? 'UTC';
}
public function getMetadata(): array
{
return [
'user_id' => $this->id,
'name' => $this->name,
'email' => $this->email,
];
}
}
// Process a payment
$invoice->pay($client, $invoice->total_amount);
// Process with Stripe
$invoice->pay($client, $invoice->total_amount, [
'processor' => 'stripe',
'payment_method_id' => 'pm_card_visa'
]);
// Create offline payment
$invoice->payOffline($client, $invoice->total_amount, [
'type' => 'bank_transfer',
'reference' => 'INV-2024-001'
]);
// Mark offline payment as paid
$payment = $invoice->payments()->pending()->first();
$payment->markAsPaid();
// Refund a payment
$payment->refund(50.00); // Partial refund
$payment->refund(); // Full refund
// Create a redirect payment
$redirect = $invoice->payRedirect($client, $invoice->total_amount, [
'processor' => 'stripe',
'success_url' => 'https://yourapp.com/success',
'cancel_url' => 'https://yourapp.com/cancel',
'failure_url' => 'https://yourapp.com/failed'
]);
// Redirect user to payment page
return redirect($redirect->getRedirectUrl());
// Or use the Facade
$redirect = Payable::createRedirect($invoice, $client, $invoice->total_amount, [
'processor' => 'stripe',
'success_url' => 'https://yourapp.com/success'
]);
// Process immediate payment
$invoice->pay($client, 100.00, [
'processor' => 'stripe',
'payment_method_id' => 'pm_card_visa'
]);
// Create payment intent for later confirmation
$invoice->pay($client, 100.00, [
'processor' => 'stripe'
]);
$invoice->payOffline($client, 100.00, [
'type' => 'bank_transfer',
'reference' => 'TXN-123456',
'notes' => 'Payment via bank transfer'
]);
// Later, mark as paid
$payment->markAsPaid();
$freeItem->pay($user, 0.00, ['processor' => 'none']);
// Automatically marked as completed
class Product extends Model implements PayableContract
{
use Payable;
public function getPayableAmount($payer = null): float
{
// Dynamic pricing based on user
if ($payer && $payer->is_premium) {
return $this->price * 0.9; // 10% discount
}
return $this->price;
}
}
// Usage
$product->pay($customer, $product->price * $quantity);
class ServiceInvoice extends Model implements PayableContract
{
use Payable;
public function getPayableAmount($payer = null): float
{
return $this->calculateTotal();
}
public function isPayableBy($payer): bool
{
return $this->client_id === $payer->id && $this->status === 'pending';
}
}
class Campaign extends Model implements PayableContract
{
use Payable;
public function getPayableAmount($payer = null): float
{
return $payer ? $payer->donation_amount : 0;
}
}
// Usage
$campaign->pay($donor, 100.00);
class Subscription extends Model implements PayableContract
{
use Payable;
public function getPayableAmount($payer = null): float
{
return $this->monthly_fee;
}
}
$invoice->payments; // All payments for this invoice
$invoice->completedPayments; // Only completed payments
$invoice->pendingPayments; // Only pending payments
$invoice->failedPayments; // Only failed payments
$user->payments; // All payments made by user
$user->completedPayments; // Only completed payments
$user->pendingPayments; // Only pending payments
$user->paymentsToday(); // Today's payments
$user->paymentsThisMonth(); // This month's payments
$user->paymentFor($invoice); // Specific payment for an item
$user->hasPaidFor($invoice); // Check if user paid for item
$user->getTotalPaid(); // Total amount paid
use Ideacrafters\EloquentPayable\Events\PaymentCreated;
use Ideacrafters\EloquentPayable\Events\PaymentCompleted;
use Ideacrafters\EloquentPayable\Events\PaymentFailed;
use Ideacrafters\EloquentPayable\Events\PaymentRefunded;
// Listen to events
Event::listen(PaymentCompleted::class, function ($event) {
// Send confirmation email
Mail::to($event->payment->payer)->send(new PaymentConfirmation($event->payment));
});
// For offline payments, check the isOffline flag
Event::listen(PaymentCreated::class, function ($event) {
if ($event->isOffline) {
// Handle offline payment creation
}
});
// In your Stripe dashboard, set webhook URL to:
// https://yourdomain.com/payable/webhooks/stripe
// Handle other processors
Route::post('/payable/webhooks/paypal', [WebhookController::class, 'handle']);
namespace App\Processors;
use Ideacrafters\EloquentPayable\Processors\BaseProcessor;
use Ideacrafters\EloquentPayable\Models\Payment;
class PayPalProcessor extends BaseProcessor
{
public function getName(): string
{
return 'paypal';
}
public function process($payable, $payer, float $amount, array $options = []): Payment
{
// Your PayPal integration logic
$payment = $this->createPayment($payable, $payer, $amount, $options);
// Process with PayPal API
$paypalPayment = $this->createPayPalPayment($amount, $options);
$payment->update([
'reference' => $paypalPayment->id,
'status' => 'processing'
]);
return $payment;
}
public function refund(Payment $payment, ?float $amount = null): Payment
{
// Your PayPal refund logic
return $payment;
}
public function handleWebhook(array $payload)
{
// Handle PayPal webhooks
}
}
class Invoice extends Model implements PayableContract
{
use Payable;
public function getPayableAmount($payer = null): float
{
$baseAmount = $this->subtotal;
// Apply discounts
if ($payer && $payer->hasDiscount()) {
$baseAmount *= 0.9;
}
// Add taxes
$baseAmount += $this->calculateTax($baseAmount);
return $baseAmount;
}
public function isPayableBy($payer): bool
{
// Only allow payment by the invoice client
if ($this->client_id !== $payer->id) {
return false;
}
// Check if invoice is in payable status
if (!in_array($this->status, ['pending', 'overdue'])) {
return false;
}
// Check if not already fully paid
$totalPaid = $this->completedPayments()->sum('amount');
return $totalPaid < $this->total_amount;
}
}
// Get all completed payments
Payment::completed()->get();
// Get pending offline payments
Payment::pending()->offline()->get();
// Get payments from today
Payment::today()->get();
// Get payments from this month
Payment::thisMonth()->get();
// Get payments for specific payable
$invoice->payments()->completed()->sum('amount');
use Ideacrafters\EloquentPayable\Tests\TestCase;
class PaymentTest extends TestCase
{
/** @test */
public function can_process_payment()
{
$invoice = Invoice::factory()->create(['amount' => 100]);
$user = User::factory()->create();
$payment = $invoice->pay($user, 100);
$this->assertEquals('completed', $payment->status);
$this->assertEquals(100, $payment->amount);
}
}