Update billing details for a subscription

Craft CMS Asked on December 1, 2020

The Craft Commerce config allows you to set updatebillingdetailsurl. The docs say,

The URL for a user to resolve billing issues with their subscription.

There’s an example of this in the example templates that come with Commerce and this uses getBillingIssueResolveFormHtml().

However, rather than resolve an issue, what I’m looking for is a way for customers with a subscription (via Stripe) to be able to update their billing information before there is a billing issue. Often customers realise their card has expired or want to change their card before the subscription renews, especially as we send emails to notify them about renewals. What’s the best way to create that form, or allow someone to do that?

One Answer

I've solved this in the past by just showing the payment sources, and allowing the user to delete existing payment sources:

{% set paymentSources = craft.commerce.paymentSources.getAllPaymentSourcesByUserId( %}

{% if paymentSources %}
                <th scope="col">
                    Card details
                <th scope="col">
        {% for paymentSource in paymentSources %}
                <td>{{ paymentSource.description }}</td>
                    <form method="post">
                        {{ csrfInput() }}
                        {{ actionInput('commerce/payment-sources/delete') }}
                        {{ redirectInput(entry.uri) }}
                        <input type="hidden" name="id" value="{{ }}"/>
                        <button type="submit">Delete</button>
        {% endfor %}
{% endif %}

You can then show a form to add a new payment source:

{% set customer = craft.commerce.customers.getCustomer() %}
    Note: this next line fetches a single subscription - if you support multiple 
    subscriptions, you'll need to do it a little differently 
{% set currentSubscription = customer.getSubscriptions()|first %}
{% set plan = craft.commerce.plans.getPlanById(currentSubscription.planId) %}
{% set gateway = plan.getGateway() %}

<form method="post" accept-charset="UTF-8" autocomplete="off" novalidate>
    {{ csrfInput() }}
    {{ actionInput('commerce/payment-sources/add') }}
    {{ redirectInput(entry.uri) }}
    <input type="hidden" name="gatewayId" value="{{ }}">

    {{ gateway.getPaymentFormHtml({})|raw }}

    <button type="submit">Add card</button>      

This is probably the simplest answer to your question, though you can get creative with how you present the payment sources and the add card form to the user.

Correct answer by Martin Spain on December 1, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP