Guides & tutorials

Upgrade and downgrade subscriptions with Stripe

Table of contents

Learn how to create a form and a flow that will allow users to change their subscription plan. The context in which we are going to use this form is when the user is already logged in and simply wants to update the subscription plan to our service.

Previous requirements

To build this use case in a few minutes you just need:

  • A user JSON web token. You will need a secure JWT token with the current user information (customer ID and current subscription ID).
  • Arengu. We will use it to create the form and its server-side logic.
  • A Stripe account. We will manage payments and subscriptions with this service, which you can easily integrate into Arengu's forms and flows thanks to native actions.

What are we going to build?

A two-step form that will allow the user to upgrade or downgrade their subscription plan and make the payment.

This form will run a flow between steps to obtain the customer's ID in Stripe, automatically configure the payment field and update the data once the user has made the payment.

1. Create a two-step form

First, go to Arengu and build a form with 2 steps and the following fields on each one:

Step 1: Choice field

Include a choice field in the first step of the form to allow users to choose the subscription plan they want to switch to. 

Set this field like this:

  • Field ID: replace the default ID with "plan" for simplicity.
  • Required: enable the required checkbox.
  • Options: list the subscription plans that you offer to the user.
  • Internal values: copy the ID of each subscription plan in Stripe and paste it in the corresponding input. You will find them in the Products section of your Stripe account.

Step 2: Payment field

Add a payment field with the following settings:

  • Field ID: replace the default ID with "payment" for simplicity.
  • Required: enable the required checkbox.
  • Publishable key & Secret key: copy these keys from your Stripe account and paste each of them on the proper field.
  • Payment type: choose the “Subscription” option.
  • Action: choose the “Update subscription” option.

We will finish the configuration of this field with: 

  • Subscription ID: reference the {{state.subscriptionId}} variable, which we will store in a flow action.
  • Price ID: reference the {{plan}} variable from the choice action of the first step of the form.
  • Customer action: choose the “Update customer” option.
  • Customer ID: reference the {{state.customerId}} variable, which we will store in a flow action.

Hidden field: Session token

Add a hidden field to the form, by clicking on the eye icon in the upper left corner. 

To set up this field:

  • Hidden field: include the “token” parameter in the first input and leave the second input empty. It will auto-populate with the proper value from the session URL.

2. Build the flow

To create the server-side logic, go to the Flows tab, click on the + icon to create a flow connected to the first step of the form and publish the changes.

To make this form work we need a flow to:

  • Check the session JSON Web Token from the hidden field of the form and show an error message if it is not valid.
  • Get customer data from our customer list in Stripe.
  • Store the IDs of the customer and the current subscription.
  • Redirect to the second step of the form, so the user can pay for the new subscription.

2.1. Verify the JSON Web Token

Configure the first action of the flow as follows:

  • Token: reference the {{input.body.token}} variable from the hidden field of the form.
  • Secret or public key: paste the same key with which the JWT has been signed to check that it has not been corrupted.

2.2. Set up the conditional logic

Include an If/then condition action and configure the condition as follows:

  • Condition: reference the {{verifyJWT.valid}} variable from the outputs of the previous action.

Then add a Show error message action on the False branch and write a custom message to display on the form.

2.3. Get customer data from Stripe

On the True branch, include a Get customer action and configure it like this:

  • Secret key: paste the Secret key from your Stripe account.
  • Customer ID: reference the {{verifyJWT.payload.customerId}} variable from the outputs of the Verify JSW action.

2.4. Store state variables

Next, we will store the customer data that we need to configure the payment field of the second step of the form. The Store state variable action allows you to save custom variables and then recall them in the form and any other flow connected to it.

In this case, we need to set up this action as follows:

  • Data fields: write the name of the custom variable in the first input and reference the proper variable on the second one. In this case, we will store as “customerId” the variable {{verifyJWT.payload.customerId}} and as “subscriptionId” the {{verifyJWT.payload.subscriptionId}} from the outputs of the Verify JWT action.

2.5. Go to the next step of the form

Finally, close this branch with a Go to the next form step action, which does not need to be configured, and publish the changes.

3.  Preview, test and debug it

Go back to the form editor and click on the Preview button to test the form. You can check if everything is working properly on the Executions tab of the flow.


You might like to read

Getting started with Arengu

Arengu allows you to build all your user flows connected to your current stack, and avoids coding all the UI, complex integrations, validations or logic from scratch. Try it for free and start building faster and scaling your application needs as they grow.