LaravelPackages.net
Acme Inc.
Toggle sidebar
creem/laravel

Official Laravel package for CREEM - Accept payments globally with automatic tax handling

152
5
v1.0.0
About creem/laravel

creem/laravel is a Laravel package for official laravel package for creem - accept payments globally with automatic tax handling. It currently has 5 GitHub stars and 152 downloads on Packagist (latest version v1.0.0). Install it with composer require creem/laravel. Discover more Laravel packages by creem or browse all Laravel packages to compare alternatives.

Last updated

CREEM for Laravel

The official Laravel package for CREEM — accept payments globally with automatic tax handling, subscription management, and license key distribution.

Latest Version on Packagist Tests PHP Laravel License

Features

  • Facade APICreem::createCheckout(), Creem::getProduct(), and 24 methods total
  • Webhook handling — Automatic signature verification with typed Laravel events
  • Billable trait — Add checkout, subscription, and billing portal to any Eloquent model
  • Artisan commandscreem:webhook-secret, creem:list-products
  • Full API coverage — Products, Checkouts, Subscriptions, Customers, Transactions, Licenses, Discounts
  • Auto sandbox detection — Automatically routes to sandbox API when using test keys
  • Laravel 10, 11 & 12 support with PHP 8.1+

Installation

composer require creem/laravel

Publish the configuration file:

php artisan vendor:publish --tag=creem-config

Add your API credentials to .env:

CREEM_API_KEY=creem_test_your_api_key_here CREEM_WEBHOOK_SECRET=your_webhook_secret_here

Quick Start

Create a Checkout Session

use Creem\Laravel\Facades\Creem;

$checkout = Creem::createCheckout('prod_abc123', [
    'success_url' => route('checkout.success'),
    'customer' => ['email' => $user->email],
    'metadata' => ['user_id' => $user->id],
]);

return redirect($checkout['checkout_url']);

Using the Billable Trait

Add the trait to your User model:

use Creem\Laravel\Traits\Billable;

class User extends Authenticatable
{
    use Billable;
}

Run the migration to add the creem_customer_id column:

php artisan vendor:publish --tag=creem-migrations
php artisan migrate

Now you can use billing methods directly on your User model:

// Create a checkout for this user
$checkout = $user->checkout('prod_abc123', [
    'success_url' => route('checkout.success'),
]);

// Get billing portal URL
$portal = $user->billingPortalUrl();

// Get all subscriptions
$subscriptions = $user->creemSubscriptions();

// Cancel a subscription
$user->cancelSubscription('sub_xyz', 'scheduled');

API Reference

Checkouts

// Create a checkout session
Creem::createCheckout('prod_123', [
    'success_url' => 'https://yourapp.com/success',
    'customer' => ['email' => '[email protected]'],
    'metadata' => ['key' => 'value'],
    'discount_code' => 'LAUNCH20',
    'request_id' => 'idempotency-key',
]);

// Retrieve a checkout session
Creem::getCheckout('chk_abc123');

Products

// Create a product (price in cents)
Creem::createProduct([
    'name' => 'Pro Plan',
    'price' => 2999, // $29.99
    'currency' => 'USD',
    'billing_type' => 'recurring', // or 'onetime'
    'billing_period' => 'every-month',
    'tax_category' => 'saas',
]);

// Get a product
Creem::getProduct('prod_123');

// Search products
Creem::searchProducts(['limit' => 10]);

Customers

// Get customer by ID or email
Creem::getCustomer(['id' => 'cus_123']);
Creem::getCustomer(['email' => '[email protected]']);

// List all customers
Creem::listCustomers(['limit' => 50]);

// Generate billing portal link
Creem::customerBillingPortal('cus_123');

Subscriptions

// Get a subscription
Creem::getSubscription('sub_123');

// Search subscriptions
Creem::searchSubscriptions(['status' => 'active']);

// Update (seats, units, add-ons)
Creem::updateSubscription('sub_123', ['units' => 5]);

// Upgrade to different product
Creem::upgradeSubscription('sub_123', 'prod_pro');

// Cancel (immediate or at period end)
Creem::cancelSubscription('sub_123', 'scheduled');
Creem::cancelSubscription('sub_123', 'immediate');

// Pause & Resume
Creem::pauseSubscription('sub_123');
Creem::resumeSubscription('sub_123');

Transactions

