Download the PHP package joynala/multi-pay without Composer

On this page you can find all versions of the php package joynala/multi-pay. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package multi-pay

MultiPay

One body, any gateway. One confirm, any gateway.

MultiPay is a Laravel package that lets you accept payments through 30+ payment gateways with a single, stable API. Your application sends the same normalized payload to every gateway and gets back a hosted payment URL; when the customer returns, one call verifies the payment server-side with the gateway itself — no trusting redirects.


Table of contents


Features

Supported gateways

Key Gateway Region / notes
stripe Stripe Checkout Global
razorpay Razorpay Payment Links India
paystack Paystack Africa
paytabs PayTabs MENA
adyen Adyen Payment Links Global
square Square Payment Links US, global
braintree Braintree (drop-in) Global
flutterwave Flutterwave Africa
hesabe Hesabe Kuwait
tingg Tingg (Cellulant) Africa
mollie Mollie Europe
mercadopago Mercado Pago Latin America
dpo DPO Group Africa
payu PayU (hosted form) India
cashfree Cashfree India
worldpay Worldpay Hosted Payment Pages Global
authorizenet Authorize.Net Accept Hosted US
checkout Checkout.com Hosted Payments Global
telr Telr MENA
moyasar Moyasar Saudi Arabia
iyzico iyzico Checkout Form Turkey
ccavenue CCAvenue India
paytm Paytm India
payhere PayHere Sri Lanka
fawry FawryPay Egypt
payfort Amazon Payment Services (PayFort) MENA
hyperpay HyperPay (COPYandPAY) MENA
ngenius N-Genius (Network International) MENA
twocheckout 2Checkout (Verifone) Global
voguepay VoguePay Nigeria
payfast PayFast South Africa
fygaro Fygaro Caribbean / Latin America
ecocash EcoCash Zimbabwe
innbucks InnBucks Zimbabwe
demo Demo gateway Local testing only — never enable in production
onafriq, palmpay, toppay, stepay Scaffolds Registered but not implemented (no public API docs); they throw a clear exception

Requirements

Installation

If you are installing from a private/self-hosted git repository instead of Packagist, add the repository to your app's composer.json first:

The service provider and the MultiPay facade are auto-discovered.

Setup

1. Publish config & migrations

This publishes config/multipay.php and creates the payment_sessions table.

Tags are also available individually: --tag=multi-pay-config, --tag=multi-pay-migrations.

2. Register your routes

MultiPay deliberately does not own your success / cancel / failure / callback endpoints — only your app knows which order to update and where to send the customer next. Register one common set of routes (it covers all gateways; the {session} UUID in the URL tells the package which gateway and payment it was):

Notes:

3. Exclude the routes from CSRF

Gateways POST to your routes without a CSRF token.

Laravel 11+ — bootstrap/app.php:

Laravel 10 — add 'payment/*' to $except in App\Http\Middleware\VerifyCsrfToken.

4. Store gateway credentials

Credentials live in your database so they can be changed at runtime (e.g. from an admin panel). By default the package reads the gateways table, data JSON column — both configurable in config/multipay.php (data_table, json_column).

Each gateway needs one row: name = the gateway key, and the JSON column holding its credentials. config/multipay.php → gateways maps the package's required key names to your JSON field names, so you can keep whatever JSON shape you already have.

Setting is_active => false disables a gateway — gateway() will refuse to build it.

