Building the CREEM Laravel Package: Accept Global Payments in Minutes
Source: Dev.to
I recently built a full‑featured Laravel package for CREEM, the developer‑first Merchant of Record platform. It lets you accept global payments in under five minutes.
Why it matters
If you sell SaaS, digital products, or software licenses, you have to deal with:
- VAT/GST/sales tax in 190+ countries
- Payment processor integration
- Subscription lifecycle management
- License key distribution
- Refunds and disputes
CREEM handles all of this as a Merchant of Record at 3.9 % + 30 ¢ with zero monthly fees, taking legal responsibility for tax compliance so you can focus on building your product. The missing piece was a native Laravel package.
Package overview
creem/laravel wraps the entire CREEM API with Laravel‑native patterns.
route('checkout.success'),
'customer' => ['email' => $user->email],
]);
return redirect($checkout['checkout_url']);
All API endpoints are covered: Products, Checkouts, Subscriptions, Customers, Transactions, Licenses, and Discounts.
Billable trait
Attach the Billable trait to your User model to expose billing methods directly:
checkout('prod_abc123', ['success_url' => '/thanks']);
$user->creemSubscriptions();
$user->cancelSubscription('sub_xyz', 'scheduled');
$user->billingPortalUrl();
Webhooks & events
The package auto‑registers a webhook endpoint at POST /creem/webhook with HMAC‑SHA256 signature verification. Each webhook type maps to a typed Laravel event.
// EventServiceProvider example
protected $listen = [
CheckoutCompleted::class => [
GrantAccessListener::class,
],
SubscriptionCanceled::class => [
RevokeAccessListener::class,
],
];
Convenience events AccessGranted and AccessRevoked fire automatically for the appropriate webhook combinations:
Event::listen(AccessGranted::class, function ($event) {
// Fires on: checkout.completed, subscription.active, subscription.paid
$user = User::where('email', $event->payload['customer']['email'])->first();
$user->update(['has_access' => true]);
});
Test & CI
- 73 tests, 137 assertions covering every API method, webhook verification, and event dispatch.
- CI matrix runs on PHP 8.1–8.4 and Laravel 10, 11, 12.
Installation
-
Require the package
composer require creem/laravel -
Publish config & migrations
php artisan vendor:publish --tag=creem-config php artisan vendor:publish --tag=creem-migrations php artisan migrate -
Configure environment variables
CREEM_API_KEY=creem_test_your_key CREEM_WEBHOOK_SECRET=whsec_your_secret -
Add the Billable trait to
User(see above). -
Create a checkout route
user()->checkout('prod_your_product', [ 'success_url' => url('/thanks'), ]); return redirect($checkout['checkout_url']); }); -
Handle webhooks
payload['customer']['email'] ?? null; User::where('email', $email)->update(['is_premium' => true]); } }
That’s it—CREEM takes care of the payment page, tax calculation, and receipt. Your webhook listener grants access when payment succeeds.
Demo & resources
-
Live demo: https://creem.h90.space
(Docker app connected to the CREEM sandbox API, with a dark glassmorphism UI.) -
Run the demo locally
cd examples/demo cp .env.example .env # add your CREEM API key docker compose up -d --build -
Packagist: https://packagist.org/packages/creem/laravel
-
CREEM website: https://creem.io
-
CREEM docs: https://docs.creem.io
Feature summary
| Feature | Details |
|---|---|
| API Methods | 26 (full CREEM coverage) |
| Webhook Events | 15 typed Laravel events |
| Tests | 73 tests, 137 assertions |
| PHP Support | 8.1, 8.2, 8.3, 8.4 |
| Laravel Support | 10, 11, 12 |
| Code Style | Laravel Pint enforced |
| CI/CD | GitHub Actions matrix |
| Artisan Commands | creem:webhook-secret, creem:sync-products |
| Error Handling | 4 typed exception classes with trace IDs |
Built by Hani Amin (Discord: xh90) for the CREEM Scoops Laravel integration bounty.