Creem::getTransaction('txn_123');
Creem::searchTransactions([
    'customer' => 'cus_123',
    'limit' => 20,
]);

Licenses

// Activate a license on a device
$result = Creem::activateLicense('ABCD-1234-EFGH', 'MacBook Pro');
$instanceId = $result['instance_id'];

// Validate a license
Creem::validateLicense('ABCD-1234-EFGH', $instanceId);

// Deactivate
Creem::deactivateLicense('ABCD-1234-EFGH', $instanceId);

Discounts

// Create a discount
Creem::createDiscount([
    'name' => 'Launch Sale',
    'code' => 'LAUNCH20',
    'type' => 'percentage', // or 'fixed'
    'percentage' => 20,
    'duration' => 'forever', // 'forever', 'once', or 'repeating'
    'applies_to_products' => ['prod_abc123'],
    'max_redemptions' => 100,
]);

// Get a discount
Creem::getDiscount(['code' => 'LAUNCH20']);

// Delete a discount
Creem::deleteDiscount('disc_123');

Webhooks

CREEM webhooks are handled automatically. The package registers a POST route at /creem/webhook (configurable) and verifies signatures using HMAC-SHA256.

Setup

  1. Set your webhook secret in .env:

    CREEM_WEBHOOK_SECRET=your_webhook_secret
  2. Register your webhook URL in the CREEM dashboard under Developers > Webhook:

    https://yourapp.com/creem/webhook
    

Listening to Events

Register listeners in your EventServiceProvider or use Laravel's event discovery:

use Creem\Laravel\Events\CheckoutCompleted;
use Creem\Laravel\Events\SubscriptionActive;
use Creem\Laravel\Events\SubscriptionCanceled;

class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        CheckoutCompleted::class => [
            GrantAccessListener::class,
        ],
        SubscriptionCanceled::class => [
            RevokeAccessListener::class,
        ],
    ];
}

Create a listener:

use Creem\Laravel\Events\CheckoutCompleted;

class GrantAccessListener
{
    public function handle(CheckoutCompleted $event): void
    {
        $data = $event->payload;

        // Grant access based on checkout data
        // $data contains customer, product, and transaction info
    }
}

Available Events

| Event Class | Webhook Type | Description | |---|---|---| | CheckoutCompleted | checkout.completed | Payment successful, order created | | SubscriptionActive | subscription.active | New subscription created | | SubscriptionPaid | subscription.paid | Recurring payment processed | | SubscriptionCanceled | subscription.canceled | Subscription ended | | SubscriptionScheduledCancel | subscription.scheduled_cancel | Cancellation pending at period end | | SubscriptionPastDue | subscription.past_due | Payment failed, retrying | | SubscriptionExpired | subscription.expired | Period ended without payment | | SubscriptionTrialing | subscription.trialing | Trial period started | | SubscriptionPaused | subscription.paused | Subscription paused | | SubscriptionUpdated | subscription.update | Subscription modified | | RefundCreated | refund.created | Refund issued | | DisputeCreated | dispute.created | Chargeback opened |

Convenience Access Events

