einenlum / creem-php-sdk
PHP SDK for the Creem merchant of records API
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/einenlum/creem-php-sdk
Requires
- php: ^8.1
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1 || ^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- guzzlehttp/guzzle: ^7.0
- nyholm/psr7: ^1.8
- php-http/mock-client: ^1.6
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0 || ^11.0
README
A PHP SDK for the Creem merchant of records API. This library provides a clean, type-safe interface for interacting with all Creem API endpoints and handling webhooks.
Requirements
- PHP 8.1 or higher
- A PSR-18 HTTP client (e.g., Guzzle)
- A PSR-17 HTTP factory (e.g., Nyholm PSR-7 or Guzzle PSR-7)
Installation
composer require einenlum/creem-php-sdk
If you don't have an HTTP client installed, you can install Guzzle:
composer require guzzlehttp/guzzle
Quick Start
use Einenlum\CreemPhpSdk\Creem; // Create a client (auto-discovers PSR-18/17 implementations) $creem = Creem::create( apiKey: 'creem_xxxxx', testMode: true // Use test API environment ); // Get a product $product = $creem->products->get('prod_xxxxx'); echo $product->name; // Create a checkout session $checkout = $creem->checkouts->create( productId: 'prod_xxxxx', successUrl: 'https://example.com/success' ); echo $checkout->checkoutUrl;
Configuration
Basic Configuration
use Einenlum\CreemPhpSdk\Creem; $creem = Creem::create( apiKey: 'creem_xxxxx', webhookSecret: 'whsec_xxxxx', // Optional, for webhook handling testMode: false // false = production, true = test environment );
Custom HTTP Client
If you need to customize the HTTP client (e.g., for timeouts or proxies):
use Einenlum\CreemPhpSdk\Creem; use GuzzleHttp\Client; use GuzzleHttp\Psr7\HttpFactory; $httpClient = new Client([ 'timeout' => 30, 'proxy' => 'http://proxy.example.com:8080' ]); $factory = new HttpFactory(); $creem = Creem::create( apiKey: 'creem_xxxxx', httpClient: $httpClient, requestFactory: $factory, streamFactory: $factory );
API Resources
Products
// Get a product by ID $product = $creem->products->get('prod_xxxxx'); // Create a product $product = $creem->products->create([ 'name' => 'My Product', 'price' => 1999, // Price in cents 'currency' => 'USD' ]); // Search products with pagination $result = $creem->products->search(limit: 10, page: 1); foreach ($result->items as $product) { echo $product->name; }
Checkouts
// Create a checkout session $checkout = $creem->checkouts->create( productId: 'prod_xxxxx', successUrl: 'https://example.com/success', customer: [ 'email' => 'customer@example.com', 'name' => 'John Doe' ], metadata: [ 'order_id' => '12345' ] ); // Redirect user to checkout header('Location: ' . $checkout->checkoutUrl); // Get checkout details $checkout = $creem->checkouts->get('ch_xxxxx');
Customers
// Get a customer by ID or email $customer = $creem->customers->get(customerId: 'cus_xxxxx'); $customer = $creem->customers->get(email: 'customer@example.com'); // List customers $result = $creem->customers->list(limit: 20, page: 1); // Create a billing portal session $portal = $creem->customers->createBillingPortal('cus_xxxxx'); echo $portal->url;
Subscriptions
// Get subscription details $subscription = $creem->subscriptions->get('sub_xxxxx'); echo $subscription->status->value; // 'active', 'canceled', etc. // Update subscription units $subscription = $creem->subscriptions->updateUnits('sub_xxxxx', units: 5); // Upgrade to a different product $subscription = $creem->subscriptions->upgrade('sub_xxxxx', newProductId: 'prod_yyyyy'); // Cancel subscription $subscription = $creem->subscriptions->cancel('sub_xxxxx');
Discounts
// Create a discount $discount = $creem->discounts->create([ 'code' => 'SUMMER20', 'type' => 'percentage', 'amount' => 20, 'duration' => 'forever' ]); // Get discount by ID or code $discount = $creem->discounts->get(discountId: 'disc_xxxxx'); $discount = $creem->discounts->get(code: 'SUMMER20'); // Delete a discount $creem->discounts->delete('disc_xxxxx');
Licenses
// Activate a license $license = $creem->licenses->activate( key: 'XXXX-XXXX-XXXX-XXXX', instanceName: 'My Computer' ); echo $license->instanceId; // Validate a license $license = $creem->licenses->validate( key: 'XXXX-XXXX-XXXX-XXXX', instanceId: 'inst_xxxxx' ); // Deactivate a license $license = $creem->licenses->deactivate( key: 'XXXX-XXXX-XXXX-XXXX', instanceId: 'inst_xxxxx' );
Transactions
// Search transactions $result = $creem->transactions->search( customerId: 'cus_xxxxx', limit: 50, page: 1 ); // Search by subscription $result = $creem->transactions->search( subscriptionId: 'sub_xxxxx' );
Webhook Handling
The SDK provides a WebhookHandler class for processing incoming webhooks with signature verification.
Basic Webhook Setup
use Einenlum\CreemPhpSdk\Webhook\WebhookHandler; use Einenlum\CreemPhpSdk\Exception\WebhookException; $handler = new WebhookHandler('whsec_xxxxx'); // Register event handlers $handler ->onCheckoutCompleted(function ($event) { $checkout = $event->object; // Grant access to the customer }) ->onSubscriptionActive(function ($event) { $subscription = $event->object; // Activate subscription }) ->onSubscriptionCanceled(function ($event) { $subscription = $event->object; // Handle cancellation }); // Process webhook in your endpoint try { $payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_CREEM_SIGNATURE'] ?? ''; $event = $handler->handle($payload, $signature); http_response_code(200); echo json_encode(['received' => true]); } catch (WebhookException $e) { http_response_code(400); echo json_encode(['error' => $e->getMessage()]); }
Available Webhook Events
| Event | Handler Method | Description |
|---|---|---|
checkout.completed |
onCheckoutCompleted() |
Checkout was completed |
subscription.active |
onSubscriptionActive() |
Subscription is now active |
subscription.paid |
onSubscriptionPaid() |
Subscription payment received |
subscription.canceled |
onSubscriptionCanceled() |
Subscription was canceled |
subscription.expired |
onSubscriptionExpired() |
Subscription has expired |
subscription.trialing |
onSubscriptionTrialing() |
Subscription is in trial |
subscription.paused |
onSubscriptionPaused() |
Subscription was paused |
subscription.update |
onSubscriptionUpdate() |
Subscription was updated |
refund.created |
onRefundCreated() |
Refund was created |
dispute.created |
onDisputeCreated() |
Dispute was created |
Generic Event Handler
use Einenlum\CreemPhpSdk\Enum\WebhookEvent; $handler->on(WebhookEvent::CheckoutCompleted, function ($event) { // Handle event });
Error Handling
The SDK throws specific exceptions for different error types:
use Einenlum\CreemPhpSdk\Exception\AuthenticationException; use Einenlum\CreemPhpSdk\Exception\ValidationException; use Einenlum\CreemPhpSdk\Exception\NotFoundException; use Einenlum\CreemPhpSdk\Exception\RateLimitException; use Einenlum\CreemPhpSdk\Exception\ApiException; use Einenlum\CreemPhpSdk\Exception\CreemException; try { $product = $creem->products->get('prod_xxxxx'); } catch (AuthenticationException $e) { // Invalid API key (401/403) } catch (ValidationException $e) { // Invalid request data (400) } catch (NotFoundException $e) { // Resource not found (404) } catch (RateLimitException $e) { // Too many requests (429) } catch (ApiException $e) { // Server error (500+) } catch (CreemException $e) { // Other errors }
All exceptions include response details:
try { $product = $creem->products->get('invalid_id'); } catch (CreemException $e) { echo $e->getMessage(); print_r($e->getResponseBody()); print_r($e->getResponseHeaders()); }
Enums
The SDK uses PHP enums for type-safe values:
use Einenlum\CreemPhpSdk\Enum\SubscriptionStatus; use Einenlum\CreemPhpSdk\Enum\LicenseStatus; use Einenlum\CreemPhpSdk\Enum\DiscountType; use Einenlum\CreemPhpSdk\Enum\DiscountDuration; // Check subscription status if ($subscription->status === SubscriptionStatus::Active) { // Subscription is active } // All enum values SubscriptionStatus::Active; SubscriptionStatus::Canceled; SubscriptionStatus::Expired; SubscriptionStatus::Trialing; SubscriptionStatus::Paused;
Testing
For testing your integration, use the test mode:
$creem = Creem::create( apiKey: 'creem_test_xxxxx', testMode: true );
This will route all API calls to https://test-api.creem.io.
License
MIT License