💲

STUDIOのサイトにStripe決済を実装する方法

2020/11/19に公開
16

2021/05/27 追記

リンクだけで決済ページを生成できる「Stripe Links」がリリースされたので、今後はこっちを使えば行けそうです!ありがとうGTM😂でもこの記事でニーズの高さを実感できたのは面白かった。
https://stripe.com/jp/payments/payment-links

はじめに

決済サービスStripeのCheckout機能は、サーバーサイドの実装をしなくてもJavaScriptのコードスニペットをペッと貼り付けるだけで綺麗なボタンと、美しいデザイン・UIの決済画面を実装することが可能です。一方でSTUDIOで作ったサイトはJavaScriptを埋め込むことができません。しかし Google Tag Manager(GTM)を使うとHTMLコードとしてJavaScriptを埋め込むことが可能となり、これによりSTUDIOでもStripe決済を実装することができます!(単発・定期どちらも可。URLは一度stripeに遷移して再度STUDIOのURLにリダイレクトされます)

全体的な流れ

STUDOにはGTMがAppとして提供されているので、GTMで作ったStripeのコードスニペットのタグを埋め込みます。本来はStripeのコードスニペットで生成されたボタンが押されるとJavaScriptが実行されて決済ページにリダイレクトされるのですが、今回はSTUDIOで作ったボタンにIDを付与し、そのIDをもつボタンが押されたらStripeのJavaScriptが実行されるようにカスタマイズをします。

STUDIOで決済ボタンを作成

STUDIOではStripeのJavaScriptが実行されるためのIDを持ったボタンを作るだけです。ボックス要素を追加して任意のIDを設定してください。デザインはお好みで。今回は#plan-jpy-premiumとしました。

また決済成功時とキャンセル時にリダイレクトされるページも作っておきます。

  • /success
  • /canceled

Stripe側の準備

まずStripeをテストモードにします。左メニューにあるテストデータを表示をオンにするとAPIキーや商品が全てテスト用になります。

Checkoutの設定

設定>商品の設定>Payments>Checkout の設定 にて以下2つの設定をします。

  • ドメイン
  • 商品

商品の追加は専用の作成画面に飛びます。

商品と料金体系を作成したら、(これがCheckoutでは非常にわかりにくいところにあるのですが)料金の右にある...マークを開くとCheckout コードスニペットを取得を押すと Checkout スニペットジェネレータ が起動します。

料金の詳細画面にいってしまうとコードスニペットは取得できませんので迷子にならないようお気をつけを。

この画面で決済成功時のリダイレクト先URL、決済キャンセル時のリダイレクト先URLを入力してやればコードスニペットが生成されるので、本来はこれをコピーしてウェブサイトに貼り付ければStripe決済ボタンの完成という簡単なシステムなのですが、STUDIOではこれを貼り付けるブロックが現時点でないので、これをカスタマイズしてきます。

<!-- Load Stripe.js on your website. -->
<script src="https://js.stripe.com/v3"></script>

<!-- Create a button that your customers click to complete their purchase. Customize the styling to suit your branding. -->
<button
  style="background-color:#6772E5;color:#FFF;padding:8px 12px;border:0;border-radius:4px;font-size:1em"
  id="checkout-button-price_xxxxx"
  role="link"
  type="button"
>
  Checkout
</button>

<div id="error-message"></div>

<script>
(function() {
  var stripe = Stripe('pk_xxxxx');

  var checkoutButton = document.getElementById('checkout-button-price_xxxxx');
  checkoutButton.addEventListener('click', function () {
    // When the customer clicks on the button, redirect
    // them to Checkout.
    stripe.redirectToCheckout({
      lineItems: [{price: 'price_xxxxx', quantity: 1}],
      mode: 'subscription',
      // Do not rely on the redirect to the successUrl for fulfilling
      // purchases, customers may not always reach the success_url after
      // a successful payment.
      // Instead use one of the strategies described in
      // https://stripe.com/docs/payments/checkout/fulfill-orders
      successUrl: 'https://your-website.com/success',
      cancelUrl: 'https://your-website.com/canceled',
    })
    .then(function (result) {
      if (result.error) {
        // If `redirectToCheckout` fails due to a browser or network
        // error, display the localized error message to your customer.
        var displayError = document.getElementById('error-message');
        displayError.textContent = result.error.message;
      }
    });
  });
})();
</script>

