4
2

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.

svelte-stripeを利用してSvelteにStripeの決済フォームを実装する

Posted at

この記事は、Svelte Advent Calendar 2022 13日目の記事です。

Svelteは、WebアプリケーションやGUIを構築するためのUIライブラリの1つです。

Reactなどと異なり、仮想DOMを利用せず、軽量かつシンプルに実装できることを謳っています。

Svelteでアプリケーションを開発する場合、svelte-stripeライブラリを利用することで、Stripeでのオンライン決済機能の組み込みが簡単に行えます。

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

早速Svelteアプリを作成しましょう。

今回はViteを利用します。

$ yarn create vite svelte-app --template svelte-ts

..

Scaffolding project in /Users/sandbox/svelte-app...

Done. Now run:

  cd svelte-app
  yarn
  yarn dev

✨  Done in 3.34s.

完了メッセージに表示されたコマンドを実行して、セットアップされたアプリを起動しましょう。

$ cd svelte-app
$ yarn
$ yarn dev

スクリーンショット 2022-11-15 17.46.19.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_...

Stripe用のコンポーネントファイルを作成

Stripeに関するリソースをまとめるファイル・コンポーネントを用意しましょう。

今回は、src/lib/Stripe.svelteファイルを作成しました。

<script>
  import { loadStripe } from '@stripe/stripe-js'
  import { Elements } from  'svelte-stripe'
  import { onMount } from 'svelte';

  let stripe = null

  onMount(async () => {
    stripe = await loadStripe(import.meta.env.VITE_STRIPE_PUBLIC_KEY)
  })
</script>

{#if stripe}
  <Elements {stripe}>
    <!-- this is where your Stripe components go -->
    <b>Hello Stripe</b>
  </Elements>
{/if}

これをsrc/App.svelteで読み込みます。

<script lang="ts">
  import svelteLogo from './assets/svelte.svg'
  import Counter from './lib/Counter.svelte'
+  import StripeFrom from './lib/Stripe.svelte'
</script>

...

  <div class="card">
    <Counter />
+    <StripeFrom />
  </div>

カウンターの横に、「Hello Stripe」が表示されていれば、追加成功です。

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

Stripeの決済フォームを描画する

Stripe組み込みの準備ができましたので、決済フォームを表示させましょう。

Svelteにはサーバー側の機能がないため、Stripeのクイックスタートなどで別途Payment Intentを作成するAPIを用意します。

続いてコンポーネント内のコードを変更します。

<script>
  import { loadStripe } from '@stripe/stripe-js'
-  import { Elements } from  'svelte-stripe'
+  import { Elements, PaymentElement } from  'svelte-stripe'
  import { onMount } from 'svelte';

  let stripe = null
+  let clientSecret = ''
+  let elements

  onMount(async () => {
    stripe = await loadStripe(import.meta.env.VITE_STRIPE_PUBLIC_KEY)
+    const response = await fetch('http://localhost:3100/stripe', {
+        method: 'POST'
+    })
+    const result = await response.json()
+    clientSecret = result.client_secret // クイックスタートの場合、「result.clientSecret」
  })
</script>

-{#if stripe}
+{#if stripe && clientSecret}
-  <Elements {stripe}>
+  <Elements {stripe} {clientSecret} bind:elements>
+    <PaymentElement />
  </Elements>
{/if}

まず、onMountにてPayment Intentを作成するAPIを呼び出し、ClientSecretを取得しています。

次に、取得したClientSecretを利用して、PaymentElementを表示させています。

最後に、Elementsをelements変数にbindして、この後のsubmitイベントに備えています。

変更を保存すると、決済フォームが画面に表示されます。

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

決済フォームのSubmit処理を実装する

最後に、決済を完了するためのイベントを実装します。

以下の関数をStripe.svelteに追加しましょう。

  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')
    }
  }

続いて、Stripe.svelteのHTMLを以下のように変更します。

-  <Elements {stripe} {clientSecret} bind:elements>
-    <PaymentElement />
-  </Elements>
+    <form on:submit|preventDefault={submit}>
+      <Elements {stripe} {clientSecret} bind:elements>
+        <PaymentElement />
+        <button type='submit'>Pay now</button>
+      </Elements>

formタグを追加し、on:submitでフォームのsubmitイベントを設定しました。

これでフォームにボタンが追加され、決済を完了できるようになります。

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

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

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

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

追加の学習リソース

PaymentElementを利用しない場合の、クレジットカード以外の実装方法などについては、公式のサンプルを参考にできます。

コンビニ決済やApple Pay/Google Payなどもサポートされています。

SvelteKitを利用して、Payment IntentやSetup Intentを作成する方法やWebhook APIを実装する方法なども紹介されています。

4
2
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
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?