PHP code example of climactic / laravel-polar

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;
}

Route::middleware('polar.subscribed')->group(function () {
    Route::get('/dashboard', DashboardController::class);
});

// 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 () {
    // ...
});

'middleware_redirect_url' => '/billing',

->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: [
        'polar/*',
    ]);
})

use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->checkout(['product_id_123']);
});

use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->checkout(['product_id_123', 'product_id_456']);
});

use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->charge(1000, ['product_id_123']);
});

use Illuminate\Http\Request;

Route::get('/billing', function (Request $request) {
    $checkout = $request->user()->checkout(['product_id_123'])
        ->withEmbedOrigin(config('app.url'));

    return view('billing', ['checkout' => $checkout]);
});

public function polarName(): ?string; // default: $model->name
public function polarEmail(): ?string; // default: $model->email

$request->user()->checkout('variant-id')
    ->withSuccessUrl(url('/success'));

$request->user()->checkout('variant-id')
    ->withSuccessUrl(url('/success?checkout_id={CHECKOUT_ID}'));

$request->user()->checkout('variant-id')
    ->withMetadata(['key' => 'value']);

$request->user()->checkout('variant-id')
    ->withCustomerMetadata(['key' => 'value']);

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();

$refunds = $order->refunds(); // Collection<Refund>

// 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();

Subscription::query()->incomplete();
Subscription::query()->incompleteExpired();
Subscription::query()->onTrial();
Subscription::query()->active();
Subscription::query()->pastDue();
Subscription::query()->unpaid();
Subscription::query()->cancelled();

use App\Models\User;

$user = User::find(1);

$user->subscription()->swap('product_id_123');

$user = User::find(1);

$user->subscription()->swapAndInvoice('product_id_123');

$user = User::find(1);

$checkout = $user->subscribe('product_id_123', 'swimming');

$user = User::find(1);

// Retrieve the swimming subscription type...
$subscription = $user->subscription('swimming');

// Swap plans for the gym subscription type...
$user->subscription('gym')->swap('product_id_123');

// Cancel the swimming subscription...
$user->subscription('swimming')->cancel();

$user = User::find(1);

$user->subscription()->cancel();

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(),
    )
);

$benefits = $user->listBenefits('your-org-id');

$benefit = $user->getBenefit('benefit-id-123');

$grants = $user->listBenefitGrants('benefit-id-123');

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');

$user->checkout(['product_id_123'])
    ->withDiscountId('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');

$subscription->seats();
$subscription->assignSeat(email: '[email protected]');
$subscription->revokeSeat('seat-id');
$subscription->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');

$user->ingestUsageEvent('api_request', [
    'endpoint' => '/api/v1/data',
    'method' => 'GET',
    'duration_ms' => 145,
]);

$user->ingestUsageEvents([
    [
        'eventName' => 'api_request',
        'properties' => [
            'endpoint' => '/api/v1/data',
            'method' => 'GET',
        ],
    ],
    [
        'eventName' => 'storage_used',
        'properties' => [
            'bytes' => 1048576,
        ],
        'timestamp' => time(),
    ],
]);

$meters = $user->listCustomerMeters();

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,
    ];
}

// config/polar.php
'webhook_handlers' => [
    'subscription.created' => App\Webhooks\CustomSubscriptionHandler::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

$fake = LaravelPolar::fake();
$fake->stub('listProducts', $myProductList);

$result = LaravelPolar::listProducts(); // returns $myProductList

$fake->assertCalledWith('getProduct', function (string $id) {
    return $id === 'product-id-123';
});

$fake->tearDown();
bash
php artisan polar:install
bash
php artisan vendor:publish --tag="polar-migrations"
bash
php artisan vendor:publish --tag="polar-config"
bash
php artisan vendor:publish --tag="polar-views"
bash
php artisan migrate
jsx
// button.{jsx,tsx}

export function Button() {
  return (
    <a href="<CHECKOUT_LINK>" data-polar-checkout>Buy now</a>
  );
}
blade
<table>
    @foreach ($user->orders as $order)
        <td>{{ $order->ordered_at->toFormattedDateString() }}</td>
        <td>{{ $order->polar_id }}</td>
        <td>{{ $order->amount }}</td>
        <td>{{ $order->tax_amount }}</td>
        <td>{{ $order->refunded_amount }}</td>
        <td>{{ $order->refunded_tax_amount }}</td>
        <td>{{ $order->currency }}</td>
        <!-- Add more columns as needed -->
    @endforeach
</table>