Library / SDK
shetabit/payment avatar
shetabit/payment

shetabit/payment: one Laravel payment package across dozens of regional gateways

simple laravel payment package , supports multiple drivers

957 stars153 forksPHPMIT

At a glance

What is it?
shetabit/payment is a Laravel package that puts a single invoice and driver interface in front of a long list of payment gateways, most of them Iranian, with Stripe, Xendit and a local test driver also included. It suits Laravel shops that need several regional gateways behind one API, and it requires PHP 8.4 and Laravel 12 to install.
Who is it for?
Adopt shetabit/payment if your Laravel application sells to customers who pay through regional gateways and you want one invoice API and one configuration file rather than a separate integration per provider.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 25 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A gateway-agnostic invoice on top of Laravel

The package is described as a Laravel Package for Payment Gateway Integration, and it states its requirements plainly: PHP 8.4 or newer and support for Laravel 12 or above. The primary language is PHP and the licence is MIT.

The idea is a single interface in front of a long tail of providers. Your application creates an Invoice, hands it to the package, and the package talks to whichever gateway is configured. The service provider and the Payment alias are registered by Laravel's package discovery, so the README is explicit that there is nothing to add to config/app.php or to bootstrap/providers.php.

The scope is not only Laravel. For plain PHP integration the README points at a sibling package, shetabit/multipay, and the Invoice class you use in the examples comes from that namespace, Shetabit\Multipay\Invoice. The naming is slightly confusing for a newcomer, since a Laravel package depends on a class from another package, but it explains why the same invoice model can be shared by a Laravel application and a non-Laravel one.

Documentation is available in Persian, English and Chinese, with the English and Chinese versions kept as separate README files in the repository root.

The driver list is the real product

What distinguishes this package is the breadth of the driver list, and reading it tells you who the package is for. The great majority of the gateways are Iranian: Zarinpal, Parsian, Pasargad, Sep, Saman, Saderat through Sepehr, Mellat through Behpardakht, Mellat through Sadad, Zibal, Snapppay, DaraCard, FanavaCard, Payping, PayStar, NextPay, NovinoPay, OmidPay, Panapal, Poolam, RayanPay, Refah, SizPay, Shepa, Sepordeh, Toman, TorobPay, Vandar, Yekpay, GooyaPay, BitPay, Daracard, DigiPay, Jibit, Irandargah, Irankish, Minipay, Payfa, AqaYePardakht, AsanPardakht, ATiPay, Etebarino and AzkiVam, several of which are marked as installment payment providers.

Alongside those sit Stripe and Xendit for international and Indonesian markets, a local driver for testing, and PayPal, which is listed as will be added soon in the next version rather than as available.

The README also maintains a list of gateways that contributors are asked to add by opening pull requests, naming authorize, 2checkout, braintree, skrill, payU, amazon payments, wepay, payoneer and paysimple among them. And the package states that you can create your own custom drivers if the gateway you need is not in the list.

That custom driver route is the part that decides whether this package ages well. A gateway list is a maintenance liability, and a package that lets the community extend it turns that liability into a contribution model.

Installing the package and publishing its files

Installation is a single Composer command:

bash
composer require shetabit/payment

Two publish steps follow, and they are separate because they serve different purposes. The configuration file holds the credentials and the default driver, and the views are the templates you can override if you want your own checkout markup:

bash
php artisan vendor:publish --tag=payment-config
bash
php artisan vendor:publish --tag=payment-views

Publishing the configuration is not optional in practice, since the gateway credentials live there, and publishing the views is optional in the sense that the defaults will render something.

After that the plugin is usable: the service provider and the Payment alias are registered automatically by package discovery, so there is no manual registration step to forget, and no config/app.php edit.

One default driver, but the driver can change at runtime

The configuration file sets a default driver to use for all payments, and the README also notes that you can change the driver at runtime. That combination is what makes the package usable for more than one market: you set the sensible default for your business and override it where a specific order needs a different gateway.

The default is a single key in the config:

