Self Service

You may want to allow your users to self-service their recurring payments.

You can offer your users the option to end, modify, and restart their subscriptions, from the front-end.

End Subscription #

You can allow a user to cancel their own recurring payment subscription from the front-end. This requires the user is logged in and is the owner of the subscription. We perform additional safety and validation checks on all possible user facing actions.

To setup the option for user's to end their subscriptions you need to add a new form in a protected user area.

Usage

The user must post to an action endpoint of charge/endSubscription, with the subscriptionId for the subscription that is being cancelled.

An example form for this might look like:

<form class="form-horizontal" method="post">
    {{ forms.hidden({ name: 'action', value: 'charge/endSubscription'}) }}
    {{ forms.hidden({ name: 'subscriptionId', value: charge.subscription.id }) }}

     <input type="submit" class="btn btn-danger" value="End this Subscription"/>
</form>

Subscriptions Cancel at Period End When a user (or Admin) cancels a subscription, the subscription moves to a cancelled state. The subscription only fully ends, once the current period ends. ie. If a user cancels their subscription 10 days into a 30 day recurring subscription, they'll still have access for the remaining 20 days. A cancelled subscription will move to an ended state once past the final period date.

Make sure you handle all the possible states Subscriptions can be in a number of additional states, and you need to make sure your users see the appropriate language and available actions. A subscription can be in an active, cancelled or ended state.

When giving your users the options to cancel you need to make sure you're showing the correct options and details for a subscription.

You can check the subscription status like charge.subscription.status. Only active subscriptions can be cancelled. In other states you'll need to show updated language.

A fuller example for a self-service page is included in the charge demo templates, and might look like this:

{% set charges = craft.charge.getChargesByUser %}
{% if currentUser %}
<p>You have the following charges :</p>

{% for charge in charges %}
<div class="panel panel-default">
    <div class="panel-body">
        {{ charge.id }} <code>{{ charge.mode }}</code> <strong>{{ charge.type }}</strong>
        <ul>
            {% for payment in charge.payments %}
                <li>{{ payment.formatAmount }} paid on {{ payment.dateCreated }}</li>
            {% endfor %}
        </ul>

        {% if charge.type == 'recurring' %}
            <p>This is a recurring Charge</p>
            <p>Subscription is : <span class="label label-success">{{ charge.subscription.status }}</span></p>

            {% if charge.subscription.status == 'active' %}
                <h4>End Subscription</h4>
                <p>You can cancel your recurring payment. <br/>
                    You will still have access until the end of the current payment period on <em>{{ charge.subscription.currentPeriodEnd | date }}</em></p>

                <form class="form-horizontal" method="post">
                    {{ forms.hidden({ name: 'action', value: 'charge/endSubscription'}) }}
                    {{ forms.hidden({ name: 'subscriptionId', value: charge.subscription.id }) }}

                    <input type="submit" class="btn btn-danger" value="End this Subscription"/>
                </form>
            {% endif %}

            {% if charge.subscription.status == 'cancelled' %}
                <p>This subscription has been cancelled. You'll still have access until <em>{{ charge.subscription.currentPeriodEnd | date }}</em>.</p>
            {% endif %}
        {% endif %}
    </div>
</div>
{% endfor %}
{% else %}
<p>Sorry, you need to be logged in to view your Charges.</p>
{% endif %}

The same options for ending a subscription are available to admins from the CP, along with options to Refund specific payments.

Further options to alter active subscriptions, including options to pro-rate the payments are on the roadmap for upcoming releases.

Reactivating a Cancelled Subscription #

When a user cancel's their subscription, it will run until the end of the currently active period.

For example - if they are normally billed on the 28th of each month, and they cancel on the 4th, they'll still have access through till the 28th of the current month.

In this case, their account moves to a cancelled status.

You can offer the option for customers to reactivate a subscription while it is in a cancelled by posting to the charge/reactivateSubscription endpoint.

It'd look something like this:

{% if subscription.status == 'cancelled' %}
<p>The subscription is currently active but has been <span class="label label-warning">cancelled</span> and will not renew at the end of the current billing period.</p>
<p>You will still have access to the site until <em>{{ subscription.currentPeriodEnd | date }}</em>.</p>

<hr/>

<p><strong>Reactivate subscription?</strong></p>
<p>Changed your mind? No problem. You can reactivate your subscription during the cancellation period with no affect on your ongoing subscription.</p>

<form class="form-horizontal" method="post">
    {{ forms.hidden({ name: 'action', value: 'charge/reactivateSubscription'}) }}
    {{ forms.hidden({ name: 'subscriptionId', value: subscription.id }) }}
    {{ getCsrfInput() }}

    <input type="submit" class="btn btn-primary" value="Reactivate your Subscription"/>
</form>
{% endif %}

Moving Subscriptions #

Allowing a user to move subscriptions follows almost exactly the same format as allowing them to pick their plan during the first setup. Simply point the form to the charge/updateSubscription endpoint instead. Think of a Change subscription form, like a payment form without the payment card inputs.

Below the example _planChoice template is exactly the same as the one used during the payment form.

{% if subscription.status == 'active' %}
<h4>Change Your Subscription</h4>
<p>You can update your subscription.</p>

<form class="form-horizontal" method="post">
    {{ forms.hidden({ name: 'action', value: 'charge/updateSubscription'}) }}
    {{ forms.hidden({ name: 'subscriptionId', value: subscription.id }) }}
    {{ getCsrfInput() }}

     {% include 'charge/account/_planChoice' with  { activePlan: 'monthly' } %}
     {% if allErrors is defined %}
         {{ forms.errorBlock(allErrors) }}
     {% endif %}
     <input type="submit" class="btn btn-primary" value="Update your Subscription"/>
</form>
{% endif %}