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

Transactor Laravel Package

orkestra/transactor

Orkestra Transactor is a Laravel package for clean, reliable database transaction handling. Wrap operations in transactions, manage nested transactions, retry deadlocks, and run after-commit callbacks with a simple, expressive API.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a framework-agnostic payment library that happens to run fine inside Laravel — there is no Laravel service provider, facade, or config file shipped with it. Budget an hour to write that glue yourself; it is the same hour every project spends on it.

  1. Install and pin. composer require <vendor>/<package>:^1.2. The 1.2.0 release widens support to Symfony 2.3+/3.0+ components, which is mostly a dependency-resolution concern for you: Laravel's own constraints usually pull a modern symfony/* tree, so run composer why symfony/http-foundation if resolution fights back.
  2. Read the transactor first. Open TransactorInterface and one concrete implementation (start with the Authorize.Net card transactor added in this release). Everything else — accounts, credentials, responses — is shaped by that interface.
  3. Wire credentials through config, not code. 1.2.0 added TransactorInterface::createCredentials(), intended to return a default credential set for the transactor. That is your hook: implement it (or subclass the shipped transactor) to read from config('services.authorize_net'), which in turn reads env().
  4. Bind it once. A small service provider that binds the transactor as a singleton is enough for a first use case.
  5. First use case: a one-off card charge. Build a card Account, call the transactor's authorize/purchase method, inspect the response object. Do this in a Tinker session or an artisan command against the Authorize.Net sandbox before touching a controller.

Implementation Patterns

Keep the transactor behind your own interface. The package's API is stable-ish but has already shipped one BC break (see below). Wrap it:

interface PaymentGateway {
    public function charge(Money $amount, CardDetails $card): PaymentResult;
}

Bind your adapter to TransactorInterface in the container and inject your interface into controllers and jobs. Tests then fake at your boundary instead of mocking a vendor object graph.

Credential resolution belongs in one place. Implement createCredentials() to pull from config(), not env(). Centralize per-gateway config (driver, login_id, transaction_key, sandbox, default_currency) in config/services.php and validate it in a service provider so a missing key fails at boot, not mid-checkout.

Multi-gateway: use a manager, not conditionals. If you support more than one processor, resolve a transactor by name from a small factory, mirroring Laravel's own manager pattern. The Authorize.Net card and ACH transactors added in 1.2.0 are distinct collaborators — treat "card" and "e-check" as separate drivers rather than branching inside one class.

Swiped/track data is now a two-step flow. Since 1.2.0, SwipedCardAccount no longer parses account information out of track data. Decode explicitly with a TrackDecoder, then construct the account from the decoded values:

$decoded = $trackDecoder->decode($trackData);
$account = new CardAccount($decoded->getAccountNumber(), $decoded->getExpiration());

For anything where you must retain the raw track, use the new EncryptedSwipedCardAccount. Keep decoding in a dedicated service so the PCI-sensitive string touches exactly one class and never reaches a model, a log, or a session.

Tokenization plumbing is available but thin. 1.2.0 adds basic support for tokenizing sensitive account data. Use it for repeat billing: tokenize once at card capture, persist only the token plus last-four/brand, then charge against the token thereafter. Expect to own the persistence layer — the package supplies the value objects, not the storage.

Persist payment records in the same transaction as the order. Write your payments row, then call the transactor, then update the row — or better, write a pending row, call out, update to succeeded/failed. Never rely on the HTTP response alone to decide whether money moved; store the gateway transaction ID and raw response.

Log both directions, redacted. A decorator around your adapter that logs the request shape and the full response (minus PAN, CVV, track data) will save you hours during the first production dispute.

Gotchas and Tips

The 1.2.0 BC break will bite you if you wrote a custom transactor. TransactorInterface gained createCredentials(). Any hand-rolled implementation is now a fatal "abstract method not implemented" error at class load. Add the method and have it return a sensible default credential object.

SwipedCardAccount now fails silently-ish. The account no longer populates itself from track data, so a reader-upgraded codebase will start throwing validation or "missing account number" errors deep in the transactor rather than at the call site. Grep for SwipedCardAccount before you upgrade and route every construction through a TrackDecoder.

Beware env() inside createCredentials(). If that method runs per-request (it may, depending on when transactors are constructed), env() returns null once php artisan config:cache has run. Always go through config().

Amounts are almost certainly minor units and integers. Do not pass floats. Use an integer-cents value object and convert at the edge; currency must be explicit for Authorize.Net, even when it feels implicit.

Symfony version drift is the most likely install failure. If your composer.json locks older symfony/* packages for other reasons, 1.2.0's widened constraints may not help you. Check composer update --dry-run before committing to the upgrade.

Responses are objects, not booleans. Read the response code and message; many gateways return HTTP 200 with a declined transaction. Treat exceptions as transport failures and response codes as business outcomes — your retry logic differs for each.

Extension points worth knowing:

  • Implement TransactorInterface directly for an unsupported gateway — it is a small interface, and createCredentials() makes it self-configuring.
  • Custom TrackDecoder implementations for non-standard readers.
  • A decorator around your adapter for logging, metrics, idempotency keys, and circuit breaking, without touching package code.

Debugging checklist: confirm you are pointed at the sandbox endpoint; dump the credential object first (gateways fail opaquely on bad credentials); enable your redacted response logger; and reproduce outside Laravel with a plain PHP script — if it fails there too, the problem is configuration, not your service container.

Upgrade order for 1.2.0: add createCredentials() to custom transactors → migrate swiped-card flows to explicit TrackDecoder → add tests around tokenization → deploy. Do not bundle this with other dependency upgrades.

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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core