5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SvelteKitとsvelte-stripeで、サブスクリプション申込フローを実装する方法

Last updated at Posted at 2022-12-14

この記事は、SvelteKit Advent Calendar 2022 14日目の記事です。

SveltKitはSvelteでアプリケーションを構築するためのフレームワークです。

2022/11時点では、まだVersion1.0.0がリリースされていませんが、Svelteを使う上では注目しておきたいフレームワークではないかと思います。

この記事では、svelte-stripeライブラリを利用して、SveltKitでサブスクリプション申込のUI / APIを実装する方法を紹介します。

SvelteKitプロジェクトをセットアップする

セットアップは、以下のコマンドで開始します。

$ npm create svelte@latest sveltekit-app

テンプレートを利用するかどうかや、TypeScript, ESLint, Prettier, Playwriteを利用するかを聞かれます。

? Which Svelte app template? › - Use arrow-keys. Return to submit.
❯   SvelteKit demo app - A demo app showcasing some of the features of SvelteKit - play a word guessing game that works without JavaScript!
    Skeleton project
    Library skeleton project

今回は、以下の設定でセットアップしました。

✔ Which Svelte app template? › SvelteKit demo app
✔ Add type checking with TypeScript? › Yes, using TypeScript syntax
✔ Add ESLint for code linting? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
✔ Add Playwright for browser testing? … No / Yes

Next stepsが表示されれば、セットアップ完了です。

Next steps:
  1: cd sveltekit-ap
  2: npm install (or pnpm install, etc)
  3: git init && git add -A && git commit -m "Initial commit" (optional)
  4: npm run dev -- --open

To close the dev server, hit Ctrl-C

Stuck? Visit us at https://svelte.dev/chat

指示に従ってコマンドを実行しましょう。

$ cd sveltekit-app
$ npm install (or pnpm install, etc)
$ git init && git add -A && git commit -m "Initial commit"
$ npm run dev -- --open

セットアップに成功していれば、デモアプリが立ち上がります。

スクリーンショット 2022-11-17 17.53.12.png

svelte-stripeでStripeの決済フォームを組み込む

セットアップが完了しましたので、Stripeの組み込みを行いましょう。

今回はコミュニティライブラリのsvelte-stripeを利用します。

ライブラリのインストール

まずはライブラリをインストールしましょう。

$ yarn add stripe svelte-stripe

環境変数の設定

StripeのAPIキーを.env.localファイルに保存しましょう。

VITE_STRIPE_PUBLIC_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...

ページ読み込み時に、Subscriptionデータを生成する

SvelteKitがページを読み込む際に、サーバー側でサブスクリプションデータを生成させます。

src/routes/subscription/+page.server.tsファイルを作成し、以下のコードを追加しましょう。

import { STRIPE_SECRET_KEY } from '$env/static/private';
import Stripe from 'stripe';
 
/** @type {import('./$types').PageServerLoad} */
export async function load() {
    const stripe = new Stripe(STRIPE_SECRET_KEY, {
        apiVersion: '2022-11-15'
    });
    const customer = await stripe.customers.create()
    const product = await stripe.products.create({
        name: 'SvelteKitデモ用'
    })
    const subscription = await stripe.subscriptions.create({
        customer: customer.id,
        items: [{
            price_data: {
                unit_amount: 1000,
                currency: 'jpy',
                recurring: {
                    interval: 'month',
                },
                product: product.id
            }
        }],
        payment_behavior: 'default_incomplete',
        expand: ['latest_invoice.payment_intent'],
        payment_settings: {
            save_default_payment_method: 'on_subscription',
        },
    })

    return {
        subscriptionId: subscription.id,
        clientSecret: ((subscription.latest_invoice as Stripe.Invoice).payment_intent as Stripe.PaymentIntent).client_secret
    }
}

Subscription作成処理の参考

今回のサンプルコードは、事前にダッシュボードでデータを作成する必要のないように用意しました。

事前準備が不要な代わりに、ページ読み込みの度にCustomerや商品データが生成されますのでご注意ください。

引数の解説等については、以下の記事で紹介しています。

生成したSubscriptionデータを元に、決済フォームを表示する

続いて決済フォームを表示させましょう。

src/routes/subscription/+page.svelteを作成します。

<script lan="ts">
  /** @type {import('./$types').PageData} */
  import { loadStripe } from '@stripe/stripe-js'
  import { Elements, PaymentElement } from  'svelte-stripe'
  import { onMount } from 'svelte';
  import { PUBLIC_STRIPE_PUBLIC_KEY } from '$env/static/public';

    export let data
    export const { clientSecret } = data
    let stripe = null
    let elements

    onMount(async () => {
        stripe = await loadStripe(PUBLIC_STRIPE_PUBLIC_KEY)
    })
</script>

<div>
    <h1>hello</h1>
    {#if stripe && clientSecret}
        <form>
            <Elements {stripe} {clientSecret} bind:elements>
                <PaymentElement />
                <button type='submit'>Subscribe</button>
            </Elements>
        </form>
    {/if}
</div>

http://localhost:5173/subscription にアクセスして、決済フォームが表示されれば成功です。

スクリーンショット 2022-11-18 16.17.02.png

実際の組み込みでは、契約内容(料金・期間など)を表示する必要がある点にご注意ください。

サブスクリプションの申込処理を完了する

あとはformのsubmit処理を追加して、申し込みを完了させるだけです。

先ほど作成した+page.svelteを編集して、submit処理を追加しましょう。

<script lan="ts">
  /** @type {import('./$types').PageData} */
  import { loadStripe } from '@stripe/stripe-js'
  import { Elements, PaymentElement } from  'svelte-stripe'
  import { onMount } from 'svelte';
  import { PUBLIC_STRIPE_PUBLIC_KEY } from '$env/static/public';

    export let data
    export const { clientSecret } = data
    let stripe = null
    let elements

    onMount(async () => {
        stripe = await loadStripe(PUBLIC_STRIPE_PUBLIC_KEY)
    })
+    async function submit() {
+        if (!stripe || !elements) {
+            throw new Error('stripe or elements not defined')
+        }
+        const { error, paymentIntent } = await stripe.confirmPayment({
+            elements,
+            redirect: 'if_required'
+        })
+        if (error) {
+            window.alert(JSON.stringify(error))
+        } else {
+            window.alert('done')
+        }
+    }
</script>

続いてformタグを編集し、submitイベントを設定します。

-        <form>
+        <form on:submit|preventDefault={submit}>

Stripeが用意している「テストカード番号」を利用して、決済をテストしましょう。

成功メッセージが表示されれば、実装完了です。

スクリーンショット 2022-11-15 21.29.58.png

Stripeの料金表を使って、手早く組み込む方法

ここまで決済フォームを埋め込む方法を紹介しましたが、Stripeでは料金表そのものを埋め込むことも可能です。

ダッシュボードで生成した料金表の、コードスニペットを埋め込むだけで実装できますので、手軽に実装できます。


<div class="text-column">
	<h1>料金表</h1>
</div>

<script async src="https://js.stripe.com/v3/pricing-table.js"></script>
<stripe-pricing-table
	pricing-table-id="prctbl_xxxx"
	publishable-key="pk_test_xxxxx">
</stripe-pricing-table>

スクリーンショット 2022-11-18 16.26.29.png

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?