この記事は、AWS Advent Calendar 2022 8日目の記事です。
Webサービスやアプリケーションをリリースする際、ユーザー管理機能としてCognito User Poolsは欠かすことができません。
AWS Amplifyでも、Auth機能を利用するとこのサービスがセットアップされるなど、さまざまな場面で登場します。
この記事では、Cognito User Poolsで管理しているユーザー情報のうち、住所情報を入力するフォームを、Stripeが用意するAddress Elementsで実装する方法を紹介します。
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>
)
}
このコンポーネントを読み込むと、住所フォームが表示されます。
郵便番号をセットすると、残りのフォームが表示されます。
日本以外の住所を受け付ける方法
AddressElement
のallowedCoutries
を削除、またはサポートしたい国を追加してください。
<AddressElement
options={{
mode: 'billing',
- allowedCountries: ['JP'],
fields: {
phone: 'always'
}
}}
/>
入力フォームが変わり、指定した国によってフォームが変わるようになります。
[optional] オートコンプリートをサポートする
Google Map APIを利用したり、決済フォームと併せて配置することで、オートコンプリートを有効できます。
それぞれの方法は、以下の記事をご覧ください。
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を利用することで、入力フォームのローカライズと、データのハンドルを簡単に行えます。