カスタマイズ後のJavaScriptコード

主な変更点は(今回はSTUDIOで作ったので)button要素を削除したことと、document.getElementById('plan-jpy-premium')のIDをSTUDIOで設定したIDに変更したことです。

<script src="https://js.stripe.com/v3"></script>

<div id="error-message"></div>

<script>
(function() {
  var stripe = Stripe('pk_xxxxx');

  var checkoutButton = document.getElementById('plan-jpy-premium');
  checkoutButton.addEventListener('click', function () {
    stripe.redirectToCheckout({
      lineItems: [{price: 'price_xxxxx', quantity: 1}],
      mode: 'subscription',
      successUrl: 'https://your-website.com/success',
      cancelUrl: 'https://your-website.com/canceled',
    })
    .then(function (result) {
      if (result.error) {
        var displayError = document.getElementById('error-message');
        displayError.textContent = result.error.message;
      }
    });
  });
})();
</script>

Webhookについて

Checkoutの設定の3つ目のWebhookというのは、Stripeで決済イベントが発生したときに別のエンドポイント(URL)に通知をして、そっちでも何かごにょごにょしたいとき(例えば決済データをサービスのDBにも保存したいなど)に使う仕組みのことなので、STUDIOに決済システムを導入するだけなら不要です。

JavaScriptのコードコードスニペット側で任意の値をclient_refference_idとして渡してあげると、決済イベント時にWebhook側に渡してあげることができるので、QueryString(URLの?の跡につくやつ)や Cloud Functions for Firebase などと連携してある程度のカスタマイズは可能です。しかし複数の値を通知したいなどあればFullfillmentと呼ばれる1から開発する方法を取るしか無いようです。

Google Tag Manger の設定

GTMの使い方の詳細は割愛しますが、簡単に言うと「指定した条件に合致するページに、解析ツールのJavaScriptなどの"タグ"を埋め込むことができるツール」です。この発火条件のことをトリガーといいます。主にECサイトのカートシステムを導入しているサイトや Google Adwards などの広告系のタグをまとめて管理することが多いと思います。Google Analytics は単体でもサイトに埋め込むコードを取得できますが、GTMでまとめて管理する人もいるようです。

GTMのタグとトリガーを作成