php
// Eg. if you want to use zarinpal.
'default' => 'zarinpal',

and the credentials for each gateway live in a drivers array keyed by the same name:

php
'drivers' => [
    'zarinpal' => [
        // Fill in the credentials here.
        'apiPurchaseUrl' => 'https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json',
        'apiPaymentUrl' => 'https://www.zarinpal.com/pg/StartPay/',
        'apiVerificationUrl' => 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json',
        'merchantId' => '',
        'callbackUrl' => 'http://yoursite.com/path/to',
        'description' => 'payment in '.config('app.name'),
    ],
    ...
]

Two details in that snippet are worth reading. The callback URL is a plain config value, so the return path from the gateway is something you control and must keep in sync with your routes. And the description uses config('app.name'), which means the description sent to the gateway follows your application name unless you override it.

The driver names are the keys of that array, so a driver added by a third party is configured in exactly the same place, with no separate registry.

The Invoice object carries the payment detail

Your Invoice holds your payment details, and the README says that before doing anything you need to use the Invoice class to create an invoice. The class is imported from the multipay namespace:

php
// At the top of the file.
use Shetabit\Multipay\Invoice;
...

// Create new invoice.
$invoice = new Invoice;

// Set invoice amount.
$invoice->amount(1000);

The detail lines can be written in four different syntaxes, which the README lists explicitly:

php
// Add invoice details: There are 4 syntax available for this.
// 1
$invoice->detail(['detailName' => 'your detail goes here']);
// 2 
$invoice->detail('detailName','your detail goes here');
// 3
$invoice->detail(['name1' => 'detail1','name2' => 'detail2']);
// 4
$invoice->detail('detailName1','your detail1 goes here')

Offering four ways to do the same thing is generous, and it is the kind of generosity that shows a package tuned for real use rather than for an idealised API. The amount is set on the invoice, so the unit is whatever your application decides, and there is no currency handling visible in these examples, which means currency conversion is the application's business.

The README's table of contents also lists the operations that follow: purchase invoice, pay invoice, verify payment, useful methods, create custom drivers and events. The events entry matters for anything that reacts to a completed payment, and the create custom drivers section is where a gateway that the list does not cover gets implemented.

Running the suite inside a container, with no PHP on the host

The repository ships a development image and a Makefile that wraps it, and the stated goal is that no PHP installation is needed on the host. The Dockerfile comment lists the three commands it expects:

bash
docker build --build-arg PHP_VERSION=8.4 --tag payment-dev .
docker run --rm --volume "$PWD":/app payment-dev composer install
docker run --rm --volume "$PWD":/app payment-dev phpunit

The Makefile exposes the same thing as targets, and documents the knobs:

bash
make install
make test
make ci

The PHP version is a build argument and can be changed per invocation, for example make test with PHP_VERSION set to 8.5, and a single Laravel version can be tested with make test-laravel and a LARAVEL value such as 11. Extra Docker flags can be passed through DOCKER_ARGS, which the comment says is handy when the host needs a custom certificate bundle or proxy settings. The container runs as the invoking user id and group id rather than root, and the package is mounted into /app so the image does not have to be rebuilt on every code change.

The image itself is more than PHP. The intl, soap and pdo_mysql extensions are installed, pcov is built from source as the coverage driver because not every network can reach pecl, and Composer 2 is copied in from the composer image.

Where this package is the wrong choice

The constraints are visible in the README and in the repository.

The first is the platform floor. PHP 8.4 and Laravel 12 are the stated requirements, so a project on Laravel 11 cannot use this version, and the maintenance tooling in the repository, phpstan.neon.dist, phpcs.xml.dist, rector.php and phpunit.xml, assumes that modern stack. The second is the driver set itself. A long list of gateways is only useful if the ones you need are in it, and for most of the world that means Stripe or Xendit, with PayPal still marked as coming. The Iranian gateways are the deep part of the coverage, and for a shop outside Iran the package is closer to a single-driver integration than to a multi-gateway abstraction.

