Stripe ElementのAPIがアップデートされ、「決済フォームをReadOnlyモードに設定する」オプションが追加されました。
コードサンプル
実装方法はとても簡単で、elements.create
の第二引数にreadOnly: true
を設定するだけです。
<script src="https://js.stripe.com/v3/"></script>
<!-- 中略 -->
<div id="payment-element"></div>
<script>
const stripe = Stripe('pk_test_YOUR_STRIPE_PUBLISHABLE_API_KEY')
const elements = stripe.elements({
appearance: {
theme: 'stripe'
},
clientSecret: 'pi_YOUR_PAYMENT_INTENT'
});
const paymentElement = elements.create('payment', {
readOnly: true
});
paymentElement.mount("#payment-element");
</script>
これにより、element.create().mount()
で生成された入力フィールドにreadonly
属性が追加されます。
element.update()
での切り替えも可能
update
でreadOnly
のステータスを変更することもできます。
以下のコードでは、Disable
/ Enable
それぞれのボタンを押すことで、readOnly
にするかしないかのステータスを変更できます。
<script src="https://js.stripe.com/v3/"></script>
<!-- 中略 -->
<button onclick="handleDisable()">Disable</button>
<button onclick="handleEnable()">Enable</button>
<div id="payment-element"></div>
<script>
// ...一部省略
const paymentElement = elements.create('payment', {
readOnly: true
});
paymentElement.mount("#payment-element")
function handleDisable() {
paymentElement.update({
readOnly: true
})
}
function handleEnable() {
paymentElement.update({
readOnly: false
})
}
</script>
ユースケース
特定の条件を満たした場合のみ、カード情報を入力させたい
配送先などの顧客情報が入力された状態になってから、カード情報を入力させるUIを設計したい場合にreadOnly
が利用できます。
以下のサンプルでは、name
が空の場合はカード情報が入力できない(readOnly)状態になります。
import { loadStripe } from "@stripe/stripe-js";
import { Elements, PaymentElement, useElements, useStripe } from "@stripe/react-stripe-js";
import { useEffect, useState } from 'react';
const stripePromise = loadStripe(process.env.STRIPE_PUBLISHABLE_API_KEY);
// 中略
const Payment = () => {
const [isReadOnly, setIsReadOnly] = useState<boolean>(false);
const [name, setName] = useState('')
useEffect(() => {
setIsReadOnly(!name)
}, [setIsReadOnly,name])
return (
<input value={name} onChange={e => {
setName(e.target.value)
}} />
<PaymentElement id="payment-element" options={{
readOnly: isReadOnly,
}} />
)
}
const Home = () => {
const options = {
appearance:{
theme: 'stripe',
},
clientSecret,
}
return (
<Elements stripe={stripePromise} options={options}>
<Payment />
</Elements>
)
}
処理中に入力内容を変更させたくない場合
サービスによっては、Submit時の処理にすこし時間がかかる場合があります。そしてその処理が終わるまでの間、フォームの内容を変更させたくないケースもあります。
その場合、処理が実行中はreadOnly: true
をセットして、内容の変更をブロックすることができます。
import { loadStripe } from "@stripe/stripe-js";
import { Elements, PaymentElement, useElements, useStripe } from "@stripe/react-stripe-js";
import { useEffect, useState } from 'react';
const stripePromise = loadStripe(process.env.STRIPE_PUBLISHABLE_API_KEY);
// 中略
const Payment: FC = () => {
const [isReadOnly, setIsReadOnly] = useState<boolean>(false);
const stripe = useStripe();
const elements = useElements();
return (
<form onSubmit={async e => {
e.preventDefault()
if (!elements || !stripe) return;
// 処理開始と同時に、変更できなくする
setIsReadOnly(true)
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: 'http://localhost:3000'
}
})
// エラーが返ってきた場合、再入力可能にする
if (error) {
alert(error.message)
setIsReadOnly(false)
return;
}
// 時間のかかる処理の例
await new Promise(resolve => {
setTimeout(() => {
resolve(true)
}, 10000)
})
// 処理が完了したので、変更可能にする
setIsReadOnly(false)
}}>
<PaymentElement id="payment-element" options={{
readOnly: isReadOnly,
}} />
<button type="submit">Submit</button>
</form>
)
}
参考資料
- https://stripe.com/docs/js/elements_object/create_payment_element#payment_element_create-options-readOnly
- https://stripe.com/docs/js/elements_object/update_payment_element#payment_element_update-options-readOnly
[PR] Stripe開発者向け情報をQiitaにて配信中!
2021年12月よりQiitaにて、Stripe開発者のためのブログ記事更新を開始しました。
- [Stripe Updates]:開発者向けStripeアップデート紹介・解説
- ユースケース別のStripe製品や実装サンプルの紹介
- Stripeと外部サービス・OSSとの連携方法やTipsの紹介
- 初心者向けのチュートリアル(予定)
など、Stripeを利用してオンラインビジネスを始める方法について随時更新してまいります。