The package also dispatches AccessGranted and AccessRevoked events for simplified access management (inspired by the CREEM TypeScript SDK's onGrantAccess/onRevokeAccess pattern):

use Creem\Laravel\Events\AccessGranted;
use Creem\Laravel\Events\AccessRevoked;

// AccessGranted fires on: checkout.completed, subscription.active, subscription.paid
// AccessRevoked fires on: subscription.canceled, subscription.expired

class ManageUserAccess
{
    public function handleGrant(AccessGranted $event): void
    {
        // $event->reason — the original event type (e.g., 'checkout.completed')
        // $event->payload — the webhook object data
    }

    public function handleRevoke(AccessRevoked $event): void
    {
        // Revoke the user's access
    }
}

You can also listen to the generic CreemWebhookReceived event to catch all webhook types:

use Creem\Laravel\Events\CreemWebhookReceived;

class LogAllWebhooks
{
    public function handle(CreemWebhookReceived $event): void
    {
        logger()->info("CREEM webhook: {$event->eventType}", $event->payload);
    }
}

Artisan Commands

Generate Webhook Secret

# Generate a new webhook secret and add it to .env
php artisan creem:webhook-secret

# Show the current webhook secret
php artisan creem:webhook-secret --show

# Force overwrite an existing secret
php artisan creem:webhook-secret --force

List Products

# List all products from your CREEM account
php artisan creem:list-products

Configuration

The config file (config/creem.php) supports these options:

| Option | Env Variable | Default | Description | |---|---|---|---| | api_key | CREEM_API_KEY | '' | Your CREEM API key | | webhook_secret | CREEM_WEBHOOK_SECRET | '' | Webhook signing secret | | api_url | CREEM_API_URL | Auto-detected | Override the API base URL | | webhook_path | CREEM_WEBHOOK_PATH | creem/webhook | Webhook route path | | currency | CREEM_CURRENCY | USD | Default currency | | customer_model | CREEM_CUSTOMER_MODEL | App\Models\User | Billable model class |

Sandbox vs Production

The package automatically detects sandbox mode based on your API key prefix:

  • creem_test_* → Sandbox API (https://test-api.creem.io)
  • creem_* → Production API (https://api.creem.io)

Error Handling

The package throws typed exceptions for different error scenarios:

use Creem\Laravel\Exceptions\CreemApiException;
use Creem\Laravel\Exceptions\CreemAuthenticationException;
use Creem\Laravel\Exceptions\CreemRateLimitException;

try {
    $product = Creem::getProduct('prod_123');
} catch (CreemAuthenticationException $e) {
    // Missing or invalid API key (401/403)
} catch (CreemRateLimitException $e) {
    // Rate limited (429) - check $e->getRetryAfter() for seconds to wait
} catch (CreemApiException $e) {
    // Other API errors (400, 404, 500, etc.)
    $traceId = $e->getTraceId(); // For CREEM support debugging
}

Demo App

Live Demo: https://creem.h90.space — see the package in action with real CREEM API integration.

A fully functional Docker-based demo app is included in examples/demo/. It demonstrates:

  • Facade API calls (Creem::searchProducts(), Creem::createProduct())
  • Billable trait ($user->checkout())
  • Webhook event handling with live dashboard
  • Sandbox/production auto-detection
  • One-click sample product seeding via API
cd examples/demo
cp .env.example .env
# Add your CREEM API key and webhook secret to .env
docker compose up -d --build
# Visit http://localhost:8000

No products yet? Click ⚡ Create Sample Products on the products page or run:

docker compose exec app php seed-products.php

See the demo README for full setup instructions.

Testing

composer test

Or run directly:

vendor/bin/phpunit

The package ships with 78 tests covering:

  • API client HTTP handling & error responses
  • All 24 Facade methods (checkout, products, subscriptions, discounts, etc.)
  • Webhook signature verification
  • Event dispatching for all 12 webhook types + AccessGranted/AccessRevoked
  • Service provider bindings & configuration
  • Artisan command registration & behavior

Package Structure

creem-laravel/
├── config/
   └── creem.php                 # Configuration file
├── database/
   └── migrations/               # Billable migration
├── src/
   ├── Api/                      # API endpoint classes
      ├── CheckoutApi.php
      ├── CustomerApi.php
      ├── DiscountApi.php
      ├── LicenseApi.php
      ├── ProductApi.php
      ├── SubscriptionApi.php
      └── TransactionApi.php
   ├── Commands/                 # Artisan commands
      ├── SyncProductsCommand.php
      └── WebhookSecretCommand.php
   ├── Events/                   # Laravel events
      ├── CheckoutCompleted.php
      ├── CreemWebhookReceived.php
      ├── SubscriptionActive.php
      ├── AccessGranted.php
      ├── AccessRevoked.php
      └── ... (15 event classes total)
   ├── Exceptions/               # Typed exceptions
   ├── Facades/
      └── Creem.php            # Facade with IDE hints
   ├── Http/
      ├── Controllers/
         └── WebhookController.php
      └── Middleware/
          └── VerifyCreemWebhook.php
   ├── Traits/
      └── Billable.php         # Eloquent billing trait
   ├── Creem.php                # Main service class
   ├── CreemClient.php          # HTTP client
   ├── CreemServiceProvider.php  # Service provider
   └── WebhookEventType.php     # Event type constants
├── tests/
   ├── Feature/                  # Integration tests
   └── Unit/                     # Unit tests
├── composer.json
└── phpunit.xml

Requirements

  • PHP 8.1+
  • Laravel 10, 11, or 12
  • Guzzle HTTP 7.0+

License

MIT License. See LICENSE for details.

Resources

Author

Built by Hani Amin@HaniAmin90 · Discord: xh90

Comments