More Tutorials

Integrate Chargebee with your Next.js app using chargebee-init

chargebee-init
Checkout

Introduction

chargebee-init is a new CLI for the Node.js ecosystem which helps with integrating various Chargebee services to an existing application. With minimal setup and configuration, it generates the required routes and handlers for most commonly used Chargebee features like:

  • Checkout one-time charges
  • Checkout a subscription plan
  • Manage payment methods
  • Customer portal
  • Handle incoming webhook events

Currently supported frameworks are Next.js and Express. Although the rest of this tutorial focuses on Next.js, the steps outlined will broadly be similar for any supported framework.

Requirements

For the purposes of this tutorial, we will bootstrap a Next.js app using create-next-app. Skip to running chargebee-init if you have an existing app.

Setup a Next.js app

To bootstrap a Next.js app, run npx create-next-app next. The important options to keep in mind are:

  • Use TypeScript as chargebee-init only generates TypeScript files for now
  • Use App Router

The options and output should look something like this:

Create a Next.js app by running `npx create-next-app`
Create a Next.js app by running `npx create-next-app`

To make sure everything works, run the following commands and point your browser to http://localhost:3000. You should be greeted by your Next.js app!

npm run build
npm run dev

For additional help regarding Next.js, please refer to their docs.

Running chargebee-init

With a working Next.js app, we can now run chargebee-init! In your app directory, simply run npx chargebee-init to download and run the CLI.

Note: If you use git or a similar SCM tool to manage your source code, create a new branch before you proceed to test the Chargebee features in isolation before merging to your main branch.

cd next
git checkout -b feat/chargebee-init
npx chargebee-init

The tool uses sensible defaults where possible, and requires only a couple of choices to be made. If all checks pass, you will see a bunch of new files and an updated package.json file:

Running chargebee-init
Running chargebee-init

Since the CLI creates and updates files in your app directory, it performs various checks before it creates/updates the required files:

  1. Ensure there is a valid package.json in the root directory
  2. Validate if "next" is a dependency and it's version matches >=15
  3. Ensure a clean working git tree. If the git command isn't available, or if the app directory has uncommitted changes, a warning is raised which can be overridden
  4. Determine if the files are to be written to app or src/app

Let's take a quick look at layout of the chargebee directory and review one of generated files.

Implementation details

Your app directory will now have a layout similar to the one shown below. Depending on your choice of prefix path, you may have a different root directory instead of chargebee.

next
└── app
    └── chargebee
        └── checkout
            └── one-time-charge
                └── route.ts
            └── subscription
            └── manage-payment-sources
        └── portal
        └── webhook

Thanks to Next.js's file-based routing, each route handler will be written to a feature-specific parent directory, with a route.ts file containing the implementation. For example, checkout/subscription/route.ts will contain the following code:

import {
	client,
	createSubscriptionCheckout,
	raiseWarning,
	type SubscriptionInput,
} from "@chargebee/nextjs";
import type { NextRequest } from "next/server.js";

export const GET = createSubscriptionCheckout({
	apiKey: process.env.CHARGEBEE_API_KEY!,
	site: process.env.CHARGEBEE_SITE!,
	apiPayload: async (req: NextRequest): Promise<SubscriptionInput> => {
		raiseWarning();
		const chargebee = await client.getFromEnv();
		// https://api-explorer.chargebee.com/item_prices/list_item_prices
		const { list } = await chargebee.itemPrice.list({
			limit: 1,
			item_type: {
				is: "plan",
			},
			status: {
				is: "active",
			},
		});

		return {
			subscription_items: [{ item_price_id: list[0]?.item_price.id }],
			redirect_url: `${req.nextUrl.origin}/chargebee/checkout/callback`,
		} as SubscriptionInput;
	},
});

Each route is set up with a GET handler, and the implementation is exported from the framework-specific adapter package @chargebee/nextjs. These adapters are thin wrappers which use the Chargebee Node SDK to perform the required requests, handle errors and return the appropriate response, all wrapped in framework specific objects.

The apiPayload method allows for the required input to the API to be constructed as per the app's implementation: it may contain a static list of subscription_items, read from a JSON file, queried from a database, etc. In this example, the default implementation uses the Chargebee API to fetch a single itemPrice and return it so it's visible as a subscription in the checkout page.

Note: The default implementations of apiPayload print a warning with a stack trace to the console. This is to encourage the developers to review those generated files and customize the implementation. Please remove the raiseWarning() method call so you don't see the following in the console everytime the route is invoked:

chargebee-init console warning
chargebee-init console warning

Additional configuration

Although chargebee-init tries to minimize manual effort, some manual configuration is required at this point. This may change in the future as more features are added.

  • Setting the required environment variables

  • Creating the webhook endpoint through the Chargebee console

You can review the list of required manual configuration at any time by running npx chargebee-init help nextjs which will output the following steps:

  • Define the required process.env.* variables either by adding them to your .env file or replacing them at build time:

    CHARGEBEE_SITE="site-name"

    CHARGEBEE_API_KEY=""

    CHARGEBEE_WEBHOOK_AUTH="username:password"

  • Run npm|pnpm|bun install to grab the required packages

  • Configure the webhook URL in the Chargebee dashboard with basic auth set to the username and password defined in CHARGEBEE_WEBHOOK_AUTH

  • Review the routes created under the chargebee/ directory and make necessary changes

In the case of our Next.js app, update or create a .env file in the root directory and set the environment variables shown above. You may optionally choose to create the webhook and set the CHARGEBEE_WEBHOOK_AUTH to test the incoming webhook handler. Don't forget to run npm install or the equivalent command for your package manager to install the required @chargebee/nextjs dependency.

Test run

Now that the hard part is done, let's take it for a spin! Running npm run build should show the new routes created by chargebee-init:

Output of `npm run build`
Output of `npm run build`

With the routes validated, run npm run dev to start the server. Visiting http://localhost:3000/chargebee/checkout/subscription should now redirect you to the hosted checkout page with a single subscription (if one exists in your test site):

Hosted checkout page
Hosted checkout page

Looking ahead

chargebee-init aims to fill the gap between the low-code and no-code solution for the Node.js ecosystem by getting rid of the boring work of setting up repetitive code, while letting the developers customize the most commonly used Chargebee features. As we continue to listen to community feedback on developer tooling, we look forward to supporting other popular Node.js frameworks and expanding the support for more Chargebee services in the future.

The Developer Experience at Chargebee can be reached at dx@chargebee.com.

Was this tutorial helpful ?
Need more help?

We're always happy to help you with any questions you might have!

support@chargebee.com