11
7

More than 1 year has passed since last update.

"use-shopping-cart"を使って、StripeとReactで簡単にECカート機能 + 決済機能を実装しよう

Posted at

Stripeを利用することで、決済機能を簡単に実装することができます。
しかし通販機能を実装するためには、決済だけではなく買い物かご(カート)機能も実装する必要があります。

今回は、「use-shopping-cart」を利用して、Reactアプリで簡単にカート機能を実装する方法を紹介します。

use-shopping-cartとは

スクリーンショット 0004-01-13 10.31.41.png

use-shopping-cartは、Reactでショッピングカート機能を実装するために必要な機能を備えたHookを提供するライブラリです。

内部的にReduxを利用しており、「カート機能」と「Stripe Checkoutへの遷移」の2機能が利用できます。

use-shopping-cartでできること(一部)

use-shopping-cartを利用することで、一般的なショッピングカートを実装するために必要なAPIを簡単に手に入れることができます。

  • 商品をカートに追加する
  • カートに追加した商品データや合計金額データを取得する
  • 商品をカートから削除する
  • カート内の商品の個数を変更する
  • etc...

use-shopping-cartを使ってカート機能を実装しよう

サンプルアプリのセットアップ

Create React AppやViteを利用してアプリをセットアップしましょう。

// CRA
% npx create-react-app my-app

// Vite
% npm init vite

ライブラリをインストールしよう

useShoppingCartライブラリをインストールします。
この際Stripe.jsも一緒にインストールします。
ただしReact SDKは不要ですのでご注意ください。

% npm install @stripe/stripe-js use-shopping-cart

CartProviderを設定しよう

use-shopping-cartは内部的にReduxを利用しています。
そのため、アプリ全体をCardProviderの子要素にする必要があります。

import ReactDOM from 'react-dom'
import { CartProvider } from 'use-shopping-cart'

import App from './App'

ReactDOM.render(
  <CartProvider
    mode="payment"
    cartMode="client-only"
    stripe={YOUR_STRIPE_API_KEY_GOES_HERE}
    successUrl="http://localhost:3000"
    cancelUrl="http://localhost:3000"
    currency="JPY"
    allowedCountries={['US', 'GB', 'JP']}
    billingAddressCollection={true}
  >
    <App />
  </CartProvider>,
  document.getElementById('root')
)

loadStriperedirectToCheckoutなどで設定するパラメータをここで設定します。

Providerで設定することで、redirectToCheckoutを呼び出す際にリダイレクトURLなどの情報を省略することができます。

cartModeでStripe Checkoutの起動方法が変更可能です

cartModeには、checkout-sessionclient-onlyの2種類が設定できます。

client-onlyを利用した場合は、checkout.sessions.createAPIを利用せずに、クライアント側だけでStripe Checkoutへのリダイレクトを実施します。

APIでCheckoutのセッションを作成したい場合は、checkout-sessionを利用しましょう。

商品・料金データを設定しよう

商品データを作成します。簡単な方法はJSONまたはオブジェクトで設定することです。
price_idpriceの2つが欠けていると、うまく動作しませんので注意しましょう。

const productData = [
  {
    name: 'Bananas',
    price_id: 'price_xxxx',
    price: 400
  },
  {
    name: 'Tangerines',
    price_id: 'price_xxxx',
    price: 100
  }
]

続いて設定した商品データをReactで表示させましょう。

import { formatCurrencyString } from 'use-shopping-cart'

...
<ul>
  {productData.map(product => (
    <li key={product.price_id}>
      {product.name} ({formatCurrencyString({ value: product.price, currency: 'JPY' })}) <br />
      <button>
        Add 1 to Cart 
      </button>
    </li>
  ))}
</ul>

formatCurrencyStringを利用することで、金額を指定した通貨に合わせた表示に変換することができます。

スクリーンショット 0004-01-12 18.19.59.png

カート機能を実装する

いよいよカート機能の実装に入ります。
カートに関するメソッドなどは、useShoppingCartフックを利用して取得します。

import { useShoppingCart } from 'use-shopping-cart'
...
const { totalPrice, cartCount, addItem, cartDetails, ...args } = useShoppingCart()

カートに商品を追加する機能を実装しよう

まずは表示している商品をカートに追加するボタンを実装しましょう。

import { formatCurrencyString, useShoppingCart } from 'use-shopping-cart'

const Shop = () => {

  const {
    addItem
  } = useShoppingCart()

  return (
   <div>
    <ul>
    {productData.map(product => (
      <li key={product.price_id}>
        {product.name} ({formatCurrencyString({ value: product.price, currency: 'JPY' })}) <br />
        <button onClick={() => addItem(product)}>
          Add 1 to Cart 
        </button>
      </li>
    ))}
   </ul>
  </div>
 )
}

buttononClickイベントにaddItemを設定しました。
これで選択した商品をカートに追加完了です。

カートの中身を確認しよう

追加に成功しましたが、実際にカートの中に何が登録されているかがわかりません。
そこでカートの中身についても表示させてみましょう。


const Shop = () => {

  const {
    addItem,
+   cartDetails,
  } = useShoppingCart()

  return (
   <div>
...
      <section>
        <h1>Cart</h1>
        <ul>
          {Object.entries(cartDetails).map(([priceId, cartItem]) => (
            <li key={`cart-${priceId}`}>
              {cartItem.name} ({cartItem.formattedPrice} * {cartItem.quantity} = {cartItem.formattedValue})<br/>
              <button>Increase</button>
              <button>Decrease</button>
              <button>Cancel</button>
            </li>
          ))}
        </ul>
      </section>
  </div>
 )
}

cartDetailsを使用することで、カートに追加された商品データを取得・表示することができます。

スクリーンショット 0004-01-12 18.35.40.png

# カートの商品数を変更できるようにしよう

カートに追加した商品の数を増減させたり、削除することもできます。
以下のサンプルを参考に、コードを更新しましょう。


const Shop = () => {

  const {
    addItem,
    cartDetails,
+     incrementItem, decrementItem, removeItem,
  } = useShoppingCart()

  return (
   <div>
...
      <section>
        <h1>Cart</h1>
        <ul>
          {Object.entries(cartDetails).map(([priceId, cartItem]) => (
            <li key={`cart-${priceId}`}>
              {cartItem.name} ({cartItem.formattedPrice} * {cartItem.quantity} = {cartItem.formattedValue})<br/>
+              <button onClick={() => incrementItem(priceId)}>1つ増やす</button>
+              <button onClick={() => decrementItem(priceId)}>1つ減らす</button>
+              <button onClick={() => removeItem(priceId)}>削除</button>
            </li>
          ))}
        </ul>
      </section>
  </div>
 )
}

これだけでカートの中身を増減や削除できるようになりました。

Stripe Checkoutにリダイレクトさせて、注文できるようにしよう

最後にカートに登録した商品を注文できるようにしましょう。
これもuseShoppingCartで取得できるメソッドを利用するだけです。


const Shop = () => {

  const {
    addItem,
    cartDetails,
      incrementItem, decrementItem, removeItem,
+   redirectToCheckout,
  } = useShoppingCart()

  return (
   <div>
...
+      <button onClick={() => redirectToCheckout()}>
+        注文する
+      </button>
  </div>
 )
}

追加した「注文する」ボタンをクリックすると、カートに追加した商品・料金データと個数が反映されたCheckoutページが表示されます。

スクリーンショット 0004-01-12 18.41.13.png

Appendix: カート情報はどこに保存されている?

実装を見る限り、カートの情報はlocalStorageに保存されています。

スクリーンショット 0004-01-12 18.42.35.png

そのため、途中でユーザーがサイトから離脱した場合でも、同じブラウザであればカートの内容を維持することができます。

終わりに

use-shopping-cartの基本的な機能について紹介しました。
APIでCheckoutセッションを作成した場合など、ここでは紹介できていないユースケースもまだまだありますので、また改めて紹介したいと思います。

[PR] Stripe開発者向け情報をQiitaにて配信中!

2021年12月よりQiitaにて、Stripe開発者のためのブログ記事更新を開始しました。

  • [Stripe Updates]:開発者向けStripeアップデート紹介・解説
  • ユースケース別のStripe製品や実装サンプルの紹介
  • Stripeと外部サービス・OSSとの連携方法やTipsの紹介
  • 初心者向けのチュートリアル(予定)

など、Stripeを利用してオンラインビジネスを始める方法について随時更新してまいります。

-> Stripe Organizationsをフォローして最新情報をQiitaで受け取る

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