yousefkadah/laravel-pelecard 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

yousefkadah/laravel-pelecard

Composer 安装命令:

composer require yousefkadah/laravel-pelecard

包简介

Laravel package for Pelecard payment gateway integration with Cashier-compatible subscription billing and multi-tenancy support

README 文档

README

Latest Version on Packagist Total Downloads

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 Billable trait 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 (PHP 8.3+ recommended for Laravel 13)
  • Laravel 10.x, 11.x, 12.x, or 13.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'

Billable Model

By default the billable entity — the model that owns subscriptions, transactions and the saved card token — is your App\Models\User. To bill a different model (e.g. a Tenant or Team in a SaaS app), set it in config/pelecard.php (or the PELECARD_MODEL env var):

'model' => env('PELECARD_MODEL', App\Models\Tenant::class),

The model's table and foreign key drive both the migration and the relationships, so a Tenant model (table tenants) automatically uses a tenant_id foreign key on the subscriptions and pelecard_transactions tables — no migration editing required. Just add the Billable trait to that model. (This mirrors Laravel Cashier's configurable customer model.)

Multi-Tenancy Configuration

For applications that need separate Pelecard credentials per tenant, enable multi-tenancy in config/pelecard.php:

'multi_tenant' => true,

Usage

Basic Setup

Add the Billable trait to your billable model (your User, or whatever pelecard.model points at):

use Yousefkadah\Pelecard\Billable;

class User extends Authenticatable
{
    use Billable;
}
// Or a tenant / team, when pelecard.model is set to it
class Tenant extends Model
{
    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 has no dedicated capture service — capturing a held (J5) authorization is done by charging the saved token with ActionType J4:

// Pass the token saved from the authorization response
Pelecard::capture($token, 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 page
  • bottom_text - Text displayed at the bottom
  • logo_url - Your company logo URL
  • hide_pelecard_logo - Hide Pelecard branding (boolean)
  • show_confirmation - Show confirmation checkbox (boolean)
  • min_payments - Minimum number of installments
  • max_payments - Maximum number of installments
  • param_x - Custom parameter to track the transaction

Subscriptions

The subscription API follows current Laravel Cashier conventions: subscriptions have a type (e.g. 'default') and one or more prices.

Create a Subscription

// Single price
$user->newSubscription('default', 'price_monthly')
    ->trialDays(14)
    ->create($paymentMethod);

// Multiple prices (stored in subscription_items)
$user->newSubscription('default', ['price_seat', 'price_addon'])
    ->quantity(3, 'price_seat')
    ->create($paymentMethod);

Check Subscription Status

if ($user->subscribed('default')) {
    // User has a valid subscription (active, on trial, or on grace period)
}

// Subscribed to a specific price or product
$user->subscribed('default', 'price_monthly');
$user->subscribedToPrice('price_monthly', 'default');
$user->subscribedToProduct('prod_premium', 'default');

if ($user->onTrial('default')) {
    // User is on trial
}

// Payment state
$user->hasIncompletePayment('default');

$subscription = $user->subscription('default');
$subscription->active();
$subscription->canceled();
$subscription->onGracePeriod();
$subscription->ended();
$subscription->pastDue();

Cancel a Subscription

// Cancel at end of billing period (enters grace period)
$user->subscription('default')->cancel();

// Cancel immediately
$user->subscription('default')->cancelNow();

// Cancel at a specific time
$user->subscription('default')->cancelAt(now()->addDays(10));

Resume a Canceled Subscription

$user->subscription('default')->resume();

Swap Prices

// Swap to a single price
$user->subscription('default')->swap('price_yearly');

// Swap to multiple prices
$user->subscription('default')->swap(['price_yearly', 'price_addon']);

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 successful
  • PaymentFailed - When a payment fails
  • SubscriptionCreated - When a subscription is created
  • SubscriptionCancelled - When a subscription is cancelled
  • SubscriptionUpdated - 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.

yousefkadah/laravel-pelecard 适用场景与选型建议

yousefkadah/laravel-pelecard 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 1, 最近一次更新时间为 2025 年 12 月 26 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「payment」 「subscription」 「gateway」 「laravel」 「billing」 「multi-tenant」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 yousefkadah/laravel-pelecard 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 yousefkadah/laravel-pelecard 我们能提供哪些服务?
定制开发 / 二次开发

基于 yousefkadah/laravel-pelecard 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 19
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-12-26