LoginSignup
5
5

More than 1 year has passed since last update.

React で stripe 決済 を実装する

Last updated at Posted at 2022-05-22

備忘録。

react で stripe 決済を実装する

実装には、推奨されている paymentIntent を使う。
実装のフローとしては、

1:フロントで決済画面に移行する
2:フロントからサーバーに paymentIntent を create する通信を投げる
3:サーバー側で paymentIntent を create ( paymentIntent を参照) し、client_secret をフロントに返す
4:サーバーから返ってきた client_secret と 顧客が入力したカード情報で、決済を行う ( confirmCardPayment を参照)。

のようになる。

サーバー側 (Express)

app.js
import express from "express"
import Stripe from "stripe"

const stripeSecret = new Stripe(STRIPE_SECRET_KEY)

app.post("/api/payment/create", async (request, response) => {
  const total = calculate_total(request.body.total) // 合計金額を計算する関数を作る
  const paymentIntent = await stripeSecret.paymentIntents.create({
    amount: total,
    currency: "JPY"
  })
  response.status(201).send({
    clientSecret: paymentIntent.client_secret
  })
})

フロント側 (React)

App,js
import { Elements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";

const stripePromise = loadStripe(STRIPE_PUBLISHABLE_KEY)

function App() {
  return(
    <Elements stripe={stripePromise}>
      <CheckoutPage/>
    </Elements>
  )
}

export default App
CheckoutPage.js
import React, {useEffect} from "react"
import {CardElement, useElements, useStripe} from "@stripe/react-stripe-js"

function CheckoutPage () {

  const stripe = useStripe()
  const elements = useElements()

  const [clientSecret, setClientSecret] = useState("")
  const [errorMsg, setErrorMsg] = useState("")
  const [processing, setProcessing] = useState(false)
  const [success, setSuccess] = useState(false)

  useEffect(() => {
    async function getClientSecret(total) {
      try {
        const {data} = await axios.post("/api/payment/create", {total: hogehoge})
        setClientSecret(data.clientSecret)
      } catch(error) {
        setErrorMsg(error.message)
      }
    }
    getClientSecret(total)
  }, [total])

  async function paymentHandler(e) {
    e.preventDefault()
    if (!stripe || !elements) {
      return
    }
    setProcessing(true)
    const cardElement = elements.getElement(CardElement);
    if (!cardElement) { return }
    await stripe.confirmCardPayment(clientSecret, {
      payment_methods: {
        card: cardElement,
      }
    })
    .then(({paymentIntent}) => {
      setErrorMsg(false)
      setProcessing(false)
      setSuccess(true)
    })
    .catch((error) => {
      setErrorMsg(error.message)
      setProcessing(false)
      setSuccess(false)
    })
  }

  return (
    <div>
      <Form onSubmit={paymentHandler}>
        <CardElement/>
        {errorMsg && <div className="errorMsg">{errorMsg}</div>}
        <button disabled={!stripe || !elements}>Pay Now</button>
      </Form>
    </div>
  )
}

export default CheckoutPage;

参考資料

を参考にしました

5
5
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
5
5