Next.jsとClerk Billingを使用したサブスクリプション管理の実装方法
Clerk Billingを使ったサブスクリプション管理をNext.jsで実装する方法を解説。環境構築から料金プラン設定、認証連携まで、Clerkの新機能を活用したサブスク機能の導入手順を詳しく紹介します。
目次
Clerkから新しく「Clerk Billing」がリリースされました。この記事では、Next.jsアプリケーションでの実装方法と基本的な使い方を解説していきます。
環境構築
まずは新しいNext.jsアプリケーションを作成してみましょう。
npx create-next-app@latest nextjs-clerk-billing-app
今回は設定をデフォルトのまま進めましょう。Enterキーを連打すると、こんな感じになるはずです。
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a src/ directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack for next dev? … No / Yes
✔ Would you like to customize the import alias (@/* by default)? … No / Yes
Clerk SDKのセットアップ

アプリケーションを作成したら、Clerk SDKをインストールします。この辺りはClerkのダッシュボードに手順が載っていますので、それを参考に進めましょう。
npm install @clerk/nextjs
環境変数の設定
プロジェクトのルートに.env
ファイルを作成し、ClerkのAPIキーを設定する必要があります。ダッシュボードのチュートリアル通りに進めると、このデータをコピーアンドペーストで設定できます。
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxx
CLERK_SECRET_KEY=sk_test_xxx
ミドルウェアの設定
続いて、src/middleware.ts
ファイルを作成してClerkのミドルウェアを設定します。これによりユーザー認証の基盤が整います。
import { clerkMiddleware } from '@clerk/nextjs/server';
export default clerkMiddleware();
export const config = {
matcher: [
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
'/(api|trpc)(.*)',
],
};
Clerk Billingをセットアップする
Clerk Billingはダッシュボード操作で有効化する必要があります。ダッシュボードに[ Subscription ( beta ) ] タブが増えていますので、[ Get Started ]ボタンを押しましょう。

Clerk Billingを使うには、プランの登録と Session JWT v2への移行が必要です。JWT v2については、Changelogを確認しながら対応しましょう。

料金データを設定する
Clerk Billingは、Clerkダッシュボード上でサブスクリプションのプラン情報などを設定します。

Freeプランが用意されていますので、[ Add plan ]をクリックして新しいプランを作りましょう。あとで消すことも可能です。

プラン名・スラッグ・説明文を設定します。プラン名を入れると、小文字やアンダーバー( _ )などを使ってスラッグを生成してくれます。

その後、価格の設定を行いましょう。現時点では、USDでのサブスクリプションのみ対応している様子です。[ Annual Discount ]は、割引額ではなく割引後の月額に換算した料金を設定しましょう。月額4.98ドルプランの年額を48ドルにする場合、ここでは 48 / 12 = 4を入力します。また、Publicly availableをオフにすると、Clerkが提供するコンポーネントに表示されなくなります。

料金を作成するタイミングで、機能リストも作りましょう。

機能名とslugを設定します。slugはClerkコンポーネントで利用します。

機能も保存したら、最後にsaveして追加完了です。

Clerk Billingを有効化する
事前の準備が完了したら、ダッシュボードに[ Enable Billing ]ボタンが表示されます。これをクリックして有効化しましょう。

有効化完了しました。Stripeのアカウントを持ち込むこともできるみたいですね。

Clerk Billingの基本的な使い方
料金表の表示
ホームページに料金表を表示するのは驚くほど簡単です。PricingTable コンポーネントを使うだけで済みます。
import { PricingTable } from "@clerk/nextjs";
import Image from "next/image";
export default async function Home() {
return (
<main>
<PricingTable />
</main>
);
}
プランを2つ登録していると、このように表示されます。機能に登録した情報が、機能表として料金表要素に表示されます。

ちなみに、決済をするにはClerkでのログインが必須です。そのため、PricingTable
コンポーネントは、ログイン状態で表示されるページに配置するのが良さそうです。

ちなみに決済フォームはfloatしたパネルのような形で表示されます。

決済が完了すると、PricingTable
などのClerkコンポーネントがすぐに変更を反映します。

アクセス制御
サブスクリプションに応じて特定の機能へのアクセスを制御したいときは、Protect コンポーネントが便利です。
import { PricingTable, Protect } from "@clerk/nextjs";
import Image from "next/image";
export default async function Home() {
return (
<main>
<Protect
feature="dashboard_access"
fallback={<p>Sorry, you don't have dashboard Access.</p>}
>
<div>
<h1>Protected</h1>
</div>
</Protect>
</main>
);
}
この状態ですと、対象のslugを持つ機能があるプランを契約している人だけ、子要素が表示されます。

サーバーサイドでの制御
クライアントだけでなく、APIやSSRなどサーバー側の処理でも機能制限を実装できます。APIでの制御にも使えそうなので、Protect
との使い分けについては研究テーマになりそうな予感がします。
import { PricingTable, Protect } from "@clerk/nextjs";
import { auth } from "@clerk/nextjs/server";
import Image from "next/image";
export default async function Home() {
const { has } = await auth()
const canAccessDashboard = has({ feature: "dashboard_access" })
if (!canAccessDashboard) {
return (
<main>
<p>Sorry, you don't have dashboard Access.</p>
</main>
)
}
return (
<main>
<PricingTable />
<Protect
feature="dashboard_access"
fallback={<p>Sorry, you don't have dashboard Access.</p>}
>
<div>
<h1>Protected</h1>
</div>
</Protect>
</main>
);
}
料金について
Clerk Billingを利用する場合は、Stripe決済手数料に加えて0.7%の追加手数料が発生します。

この追加料金は本番環境でのみ適用されますが、実装や保守の手間が大幅に削減できるメリットがあるため、多くのケースで費用対効果は高いと言えるでしょう。
まとめ
Clerk Billingを導入すれば、料金表の表示からサブスクリプションに基づくアクセス制御まで、簡単に実装できます。クライアントサイドとサーバーサイド両方で機能制限を適用できるため、柔軟な実装が可能です。実装の手間や運用コストを考えると、少々の追加手数料を支払っても十分な価値があると思います。特に小規模チームや個人開発者にとっては、開発時間の節約という大きなメリットをもたらすはずです。