

























Businesses tend to spend more money on software compared to individual consumers.
One of the most popular monetization models for B2B applications is the Per-User model, where a business purchases one “seat” for each user who will be using the application. Per-user pricing is a great way for application developers to generate income. The model is relatively straightforward, provides predictable pricing for finance departments, and allows for a steady stream of income that scales with the use of your application
In this article, you'll learn how Clerk Organizations and Stripe can be configured to implement per-user monetization into a web application.
This guide focuses on implementation details. For a comprehensive overview of B2B SaaS architecture and features, learn more about our B2B SaaS solution.
This article will use an open-source application called Team Task that is preconfigured with the functionality described below. All of the critical parts of the code that enable per-user licensing will be thoroughly explained, however, you are welcome to dive right into the code hosted in GitHub.
Everything is built with self-service in mind, so users will be able to do the following without assistance from you:
Using the pre-built Clerk components, users will be able to create organizations and invite users.
Once the organization is created, they will be prompted to purchase licenses via Stripe. Once purchased, administrators can toggle users to gain full use of the application.
Finally, administrators will also be able to easily manage their Stripe subscription with the click of a button.
Clerk Organizations allows you to easily add multi-tenancy into an application by letting users create organizations and invite users into them using the OrganizationSwitcher component.
When a user creates an organization, they'll immediately be asked if there are any users they want to invite into the organization by simply providing a list of email addresses. Behind the scenes, our system will also check to see if the Clerk application has any endpoints that are configured to receive a webhook when an organization is created.
Webhooks are a way for one service to inform another when an event occurs. The event, in this case, was that an organization was created. Team Task contains a route handler at /api/clerk-hooks that is configured to accept the following payload that Clerk will send when an organization is created:
To automate the process of creating Stripe customer records based on organizations in the application, we can accept the webhook message, create a Stripe customer, and create a record in a Neon table to associate the Clerk org_id to the Stripe customer_id.
This table will also track the number of licenses an organization has purchased, using a default value of 0 when the record is created.


Once the organization is created and users are invited, we'll redirect the current user to a page that lets them purchase licenses for the organization.
The OrganizationSwitcher uses the afterCreateOrganizationUrl prop to automatically forward the user to the /licensing page.
The licensing page is used for both the initial license purchase as well as managing and allocating licesnes over time. When the page is loading, it queries the license_count value in the orgs table for that organization to determine how to render the page.
The PurchaseLicensesCard component displays an input for the user to select how many licenses are required. Selecting the "Purchase via Stripe" button will use that value to create a Stripe Checkout Session using a server action.
Creating a Checkout Session requires the customer ID, a product ID that represents the per-user rate, purchase quantity, and redirect URLs. The session object returned from Stripe will contain the url that the user should be sent to for completing the transaction.
Since the PurchaseLicensesCard is a client component, we can redirect them using window.location.href:
The user will then be prompted for payment info to complete the transaction.

After payment, they'll be redirected back to /licensing, where a list of users will be displayed to allocate licenses to.
Stripe offers webhooks for a wide array of events that occur on their end as well. The customer.subscription.created webhooks can be used to update the license_count value of an organization in the Neon database to match the value that was purchased:
license_count value for that organization in the Neon database.
Now that licenses have been purchased, they need to be assigned to users.
As mentioned in the previous section, the /licensing page will automatically be updated to render a list of users who are members of an organization by querying the license_count value on load.
Since individual users can have access to multiple organizations within a single Clerk application, we use the concept of a “membership” to associate a user to an organization, modeling what is effectively a “many to many” relationship:

Clerk offers various types of metadata to add arbitrary data to entities in Clerk, and memberships can also contain metadata independent of the organization or user. Toggling on the last column will flag the user as “licensed” in their membership metadata using the following server action:
When the licensing page loads, the Clerk Backend API is used to query the memberships of the organization, which includes the metadata used to flag a specific user as licensed in that organization. This both sets the toggle for the user row as well as to aggregate the total number of currently licensed users, which will also be used to determine how many licenses are available.
If the currentlyLicensedUsers value is equal or greater than currentLicenseCount and the user is not already licensed, the ability to enable licenses for a user can be disabled:
Besides rendering a list of users, the /licensing page now also renders the ManageLicensesCard component to display the available of licenses along with a button to manage the current subscription using the Stripe Customer Portal.

The Customer Portal is a hosted solution from Stripe that allows users to manage their own subscriptions without developers having to build a custom user interface.
This feature is off by default, but can easily be enabled in the Stripe Dashboard. Since licenses are managed via Stripe subscriptions, we only need to allow subscription management for our customers for this specific SKU.

As with the Checkout Session for the initial license purchase, a custom URL will be generated based on the Stripe customer ID:
After the URL is returned to the front end, the user will be redirected to the Customer Portal where they can adjust their licenses as needed:

The customer.subscription.updated event from Stripe will also be handled in the route handler to update the license count for a specific organization:
license_count in the database.
Clerk makes it easy to access information about the currently logged-in user, and accessing membership metadata is no exception.
Recall that we stored the isLicensed flag within the membership metadata. To access these values, the sessionClaims object of the auth() function can be used:
Then you can decide what functionality of the application can be restricted based on that flag, for example:
Per-user licensing is a great way to monetize an application. Stripe offers a great suite of tools that allows developers to process transactions and generate revenue from their work. By combining with power of Clerk Organizations with Stripe, you can build a seamless workflow for your users to independently create their own tenants, purchase and assign licenses for those tenants, and change the subscription at any time.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。