🕌
Stripe関連
カードの変更
- カードフォームで新しいカード情報を入力
- 一時的なトークンを取得
- create card apiに投げてカード作成
- カスタマーに新しいカード紐付け
カードフォーム
CardElementを使う
export default function CheckoutForm() {
const userInfo = useRecoilValue(userInfoState)
const stripe = useStripe()
const elements = useElements()
const [message, setMessage] = useState('')
const [isLoading, setIsLoading] = useState(false)
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (!stripe || !elements || !userInfo) {
return
}
const cusId = userInfo.stripeCusId
if (!cusId) {
return
}
setIsLoading(true)
const cardElement = elements.getElement(CardElement)
if (!cardElement) {
return
}
const result = await stripe.createToken(cardElement)
if (result.error) {
setMessage(result.error.message!)
setIsLoading(false)
return
}
const card = result.token.card
if (!card) {
setMessage('Something went wrong.')
setIsLoading(false)
return
}
const res = await fetch('/api/payment/updateCustomer', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
cusId,
cardId: card.id,
token: result.token.id,
}),
})
const data = await res.json()
console.log(JSON.stringify(data))
setIsLoading(false)
}
return (
<form onSubmit={handleSubmit} className="p-6">
<CardElement
className="py-3 px-4 border border-gray-200 rounded-md"
options={{
style: {
base: {
padding: '10px 12px',
color: '#000000',
fontWeight: '500',
fontSize: '16px',
fontSmoothing: 'antialiased',
'::placeholder': {
color: 'gray',
},
},
invalid: {
iconColor: '#FFC7EE',
color: '#FFC7EE',
},
},
}}
/>
<button disabled={isLoading || !stripe || !elements} id="submit">
<span id="button-text">
{isLoading ? <div className="spinner" id="spinner"></div> : 'Pay now'}
</span>
</button>
{message && <div id="payment-message">{message}</div>}
</form>
)
}
Discussion