承接 qbe-digital/payments 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

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

qbe-digital/payments

Composer 安装命令:

composer require qbe-digital/payments

包简介

A unified payments package for Laravel supporting Tabby, Tamara and more.

README 文档

README

A unified payments package for Laravel, supporting Tabby and Tamara with a clean, driver-based architecture.

Features

  • 🔌 Driver-based architecture — Switch payment providers with zero code changes
  • 🪝 Webhook handling — Automatic signature validation and normalized event dispatching
  • 💳 Checkout sessions — Unified API for creating payment sessions
  • ↩️ Refunds — Full and partial refund support
  • 📦 Installments — BNPL support for Tabby & Tamara
  • 📋 Transaction logging — Built-in migration and model for tracking payments
  • 🧩 Billable trait — Add pay() to any Eloquent model

Installation

composer require qbe-digital/payments

Publish the config:

php artisan vendor:publish --tag=payments-config

Publish the migrations:

php artisan vendor:publish --tag=payments-migrations
php artisan migrate

Configuration

Add your credentials to .env:

PAYMENTS_DRIVER=tabby

# Regional defaults (applied to all drivers; override per-driver in config/payments.php)
PAYMENTS_CURRENCY=SAR
PAYMENTS_LOCALE=ar
PAYMENTS_COUNTRY=SA

# Tabby
TABBY_SECRET_KEY=your-secret-key
TABBY_PUBLIC_KEY=your-public-key
TABBY_MERCHANT_CODE=your-merchant-code
TABBY_WEBHOOK_KEY=your-webhook-key
TABBY_SANDBOX=true

# Tamara
TAMARA_API_TOKEN=your-api-token
TAMARA_NOTIFICATION_TOKEN=your-notification-token
TAMARA_SANDBOX=true

Usage

Basic Checkout

use QBE\Payments\Facades\Payments;
use QBE\Payments\Support\CheckoutSession;
use QBE\Payments\Support\CustomerInfo;

$session = new CheckoutSession(
    amount: 500.00,
    currency: 'SAR',
    referenceId: 'order-123',
    description: 'Premium Package',
    successUrl: route('payment.success'),
    failureUrl: route('payment.failure'),
    customer: CustomerInfo::make('Ahmed', 'ahmed@example.com', '+966500000000'),
);

// Use default driver
$result = Payments::createCheckout($session);

// Or specify a driver
$result = Payments::driver('tabby')->createCheckout($session);

if ($result->requiresRedirect()) {
    return redirect($result->redirectUrl);
}

Verify Payment

$result = Payments::verify($transactionId);

if ($result->isSuccessful()) {
    // Payment confirmed
}

Refund

$refund = Payments::refund($transactionId, 100.00, 'Customer requested');

// Pass the original transaction currency for multi-currency correctness:
$refund = Payments::refund($transactionId, 100.00, 'Customer requested', 'AED');

if ($refund->isSuccessful()) {
    // Refund processed
}

Billable Trait

Add the Billable trait to any model:

use QBE\Payments\Traits\Billable;
use QBE\Payments\Support\CustomerInfo;

class Order extends Model
{
    use Billable;

    public function getPaymentAmount(): float
    {
        return $this->total;
    }

    public function getPaymentReference(): string
    {
        return "order-{$this->id}";
    }

    public function getPaymentCustomer(): ?CustomerInfo
    {
        return CustomerInfo::make(
            $this->customer_name,
            $this->customer_email,
            $this->customer_phone,
        );
    }
}

// Then simply:
$result = $order->pay();            // Default driver
$result = $order->pay('tamara');     // Specific driver
$order->verifyPayment($transactionId);
$order->refundPayment($transactionId, 50.00);

Webhooks

Webhook routes are registered automatically:

POST /api/payments/webhook/tabby
POST /api/payments/webhook/tamara

Listen for events in your EventServiceProvider:

use QBE\Payments\Events\PaymentSucceeded;
use QBE\Payments\Events\PaymentFailed;
use QBE\Payments\Events\WebhookReceived;
use QBE\Payments\Events\RefundProcessed;

protected $listen = [
    PaymentSucceeded::class => [
        UpdateOrderStatus::class,
        SendPaymentConfirmation::class,
    ],
    PaymentFailed::class => [
        HandleFailedPayment::class,
    ],
    WebhookReceived::class => [
        LogWebhook::class,
    ],
];

Transaction Records

When transaction persistence is enabled (default), the package keeps a payment_transactions row in sync through the payment lifecycle:

  • $model->pay() (via the Billable trait) records a pending row linked to the payable model.
  • Payment/refund webhooks update the row to paid, failed, or refunded (and stamp paid_at) through built-in event listeners.
use QBE\Payments\Models\PaymentTransaction;

$transactions = $order->payments;            // if you add the morph relation
$paid = PaymentTransaction::paid()->get();   // built-in scopes: paid(), pending()

Opt out or swap the backing model in config/payments.php:

'transactions' => [
    'enabled' => env('PAYMENTS_RECORD_TRANSACTIONS', true),
    'model'   => \App\Models\PaymentTransaction::class,
],

Installments (Tabby & Tamara)

use QBE\Payments\Contracts\SupportsInstallmentsInterface;

$driver = Payments::driver('tabby');

if ($driver instanceof SupportsInstallmentsInterface) {
    $plans = $driver->getInstallmentPlans(1000.00);
    // Returns available installment plans
}

Feature Detection

use QBE\Payments\Enums\PaymentFeature;

if (Payments::driver('tamara')->supports(PaymentFeature::PARTIAL_REFUNDS->value)) {
    // Tamara supports partial refunds
}

Adding a Custom Driver

  1. Extend AbstractDriver:
use QBE\Payments\Drivers\AbstractDriver;

class StripeDriver extends AbstractDriver
{
    public function driverName(): string { return 'stripe'; }
    protected function baseUrl(): string { return 'https://api.stripe.com/v1/'; }
    protected function defaultHeaders(): array { /* ... */ }
    protected function supportedFeatures(): array { /* ... */ }
    public function createCheckout(CheckoutSession $session): PaymentResult { /* ... */ }
    public function verify(string $transactionId): PaymentResult { /* ... */ }
    public function refund(string $transactionId, float $amount, string $reason = ''): RefundResult { /* ... */ }
}
  1. Register in your AppServiceProvider:
use QBE\Payments\PaymentManager;

app(PaymentManager::class)->extend('stripe', function () {
    return new StripeDriver(config('payments.drivers.stripe'));
});

Testing

composer test

License

MIT

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-21

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固