Plain Dev Blog
← Back to all posts

Stripe: Pending Updates

Β·

Stripe: Pending Updates

When something happens with your Subscriptions (most of the times) Stripe sends events for it and it makes certain changes to the status, to the dates like the trial_ends_at , ends_at and so forth.

For example when a subscription is created with a faulty payment method it goes to incomplete status and the payment should be confirmed in order to change the subscription status to active which is normal way a handling those situations because it gives the user the ability to resume the subscription when a proper payment method is added.

But not in every case you need that behavior to happen like this that's why Stripe provides the Pending Updates which allows postponing updates for your subscriptions, for example: A user has an active subscription, on the billing cycle something went wrong and no payment was made

Instead of changing the status to past_due Stripe can "wait" for a successful payment and then sent a web-hook event to your system to inform that the user has paid, which allows you to provide a better user experience and to spare your users of the confirm process and in the mean time to restrict their access to the your service.

Prerequisites

  • collection method of the subscriptions should be charge_automatically

  • The payment method used should be one of those

Usage

You can use pending updates with:

How to use it with subscription update:

// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
// Find your keys at https://dashboard.stripe.com/apikeys.
$stripe = new \Stripe\StripeClient('sk_test_51RRquARcy99RV4czPtcirlPrgNttCr026zIC57B3Y9ZsYW6LWUv0sZv2sOgizGtNGijy6sMFPubOpO1bqTuM2lRg00t5TbV7SG');

$subscription = $stripe->subscriptions->retrieve('sub_49ty4767H20z6a');

$stripe->subscriptions->update(
  $subscription->id,
  [
    'payment_behavior' => 'pending_if_incomplete',
    'proration_behavior' => 'always_invoice',
    'items' => [
      [
        'id' => $subscription->items->data[0]->id,
        'price' => 'price_CBb6IXqvTLXp3f',
      ],
    ],
  ]
);

if the everything goes smooth and everything is well and good, the subscription is updated, if the things go sideways you will receive:

{
  "id": "sub_49ty4767H20z6a",
  "object": "subscription",
  "application_fee_percent": null,
  "pending_update": {
    "expires_at": 1571194285,
    "subscription_items": [
      {
        "id": "si_09IkI4u3ZypJUk5onGUZpe8O",
        "price": "price_CBb6IXqvTLXp3f"
      }
    ]
  }
}

Failed payments

As stated in the Stripe own documentation:

After making the update, check the pending_update hash on the subscription or listen for the customer.subscription.updated event in your webhook. A populated pending_update hash means the payment failed and your subscription update isn’t applied.

In other words: "we give you the heads up, the rest is up to you"

For these cases you need create custom logic that will handle:

there some things regarding the fields that can be upgraded, not all subscription fields can be upgraded a complete list can be found here

Expiration

If nothing happens the pending update can expire that's why you need to pay attention to the expired_at date when it passes Stripe will void the invoice and removes the update.

A pending update’s expired_at time matches the first occurrence of either the trial end or the earliest items.current period end. This applies if either time is within 23 hours of the update request. Otherwise, the expiration is 23 hours from the update request.

Webhook events

The are a few events fired in regards of the pending update:

Event

Purpose

customer.subscription.updated

Receive notifications for subscriptions, checking for the pending_updates hash and resolving payment failures if needed.

customer.subscription.pending_update_applied

Receive notifications when pending updates are applied so that you can take further actions like upgrading, downgrading, provisioning, or deprovisioning services.

customer.subscription.pending_update_expired

Receive notifications when pending updates expire or are automatically voided, and if needed, try the update request again.

Conclusion

Stripe provides a lot of powerful features and this is one of them, using such feature can make the UX for your customers much better and will allow you be more "flexible" in some cases. Well documented(as always), it easy to setup(depends on the project of course).

Share this post