Search by

payum / offline

makasim

The Payum extension. Payments settled outside an online PSP: cash, bank transfer, store credit.

Package info

github.com/Payum/Offline

Homepage

pkg:composer/payum/offline

Fund package maintenance!

payum

Thanks Dev

Statistics

Installs: 4 607 062

Dependents: 10

Suggesters: 0

Stars: 30

2.0.0-alpha1 2026-11-06 15:23 UTC

README

Payum is an MIT-licensed open source project with its ongoing development made possible entirely by the support of community and our customers. If you'd like to join them, please consider:

Offline

Total Downloads Latest Stable Version

Payments that are settled outside an online payment provider: cash, cheque, bank transfer, store credit. No external API is called. The gateway records each operation in the payment's details and reports its status.

Register it

Register the gateway once for each payment method you offer:

<?php

use Payum\Core\PayumBuilder;
use Payum\Offline\OfflineConfig;

$payum = (new PayumBuilder())
    ->addDefaultStorages()
    ->registerGateway('cash', new OfflineConfig())
    ->registerGateway('bank_transfer', new OfflineConfig(paid: false))
    ->getPayum();

A captured payment is paid at once unless the config says paid: false. Then it stays pending until you set its paid detail to true and capture it again. A paid detail set on the payment before the capture always wins.

It answers capture, authorize, refund (also partial), cancel, sync and payout.

Replace a handler

Give your own handler for an operation that has to do more, such as taking the amount off a customer's store credit. It replaces the gateway's handler for that command on this registration only:

<?php

use Payum\Core\Command\CaptureCommand;
use Payum\Core\Handler\CaptureHandlerInterface;
use Payum\Core\Handler\Context;
use Payum\Core\Result\CaptureResult;
use Payum\Core\Result\Failure;
use Payum\Core\Result\FailureReason;

final class StoreCreditCaptureHandler implements CaptureHandlerInterface
{
    public function __construct(private readonly StoreCreditLedger $ledger)
    {
    }

    public function handle(CaptureCommand $command, Context $context): CaptureResult
    {
        $payment = $context->payment();

        if (! $this->ledger->withdraw($payment->getClientId(), $context->amount())) {
            return CaptureResult::failed(new Failure(FailureReason::InsufficientFunds));
        }

        return CaptureResult::captured();
    }
}

$payum = (new PayumBuilder())
    ->addDefaultStorages()
    ->addGlobalService(StoreCreditLedger::class, $ledger)
    ->registerGateway('store_credit', new OfflineConfig(handlers: [StoreCreditCaptureHandler::class]))
    ->getPayum();

A class name is autowired, with services registered by addGlobalService(). You can pass an instance instead. The status your handler returns is written to the payment's status detail, so the other operations see it.

Extend it

OfflineConfig and OfflineGateway can be extended. A StoreCreditConfig extends OfflineConfig passes its handlers to the parent constructor and can add settings of its own. A StoreCreditGateway extends OfflineGateway gives the method its own name, logo and handler list. Point the config's getGatewayClass() at it and the gateway's configClass() at the config. See the Offline docs for an example.

Resources

License

Offline is released under the MIT License.