yousefkadah / laravel-pelecard
Laravel package for Pelecard payment gateway integration with Cashier-compatible subscription billing and multi-tenancy support
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/yousefkadah/laravel-pelecard
Requires
- php: ^8.1|^8.2|^8.3
- guzzlehttp/guzzle: ^7.5
- illuminate/contracts: ^10.0|^11.0|^12.0
- illuminate/database: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- larastan/larastan: ^2.9
- laravel/pint: ^1.13
- orchestra/testbench: ^8.0|^9.0
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0|^11.0
- rector/rector: ^1.0
README
A comprehensive Laravel package for integrating with the Pelecard payment gateway. Built with Laravel Cashier-level code quality, featuring subscription billing, multi-tenancy support, and a familiar Billable trait interface.
Features
- 🔐 Multi-Tenancy Support - Multiple Pelecard accounts in one application
- 💳 Cashier-Compatible - Familiar
Billabletrait interface - 📦 Subscription Management - Create, cancel, resume, and swap subscriptions
- 🔄 Recurring Payments - Tokenization and automated billing
- 💰 One-Time Payments - Authorize, charge, refund, and void transactions
- 🖼️ iFrame Integration - Hosted payment pages with full customization
- 🔒 3D Secure - Enhanced security authentication
- 📱 Google Pay - Digital wallet support
- 🎯 Type-Safe DTOs - Request objects with validation and IDE autocomplete
- 🪝 Webhook Support - Automated payment notifications
- 📊 Transaction Logging - Complete payment history
- 🎯 Events - Listen to payment lifecycle events
- 🔒 Secure - Encrypted credential storage
Requirements
- PHP 8.1 or higher
- Laravel 10.x, 11.x, or 12.x
- Pelecard merchant account
Installation
Install the package via Composer:
composer require yousefkadah/laravel-pelecard
Publish the configuration file:
php artisan vendor:publish --tag=pelecard-config
Run the migrations:
php artisan migrate
Configuration
Add your Pelecard credentials to your .env file:
PELECARD_TERMINAL=your_terminal_number PELECARD_USER=your_api_user PELECARD_PASSWORD=your_api_password PELECARD_ENV=sandbox # or 'production'
Multi-Tenancy Configuration
For multi-tenant applications, enable multi-tenancy in config/pelecard.php:
'multi_tenant' => true,
Usage
Basic Setup
Add the Billable trait to your User model:
use Yousefkadah\Pelecard\Billable; class User extends Authenticatable { use Billable; }
One-Time Payments
Security Note: Always use tokens for payments. Only collect card details for the initial tokenization.
Charge a Customer (Using Token)
// Recommended: Use saved token $user->charge(10000, 'Product purchase', [ 'token' => $user->pelecard_token, ]);
First-Time Payment (Tokenize Card)
// Only for first payment: tokenize the card $response = Pelecard::convertToToken([ 'card_number' => '4580000000000000', 'expiry_month' => '12', 'expiry_year' => '2025', ]); $token = $response->get('Token'); $user->update(['pelecard_token' => $token]); // Then charge using the token $user->charge(10000, 'Product purchase', [ 'token' => $token, ]);
Automatic Card Saving (Recommended)
The package automatically extracts tokens from payment responses (J2/J4/J5):
// Option 1: Charge and save card in one step $response = $user->chargeAndSaveCard(10000, 'Product purchase', [ 'card_number' => '4580000000000000', 'expiry_month' => '12', 'expiry_year' => '2025', 'cvv' => '123', ]); // Token is automatically extracted and saved! // Future payments can now use: $user->charge(amount, desc) // Option 2: Save card from any payment response $response = Pelecard::charge([ 'amount' => 10000, 'currency' => 'ILS', 'card_number' => '4580000000000000', 'expiry_month' => '12', 'expiry_year' => '2025', 'cvv' => '123', ]); if ($response->isSuccessful()) { // Automatically extract and save token $user->updateDefaultPaymentMethodFromResponse($response); } // Option 3: Manual token extraction use Yousefkadah\Pelecard\Helpers\TokenExtractor; $token = TokenExtractor::extractToken($response); $cardDetails = TokenExtractor::extractCardDetails($response); if ($token) { $user->updateDefaultPaymentMethod($token, $cardDetails); }
Authorize (Hold Funds)
// Use token for authorization $response = Pelecard::authorize([ 'amount' => 5000, 'currency' => 'ILS', 'token' => $user->pelecard_token, ]); $transactionId = $response->getTransactionId();
Capture Authorization
Pelecard::capture($transactionId, 5000);
Refund a Transaction
$user->refund($transactionId, 5000);
Using DTOs (Type-Safe Requests)
The package provides Data Transfer Objects for type-safe API requests with IDE autocomplete:
use Yousefkadah\Pelecard\DTO\ChargeRequestDTO; use Yousefkadah\Pelecard\DTO\AuthorizeRequestDTO; ### Custom Parameters (ParamX & ParamZ) Pelecard supports custom parameters that are returned in callbacks and webhooks for tracking: #### API Calls (ParamX & ParamZ) Both ParamX and ParamZ are supported in direct API calls: ```php // Using ParamX and ParamZ for order tracking $response = Pelecard::charge([ 'amount' => 10000, 'currency' => 'ILS', 'token' => $user->pelecard_token, 'param_x' => 'order_12345', // Order ID 'param_z' => json_encode([ // Additional metadata 'customer_id' => $user->id, 'source' => 'mobile_app', ]), ]); // In webhook callback, retrieve the parameters $paramX = $request->input('ParamX'); // 'order_12345' $paramZ = $request->input('ParamZ'); // JSON data // With DTOs $charge = new ChargeRequestDTO( amount: 10000, currency: 'ILS', token: $user->pelecard_token, ); $charge->paramX = 'order_12345'; $charge->paramZ = json_encode(['user_id' => $user->id]); $response = Pelecard::charge($charge->toArray());
iFrame (ParamX Only)
Note: iFrame only supports ParamX, not ParamZ:
{{-- Only ParamX is supported in iframe --}} <x-pelecard::payment-iframe :amount="10000" param-x="order_12345" />
use Yousefkadah\Pelecard\DTO\ThreeDSRequestDTO;
// Charge with token (recommended for security) $chargeRequest = new ChargeRequestDTO( amount: 10000, currency: 'ILS', token: $user->pelecardToken, // Use saved token email: 'customer@example.com', payments: 1 );
$response = Pelecard::charge($chargeRequest->toArray());
// Or charge with card details (for first-time payments) $chargeRequest = new ChargeRequestDTO( amount: 10000, currency: 'ILS', cardNumber: '4580000000000000', expiryMonth: '12', expiryYear: '2025', cvv: '123', email: 'customer@example.com' );
$response = Pelecard::charge($chargeRequest->toArray());
// Authorize with token $authorizeRequest = new AuthorizeRequestDTO( amount: 5000, currency: 'ILS', cardNumber: '4580000000000000', expiryMonth: '12', expiryYear: '2025', cvv: '123' );
$response = Pelecard::authorize($authorizeRequest->toArray());
// 3DS with DTO $threeDSRequest = new ThreeDSRequestDTO( amount: 10000, currency: 'ILS', cardNumber: '4580000000000000', expiryMonth: '12', expiryYear: '2025', email: 'customer@example.com' );
$response = Pelecard::initiate3DS($threeDSRequest->toArray());
### 3D Secure Authentication
3D Secure provides an additional layer of security for online card transactions.
#### Using 3DS with Saved Token
```php
// Use saved token with 3DS authentication
$response = Pelecard::initiate3DS([
'amount' => 10000,
'currency' => 'ILS',
'token' => $user->pelecard_token,
]);
// Redirect user to 3DS authentication page
$redirectUrl = $response->get('RedirectUrl');
return redirect($redirectUrl);
3DS with iFrame (Recommended)
Enable 3DS in the iframe payment page:
<x-pelecard::payment-iframe :amount="10000" currency="ILS" :success-url="route('payment.success')" :error-url="route('payment.error')" :use-3ds="true" {{-- This enables 3D Secure authentication --}} />
Or programmatically:
$iframeHelper = Pelecard::for($user)->iframe(); $url = $iframeHelper->generatePaymentUrl([ 'amount' => 10000, 'currency' => 'ILS', 'success_url' => route('payment.success'), 'use_3ds' => true, // Enable 3DS 'token' => $user->pelecard_token, // Use saved token ]);
Get 3DS Data After Authentication
// After 3DS authentication completes $data = Pelecard::get3DSData($transactionId); // The response contains the token if ($data->isSuccessful()) { $token = $data->get('Token'); if ($token) { $user->updateDefaultPaymentMethodFromResponse($data); } }
Google Pay
$response = Pelecard::debitByGooglePay([ 'amount' => 10000, 'currency' => 'ILS', 'google_pay_token' => $googlePayToken, ]);
Advanced Token Management
Best Practice: Always tokenize cards and use tokens for recurring payments to comply with PCI-DSS.
Convert Card to Token
// First time: convert card to token $response = Pelecard::convertToToken([ 'card_number' => '4580000000000000', 'expiry_month' => '12', 'expiry_year' => '2025', ]); $token = $response->get('Token'); // Save token to user $user->update(['pelecard_token' => $token]);
Charge Using Token
// Subsequent payments: use token (no card details needed) $response = Pelecard::charge([ 'amount' => 10000, 'currency' => 'ILS', 'token' => $user->pelecard_token, ]);
Retrieve Token Details
$tokenDetails = Pelecard::retrieveToken($user->pelecard_token);
Update Token
// Update expiry date when card is renewed Pelecard::updateToken($user->pelecard_token, [ 'expiry_month' => '01', 'expiry_year' => '2026', ]);
Transaction Retrieval
// Get complete transaction data $transactions = Pelecard::getCompleteTransData([ 'from_date' => '2025-01-01', 'to_date' => '2025-01-31', ]); // Get specific transaction $transaction = Pelecard::getTransaction($uniqueId);
Invoice Creation
The package provides a flexible invoice builder with customizable templates.
Creating an Invoice
use Yousefkadah\Pelecard\Helpers\InvoiceBuilder; $invoice = (new InvoiceBuilder()) ->number('INV-2025-001') ->date(now()) ->dueDate(now()->addDays(30)) ->vendor([ 'name' => 'Your Company', 'address' => '123 Main St, City', 'phone' => '+972-50-1234567', 'email' => 'billing@company.com', ]) ->customer([ 'name' => $user->name, 'email' => $user->email, 'address' => $user->address, ]) ->addItem('Premium Subscription', 1, 10000) ->addItem('Setup Fee', 1, 5000) ->taxRate(17) // 17% VAT ->notes('Thank you for your business!') ->terms('Payment due within 30 days') ->currency('ILS') ->build(); // Render as HTML $html = $invoice->render(); // Or use the builder directly $html = (new InvoiceBuilder()) ->number('INV-001') ->customer(['name' => 'John Doe']) ->addItem('Service', 1, 10000) ->render();
Customizing Invoice Template
Publish the invoice templates:
php artisan vendor:publish --tag=pelecard-invoices
This creates resources/views/vendor/pelecard/invoices/default.blade.php which you can customize:
{{-- resources/views/vendor/pelecard/invoices/default.blade.php --}} <!DOCTYPE html> <html> <head> <title>Invoice #{{ $invoice->number() }}</title> <style> /* Your custom styles */ .invoice-header { background: #your-brand-color; } </style> </head> <body> <div class="invoice-container"> <!-- Add your logo --> <img src="{{ asset('images/logo.png') }}" alt="Logo"> <!-- Customize layout --> <h1>Invoice #{{ $invoice->number() }}</h1> @foreach($invoice->items() as $item) <div>{{ $item['description'] }}</div> @endforeach <div>Total: {{ $invoice->formatAmount($invoice->total()) }}</div> </div> </body> </html>
Using Custom Template
$html = (new InvoiceBuilder()) ->template('invoices.custom') // Use your custom template ->number('INV-001') ->build() ->render();
Error Messages
// Get error message in Hebrew $errorMessage = Pelecard::getErrorMessageHe('001'); // Get error message in English $errorMessage = Pelecard::getErrorMessageEn('001'); // Auto-detect language from config $errorMessage = Pelecard::getErrorMessage('001');
Invoice Creation
// Create ICount invoice Pelecard::createICountInvoice([ 'customer_name' => 'John Doe', 'amount' => 10000, 'items' => [...], ]);
iFrame Payment Integration
Pelecard's iframe integration allows customers to complete payments directly on your website without being redirected to an external payment page.
Using the Blade Component
<x-pelecard::payment-iframe :amount="10000" currency="ILS" :success-url="route('payment.success')" :error-url="route('payment.error')" :cancel-url="route('payment.cancel')" language="he" top-text="Complete Your Payment" bottom-text="Secure payment powered by Pelecard" width="100%" height="600" />
Using the Helper Directly
$client = Pelecard::for($user); $iframeHelper = $client->iframe(); // Generate iframe URL $url = $iframeHelper->generatePaymentUrl([ 'amount' => 10000, 'currency' => 'ILS', 'success_url' => route('payment.success'), 'error_url' => route('payment.error'), 'cancel_url' => route('payment.cancel'), 'language' => 'he', 'param_x' => 'order_123', ]); // Generate iframe HTML $iframeHtml = $iframeHelper->generateIframe([ 'amount' => 10000, 'currency' => 'ILS', 'success_url' => route('payment.success'), ], [ 'width' => '100%', 'height' => '600', ]); // Or generate a payment form (redirect method) $formHtml = $iframeHelper->generatePaymentForm([ 'amount' => 10000, 'currency' => 'ILS', ]);
Customization Options
top_text- Text displayed at the top of the payment pagebottom_text- Text displayed at the bottomlogo_url- Your company logo URLhide_pelecard_logo- Hide Pelecard branding (boolean)show_confirmation- Show confirmation checkbox (boolean)min_payments- Minimum number of installmentsmax_payments- Maximum number of installmentsparam_x- Custom parameter to track the transaction
Subscriptions
Create a Subscription
$user->newSubscription('default', 'plan_123') ->trialDays(14) ->create($paymentMethod);
Check Subscription Status
if ($user->subscribed('default')) { // User has an active subscription } if ($user->onTrial('default')) { // User is on trial }
Cancel a Subscription
// Cancel at end of billing period $user->subscription('default')->cancel(); // Cancel immediately $user->subscription('default')->cancelNow();
Resume a Cancelled Subscription
$user->subscription('default')->resume();
Swap Plans
$user->subscription('default')->swap('plan_456');
Update Quantity
$subscription = $user->subscription('default'); $subscription->incrementQuantity(); $subscription->decrementQuantity(); $subscription->updateQuantity(5);
Multi-Tenancy
Per-Team Credentials (SaaS Applications)
// Team model use Yousefkadah\Pelecard\Concerns\ManagesPelecardCredentials; class Team extends Model { use ManagesPelecardCredentials; } // Setup team credentials $team->createPelecardCredentials( terminal: '1234567', user: 'api_user', password: 'api_password' ); // User model class User extends Model { use Billable; public function pelecardCredentials() { return $this->team->pelecardCredentials; } } // Usage - automatically uses team's credentials $user->charge(10000, 'Payment');
Direct Client Usage
// Create client for specific tenant $client = PelecardClient::for($user); $client = PelecardClient::for($team); // Use client $response = $client->charge([ 'amount' => 10000, 'currency' => 'ILS', 'token' => 'payment_token', ]);
Webhooks
Display webhook URL:
php artisan pelecard:webhook
Configure the webhook URL in your Pelecard dashboard to receive payment notifications.
Listen to Webhook Events
use Yousefkadah\Pelecard\Events\PaymentSucceeded; use Yousefkadah\Pelecard\Events\PaymentFailed; // In EventServiceProvider protected $listen = [ PaymentSucceeded::class => [ SendPaymentConfirmation::class, ], PaymentFailed::class => [ NotifyPaymentFailure::class, ], ];
Payment Methods
Update Default Payment Method
$user->updateDefaultPaymentMethod($token, [ 'type' => 'card', 'last_four' => '4242', ]);
Check for Payment Method
if ($user->hasDefaultPaymentMethod()) { // User has a payment method on file }
Transaction History
// Get all transactions for a user $transactions = $user->pelecardTransactions; // Get successful transactions $successful = $user->pelecardTransactions()->successful()->get(); // Get transactions of specific type $charges = $user->pelecardTransactions()->ofType('charge')->get();
Artisan Commands
Display Webhook URL
php artisan pelecard:webhook
Sync Subscriptions
# Sync all subscriptions php artisan pelecard:sync-subscriptions # Sync for specific user php artisan pelecard:sync-subscriptions --user=1
Events
The package dispatches the following events:
PaymentSucceeded- When a payment is successfulPaymentFailed- When a payment failsSubscriptionCreated- When a subscription is createdSubscriptionCancelled- When a subscription is cancelledSubscriptionUpdated- When a subscription is updated
Code Quality Tools
This package uses industry-standard code quality tools to maintain high code standards:
Laravel Pint (Code Formatting)
# Format code automatically composer format # Check formatting without making changes composer format-check
Rector (Automated Refactoring)
# Apply automated refactoring composer refactor # Preview changes without applying composer refactor-dry
PHPStan (Static Analysis)
# Run static analysis
composer analyse
Run All Quality Checks
# Run formatting, refactoring check, analysis, and tests
composer quality
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Security
If you discover any security-related issues, please email yousef@example.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.