Search by

balerka / laravel-payhub

Balerka

Reusable Laravel payment foundation with headless endpoints and embeddable React components.

Package info

github.com/Balerka/laravel-payhub

pkg:composer/balerka/laravel-payhub

Statistics

Installs: 34

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.5.1 2026-09-05 13:08 UTC

This package is auto-updated.

Last update: 2026-09-05 13:09:38 UTC


README

Reusable payment foundation for Laravel applications.

It provides:

  • Laravel models for cards, orders, transactions, and subscriptions.
  • Migrations and configurable table names.
  • Auth-protected JSON endpoints for custom frontends.
  • Embeddable React components for checkout and payment card management.
  • A local test payment endpoint for development.

Install

composer require balerka/laravel-payhub
php artisan vendor:publish --tag=payhub-config
php artisan vendor:publish --tag=payhub-migrations
php artisan migrate

If the host app wants to customize Payhub Eloquent models, publish them and point config/payhub.php to the published classes:

php artisan vendor:publish --tag=payhub-models

This publishes:

app/Models/Card.php
app/Models/Order.php
app/Models/Transaction.php
app/Models/Subscription.php

For local development from this repository:

{
  "repositories": [
    {
      "type": "path",
      "url": "../laravel-payhub"
    }
  ]
}

Then run:

composer require balerka/laravel-payhub:@dev

Frontend Components

Payhub does not register checkout or cards page routes. Publish the React assets and embed the exported components in your own pages:

composer require inertiajs/inertia-laravel
php artisan vendor:publish --tag=payhub-react

The React files publish to:

resources/js/pages/payhub

Example:

import { Checkout, PaymentCards, PayhubRefunds, PayhubSubscriptions } from '@/pages/payhub'

Basic usage:

<Checkout products={[{ name: 'Premium', price: 990, quantity: 1, unit: 'item' }]} currency="RUB" locale="ru" />
<PaymentCards locale="ru" />
<PayhubSubscriptions locale="ru" />
<PayhubRefunds locale="ru" />

Payhub does not manage catalogs. Your application selects products and passes their payment data into Checkout; Payhub calculates the total and builds the receipt:

  • products - required list of products; each product has name, price, and optional quantity, unit, vat, method, and object
  • currency - optional ISO currency code, defaults to PAYHUB_CURRENCY
  • description - optional gateway description; defaults to the joined product names
  • receipt - optional full receipt object with items, email, amounts, currency, description, and any gateway-specific receipt data
  • items - shorthand for receipt.items if you do not need to pass the full receipt object
  • subscription.products - required product list for recurring payments; Payhub independently calculates the recurring amount and receipt

Payhub ships with embedded English and Russian dictionaries inside the published React files, so the component can pick its own translations from locale without touching host project files.

Translations

If the host project wants to reuse the same strings in its own i18n system, publish the standalone dictionaries too:

php artisan vendor:publish --tag=payhub-locales

This creates:

resources/js/locales/en/payhub.json
resources/js/locales/ru/payhub.json

Payhub does not edit host project files. The host app can either:

  • let the components localize themselves from locale
  • import payhub.json directly and pass messages overrides when needed
  • load payhub.json into its own i18n system if it already has one
  • do nothing and use the built-in English fallback messages

Checkout example:

import { Checkout } from '@/pages/payhub'

export default function CheckoutPage() {
  return (
    <Checkout
      currency="RUB"
      products={[
        { name: 'Premium', price: 590, quantity: 1, unit: 'item' },
        { name: 'Boost', price: 200, quantity: 2, unit: 'item' },
      ]}
      locale="ru"
    />
  )
}

Override example:

import { Checkout } from '@/pages/payhub'
import ruPayhub from '@/locales/ru/payhub.json'

<Checkout
  products={[{ name: 'Premium', price: 990 }]}
  locale="ru"
  messages={{
    ...ruPayhub,
    checkout: {
      ...ruPayhub.checkout,
      pay: 'Купить',
    },
  }}
/>

Routes

Routes are registered with the payhub. name prefix and use /payhub as the default URL prefix:

  • GET /payhub/cards/data returns cards as JSON.
  • GET /payhub/checkout/data returns gateway metadata and saved cards as JSON.
  • POST /payhub/checkout/orders idempotently creates a pending order from the required idempotency_key and products, plus optional currency, description, receipt, and subscription metadata. Payhub calculates the amount and stores the generated receipt on the order. When card_id is passed with the cloud_payments gateway, Payhub charges that saved card token through CloudPayments.
  • DELETE /payhub/checkout/orders/{order} cancels a pending order.
  • PUT /payhub/cards/default sets the default card.
  • DELETE /payhub/cards/{card} deletes a card owned by the current user.
  • GET /payhub/subscriptions/data returns subscriptions owned by the current user.
  • POST /payhub/subscriptions/cancel cancels a current user's CloudPayments subscription.
  • POST /payhub/subscriptions/cancel-by-email cancels an active subscription by customer email and saved card last four digits.
  • GET /payhub/refunds/data returns refundable payment transactions owned by the current user.
  • POST /payhub/refunds/refund refunds or voids a current user's CloudPayments payment transaction.
  • POST /payhub/payments/test/pay creates a local test payment only when payhub.gateway=test and payhub.test_mode=true.

For checkout, cards, subscriptions, and refunds UI, publish the React assets and embed Checkout, PaymentCards, PayhubSubscriptions, or PayhubRefunds in any application page. Payhub does not register page routes for these components. For a custom frontend, call the JSON endpoints directly and send Accept: application/json when you want JSON responses from mutation endpoints.

Configuration

config/payhub.php controls route prefix, route middleware, model classes, table names, user model, currency, test mode, and gateway metadata. User payment routes use web and auth middleware by default, the public cancellation route uses web and throttling, and CloudPayments callbacks use signature verification without session or CSRF middleware.

Set checkout currency with:

PAYHUB_CURRENCY=RUB

Select the active gateway with:

PAYHUB_GATEWAY=test

Failed payment attempts are not stored in the transactions table by default. To store them with status=false, set:

PAYHUB_STORE_FAILED_TRANSACTIONS=true

The published checkout component supports the test gateway and CloudPayments widget flow. When the current user has saved cards, the checkout component lists them, selects the default card, and sends the selected card_id for saved-card payment. Users can still choose a new-card payment, which opens the CloudPayments widget.

For CloudPayments:

PAYHUB_GATEWAY=cloud_payments
CP_PUBLIC_ID=pk_...
CP_SECRET=...

Configure CloudPayments callbacks to:

POST /api/cloudpayments/check
POST /api/cloudpayments/pay
POST /api/cloudpayments/fail

The callbacks are protected with the CloudPayments Content-HMAC signature.

To choose the payment table names before the first migration, set:

PAYHUB_CARDS_TABLE=cards
PAYHUB_ORDERS_TABLE=orders
PAYHUB_TRANSACTIONS_TABLE=transactions
PAYHUB_SUBSCRIPTIONS_TABLE=subscriptions

Only PAYHUB_* environment variables are supported.