Third, the invoice model is a flat set of details. The README does not document a line item model with quantities, tax or currency, so an order with several products and a total in a currency other than the gateway's would need the application to compute and pass a single amount. Fourth, the README's table of contents lists purchase, pay and verify, but nothing about refunds, subscriptions, recurring charges or partial captures, so anything beyond a one-off payment is your own code against the gateway.

Fifth, the credential model is a config file with merchant ids and callback URLs. That is normal for Laravel, but it means the package has no built-in notion of multiple merchant accounts, sandbox and live separation beyond separate config entries.

Against writing the gateway calls yourself

The alternative is to call the gateway's HTTP API directly from your application, which is what many Laravel teams do for one or two providers.

The difference in approach is where the provider knowledge lives. With a hand-written integration, the request shape, the signature scheme, the redirect flow and the verification callback are all in your code, and adding a second provider means writing a second integration. With this package, that knowledge is in a driver, the redirect and verification flow is shared, and the switch between providers is a configuration key or a runtime argument.

The cost of the abstraction is the abstraction itself. Your code now depends on the package's Invoice model and its driver interface, so a payment flow is expressed in the package's vocabulary rather than the gateway's, and when a gateway behaves unusually you are waiting on the package rather than on the API. There is also a shared-fate risk that is real for long-lived applications: the driver list, the credential fields and the callback assumptions are all things the package can change between major versions, and this project has already released v7.0.0 while still documenting PayPal as pending.

There is a middle option worth naming, the shetabit/multipay package the README recommends for plain PHP integration. If you have a Laravel application but a legacy or non-Laravel service that also needs to take payments, using both keeps one invoice model across the two worlds, which is a genuine advantage that a hand-written integration in each codebase would not have.

Editorial conclusion

Adopt shetabit/payment if your Laravel application sells to customers who pay through regional gateways and you want one invoice API and one configuration file rather than a separate integration per provider. Do not adopt it if you are still on Laravel 11 or PHP 8.3, since the README states the package requires PHP 8.4 and supports Laravel 12 and above, and do not assume a gateway is present because the list looks long, since PayPal is listed as will be added soon in the next version. Verify first that a driver exists for the gateway you need and that its credential fields match your merchant account, and note the licence is MIT with v7.0.0 released on 2026-08-12 and the last push on 2026-09-28.

Frequently asked questions

How do I install the shetabit/payment Laravel package?

Run composer require shetabit/payment, then publish the configuration with php artisan vendor:publish --tag=payment-config and, if you want to override the templates, the views with php artisan vendor:publish --tag=payment-views. The service provider and Payment alias are registered by package discovery.

Which gateways does shetabit/payment support?

The driver list covers a large set of Iranian gateways including Zarinpal, Parsian, Pasargad, Sep, Saman, Sepehr, Zibal, Snapppay and installment providers such as AzkiVam, Etebarino and TorobPay, plus Stripe, Xendit and a local driver for testing. PayPal is listed as will be added soon in the next version.

How do I set the default payment gateway?

Set the default key in the published configuration, for example 'default' => 'zarinpal', and fill in the credentials for that gateway in the drivers array under the same name. You can also change the driver at runtime, and you can use several gateways in one project.

Can I add a gateway that is not in the driver list?

Yes. The README states that you can create custom drivers if the gateway is not in the current list, and it links a section on creating custom drivers. It also invites pull requests for gateways that are still on the wanted list.

What PHP and Laravel versions does the package require?

The README states that the package requires PHP 8.4 or newer and supports Laravel 12 or above. The development tooling in the repository includes phpstan.neon.dist, phpcs.xml.dist, rector.php and phpunit.xml for that stack.

How do I run the test suite for shetabit/payment?

The package ships a development container and a Makefile, so you need no PHP on the host. Use make install, make test and make ci, and pass PHP_VERSION=8.5 or LARAVEL=11 to change the matrix, with DOCKER_ARGS for extra Docker flags.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. shetabit/payment on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/shetabit-payment.svg)](https://hysenlabs.com/projects/shetabit-payment)

Was this useful?