Subscription Plans

Listing subscription plans

You can use the Klub plugin API to retrieve the available subscription plans and check which of them the current member owns.

Checking ownership

The easiest way to check if a user owns a subscription is below. However, remember that it will request Stripe for every plan checked. But it should be ok if you do not have too many.

foreach (klub()->plans() as $plan) {
    $subscription = $user->owns($plan['id']);
    if($subscription) {
       // is owned
    }
}

A more performant way would be to retrieve all owned subscriptions first and then compare the price ID values.

$subscriptions = $user->subscriptions();
foreach (klub()->plans() as $plan) {
    foreach($subscriptions as $subscription) {
        if ($plan['price'] === $subscription['items']['data'][0]['price']['id']) {
            // is owned
        }
    }
}

State & Suggested Action

Subscription plans can be in various states, and each targeted action requires a different endpoint. To keep this manageable the Klub plugin has a subscriptionAction()-helper method. You can use the state to structure your frontend response and the action to initiate changes.

Possible states are: subscribe, change, renew or cancel

The Klub plugin is limited to suggesting one action. But you can always make the form call any of the following endpoints.

After any action, it will return to the page defined by the redirect form data.

<?php

foreach (klub()->plans()as $plan) {
    [$state, $action] = klub()->provider()->subscriptionAction($plan['id']);
    ?>
    <div>
        <p>
            <?= $plan['product']['name'] ?><br>
            <?= $plan['nickname'] ?><br>
            <?= $plan['price'] ?>
        </p>
        <!-- form with POST to prevent browser URL preloading -->
        <form method="post" action="<?= $action ?>">
            <input type="hidden" name="redirect" value="<?= $page->url() ?>">
            <input type="hidden" name="token" value="<?= csrf() ?>">

            <?php if ($state === 'cancel') { ?>
                <button type="submit">Cancel</button>
                <?php $subscription = klub()->provider()->findSubscription($plan['id']); ?>
                <small>Your plan will be cancelled but is still available until the end of your billing period on <?= date('Y-m-d', A::get($subscription, 'current_period_end')) ?></small>

            <?php } elseif ($state === 'renew') { ?>
                <button type="submit">Renew plan</button>
                <?php $subscription = klub()->provider()->findSubscription($plan['id']); ?>
                <small>Your plan has been cancelled but is still available until the end of your billing period on <?= date('Y-m-d', A::get($subscription, 'current_period_end')) ?></small>

            <?php } elseif ($state === 'change') { ?>
                <button type="submit">Change</button>

            <?php } elseif ($state === 'subscribe') { ?>
                <button type="submit">Subscribe</button>
            <?php } ?>
        </form>
    </div>
<?php } ?>

Endpoint: klub/subscribe

Submitting the form with the given Stripe price ID to the klub/subscribe-endpoint will initiate a new Stripe Checkout session and purchase the subscription plan.

Endpoint: klub/change

Submitting the form with the given Stripe subscription and price ID to the klub/change-endpoint will swap between pricing tiers of the same subscription plan.

You need to set up multiple recurring prices for the same product in Stripe to make this work as intended.

This will be done directly without asking the user for their payment details.

Endpoint: klub/cancel

Submitting the form with the given Stripe subscription ID to the klub/cancel-endpoint will cancel the subscription plan but keep it available until the end of the billing period.

Endpoint: klub/renew

Submitting the form with the given Stripe subscription ID to the klub/renew-endpoint will resume billing for the subscription plan.

This will be done directly without asking the user for their payment details.

Fulfilment hook

If you want to perform additional steps for example after the completion of a recurring purchase, you can add your logic to the klub.subscription:after-hook provided by the Klub plugin.

You can find all hooks in the guide.

site/config/config.php
<?php

return [
  'hooks' => [
     'klub.subscription:after' => function (User $user, array $session) {
        // your code here
     }
  ],
  // other options
];

Checking for ownership of Subscriptions

If you have the product ID/name or the price ID/name, you can use them to retrieve ownership information. However, keep in mind that each time you call this function, you will be requesting information from the Stripe API. Therefore, avoid using it in foreach loops or when performing time-critical operations.

if ($user->owns($searchTerm)) {
   // ...
}
This only works for subscriptions. You need to track ownership of purchased products yourself using the fulfilment hook. The plugin tries to do that for you automatically - see next chapter.
Kirby Klub is not affiliated with the developers of Kirby CMS. We are merely standing on the shoulder of giants.
© 2024 Bruno Meilick All rights reserved.