PHPackages                             vblinden/laravel-cashier-creem - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. vblinden/laravel-cashier-creem

ActiveLibrary[Payment Processing](/categories/payments)

vblinden/laravel-cashier-creem
==============================

Cashier Creem provides an expressive, fluent interface to Creem's subscription billing services.

v1.2.0(2w ago)0152↓71.4%MITPHPPHP ^8.1CI passing

Since Jul 3Pushed 1mo agoCompare

[ Source](https://github.com/vblinden/laravel-cashier-creem)[ Packagist](https://packagist.org/packages/vblinden/laravel-cashier-creem)[ RSS](/packages/vblinden-laravel-cashier-creem/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (1)Dependencies (22)Versions (4)Used By (0)

Laravel Cashier Creem
=====================

[](#laravel-cashier-creem)

Cashier Creem provides an expressive, fluent interface to [Creem](https://creem.io)'s subscription billing services. It mirrors the developer experience of [Laravel Cashier Paddle](https://github.com/laravel/cashier-paddle) while integrating with Creem's Merchant of Record API.

Installation
------------

[](#installation)

```
composer require vblinden/laravel-cashier-creem
```

Publish the configuration and migrations:

```
php artisan vendor:publish --tag="cashier-config"
php artisan vendor:publish --tag="cashier-migrations"
php artisan migrate
```

Add your Creem credentials to `.env`:

```
CREEM_API_KEY=creem_test_...
CREEM_WEBHOOK_SECRET=whsec_...
CREEM_SUCCESS_URL="${APP_URL}/billing/success"
CASHIER_PATH=creem
```

Register the webhook endpoint in your [Creem dashboard](https://creem.io/dashboard/developers):

```
https://your-app.test/creem/webhook

```

Integrating in a Laravel App
----------------------------

[](#integrating-in-a-laravel-app)

### CSRF exemption

[](#csrf-exemption)

Creem sends webhooks as `POST` requests without a CSRF token. Exclude the webhook route in `bootstrap/app.php`:

```
->withMiddleware(function (Middleware $middleware): void {
    $middleware->validateCsrfTokens(except: [
        'creem/webhook',
    ]);
})
```

If you change `CASHIER_PATH`, exclude `{your-path}/webhook` instead.

### Billable metadata

[](#billable-metadata)

Every checkout automatically includes metadata so webhooks can resolve the local user:

```
[
    'billable_id' => (string) $user->getKey(),
    'billable_type' => $user->getMorphClass(),
]
```

When starting a subscription, `subscribe()` also adds `subscription_type` (defaults to `default`). This maps to the `type` column on your local `subscriptions` table.

You can add your own metadata on top:

```
return $user
    ->subscribe('prod_YOUR_PRODUCT_ID', 'default')
    ->metadata(['plan' => 'pro'])
    ->redirect();
```

Set `billable_model` in `config/cashier.php` if you need a fallback lookup path:

```
'billable_model' => App\Models\User::class,
```

### Granting access

[](#granting-access)

Creem fires multiple events around checkout. Use them for different purposes:

EventWhen to use`checkout.completed`Sync customer/subscription records after first checkout`subscription.active`Sync only — Creem creates the subscription object`subscription.paid`**Grant access** — Creem's recommended event for activation`subscription.canceled`Revoke access```
use Laravel\Cashier\Creem\Events\SubscriptionPaid;
use Laravel\Cashier\Creem\Events\SubscriptionCanceled;

Event::listen(SubscriptionPaid::class, function (SubscriptionPaid $event) {
    // Recommended: grant access here
    $event->billable->update(['plan' => 'pro']);
});

Event::listen(SubscriptionCanceled::class, function (SubscriptionCanceled $event) {
    // Revoke access
});
```

For most apps, `$user->subscribed('default')` is enough after webhooks have synced — you do not need a separate `plan` column unless you want one.

### Local development

[](#local-development)

**Webhooks:** Creem must reach your app over HTTPS. Use a tunnel (e.g. ngrok) and register the public URL in the Creem dashboard:

```
https://your-ngrok-url.ngrok.io/creem/webhook

```

Without webhooks, checkout redirects still work, but subscriptions will not sync to your database until Creem can deliver events.

**Test cards** (sandbox only):

CardResult`4111 1111 1111 1111`Successful payment`4507 9900 0000 0028`Card declined`4507 9900 0000 0010`Insufficient fundsUse any future expiry date, any CVV, and any billing address.

**Sandbox detection:** API keys prefixed with `creem_test_` automatically use `https://test-api.creem.io/v1`.

### Routes and controller

[](#routes-and-controller)

Register checkout and portal routes inside your authenticated middleware group:

```
// routes/web.php
use App\Http\Controllers\BillingCheckoutController;

Route::middleware(['auth'])->group(function () {
    Route::get('billing/checkout/{plan}', [BillingCheckoutController::class, 'checkout'])
        ->name('billing.checkout');

    Route::get('billing/portal', [BillingCheckoutController::class, 'portal'])
        ->name('billing.portal');
});
```

Example controller:

```
