LoginSignup
1
0

More than 1 year has passed since last update.

Amazon Cognito User Poolsに登録するユーザーの住所情報を、StripeのAddress Elementで収集する [React編]

Posted at

この記事は、AWS Advent Calendar 2022 8日目の記事です。

Webサービスやアプリケーションをリリースする際、ユーザー管理機能としてCognito User Poolsは欠かすことができません。

AWS Amplifyでも、Auth機能を利用するとこのサービスがセットアップされるなど、さまざまな場面で登場します。

この記事では、Cognito User Poolsで管理しているユーザー情報のうち、住所情報を入力するフォームを、Stripeが用意するAddress Elementsで実装する方法を紹介します。

スクリーンショット 2022-11-19 10.06.55.png

Address Elementsで住所入力フォームを作成する

Stripeの埋め込み型住所入力フォームは、@stripe/react-stripe-jsライブラリを利用します。

$ npm i @stripe/stripe-js @stripe/react-stripe-js

また、AWS AmplifyのSDKもインストールしましょう。

$ npm i aws-amplify

フォームを表示させるために、Provider要素のElementsと一緒にAddressElementを配置しましょう。

import { loadStripe } from '@stripe/stripe-js'
import { AddressElement, Elements } from '@stripe/react-stripe-js'

export default function Root() {
  return (
    <Elements
      stripe={loadStripe('pk_test_から始まるStripeのテスト用公開可能APIキーを配置')}
      options={{
        appearance: {
          theme:  'stripe',
        },
      }}
    >
      <form>
          <AddressElement
            options={{
              mode: 'billing',
              allowedCountries: ['JP'],
              fields: {
                phone: 'always'
              }
            }}
          />
          <button type='submit'>保存する</button>
      </form>
    </Elements>
  )
}

このコンポーネントを読み込むと、住所フォームが表示されます。

スクリーンショット 2022-11-30 16.35.21.png

郵便番号をセットすると、残りのフォームが表示されます。

スクリーンショット 2022-11-21 13.19.33.png

日本以外の住所を受け付ける方法

AddressElementallowedCoutriesを削除、またはサポートしたい国を追加してください。

          <AddressElement
            options={{
              mode: 'billing',
-              allowedCountries: ['JP'],
              fields: {
                phone: 'always'
              }
            }}
          />

入力フォームが変わり、指定した国によってフォームが変わるようになります。

スクリーンショット 2022-11-19 10.05.58.png

[optional] オートコンプリートをサポートする

Google Map APIを利用したり、決済フォームと併せて配置することで、オートコンプリートを有効できます。

スクリーンショット 2022-11-21 13.20.49.png

それぞれの方法は、以下の記事をご覧ください。

Amplify SDKで入力した情報をCognito User Poolsに反映する

まずは入力された情報を、useStateでハンドルしましょう。

import { loadStripe } from '@stripe/stripe-js'
import { AddressElement, Elements } from '@stripe/react-stripe-js'
+import { useState } from 'react'

export default function Root() {
+  const [userProfile, setUserProfile] = useState<{
+    address?: string;
+    phone_number?: string;
+    locale?: string;
+    name?: string;
+  }>({})
  return (
    <Elements
      stripe={loadStripe('pk_test_から始まるStripeのテスト用公開可能APIキーを配置')}
      options={{
        appearance: {
          theme:  'stripe',
        },
      }}
    >
      <form>
          <AddressElement
            options={{
              mode: 'billing',
              allowedCountries: ['JP'],
              fields: {
                phone: 'always'
              }
            }}
+            onChange={e => {
+              const {
+                address,
+                phone,
+                name,
+              } = e.value
+              setUserProfile({
+                address: address.state,
+                locale: address.country,
+                phone_number: phone,
+                name,
+              })
            }}
          />
          <button type='submit'>保存する</button>
      </form>
    </Elements>
  )
}

もしCognito User Poolsに、State以外の情報も保存したい場合は、次のようなコードを追加しましょう。

              const {
                address,
                phone,
                name,
              } = e.value
+              const supportKeys = ['state', 'city', 'line1', 'line2'] as const
+              const userAddress = supportKeys.map(key => {
+                if (!address[key]) return
+                const value = address[key]
+                return value
+              }).filter(Boolean).join(' ')
              setUserProfile({
-                address: address.state,
+                address: userAddress,
                locale: address.country,
                phone_number: phone,
                name,
              })

あとはAmplify SDKを利用して、保存するだけです。

import { loadStripe } from '@stripe/stripe-js'
import { AddressElement, Elements } from '@stripe/react-stripe-js'
import { useState } from 'react'
+import { Auth } from 'aws-amplify'

export default function Root() {
  const [userProfile, setUserProfile] = useState<{
    address?: string;
    phone_number?: string;
    locale?: string;
    name?: string;
  }>({})
  return (
    <Elements
      stripe={loadStripe('pk_test_から始まるStripeのテスト用公開可能APIキーを配置')}
      options={{
        appearance: {
          theme:  'stripe',
        },
      }}
    >
      <form
        onSubmit={async e => {
          e.preventDefault()
+          const user = Auth.currentAuthenticatedUser()
+          Auth.updateUserAttributes(user, userProfile)
        }}
      >
          <AddressElement
            options={{
              mode: 'billing',
              allowedCountries: ['JP'],
              fields: {
                phone: 'always'
              }
            }}
            onChange={e => {
              const {
                address,
                phone,
                name,
              } = e.value
              setUserProfile({
                address: address.state,
                locale: address.country,
                phone_number: phone,
                name,
              })
            }}
          />
          <button type='submit'>保存する</button>
      </form>
    </Elements>
  )
}

入力済みのデータを表示させる方法

AddressElementは、defaultValueを利用して保存済みのデータを表示できます。

  <AddressElement
    options={{
      mode: 'billing',
      defaultValues: {
        name: "John due",
        address: {
          line1: '千代田区千代田',
          line2: '11',
          city: '千代田区',
          country: 'JP',
          postal_code: '100-0001',
          state: '東京都'
        }
      }
    }}
 />

Authクラスを利用してデータを取得して、defaultValuesに値を設定しましょう。

AddressElementを利用するメリット

グローバルにサービスを提供する場合、住所入力フォームを国ごとに変更する必要があります。

しかし「国の情報を取得」して、「その国に対応した住所入力フォームを提供」する作業は手間がかかります。

StripeのAddressElementを利用することで、入力フォームのローカライズと、データのハンドルを簡単に行えます。

スクリーンショット 2022-11-30 16.59.48.png

1
0
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
1
0