ここでは決済用のページ(https://your-website.com/payment)の閲覧をトリガー(発火条件)とし、StripeのJavaScriptコードのタグが埋め込まれるように設定します。

まずはタグを作成し、タグの種類を「カスタムHTML」に。先程カスタマイズしたStripeのJavaScriptコードを貼り付けましょう。

トリガーは元々ある「All Pages(すべてのページで発火する)」を使ってもいいのですが、なるべくサイトを軽くしたいし不具合を防ぎたいので決済ページの閲覧のみで発火する「Payment Page」トリガーを作成します。

STUDIOにGTMを追加


STUDIOとGTMを紐付けます。公式のAppがあるのでここに「GTM-xxx」のIDを入力してください。

GTMタグ公開

これで準備OKなのでGTMの「公開」ボタンで公開しましょう。GTMにはプレビュー機能もあるので、影響が気になる方やバージョン履歴をキレイに管理したい方はプレビューで確認してから公開してください。

STUDIOにもキャッシュが効いているので、GTMの公開後に一度「Command+Shift+R」でスーパーリロードするとタグが反映されてるはずです。ブラウザの検証機能などでソースをみてgtmと検索してみましょう。

ちなみにGTMで埋め込んだJavaScriptそのものはソースには出てきません。あくまでタグを読み込むscriptが書かれているだけです。

これでSTUDIOのサイトでStripe決済をしてもらう準備ができました。

決済をテストする

Stripeの設定でテストデータとして商品やコードスニペットを作成しました。これであれば424242のダミークレジットカードが使えるのでこちらで試してみてください。日付は未来の日付、CVCは3桁の数字であれば何でもいいです。

https://stripe.com/docs/testing

本番環境

テストが問題なければ本番環境で運用するためにテストモードをオフにします。GTMに埋め込んだJavaScriptのAPIキー(pk_xxxx)や商品の API ID (price_xxx)も変わってしまうのでGTMで書き換えねばならないことに注意してください。本番環境のキーにGTMを変更して公開すれば顧客に決済をしてもらえるはずです。

Discussion

TはやじんTはやじん

STUDIOでの構築をしているため、非常に参考になりました!
購入後にメールでデータのダウンロードリンクを送るといった動作はできるのでしょうか…?

まったまった

こんにちは!Stripe側から決済時の自動返信メールは変更ができたはずです!ただプランごとに返信内容を変えられたかは微妙ですね…

たけのこたけのこ

おかげでSTUDIOサイトに決済機能を付けることができました!
一点、質問なのですが、今回のやり方だと、顧客が名前を記入する欄がなく、メールアドレスでしか管理ができないのですが、名前の項目を増やすにはどのようにすればよいのでしょうか?

まったまった

こんにちは!軽くググってみたのですが、checkoutに名前や電話番号を追加するのは厳しそうではあります。が、私も気になるのでもう少し調べてみますね。

たけのこたけのこ

ご丁寧にありがとうございます。もし分かりましたら改めて教えていただけますと幸いです!

key0000key0000

STUDIOでは、EC機能は使用できないと聞いていたので、大変勉強になりました!
ちなみに、stripeを使用して、STUDIOにカート機能を実装することは難しいでしょうか?…

まったまった

んー、このやり方もECというより決済機能だけを無理くり付けてる(PayPalのように)だけなので、カートとかを技術的にできたとしても、そもそも会員機能のないSTUDIOにやっちゃうと色々不整合が出そうですね…。

harada0201harada0201

そうですよね💦
わざわざご回答頂きありがとう御座いました🙇

YutaYuta

この記事のおかげでサイトに決済機能を導入できました!本当に助かりました。ありがとうございます!

ただ一つだけ問題があります。一番最初に決済ページに訪れたときには決済ボタンクリックでタグが発火するのですが、その後他のページに飛んでまた決済ページ戻ってきてボタンをクリックしてもタグが発火してくれません。ページをリロードすると解消しますがUX的にその手間は省きたいです。
備考:トリガーはページビューやクリックなどで試しましたが変わりませんでした。環境:google、safari

まったまった

導入できてよかったです🎉

えっと、最初の"発火"という言葉の使い方が悪かったですね。
GTMにおけるトリガーの発火(によるタグの埋め込み)はページビューで起こるようにしているものです。一方でボタンをクリックしたときに発生するのは(埋め込んだタグの中に書かれている)JavaScriptの中にあるcheckoutButton.addEventListener('click', function () {のイベントです。

ちょっと検証しないとなんともですが、別のページに戻ってきたときに以下のどちらが起こっているのかを確認するといいと思います!
①GTMのトリガーが発火せずにタグが埋め込まれていない
②タグは埋め込まれているがJavaScriptのイベントが発生していない

YutaYuta

早速のご返信ありがとうございます!
浅学なものではっきりしたことは分からないのですが恐らく①が原因なようです。よろしければ実際に症状をご確認いただけると幸いです。

https://sugi-interface.studio.site/checkout
(初回はcheck out をクリックするとSpriteの決済画面に遷移しますが、other pageに飛んでから戻ってきてクリックすると決済画面に遷移しません。※リロードしなおしてクリックすると遷移します)

まったまった


見たところ画面遷移をしてもずっとタグは残っていますね。ただSTUDIOの仕組み上、画面遷移しても全てのHTMLが読み込み直しされるわけではなく、一部のHTMLだけが変わるようですね(これがSPA: Single Page Application なのかな?違ってたらすみません)。

addEventListenerが初回に呼ばれたあとに、画面遷移で対象のボタンだけなくなってしまうのでそこでイベントのリッスンが切れていることが原因っぽいですね。

GTMのトリガーをウィンドウの読み込みにしてみると行けそうな気はします。
https://studio-gaz.design/blog/studio-gtm-accordion

YutaYuta

ご丁寧にどうもありがとうございます☺️とても勉強になります!

トリガーをウィンドウの読み込みにしたのですが変わらずでした...
しかし原因が分かっただけでも良かったです!試行錯誤してみます!

まったまった

そうでしたか‥面目ないです。
GTMのタグについて、STUDIOさん側に問い合わせてみると答えを持たれてるかもですね。頑張ってください!

YutaYuta

はい!頑張ります!いろいろとご教授頂きありがとうございました😊😊