Skipping the database — pass credentials directly (uses the package's own key names; handy for tests):

Usage

Creating a payment

Use a unique order_id per payment attempt. Several gateways use it as the merchant reference, and verification matches against it.

The payload

Field Required Description
amount yes Major units — 19.99 means $19.99. Minor-unit conversion (cents, paise, fils) is handled per gateway and per currency.
currency yes ISO 4217 code (USD, INR, KWD, ...).
order_id yes Your unique reference for this payment attempt.
customer.name no Customer name.
customer.email no Customer email (some gateways require it — Paystack does).
meta.* no Gateway extras: title, description, phone, address, city, country, locale, ... Unknown keys are ignored by gateways that don't use them.

A missing required field throws InvalidPaymentPayloadException before anything is sent anywhere.

The response

pay() returns an array:

A payment_sessions row is created for every attempt with a UUID session_id — that UUID is what appears in your route URLs.

Verifying a payment — confirm()

A redirect to your success URL proves nothing: anyone can open that URL. Always call confirm() first — it performs the gateway-specific server-side check, updates the session, fires the events, and returns a normalized result object:

confirm() accepts the session UUID (from the route parameter) or a PaymentSession model, plus the current Request (some gateways deliver verification material in it — PayU's signed POST, Hesabe's encrypted payload). It returns a PaymentResponseData object with the same fields as pay()'s array, as properties ($result->success, $result->status, $result->paymentId, $result->message, $result->raw).

confirm() is idempotent: once a session is paid it returns immediately without re-querying the gateway, so calling it from both the browser return and the webhook is safe.

Session statuses

Status Meaning
pending Created / awaiting payment or awaiting verification
paid Verified with the gateway — money moved
failed Gateway reported failure, or verification rejected the response
cancelled Customer cancelled, or MultiPay::cancel() was called
expired The gateway's payment window expired

Events

Verification dispatches:

Helpers — session() and cancel()

Gateway manager UI (includable Blade)

MultiPay ships a drop-in admin screen for managing gateways — list, active/inactive toggle, and a credentials modal per gateway. Include it anywhere inside your own admin layout; it brings its own styles and JavaScript (no build step, no dependencies):

What it does:

⚠️ Protect it. The UI's endpoints edit live payment credentials. Set your admin middleware in config/multipay.php:

Notes:

Listing active gateways (for your checkout page or API)

MultiPay::activeGateways() returns only the gateways that are switched on, with everything needed to render a payment-method picker — in Blade, or as a JSON API response for your mobile apps:

Display logic: use icon when present, otherwise icon_data_uri.

Testing your integration (demo gateway)

The demo gateway needs no credentials and no database row:

Point your checkout at MultiPay::gateway('demo') and you can exercise the entire loop — payload validation, session creation, your routes, confirm(), events — locally in seconds.

⚠️ Never enable demo in production. Anyone who can choose the gateway name would be able to "pay" for free. Set 'demo' => ['is_active' => false] in your published config before going live.

Gateway configuration reference

Keys listed are the package's names; map each to your JSON field in config/multipay.php. "Base URL" rows show sandbox → live.

Gateway Required keys Base URLs (sandbox → live)
stripe secret_key, public_key SDK-managed
razorpay secret_key, public_key SDK-managed
paystack secret_key SDK-managed
paytabs profile_id, secret_key, base_url region-specific, e.g. https://secure-global.paytabs.com
adyen api_key, merchant_account, country_code see Status — live env pending
square square_access_token, square_location, square_environment square_environment: sandbox / production
braintree environment, merchant_id, public_key, private_key environment: sandbox / production
flutterwave secret_key, base_url https://api.flutterwave.com
hesabe merchant_code, access_code, encryption_key, iv_key https://sandbox.hesabe.com → https://api.hesabe.com (via mode)
tingg api_key, client_id, client_secret, auth_base_url, base_url, service_code, country_code, currency_code per Tingg onboarding
mollie api_key, base_url, send_webhook_url https://api.mollie.com
mercadopago access_token, base_url, send_notification_url https://api.mercadopago.com
dpo company_token, base_url, checkout_base_url, service_type https://secure.3gdirectpay.com
payu merchant_key, salt, base_url https://test.payu.in → https://secure.payu.in
cashfree client_id, client_secret, base_url, api_version, environment https://sandbox.cashfree.com → https://api.cashfree.com
worldpay authorization, merchant_entity, narrative_line1, base_url https://try.access.worldpay.com → https://access.worldpay.com
authorizenet api_login_id, transaction_key, environment environment: sandbox / production
checkout secret_key, base_url https://api.sandbox.checkout.com → https://api.checkout.com
telr store_id, auth_key (+ test_mode: '1' test / '0' live) fixed endpoint
moyasar secret_key, base_url https://api.moyasar.com
iyzico api_key, secret_key, base_url https://sandbox-api.iyzipay.com → https://api.iyzipay.com
ccavenue merchant_id, access_code, working_key, base_url https://test.ccavenue.com → https://secure.ccavenue.com
paytm merchant_id, merchant_key, website, base_url https://securegw-stage.paytm.in → https://securegw.paytm.in; website: WEBSTAGING → DEFAULT
payhere merchant_id, merchant_secret, base_url https://sandbox.payhere.lk → https://www.payhere.lk
fawry merchant_code, secure_key, base_url https://atfawry.fawrystaging.com → https://www.atfawry.com
payfort access_code, merchant_identifier, sha_request_phrase, base_url, checkout_base_url sbpaymentservices/sbcheckout → paymentservices/checkout .payfort.com
hyperpay access_token, entity_id, base_url (+ optional brands) https://eu-test.oppwa.com → https://eu-prod.oppwa.com
ngenius api_key, outlet_ref, base_url https://api-gateway.sandbox.ngenius-payments.com → https://api-gateway.ngenius-payments.com
twocheckout merchant_code, secret_key, buy_link_secret_word fixed endpoints
voguepay merchant_id (+ optional developer_code, demo) fixed endpoint
payfast merchant_id, merchant_key, base_url (+ optional passphrase) https://sandbox.payfast.co.za → https://www.payfast.co.za
fygaro button_url, api_key, secret_key button URL from your Fygaro dashboard; set the button's Return URL to https://your-app.com/multipay/fygaro/return and Hook URL to https://your-app.com/multipay/fygaro/hook (JWT features need the Pro plan)
ecocash api_key, mode sandbox → live; requires customer.phone (EcoCash number, e.g. 0771234567) — the customer approves a PIN prompt on their phone while the package's waiting page polls the status
innbucks base_url, api_key, username, password https://staging.innbucks.co.zw → live URL from InnBucks; USD only — the waiting page shows the payment code + QR and polls until paid

How verification works

confirm() never trusts the customer's browser. Depending on the gateway it:

Signature comparisons use hash_equals; verifications match order reference and amount where the gateway returns them.

Hosted checkout pages

Some gateway flows need a browser-side step that is pure gateway plumbing — a drop-in form, a JS widget, or a signed form POST. Those pages ship inside the package under the multipay/ URL prefix (configurable via internal_routes in the config):

You don't call these directly; pay() returns their URL as the payment_url when applicable.

Amounts and currencies

You always pass major units (19.99). Each gateway adapter converts to what its API expects — minor units (cents/paise/fils) or formatted decimal strings — using the correct ISO 4217 exponent: 0-decimal currencies (JPY, KRW, ...), 3-decimal currencies (KWD, BHD, OMR, ...), and 2-decimal for the rest. Float-precision bugs (19.99 * 100 = 1998.99...) are handled by rounding.

Updating the package

After composer update joynala/multi-pay, re-publish if the release notes mention config or migration changes:

Published files are copies — they do not update automatically with the package.

Adding a new gateway

  1. Create src/Services/YourGateway.php extending BaseGateway and implement:
    • needyConfig(): array — required credential keys;
    • requestPayment(PaymentRequestData $payment): PaymentResponseData — call the gateway, return the payment URL (use successUrl() / cancelUrl() / callbackUrl() for return URLs, minorAmount() for amounts, or formPostResponse() if the gateway needs a signed browser POST);
    • verifyPayment(PaymentSession $session, Request $request): PaymentResponseData — prove the money moved server-side; return via verified() / unverified().
  2. Register it in src/Managers/BaseManager.php ($gateways), add a case to src/Enums/Gateways.php, and a config section in Config/multipay.php.
  3. Run vendor/bin/phpunit — RegistryConsistencyTest enforces that registry, enum, and config stay in sync.

PRs adding gateways are welcome — please include sandbox test notes.

Running the package tests

Status & roadmap

License

MIT — see Joynal Abedin.


All versions of multi-pay with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/support Version ^10.0|^11.0|^12.0|^13.0
illuminate/database Version ^10.0|^11.0|^12.0|^13.0
illuminate/http Version ^10.0|^11.0|^12.0|^13.0
illuminate/routing Version ^10.0|^11.0|^12.0|^13.0
stripe/stripe-php Version ^12|^13|^14|^15|^16|^17
razorpay/razorpay Version ^2.9
yabacon/paystack-php Version ^2.2
braintree/braintree_php Version ^6.32
paytabscom/laravel_paytabs Version ^1.9
adyen/php-api-library Version ^28.3
authorizenet/authorizenet Version ^2.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package joynala/multi-pay contains the following files

Loading the files please wait ...