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

Chargebee Php Laravel Package

chargebee/chargebee-php

Official Chargebee PHP client library for subscription billing and recurring payments. Integrate Chargebee's API into your Laravel or PHP app to manage subscriptions, invoices, customers, payments, and plans with a simple, easy-to-use SDK.

Deep Wiki
Context7

Getting Started

  1. Install (the package is API-versioned separately from the SDK, so pin it and upgrade deliberately):

    composer require chargebee/chargebee-php
    
  2. Configure once at bootstrap. The SDK keeps global static configuration, so wire it in a service provider (or a dedicated ChargebeeServiceProvider) rather than next to business logic:

    use Chargebee\Chargebee\Environment;
    
    Environment::configure(
        config('services.chargebee.site'),     // e.g. "acme-test"
        config('services.chargebee.api_key')
    );
    
  3. First use case — create a customer, then a subscription. Almost every integration starts here, and it exercises the two things you'll hit daily: array payloads in, result objects out.

    use Chargebee\Chargebee\Models\Customer;
    use Chargebee\Chargebee\Models\Subscription;
    
    $result = Customer::create([
        'id'    => 'cust_'.$user->id,
        'email' => $user->email,
    ]);
    
    $customer = $result->customer; // not an array
    
    $sub = Subscription::create([
        'customer_id' => $customer->id,
        'plan_id'     => 'pro-monthly',
    ])->subscription;
    
  4. Where to look first:

    • Models/ — one class per resource (Customer, Subscription, Invoice, Transaction, HostedPage, PortalSession, Estimate, …). The static methods map 1:1 to REST endpoints, so the Chargebee API docs are the SDK docs.
    • Environment — the only place to configure auth, timeouts, and base URLs.
    • Exceptions/ — read APIError and PaymentError before you write any try/catch.

Implementation Patterns

Wrap the SDK in your own thin repository. Because the SDK uses static methods and global config, calling Subscription::create() directly from controllers makes testing and multi-site support painful. A ChargebeeGateway interface with a real implementation and a fake pays for itself immediately:

interface BillingGateway {
    public function createSubscription(string $customerId, string $planId): SubscriptionDto;
}

class ChargebeeBillingGateway implements BillingGateway { /* calls the SDK */ }

Then binding a fake in tests avoids needing a sandbox site or network access.

Always unwrap the result envelope. Every call returns a result object with named properties (->customer, ->subscription, ->invoice, ->card, ->transaction). Lists are iterable containers of entries, each with the same property shape:

$page = Subscription::all([
    'limit'        => 100,
    'status[is]'   => 'active',
    'sort_by[desc]'=> 'created_at',
]);

foreach ($page as $entry) {
    $sub = $entry->subscription;
}

$nextOffset = $page->nextOffset ?? null; // feed back as 'offset'

Build an iterateAll() helper around offset/next_offset rather than writing pagination loops inline — Chargebee caps page size, and list endpoints are where you'll accidentally hammer the API.

Centralize error translation. Two exception types matter:

use Chargebee\Chargebee\Exceptions\APIError;
use Chargebee\Chargebee\Exceptions\PaymentError;

try {
    $result = Subscription::create($payload);
} catch (PaymentError $e) {
    // Card declines, gateway failures — user-actionable
    $code = $e->getApiErrorCode();   // e.g. 'card_declined'
    $msg  = $e->getMessage();
    $http = $e->getHttpStatusCode();
    Log::warning('chargebee.payment_failed', compact('code', 'http'));
} catch (APIError $e) {
    // Validation, auth, rate limits, not-found
    $code = $e->getApiErrorCode();
}

Map Chargebee error codes to your own domain exceptions so controllers and jobs never import Chargebee classes.

Webhooks: parse the raw body, verify, then queue. Chargebee delivers application/x-www-form-urlencoded payloads, not JSON. $request->json() will silently give you nothing — read php://input and run it through parse_str(). Validate the Authorization header (Basic auth using your API key as the username) before trusting anything, then persist by event.id for idempotency and dispatch to a queue. Never call back into the SDK synchronously inside the webhook handler; Chargebee retries and you'll compound timeouts.

Model subscription state locally, sourced from webhooks. Treat the SDK as the source of truth for actions (create, upgrade, cancel, charge) and webhooks as the source of truth for state (subscription_activated, subscription_renewed, subscription_cancelled, payment_failed). Don't poll Subscription::retrieve() on every page load.

Hosted pages for anything involving card data. Use HostedPage::checkoutNew() / checkoutExisting() and PortalSession::create() so PCI scope stays at zero. Redirect the user, then confirm the hosted page on return with HostedPage::retrieve($id) — the URL params alone are not trustworthy.

Retries and idempotency. Wrap create/charge calls in a retry policy with exponential backoff, but only for network errors and 5xx/429 — never blindly retry a 4xx. Chargebee supports an idempotency header; check the SDK's request-options support for your version and, if absent, implement a "did this customer already get this subscription?" guard in your own DB before retrying.

Queue workers and long-lived processes. Because config is global static state, configure it in AppServiceProvider::boot(), not in a controller, and be deliberate if you ever support multiple Chargebee sites — reconfigure immediately before each call in that case, since concurrent jobs in the same worker will otherwise inherit stale config.

Gotchas and Tips

  • Major versions renamed everything. Pre-4.x code uses Chargebee_Environment, Chargebee_Customer, underscore-style. Modern releases use Chargebee\Chargebee\Environment and Chargebee\Chargebee\Models\*. Most blog posts and StackOverflow answers are for the old API — always check your installed version's composer.json and namespace before copying a snippet.
  • Results are objects, not arrays. $result['customer'] returns null; $result->customer is correct. Same for iterating lists — each element is an entry object, not the resource itself.
  • Amounts are in the smallest currency unit. amount on an invoice is cents. Divide by 100 at the presentation boundary and store the raw integer in your DB.
  • limit is capped server-side. Requesting 1000 doesn't get you 1000. Paginate properly, and cache list results you need frequently (plans, addons) rather than re-fetching per request.
  • Rate limits are per site. A runaway background loop draining 429s will starve your interactive checkout flow. Isolate batch/reconciliation work with a queue and a rate limiter.
  • Webhook bodies are form-encoded. Also confirm your middleware isn't stripping the Authorization header (common with proxies) — that's the usual cause of "why do all my webhooks look unauthenticated."
  • Sandbox vs. live configuration. services.chargebee.* should be env-driven, and test/live sites have separate API keys and separate webhook endpoints. A staging deploy pointed at the live site is the classic incident here.
  • API keys leak easily through logs. If you enable SDK or HTTP debug logging, redact Authorization and never dd() a configured Environment.
  • Timeouts default to "long". Set explicit timeouts in Environment::configure() (or wrap calls in your own timeout) so a slow Chargebee API doesn't pin PHP-FPM workers.
  • Extension points are thin. The library is a generated REST client; there's no middleware or HTTP client injection to speak of. All cross-cutting concerns (logging, retries, metrics, idempotency) belong in your wrapper class around it — another reason not to call static SDK methods from application code.
  • Time travel / test clocks exist in Chargebee for simulating renewals; use them in the sandbox to validate your webhook state machine instead of waiting a month for a renewal event.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin