LoginSignup
10
15

More than 1 year has passed since last update.

StripeでApple PayとGoogle Payをウェブアプリに対応させる方法【Stripe, Next.js, React.js, Typescript, Javascript】

Last updated at Posted at 2020-12-04

概要

弊サービスのECサイトにApple PayとGoogle Payを実装しました。ログイン情報だけを求める決済UIUXを作ることで、ユーザーの入力時間を省き、スマートな決済体験を生み出すことができました。

本記事では、実際に開発中につまづいたポイントなども含めながら、StripeのPayment Request Buttonの実装方法を解説していきます。※Stripeの決済処理などは割愛しています。

それではApple Pay & Google Payの実装を始めましょう。

実装方法

  1. StripeのPayment Request Buttonを実装
  2. Stripeがブラウザに合わせて自動的にApple PayまたはGoogle Payを表示
  3. 購入ボタンを押してペイメントシートを表示
  4. 決済に必要な情報を編集・選択
  5. Stripeの決済処理を実行(サブスクまたは単品購入)
  6. 完了or失敗

前提条件

  • ブラウザに支払い方法を追加済みであること。Chromeにカードを保存、またはSafariで使うにはWalletにカードを保存。
  • HTTPS通信。開発/本番環境で必要です。Ngrokと言うサービスを使うとデプロイなしでHttps通信が可能になるので便利です(ローカル環境を共有できるんですね。)
  • Apple Payを使用するためには、ドメインを登録する。開発/本番環境で設定が必須です。
  • https://stripe.com/docs/stripe-js/elements/payment-request-button からdomain association fileを取得

設定

  1. domain association fileを次のようにホストする。https://your doman here.com/.well-known/apple-developer-merchantid-domain-association
  2. Stripe経由でAppleにドメインを登録(Stripeのダッシュボードで登録しました)
  3. 1と2が問題なく完了するとApple Payのテストができるようになります。

テスト方法

Google Payをテストするための環境設定は特にありませんが、Google Payのテストカードを取得するにはテストカード スイートから「ユーザーグループに参加」を見つけて、グループに参加してください。参加するだけでテスト用のGoogle Payを使えるようになります。Goole Payのテスト決済のやり方がわからずStripeのテストカードでカード登録を行ったりしていたらなんと二日くらい無駄にしました。。。

Apple Payはセキュリティー上fakeカードを登録することができないらしく、リアルカードを登録して決済テストを行います。ドキュメントによると、

Apple won’t let you add a fake credit card to Passport and the iPhone. However, if you’re using Apple Pay and your test Stripe API keys, we’ll recognize the situation when the Apple Pay request is made and return a successful test card token. To test a payment in live mode, you’ll need to use a working credit card.

Stripe側がtest API keyかどうかを判定するらしいので請求されません。

UPDATE 2021/08/16

chrome://settings/payments からGoogle PayにStripeのカードを追加できるみたいです

  1. Google Payに少なくとも一つカードを登録すること、
  2. Stripeのテストカードを追加してから開発をすると良い

と動画内で言ってました。
スクリーンショット 2021-08-16 17.55.18.png

こんな感じで追加できました。これで決済時にGoogle Pay決済ができるようになります。

実装

Stripeのドキュメントを参考に解説していきます。

import React, {useState, useEffect} from 'react';
import {PaymentRequestButtonElement, useStripe} from '@stripe/react-stripe-js';

const CheckoutForm = () => {
  const stripe = useStripe();
  const [paymentRequest, setPaymentRequest] = useState(null);

  useEffect(() => {
    if (stripe) {
      const pr = stripe.paymentRequest({
        country: 'JP', 
        currency: 'jpy',
        total: {
          label: 'Demo total',
          amount: 1099,
        },
        requestPayerName: true,
        requestPayerEmail: true,
      });

      // Check the availability of the Payment Request API.
      pr.canMakePayment().then(result => {
        if (result) {
          setPaymentRequest(pr);
        }
      });
    }
  }, [stripe]);

  if (paymentRequest) {
    return <PaymentRequestButtonElement options={{paymentRequest}} />
  }

  // Use a traditional checkout form.
  return 'Insert your form or button component here.';
}

StripeがPayment Request Buttonを使えるかどうかを判定し、使える場合はユーザーのブラウザに合わせてボタンが表示されます。SafariはApple Pay、ChromeはGoogle Payになります。Apple Pay利用可能の場合はresultが{applepay: true}になります。

PaymentRequestにはshippingOptions(配送方法)を追加することもできます。複数登録することができるため配列になっています。

 const pr = stripe.paymentRequest({
        country: 'US',
        currency: 'usd',
        total: {
          label: 'Demo total',
          amount: 1099,
        },
        requestPayerName: true,
        requestShipping: true,
        requestPayerEmail: false,
        requestPayerPhone: true,
        shippingOptions: [{
            id: 'payment id',
            label: 'ネコポス (クロネコヤマト)',
            amount: totalAmount,
     }],
});

ユーザーから取得できる情報は、name(フルネーム), shipping address(配送先), email(メール), phone(電話番号)ですがemailが不要であればfalseまたは指定しないと非表示になります。これら全て必須キーではないためオブジェクトから省いても大丈夫です。必須情報はcountrycurrencytotalです。
https://stripe.com/docs/js/payment_request/create

ユーザーの住所

Apple Pay

Google Pay

返ってくるデータは

{ 
    addressLine:        //配列住所
    city:               //市区町村
    country:            //国
    dependentLocality:  //?? 
    organization:       //組織名
    phone:              //電話番号
    postalCode:        //郵便番号
    recipient:          //名前
    region:             //都道府県
    sortingCode:        //??
}

違いとしては、Google Payの場合アパート名やマンション名などを分けて登録することができません。もしユーザーの住所情報からマンション名などを取得する必要がある場合は後述するaddress eventで登録済み住所のバリデーションを行うと良いと思います。

Event処理

ユーザーの住所変更を検知する場合はpaymentRequestに用意されているイベントリスナーを利用します。以下のコードはドキュメントのサンプルコードです。eventから変更後の住所を取得し、サーバー側で配送料を計算させていますね。

paymentRequest.on('shippingaddresschange', function(ev) {
  if (ev.shippingAddress.country !== 'JP') {
    ev.updateWith({status: 'invalid_shipping_address'});
  } else {
    // Perform server-side request to fetch shipping options
    fetch('/calculateShippingPrice', {
      data: JSON.stringify({
        shippingAddress: ev.shippingAddress
      })
    }).then(function(response) {
      return response.json();
    }).then(function(result) {
      ev.updateWith({
        status: 'success',
        shippingOptions: result.supportedShippingOptions,
      });
    });
  }
});

配送先によって配送料金を再計算させているので、shippingOptions、厳密にはamount表示の更新をするためにupdateWith()関数を呼び出しています。再計算が必要でなければ入力住所のバリデーションを行い、updateWithstatussuccessにするだけで問題ないと思います。requestShippingをtrueにすると、配送先入力が必須になるのでshippingOptionsを更新が必要みたい?です。(配送先なし = requestShipping = falseで検証してないですが...)

const shippingOptions = [{
   id: 'payment id',
   label: 'ネコポス (クロネコヤマト)',
   amount: totalAmount,
}],

以下のイベントはStripeがWalletまたはChromeに保存されたカードを処理しpaymentMemthodのidを生成してくれます。eventからpaymentMethod.idを取得できるようになっています。決済処理はここに含めると良いと思います。tokenイベントもあるので、プロジェクトに合わせてどのイベントを利用するか選ぶと良いと思います。

paymentRequest.on('paymentmethod', async (event) => {
      // 決済ロジック with event.paymentMethod.id 
      // if(payCompleted) {
      //     event.complete('success') // 必須
      // } else {
      //     event.complete('fail') // 必須
      // }
});

また、決済開始から30秒以内にeventのcompleteを呼び出す必要があります。決済開始から30秒を超えるとペイメントシートで支払い失敗のエラーが発生します。サーバー側で決済が完了するのになぜかペイメントシートでエラーが発生する場合は決済フローの見直しまたは決済処理時間を30秒以内に最適化すると良いと思います。

イベントの詳細はここで確認できます!
詳しくはこちらから: https://stripe.com/docs/js/payment_request/events/on_paymentmethod

ボタンのデザイン

オプションにstyleを含めることでデザインを変更することが可能です。

const options = {
  paymentRequest,
  style: {
    paymentRequestButton: {
      type: 'default',
      // One of 'default', 'book', 'buy', or 'donate'
      // Defaults to 'default'

      theme: 'dark',
      // One of 'dark', 'light', or 'light-outline'
      // Defaults to 'dark'

      height: '64px',
      // Defaults to '40px'. The width is always '100%'.
    },
  }
}

<PaymentRequestButtonElement options={options} />

また、Apple Payの場合以下のボタンが表示されますが
スクリーンショット 2020-12-04 19.38.36.png

Google Payは以下のボタンが表示されます。Google PayのデザインにならないのでGoogle Payを本番環境で利用するためにはGoogleのレビューが必要になると思いましたが、審査は不要でした。これはStripeの仕様で、開発環境も本番環境もこのボタンのデザインになります。

スクリーンショット 2020-12-04 19.37.49.png
詳しくはこちらから:
https://stackoverflow.com/questions/58027517/displaying-stripe-payment-request-button-as-a-google-pay-button

所感

ECサイトにApple Payのチャリーンって音が出るようになった時テンション上がりました。また新機能を開発したら記事をあげます!最後まで読んでいただきありがとうございました!

10
15
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
10
15