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

Client Laravel Package

cheddar-getter/client

A PHP client for CheddarGetter’s recurring billing API, offering convenient access to customers, plans, subscriptions, and transactions. Works in Laravel and standalone PHP apps with a simple wrapper around CheddarGetter endpoints.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require cheddar-getter/client is all the install you get — there is no Laravel auto-discovery, no service provider, no facade, and no publishable config. It is a framework-agnostic PHP client built on Guzzle, so the first 10 minutes are spent wiring it into the container yourself.

Read these two files first:

  • src/CheddarGetter/Client.php — the only public API surface; every method maps one-to-one to a CheddarGetter REST endpoint (getPlans, getCustomer, createCustomer, updateSubscription, cancelSubscription, addItem, getInvoices, etc.). The docblocks are the de-facto documentation since the README is thin.
  • src/CheddarGetter/Response.php and src/CheddarGetter/Exception.php — how results come back (ArrayAccess, not plain arrays) and how failures are surfaced (thrown exceptions, not false).

Credentials you need from the CheddarGetter control panel: API login email, password, and the product code. The client defaults to https://app.cheddargetter.com; override with setApiUrl() if you're pointed at a different host.

Minimal wiring:

// config/services.php
'cheddargetter' => [
    'email'         => env('CG_EMAIL'),
    'password'      => env('CG_PASSWORD'),
    'product_code'  => env('CG_PRODUCT_CODE'),
    'api_url'       => env('CG_API_URL', 'https://app.cheddargetter.com'),
],

// AppServiceProvider::register()
$this->app->singleton(\CheddarGetter\Client::class, function () {
    $config = config('services.cheddargetter');
    $client = new \CheddarGetter\Client(
        $config['email'],
        $config['password'],
        $config['product_code']
    );
    $client->setApiUrl($config['api_url']);
    return $client;
});

First use case: after a user completes your signup flow, call createCustomer([...]) with your own stable customer code (e.g. user-{id}), the plan code, and billing fields, then persist the returned customer code on your users/subscriptions row. Everything downstream (upgrades, cancellation, invoice history) keys off that code, so decide the format once and never change it.

Implementation Patterns

Inject, don't resolve. Bind the client as a singleton (it holds Guzzle's connection state) and type-hint CheddarGetter\Client in constructors. Never call new Client() inside a controller — you'll re-authenticate on every request.

Wrap it in a domain service, not scattered calls. Put a BillingService / SubscriptionRepository in app/Services that speaks your domain language (startTrial(User $u, Plan $p)) and delegates to the client. This is the seam where you'll later swap providers, add idempotency checks, and write tests. The raw client leaks CheddarGetter concepts (planCode, itemCode, customerCode) into controllers if you don't.

Mirror subscriptions locally. CheddarGetter is the source of truth for money, but you should not call it on every page render. Persist customer_code, plan_code, status, and next_billing_at in your own subscriptions table and reconcile via webhooks or a scheduled sync. UI reads your table; writes go through the client and then update your table.

Handle lifecycle events via webhooks. CheddarGetter posts subscription/customer events to a URL you configure. Add a controller (excluded from CSRF and auth middleware) that validates the payload, maps to your models, and dispatches jobs. Since the library has no webhook helper, keep signature/shared-secret verification in your own middleware. Make the endpoint idempotent — retries happen.

Push billing mutations onto the queue. createCustomer, updateSubscription, and cancelSubscription are network calls to a third party — always dispatch() them in a job with $tries = 3 and exponential backoff. This also gives you a natural place to catch and log API failures.

Cache catalog data aggressively. getPlans() / getPlan() change rarely. Wrap in Cache::remember('cg.plans', now()->addHours(12), ...) and bust it from a deploy or admin action. Same for getProduct().

Testing pattern. Bind a fake in the container in your TestCase:

$this->app->instance(\CheddarGetter\Client::class, Mockery::mock(\CheddarGetter\Client::class, function ($m) {
    $m->shouldReceive('createCustomer')->andReturn(new \CheddarGetter\Response([...]));
}));

Because the client is concrete rather than an interface, Mockery's mock() (not mockInterface()) is required. If you need to assert on wire-level behavior, look at whether the client exposes its underlying Guzzle instance and inject a MockHandler into the handler stack.

Gotchas and Tips

Responses are ArrayAccess objects, not arrays. json_encode($response) will not give you what you expect, and $response->toArray() (or the equivalent accessor) is what you want before passing to response()->json(). Nested data is also ArrayAccess, so $response['customer']['subscription']['planCode'] works but is_array($response['customer']) returns false.

Errors are exceptions, not return values. Catch CheddarGetter\Exception and inspect getCode()/the error code to branch: a 404 on getCustomer means "no such customer" (common on first login) and should be handled rather than logged as a failure. Validation errors (e.g. duplicate customer code, invalid plan) carry API-specific codes — map the ones you care about, let the rest bubble to your handler.

Money is integer minor units. Plan prices, charges, and invoice line totals come back in cents (sometimes as strings). Never float cast them for math; format only at the display boundary.

The package is quiet since 2020 and has zero dependents. Budget a review of PHP 8.x compatibility before adopting. Expect a possible #[\AllowDynamicProperties] patch or fork if the client was written against PHP 7 dynamics. Check the constrained Guzzle major (6 vs 7) against your composer.lock — a mismatch with other packages in the app is the most likely install-time friction.

deleteCustomer is destructive and not the same as cancel. Cancel the subscription (cancelSubscription) for normal churn; only delete when you're genuinely erasing the customer (GDPR, test data). Deleting cascades invoices and history in CheddarGetter and can't be undone.

Cancellation has timing semantics. Pass the right cancel mode (immediate vs. at period end) explicitly — the default is not always what product wants, and getting it wrong is a refund conversation.

Customer codes must be unique per product and never reused. Use a value derived from your own primary key (user-{id}) rather than random UUIDs, so retries and re-registrations are idempotent. Reusing a code after deletion can resurrect old invoices.

Rate limits and timeouts. Set an explicit Guzzle timeout (setHttpClient or a handler stack config) — the default has no timeout and will hang a queue worker. Add a retry middleware with backoff for 5xx/429; don't retry 4xx.

Don't handle card data. Everything about payment method updates goes through CheddarGetter's hosted pages/API — the client never sees PANs. If you find yourself accepting a card form, stop and re-read the billing docs.

Extension point if you need to patch: because there's no service provider, fork-to-path repository is painless — add "cheddar-getter/client": {"type": "path", "url": "packages/cheddargetter-client"} in composer.json, fix the PHP 8 issues, and you own the upgrade path. That's the realistic long-term move for a package that hasn't shipped in years.

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.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings