Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Payment Processors Laravel Package

tepuilabs/payment-processors

tepuilabs/payment-processors is a Laravel/PHP package that provides a unified approach to integrating multiple payment processors, helping developers manage gateway configuration and payment handling consistently while reducing gateway-specific code in applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and vet before you build on it.

composer require tepuilabs/payment-processors

Before writing a single line of integration code, spend five minutes on the repository because the release cadence stops in March 2022 and the project is archived. Check composer.json for the PHP and illuminate/* version constraints — if you're on Laravel 10/11 with PHP 8.2+, Composer may refuse to install it, or install it and break at runtime. Confirm whether the service provider uses package auto-discovery; if not, register TepuiLabs\PaymentProcessors\PaymentProcessorsServiceProvider manually in config/app.php.

Next, publish the config and read it end-to-end. It is the single source of truth for which processors are available and what credentials each expects:

php artisan vendor:publish --provider="TepuiLabs\PaymentProcessors\PaymentProcessorsServiceProvider"

You should end up with something like config/payment-processors.php listing drivers and their keys. Cross-reference every key against the README and against the driver classes in src/ — for an unmaintained package the code is more reliable documentation than the README.

First use case: a one-off charge in a controller.

The package is designed around a processor/driver abstraction. The shortest path is to resolve the facade or inject the manager, select a processor by name, and call the charge method:

use TepuiLabs\PaymentProcessors\Facades\PaymentProcessors;

$result = PaymentProcessors::driver('stripe')->charge([
    'amount'   => 2500,          // verify units in the driver source
    'currency' => 'USD',
    'token'    => $request->payment_token,
]);

Treat the array keys above as placeholders: open one driver class and copy the exact expected keys and the shape of the returned value before you build anything else. That single driver is your Rosetta Stone for the rest of the package.

If after this you find the driver you need doesn't exist, or the response shape is unusable, stop — you've spent 30 minutes, and the fork-or-replace decision is cheaper now than in month three.

Implementation Patterns

Wrap the package behind your own interface. This is the highest-value pattern for an archived dependency. Define App\Contracts\PaymentGateway with your domain methods (charge, refund, tokenize) and implement it with an adapter that delegates to PaymentProcessors::driver(...). Every controller, job, and test then depends on your interface, not on tepuilabs. When the package eventually fails to install on PHP 8.4, you swap the adapter implementation and nothing else moves.

Select the driver at the boundary, not in the domain. Resolve the processor from configuration or from the request's payment method (e.g. a payment_methods table with a processor column), then pass a resolved gateway object downward. Avoid scattering PaymentProcessors::driver('stripe') calls through the codebase; centralize in a factory or a container binding.

// AppServiceProvider::register()
$this->app->bind(PaymentGateway::class, fn () => new ProcessorGateway(
    PaymentProcessors::driver(config('payments.default'))
));

Two-phase flows need explicit state. Most processors split authorization and capture, or create-intent-then-confirm. Model this in your own database rather than relying on the package to remember anything:

$intent = $gateway->authorize($order->toPaymentPayload());
$order->update(['processor_ref' => $intent->id, 'status' => 'authorized']);

// later, in a queued job or a webhook handler
$gateway->capture($order->processor_ref);

Webhooks are your responsibility. The package almost certainly does not ship route registration or signature verification for every driver. Register your own route, verify the signature using the driver's documented scheme (Stripe's Stripe-Signature header, PayPal's transmission headers, etc.), then hand the parsed payload to the package. Always:

  • Verify the signature against the raw request body, not the parsed array.
  • Return 2xx quickly and dispatch a job for the actual work.
  • Store the event ID and enforce uniqueness so retries are idempotent.

Testing: fake at your interface, not the package's. Because the package predates Laravel's Http::fake conveniences being widely applied to payment SDKs, testing directly against it is brittle. Fake your own PaymentGateway contract in feature tests; keep a thin set of integration tests that hit each real driver, marked with a group so they only run when credentials exist.

$this->mock(PaymentGateway::class)
     ->shouldReceive('charge')
     ->once()
     ->andReturn(new ChargeResult(id: 'ch_123', status: 'succeeded'));

Queue everything that touches a network. Refunds, captures, and customer creation should be jobs with retries and backoff. The package will throw on transport failures; wrapping those calls in a job gives you free retry semantics and keeps request latency low.

Gotchas and Tips

The archive status is the headline risk. No security patches, no new gateway support, no compatibility updates. Before adopting, run composer outdated tepuilabs/payment-processors and read the open issues count. If you adopt, pin the version in composer.json and record a decision note in your ADR log with a review date. Budget the replacement.

Verify money units in the driver source. The single most common integration bug with payment packages is amounts: some drivers expect integer minor units (cents), others decimal strings, and a third group multiply internally. Pick one representation for your domain (integer minor units is safest) and convert exactly once, in the adapter. Add a test that charges 1000 and asserts the processor received 10.00.

Credential leakage through config caching. After php artisan config:cache, config values are frozen. If the package reads credentials in a service provider constructor or at boot, rotating a key requires a redeploy and a cache clear. Prefer reading credentials lazily at call time inside your adapter.

Exceptions are likely undocumented and shallow. Inspect the Exceptions/ directory. Most small packages throw a single generic exception or let the underlying SDK exception bubble up. Normalize at your adapter boundary into a small hierarchy (PaymentDeclined, PaymentTransportError, PaymentConfigurationError) so callers can distinguish "the card was declined" (show the user a message) from "our API key is wrong" (page on-call).

Log raw responses, but redact aggressively. Add a debug listener in your adapter that logs the full processor response at debug level when APP_DEBUG is true. Never log the request payload — PANs, CVVs, and tokens must not hit your log files, or you're in PCI scope you didn't sign up for.

Extension points are usually a register/extend call on the manager. If the manager extends Laravel's Manager, you can register a custom driver:

PaymentProcessors::extend('mygateway', fn ($app) => new MyGateway($app['config']['services.mygateway']));

This is worth checking first, because it is often cheaper than forking — you keep the upstream package's abstraction while supplying a driver that upstream never shipped.

Watch for hardcoded framework version assumptions. An early-2022 package may use $this->app->bind signatures, Str helpers, or config() calls that still work but emit deprecations on Laravel 11+. Run the full test suite with -d error_reporting=E_ALL once to surface them before they become production warnings.

Have an exit plan priced in. If the package provides a clean driver interface, replacement cost is bounded — you rewrite adapters one at a time. If drivers are tightly coupled (each with its own bespoke method names and response objects), your integration cost grows with every gateway you add, and that is the signal to abstract now rather than later.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager