1. Go to this page and download the library: Download climactic/laravel-polar library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
climactic / laravel-polar example snippets
return [
/*
|--------------------------------------------------------------------------
| Polar Access Token
|--------------------------------------------------------------------------
|
| The Polar access token is used to authenticate with the Polar API.
| You can find your access token in the Polar dashboard > Settings
| under the "Developers" section.
|
*/
'access_token' => env('POLAR_ACCESS_TOKEN'),
/*
|--------------------------------------------------------------------------
| Polar Server
|--------------------------------------------------------------------------
|
| The Polar server environment to use for API requests.
| Available options: "production" or "sandbox"
|
| - production: https://api.polar.sh (Production environment)
| - sandbox: https://sandbox-api.polar.sh (Sandbox environment)
|
*/
'server' => env('POLAR_SERVER', 'sandbox'),
/*
|--------------------------------------------------------------------------
| Polar Webhook Secret
|--------------------------------------------------------------------------
|
| The Polar webhook secret is used to verify that the webhook requests
| are coming from Polar. You can find your webhook secret in the Polar
| dashboard > Settings > Webhooks on each registered webhook.
|
| We (the developers) recommend using a single webhook for all your
| integrations. This way you can use the same secret for all your
| integrations and you don't have to manage multiple webhooks.
|
*/
'webhook_secret' => env('POLAR_WEBHOOK_SECRET'),
/*
|--------------------------------------------------------------------------
| Polar Url Path
|--------------------------------------------------------------------------
|
| This is the base URI where routes from Polar will be served
| from. The URL built into Polar is used by default; however,
| you can modify this path as you see fit for your application.
|
*/
'path' => env('POLAR_PATH', 'polar'),
/*
|--------------------------------------------------------------------------
| Default Redirect URL
|--------------------------------------------------------------------------
|
| This is the default redirect URL that will be used when a customer
| is redirected back to your application after completing a purchase
| from a checkout session in your Polar account.
|
*/
'redirect_url' => null,
/*
|--------------------------------------------------------------------------
| Currency Locale
|--------------------------------------------------------------------------
|
| This is the default locale in which your money values are formatted in
| for display. To utilize other locales besides the default "en" locale
| verify you have to have the "intl" PHP extension installed on the system.
|
*/
'currency_locale' => env('POLAR_CURRENCY_LOCALE', 'en'),
'organization_id' => env('POLAR_ORGANIZATION_ID'),
'middleware_redirect_url' => null,
'webhook_handlers' => [
// 'subscription.created' => App\Webhooks\CustomHandler::class,
],
];
use Climactic\LaravelPolar\Billable;
class User extends Authenticatable
{
use Billable;
}
// Require a subscription of type "pro"
Route::middleware('polar.subscribed:pro')->group(function () {
// ...
});
// Require a "default" subscription on a specific Polar product
Route::middleware('polar.subscribed:default,product_id_123')->group(function () {
// ...
});
use Illuminate\Http\Request;
Route::get('/customer-portal', function (Request $request) {
return $request->user()->redirectToCustomerPortal();
});
$url = $user->customerPortalUrl();
$order->status;
$order->paid();
if ($order->hasProduct('product_id_123')) {
// ...
}
if ($user->hasPurchasedProduct('product_id_123')) {
// ...
}
// Get the invoice data for an order
$invoice = $order->invoice();
// Trigger invoice generation (async)
$order->generateInvoice();
use Climactic\LaravelPolar\LaravelPolar;
$invoice = LaravelPolar::getOrderInvoice('order-id-123');
LaravelPolar::generateOrderInvoice('order-id-123');
use Polar\Models\Components\RefundReason;
// Refund the remaining unrefunded amount
$refund = $order->refund();
// Refund a specific amount (in cents)
$refund = $order->refund(1000);
// Refund with a reason, comment, and metadata
$refund = $order->refund(1000, RefundReason::CustomerRequest, comment: 'Goodwill', metadata: ['ticket' => '123']);
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components\RefundCreate;
use Polar\Models\Components\RefundReason;
$refund = LaravelPolar::createRefund(new RefundCreate(
orderId: 'order-id-123',
reason: RefundReason::CustomerRequest,
amount: 1000,
));
// List all refunds
$refunds = LaravelPolar::listRefunds();
// The generated invoice/receipt PDF URL (null for unsynced orders)
$url = $order->receiptUrl();
// Or return a redirect response to the receipt from a controller
return $order->downloadInvoice();
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Operations\OrdersListRequest;
// List all orders
$orders = LaravelPolar::listOrders();
// List with filters
$orders = LaravelPolar::listOrders(new OrdersListRequest(
productId: 'product_id_123',
));
// Get a specific order from the API
$order = LaravelPolar::getOrder('order-id-123');
use Illuminate\Http\Request;
Route::get('/subscribe', function (Request $request) {
return $request->user()->subscribe('product_id_123');
});
$subscription = $user->subscription();
if ($user->subscribed()) {
// ...
}
if ($user->subscription()->valid()) {
// ...
}
if ($user->subscription()->hasProduct('product_id_123')) {
// ...
}
if ($user->subscribedToProduct('product_id_123')) {
// ...
}
if ($user->subscribed('swimming')) {
// ...
}
if ($user->subscribedToProduct('product_id_123', 'swimming')) {
// ...
}
if ($user->subscription()->cancelled()) {
// ...
}
if ($user->subscription()->onGracePeriod()) {
// ...
}
if ($user->subscription()->pastDue()) {
// ...
}
// Get all active subscriptions...
$subscriptions = Subscription::query()->active()->get();
// Get all of the cancelled subscriptions for a specific user...
$subscriptions = $user->subscriptions()->cancelled()->get();
if ($user->subscription()->onGracePeriod()) {
// ...
}
$user->subscription()->resume();
$user->subscription()->revoke();
// Apply / remove a discount
$user->subscription()->applyDiscount('discount-id');
$user->subscription()->removeDiscount();
// Update the trial end date
$user->subscription()->updateTrial(new DateTime('+14 days'));
// Read the current trial end (Carbon|null)
$endsAt = $user->subscription()->trialEndsAt();
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Operations\SubscriptionsListRequest;
// List all subscriptions
$subscriptions = LaravelPolar::listSubscriptions();
// Get a specific subscription
$subscription = LaravelPolar::getSubscription('sub-id-123');
// Revoke a subscription via the API
$subscription = LaravelPolar::revokeSubscription('sub-id-123');
// Check if a subscription is on trial
$subscription->onTrial();
// Check if a subscription's trial has expired
$subscription->hasExpiredTrial();
// Filter subscriptions by trial status
Subscription::query()->onTrial()->get();
// Check if the customer is on a generic trial
$customer->onGenericTrial();
// Check if the customer's generic trial has expired
$customer->hasExpiredGenericTrial();
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components;
$benefit = LaravelPolar::createBenefit(
new Components\BenefitCustomCreate(
description: 'Premium Support',
organizationId: 'your-org-id',
properties: new Components\BenefitCustomCreateProperties(),
)
);
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components;
$benefit = LaravelPolar::updateBenefit(
'benefit-id-123',
new Components\BenefitCustomUpdate(
description: 'Updated Premium Support',
properties: new Components\BenefitCustomUpdateProperties(),
)
);
LaravelPolar::deleteBenefit('benefit-id-123');
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components\CustomerCreate;
use Polar\Models\Components\CustomerUpdate;
use Polar\Models\Operations\CustomersListRequest;
// Create a customer
$customer = LaravelPolar::createCustomer(new CustomerCreate(
email: '[email protected]',
));
// Get a customer
$customer = LaravelPolar::getCustomer('customer-id-123');
// Get a customer by external ID
$customer = LaravelPolar::getCustomerByExternalId('your-external-id');
// Update a customer
$customer = LaravelPolar::updateCustomer('customer-id-123', new CustomerUpdate(
name: 'Updated Name',
));
// List all customers
$customers = LaravelPolar::listCustomers();
// Delete a customer
LaravelPolar::deleteCustomer('customer-id-123');
// Get customer state (active subscriptions, orders, etc.)
$state = LaravelPolar::getCustomerState('customer-id-123');
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components;
// Create a product
$product = LaravelPolar::createProduct(new Components\ProductCreateRecurring(
name: 'Pro Plan',
prices: [/* ... */],
));
// Get a product
$product = LaravelPolar::getProduct('product-id-123');
// Update a product
$product = LaravelPolar::updateProduct('product-id-123', new Components\ProductUpdate(
name: 'Updated Pro Plan',
));
// Update product benefits
$product = LaravelPolar::updateProductBenefits('product-id-123', new Components\ProductBenefitsUpdate(
benefits: ['benefit-id-1', 'benefit-id-2'],
));
// List products (already existed)
$products = LaravelPolar::listProducts();
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components;
// Create a percentage discount
$discount = LaravelPolar::createDiscount(
new Components\DiscountPercentageOnceForeverDurationCreate(
name: '20% Off',
basisPoints: 2000, // 20%
organizationId: 'your-org-id',
)
);
// List discounts
$discounts = LaravelPolar::listDiscounts();
// Get a discount
$discount = LaravelPolar::getDiscount('discount-id-123');
// Update a discount
$discount = LaravelPolar::updateDiscount('discount-id-123', new Components\DiscountUpdate(
name: 'Updated Discount',
));
// Delete a discount
LaravelPolar::deleteDiscount('discount-id-123');
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components;
// List all license keys
$keys = LaravelPolar::listLicenseKeys();
// Get a specific license key
$key = LaravelPolar::getLicenseKey('key-id-123');
// Validate a license key
$validated = LaravelPolar::validateLicenseKey(new Components\LicenseKeyValidate(
key: 'LICENSE-KEY-VALUE',
organizationId: 'your-org-id',
));
// Activate a license key
$activation = LaravelPolar::activateLicenseKey(new Components\LicenseKeyActivate(
key: 'LICENSE-KEY-VALUE',
organizationId: 'your-org-id',
label: 'My Device',
));
// Deactivate a license key
LaravelPolar::deactivateLicenseKey(new Components\LicenseKeyDeactivate(
key: 'LICENSE-KEY-VALUE',
organizationId: 'your-org-id',
activationId: 'activation-id',
));
// List license keys (optionally filter by benefit ID)
$keys = $user->licenseKeys();
$keys = $user->licenseKeys(benefitId: 'benefit-id-123');
// Validate a license key
$validated = $user->validateLicenseKey('LICENSE-KEY-VALUE');
// Activate a license key on a device
$activation = $user->activateLicenseKey('LICENSE-KEY-VALUE', 'My Laptop');
// Deactivate a license key
$user->deactivateLicenseKey('LICENSE-KEY-VALUE', 'activation-id');
// Override the config org ID for a specific call
$validated = $user->validateLicenseKey('LICENSE-KEY-VALUE', organizationId: 'other-org-id');
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components;
$updated = LaravelPolar::updateLicenseKey('key-id-123', new Components\LicenseKeyUpdate(
// e.g. status, usage limits, expiry...
));
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components;
// List the seats on a subscription or order
$seats = LaravelPolar::listSeats(subscriptionId: 'sub-id');
// Assign a seat by email, customer id, or external customer id
$seat = LaravelPolar::assignSeat(new Components\SeatAssign(
subscriptionId: 'sub-id',
email: '[email protected]',
));
// Revoke or resend an invitation
LaravelPolar::revokeSeat('seat-id');
LaravelPolar::resendSeatInvitation('seat-id');
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components;
$link = LaravelPolar::createCheckoutLink(new Components\CheckoutLinkCreateProducts(
products: ['product-id'],
));
$link = LaravelPolar::getCheckoutLink('checkout-link-id');
$link = LaravelPolar::updateCheckoutLink('checkout-link-id', new Components\CheckoutLinkUpdate());
$links = LaravelPolar::listCheckoutLinks();
LaravelPolar::deleteCheckoutLink('checkout-link-id');
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Components;
$field = LaravelPolar::createCustomField(new Components\CustomFieldCreateText(
slug: 'referral_source',
name: 'Referral source',
properties: new Components\CustomFieldTextProperties(),
));
$field = LaravelPolar::getCustomField('custom-field-id');
$field = LaravelPolar::updateCustomField('custom-field-id', new Components\CustomFieldUpdateText());
$fields = LaravelPolar::listCustomFields();
LaravelPolar::deleteCustomField('custom-field-id');
// Read the custom field data submitted at checkout for an order
$data = $order->customFieldData();
use Climactic\LaravelPolar\LaravelPolar;
use Polar\Models\Operations;
use Polar\Models\Components;
use Brick\DateTime\LocalDate;
// Analytics metrics for a period
$metrics = LaravelPolar::getMetrics(new Operations\MetricsGetRequest(
startDate: LocalDate::of(2024, 1, 1),
endDate: LocalDate::of(2024, 1, 31),
interval: Components\TimeInterval::Day,
));
// Organizations
$org = LaravelPolar::getOrganization('org-id');
$orgs = LaravelPolar::listOrganizations();
// Files
$files = LaravelPolar::listFiles();
// Collection of payment methods for the billable's customer
$methods = $user->paymentMethods();
// Delete one
$user->deletePaymentMethod('payment-method-id');
use Climactic\LaravelPolar\LaravelPolar;
$meter = LaravelPolar::getCustomerMeter('meter-id-123');
// Events with convenience properties
public function handle(OrderCreated $event): void
{
$order = $event->order; // Direct access
$billable = $event->billable; // Direct access
}
// Events with only payload
public function handle(CheckoutCreated $event): void
{
$checkout = $event->payload->checkout; // Access via payload
}
namespace App\Listeners;
use Climactic\LaravelPolar\Events\CheckoutCreated;
class HandleCheckoutCreated
{
public function handle(CheckoutCreated $event): void
{
$checkout = $event->payload->checkout;
// Handle checkout creation...
}
}
namespace App\Listeners;
use Climactic\LaravelPolar\Events\SubscriptionUpdated;
class HandleSubscriptionUpdated
{
public function handle(SubscriptionUpdated $event): void
{
$subscription = $event->subscription;
// Handle subscription update...
}
}
namespace App\Listeners;
use Climactic\LaravelPolar\Events\CheckoutCreated;
use Climactic\LaravelPolar\Events\SubscriptionUpdated;
use Climactic\LaravelPolar\Events\WebhookHandled;
use Illuminate\Events\Dispatcher;
class PolarEventListener
{
/**
* Handle received Polar webhooks.
*/
public function handleWebhookHandled(WebhookHandled $event): void
{
if ($event->payload['type'] === 'subscription.updated') {
// Handle the incoming event...
}
}
/**
* Handle checkout created events.
*/
public function handleCheckoutCreated(CheckoutCreated $event): void
{
$checkout = $event->payload->checkout;
// Handle checkout creation...
}
/**
* Handle subscription updated events.
*/
public function handleSubscriptionUpdated(SubscriptionUpdated $event): void
{
$subscription = $event->subscription;
// Handle subscription update...
}
/**
* Register the listeners for the subscriber.
*/
public function subscribe(Dispatcher $events): void
{
$events->listen(
WebhookHandled::class,
[self::class, 'handleWebhookHandled']
);
$events->listen(
CheckoutCreated::class,
[self::class, 'handleCheckoutCreated']
);
$events->listen(
SubscriptionUpdated::class,
[self::class, 'handleSubscriptionUpdated']
);
}
}
namespace App\Providers;
use App\Listeners\HandleCheckoutCreated;
use App\Listeners\HandleSubscriptionUpdated;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Climactic\LaravelPolar\Events\CheckoutCreated;
use Climactic\LaravelPolar\Events\SubscriptionUpdated;
use Climactic\LaravelPolar\Events\WebhookHandled;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
WebhookHandled::class => [
// Add your listeners here
],
CheckoutCreated::class => [
HandleCheckoutCreated::class,
],
SubscriptionUpdated::class => [
HandleSubscriptionUpdated::class,
],
];
}
namespace App\Providers;
use App\Listeners\PolarEventListener;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
protected $subscribe = [
PolarEventListener::class,
];
}
namespace App\Webhooks;
use Climactic\LaravelPolar\Contracts\WebhookHandler;
class CustomSubscriptionHandler implements WebhookHandler
{
public function handle(array $data, \DateTime $timestamp, string $type): ?string
{
// Your custom logic here...
// $data contains the webhook payload
// Return null to mark as handled, or a string reason to mark as skipped
return null;
}
}
use Climactic\LaravelPolar\LaravelPolar;
$fake = LaravelPolar::fake();
// Run code that calls LaravelPolar methods...
LaravelPolar::listProducts();
// Assert methods were called
$fake->assertCalled('listProducts');
$fake->assertNotCalled('createProduct');
$fake->assertCalledTimes('listProducts', 1);
$fake->assertNothingCalled(); // fails if any method was called