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

Sdk Laravel Package

buckaroo/sdk

The Buckaroo SDK for Laravel provides a fluent, framework-friendly wrapper around Buckaroo's payment APIs, covering payment methods, transactions, refunds, status checks, and webhook handling. It helps PHP developers add secure online payments and simplify checkout integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the SDK and treat it as a transport dependency, not application architecture:

composer require buckaroo/sdk

Check the composer.json constraints first — PHP version, Guzzle/PSR-7 versions, and whether anything conflicts with your composer.lock. There is no Cashier-equivalent here, so nothing publishes migrations, models, or routes for you.

Buckaroo issues three things per website: a website key, a secret key, and a mode (test or live). Keep them out of the SDK's static/global configuration by owning the config yourself:

// config/buckaroo.php
return [
    'website_key' => env('BUCKAROO_WEBSITE_KEY'),
    'secret_key'  => env('BUCKAROO_SECRET_KEY'),
    'mode'        => env('BUCKAROO_MODE', 'test'),
];

Where to look first

  1. The README payment examples — they show the client constructor and the per-method service factory. The shape is roughly $buckaroo->method('ideal')->pay([...]); method naming has shifted between SDK versions, so confirm against the tag you installed rather than a blog post.
  2. The src/ tree — clients for payments, refunds, and transactions. Read the request classes for the fields each method actually requires instead of guessing from the API docs.
  3. The sandbox credentials that come with your merchant account. This is your real documentation; with 12 stars and zero dependents, there are no community examples to fall back on.
  4. Your own adapter file — the first thing you write, before any controller.

First use case: one iDEAL payment, end to end, in the sandbox.

Bind the client once in a service provider so it is injectable and swappable in tests:

// app/Providers/BuckarooServiceProvider.php
public function register(): void
{
    $this->app->singleton(BuckarooClient::class, fn () => new BuckarooClient(
        config('buckaroo.website_key'),
        config('buckaroo.secret_key'),
        config('buckaroo.mode'), // verify the exact constructor signature in the README
    ));
}

Then a single happy-path spike: create a local payments row in pending, call the SDK to create the payment with a return/callback URL, redirect the user to the returned URL, and handle the return by querying transaction status — not by trusting the query string. Get success, failure, cancel, and expired paths working in the sandbox before you add a second payment method. iDEAL first if you sell into the Netherlands; it is the highest-conversion method and the simplest redirect flow to validate.

Implementation Patterns

Anti-corruption layer, always. The SDK's request/response objects should never appear in a controller, model, or Blade view. Define your own interface and DTOs, and make the adapter the only file that imports the vendor namespace:

interface PaymentGateway
{
    public function start(StartPayment $payment): PaymentRedirect;
    public function status(string $transactionKey): PaymentStatus;
    public function refund(RefundRequest $refund): RefundResult;
}

final class BuckarooGateway implements PaymentGateway
{
    public function __construct(private BuckarooClient $client) {}
    // map DTO -> SDK request, call, map response -> DTO, catch + translate exceptions
}

This is what makes a second PSP, or an SDK replacement when the vendor bumps a major version, a bounded change instead of a checkout rewrite.

Persist before you call the API. Write the payments row (your reference, amount, currency, method, status pending) first, then call the gateway, then store the returned transaction key. If the HTTP call times out you still have a record to reconcile against — an untracked payment is the worst outcome in this domain.

Order state is driven by webhooks, not redirects. The browser return is a UX hint. The pattern that holds up:

  • Route outside web- middleware or with CSRF excluded for the webhook path.
  • Verify the signature before parsing; reject on failure and log the raw body.
  • Insert the raw payload into a webhook_events table with a unique index on the event/transaction identifier — this is your replay protection and duplicate defence in one.
  • Dispatch a queued job that runs an idempotent state machine (pending → paid → refunded); re-processing the same event must be a no-op.
  • Poll or re-query the status endpoint as a backstop for lost webhooks, on a schedule, for anything stuck in pending past a threshold.

Refunds are their own workflow. Refund against the original transaction key, support partial amounts, and store each refund as a row linked to the payment. Apply an idempotency key so a retried job cannot double-refund. Track the remaining refundable amount on the payment rather than recomputing from the vendor each time.

Reconciliation is part of the feature, not an afterthought. A scheduled job that pulls settlement/payout data and matches it against your payments and refunds tables will catch the failure modes you cannot reproduce: stuck transactions, status flips, currency rounding. Build it before go-live, not after finance asks.

Test against a fake at the interface. Bind a FakePaymentGateway in tests and assert your state machine, not the SDK. Keep a small, non-CI suite of contract tests that hit the sandbox on a schedule to catch vendor-side drift — with no community pressure on this package, nobody else will notice a breaking change for you.

Queue and time-box every outbound call. Nothing in the SDK gives you Laravel's HTTP client retry/timeout behaviour for free. Set explicit timeouts, keep payment creation out of long request cycles where possible, and process webhooks on a queue with backoff.

Feature-flag the whole integration if you are replacing an existing PSP. Run both providers, compare settlement reports, then cut over.

Gotchas and Tips

The ecosystem signals are genuinely thin. Zero dependents and a dozen stars means no Stack Overflow corpus, no third-party tutorials, and a small hiring pool. Assume you own the integration and validate every assumption against the sandbox. The advertised last-release date (2026-10-14) is a metadata anomaly — confirm the real version and changelog on Packagist and the repo before pinning.

There is no Laravel-native layer. Despite Laravel being a documented target, budget for writing the service provider binding, config, facade (if you want one), webhook route, and CSRF exclusion yourself. No migrations, no billable trait, no subscription models.

Never mark an order paid from the return URL. Anyone can hit your success route. Status comes from a verified webhook or an explicit status query — both, ideally.

Duplicate and out-of-order webhooks are normal. Enforce idempotency at the database (unique constraint), not in PHP if checks. Handle an "unknown" or unrecognised status gracefully instead of throwing — new statuses appear without your code changing.

Currency units bite. Confirm whether amounts are decimal strings or minor units, and never pass a PHP float into a money field. Store amounts as integers (cents) in your schema and format at the edges.

Exceptions must not escape the adapter. Catch vendor exceptions at the boundary and map them to your own domain exceptions with a correlation ID. Log the request payload with secrets redacted, the response, and your internal payment reference — this is what makes a support ticket to Buckaroo actionable.

Logging and HTTP may not route through Laravel. The SDK likely uses PSR-3 logging and its own Guzzle client rather than Laravel's log and HTTP factories. Bridge a PSR-3 logger in, and don't assume Http::fake() intercepts anything.

Test/live mix-ups are the classic incident. Assert the mode at boot (fail fast if live is set in a non-production environment or vice versa), and stamp the mode onto every payment record so reconciliation reports can't be compared across environments by accident.

Method naming drifts between versions. The method('ideal') style versus explicit service classes has changed across releases; pin an exact version, read the changelog on upgrade, and let your contract tests be the tripwire.

Extension points are limited to what you build. There is no plugin system — your seams are the service provider binding, your PaymentGateway interface, and your DTO mappers. Keep those clean and you can absorb an SDK major version or a PSP swap without touching domain code.

PCI scope is a design decision, not an SDK feature. A redirect/hosted flow keeps you at the lowest SAQ tier; direct card capture does not. Decide this before writing the checkout, because it determines how much of the SDK's card surface you ever call.

Bring in finance and support before launch. Runbooks for failed payments, duplicate webhooks, stuck transactions, refund failures, and refund/dispute handling are the difference between a demo and a payment system.

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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource