3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Stripe Checkoutで「カートの中身」または「実際に注文された商品」の種類と数を取得する方法

Last updated at Posted at 2022-03-03

Stripe Checkoutを利用することで、手軽に安全なオンライン注文ページを顧客に提供することができます。

また、Checkoutの設定を変更することで、「カートの中の商品の数量を変更」したり、「アップセルの提案」を行うことも可能です。

これにより、顧客は注文の直前にカートの中身を再調整することができ、前のページに戻るなどの余計な手間を省くことができます。

カートの中身を取得する方法

「ブラウザがエラーでダウンした・移動中で一時的にオフラインになった」などの理由で、Checkoutのセッションが一時的に途切れるケースが存在します。

この場合、顧客はCheckoutページで変更した後の数量で、注文を再開したいと考えます。

その場合、システム側では、Stripe APIを利用し、カートの中身を取得する必要があります。

const items = await stripe.checkout.sessions.listLineItems(sessionId); // cs_xxxx

このAPIで取得できるデータの例はこちらです。
料金データや数量などが含まれていることが確認できます。

[{
        id: 'li_xxxx',
        object: 'item',
        amount_subtotal: 1000,
        amount_total: 1000,
        currency: 'jpy',
        description: 'Starter plan',
        price: {
          id: 'price_xxxx',
          object: 'price',
          active: true,
          billing_scheme: 'per_unit',
          created: 1639111716,
          currency: 'jpy',
          livemode: false,
          lookup_key: null,
          metadata: {},
          nickname: null,
          product: 'prod_xxxx',
          recurring: null,
          tax_behavior: 'inclusive',
          tiers_mode: null,
          transform_quantity: null,
          type: 'one_time',
          unit_amount: 1000,
          unit_amount_decimal: '1000'
        },
        quantity: 1
}]

顧客に同じCheckoutセッションのURLを再提供したい場合

何かしらの理由で、顧客がCheckoutセッションから離脱してしまった場合、同じURLを再度ユーザーに提供することもできます。

  const session = await stripe.checkout.sessions.retrieve(sessionId) // cs_xxxx
  if (session.url || session.status !== 'expired') {
    return {
      url: session.url,
      id: session.id,
    };
  }
  // 有効期限が切れているので、セッション再作成

セッションの有効期限が切れていなければ、retrieveAPIのレスポンスにURLが含まれます。
これを利用して、中断したカートセッションを再開しましょう。

Webhookなどで、実際に注文された商品データを取得する

checkout.session.completedcheckout.session.async_payment_succeededイベントなどを利用し、注文が完了した後の業務を自動化することもできます。


app.post('/webhook', express.raw({type: 'application/json'}), async (request, response) => {
  let event = request.body;
  /**
   * Webhookの署名検証処理がここに入ります
   * @see https://stripe.com/docs/webhooks/signatures#verify-official-libraries
   **/

  const data = event.data.object;
  if (
    event.type !== 'checkout.session.completed' &&
    event.type !== 'checkout.session.async_payment_succeeded'
  ) {
    return response.sendStatus(200);
  }

  /**
   * 支払いが完全に完了している場合のみ処理する
   **/
    if (data.payment_status === 'paid') {
    const { data: items } = await stripe.checkout.sessions.listLineItems(data.id);
    /**
     * カートの中身の情報を利用して、発送業務などのシステムを呼び出す
     **/  
  }
  return response.sendStatus(200);
});

合計金額や配送料データなどはイベントで受信するデータに含まれています。
が、カートの中身については別途APIで取得する必要があることにご注意ください。

応用アイディア: 期限切れの場合のみ、セッションを新しく作成する

これまでの内容を応用すると、以下のような処理が作れます。

  • セッションが有効ならば、そのままURLを返して再度Checkoutページに移動させる
  • セッションが期限切れの場合、中断されたカートの中身や設定をできるだけ再現させたセッションを再作成する
// TypeScript

const recreateCheckoutSession = async (sessionId: string): Promise<{
  url: string;
  id: string;
}> => {
  const session = await stripe.checkout.sessions.retrieve(sessionId);
  if (session.url && session.status !== 'expired') {
    return {
      url: session.url,
      id: session.id,
    };
  }
  const items = await stripe.checkout.sessions.listLineItems(sessionId);
  const params: Stripe.Checkout.SessionCreateParams = {
    line_items: items.data.map(data => {
      if (!data.price) return null;
      return {
        price: data.price.id,
        quantity: data.quantity || 1,
      };
    }).filter(Boolean) as any,
    cancel_url: session.cancel_url,
    success_url: session.success_url,
    mode: session.mode,
    expires_at: session.expires_at,
  };
  if (session.customer) {
    params.customer = session.customer as string;
  } else if (session.customer_creation) {
    params.customer_creation = session.customer_creation;
  }
  const newSession = await stripe.checkout.sessions.create(params);
  return {
    newSession,
    items,
  };
};

このコードはすべての引数・料金体系をサポートしていません
そのため、このままではセッションの再開がうまく動かないケースもあることにご注意ください。

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

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

など、Stripeを利用してオンラインビジネスを始める方法について週に2〜3本ペースで更新中です。

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

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?