【Ruby on Rails】stripeの一番簡単な決済機能Checkoutを試してみた。

#はじめに
初心者な私が、stripeAPIによる決済機能をアプリケーションに実装するにあたり、
仕様を理解しきれないまま手を動かしたら、いろいろな実装方法がある事に翻弄され多大に時間を無駄にしたので、とにかくシンプルに簡単な実装方法であるCheckoutから試してみる事にしました。

Qiitaに記事を投稿するのは初めてなので、いろいろお見苦しいとは思いますが、
もし参考にしていただけるようでしたら、みてやってください。

#公式チュートリアル
https://stripe.com/docs/legacy-checkout/rails
このチュートリアルでは簡単に「料金支払い」Charge の実装を試す事ができます。
ですが、商品購入など実践的な実装をする上では Charge は使わないと思いますので、
今回はスルーします。

#stripeのアカウント作成
https://qiita.com/Rafflesia/items/5ce936656c6f99c144ef
上記の記事が分かりやすくまとめられているので
####公開可能キー、シークレットキーの取得
までを参考にダッシュボードを使えるようにしておく。
<img width="1438" alt="スクリーンショット 2020-03-07 0.43.18.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489847/57d0e7a6-719d-3323-1ae1-dda92453ce0a.jpeg">
開発者 > APIキー　から「公開可能キー」と「シークレットキー」を控えておく。

#stripeの導入
```ruby:gemfile
gem 'stripe'
```
bundle install しておく。

```ruby:.env
STRIPE_PUBLISHABLE_KEY='pk_test_****************************'
STRIPE_SECRET_KEY='sk_test_****************************'
```
控えておいた、stripe の公開キー、シークレットキーをENVに記述。
.env を gitignore しておくのも忘れずに。

```ruby:config/initializers/stripe.rb
Rails.configuration.stripe = {
  :publishable_key => ENV['STRIPE_PUBLISHABLE_KEY'],
  :secret_key      => ENV['STRIPE_SECRET_KEY']
}

Stripe.api_key = Rails.configuration.stripe[:secret_key]
```
Checkout は非常にシンプルなので、今回は商品一覧ページとしてindexアクションだけを使う事にします。

```ruby:config/routes.rb
resources :payments, only: [:index]
```

#stripeの仕様ってこんなの
私自身がまだ分かり始めた所なので、完璧ではないですし、
もっと良い解釈があるとは思いますが、僭越ながら分かった範囲で解説いたします。
これを分かっていないと私のように時間を無駄にしちゃいます・・・。


###[Product]
https://stripe.com/docs/api/products
・製品情報のオブジェクト
・販売金額などは含みません

###[SKU]
https://stripe.com/docs/api/skus
・販売情報のオブジェクト
・価格や通貨、在庫数、シッピング先など、販売に関するプロパティを持つ

製品情報である product 内には価格や通貨などの販売に関する情報が付加できません。
SKU という販売データに product.id などを持たせる事で
決済可能な商品データとなるというところでしょうか？

他にも組み合わせなどはありますが、今回はSKUを商品データとして扱っていきます。

#商品データの作成
https://dashboard.stripe.com/test/products/
[ + 新規 ] を押して Product と SKU を作成します。（同時に作成されます）
※既にいっぱいあるのは私のテストデータです。
<img width="1438" alt="スクリーンショット 2020-03-07 2.09.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489847/b4738e9c-15b3-eb32-acbd-fe3be8b3e90b.png">
<img width="1438" alt="スクリーンショット 2020-03-07 2.13.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489847/e6f6b412-ddc1-0510-9cb9-f7a2fa3169c4.png">

登録が済んだので、先ほど登録した「テスト商品」をリストから選択し
<img width="1438" alt="スクリーンショット 2020-03-07 2.21.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489847/f957a2e4-19cf-f4b2-5041-c941718a6afc.png">
<img width="1438" alt="スクリーンショット 2020-03-07 2.24.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489847/49282446-5f92-334b-4b4a-e4e411d7060b.png">
※ここでは設定しませんが、私はメタデータに商品カテゴリなどを持たせりしてます。
[Checkoutで使用] のボタンをクリック
<img width="1438" alt="スクリーンショット 2020-03-07 2.22.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489847/58408126-bb67-4177-9ae1-65a00892e280.png">

スニペットジェネレーターが View に貼り付けるコードを生成してくれます。
成功時、キャンセル時にリダイレクトされるURLは任意のものを入れてください。

#Controller
```ruby:controllers/payments_controller.rb
class PaymentsController < ApplicationController
  def index
    @items = Stripe::SKU.list().data
  end
end
```
SKUを全て取得します。

#View
スニペットジェネレータのコードは商品１アイテムに対してのものなので、それで良いならそのままコピペして調整してください。
今回は、少し改造して一覧表示できるようにしてみます。

```erb:views/payments/index.html.erb
<script src="https://js.stripe.com/v3"></script>
<ul class="grid">
  <% @items.each do |item| %>
  <li class="grid-item">
    <img src="<%= item.image %>" alt="<%= item.attributes.name %>">
    <h3><%= item.attributes.name %></h3>
    <div class="price"><%= item.price %> <%= item.currency.upcase %></div>
    <button class="btn_buy" id="<%= item.id %>" role="link">BUY</button>
  </li>
  <% end %>
</ul>
```
```ruby:app/javascripts/stripeCheckoutBtn.js
$(function(){
  $(document).on('click', '.btn_buy', function (){
    let stripe = Stripe('pk_test_*********************************');
    /* 公開キーを直接書いているが、gon使ってENV['STRIPE_PUBLISHABLE_KEY']を渡してもいいかも */
    let skuId = $(this).attr("id");
    stripe.redirectToCheckout({
      items: [{sku: skuId, quantity: 1}],
      successUrl: 'https://hoge.fuga.com/success',
      cancelUrl: 'https://hoge.fuga.com/cancel',
    })
    .then(function (result) {
      if (result.error) {
        let displayError = document.getElementById('error-message');
        displayError.textContent = result.error.message;
      }
    });
  });
});
```
これで最低限の実装は完了。

#動作確認
<img width="1438" alt="スクリーンショット 2020-03-07 3.28.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489847/3e79fb1e-153a-2c0c-446c-1138968c3e26.png">
商品一覧に、今回作成したテスト商品が表示されています。「BUY」ボタンを押してみましょう。
<img width="1438" alt="スクリーンショット 2020-03-07 3.29.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489847/37bb4bf8-213a-fccd-438e-bbd4d1453030.png">
stripe Checkout に遷移しました。ダミーの情報で支払いテストしてみましょう。
無事支払い処理が通ったらダッシュボードで確認。
<img width="1438" alt="スクリーンショット 2020-03-07 3.38.53.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489847/10e53566-034e-729a-f9c7-3f7cc6584f91.jpeg">

しっかり入金されていますね。

#最後に
単発決済の処理はできましたが、サブスクライブ決済やwebhookでのレスポンス取得など、
ほぼ必須となってくるであろう機能はまだまだあります。

次はwebhookで決済の完了を受け取って、アプリ側のDBにレコードを作成するようなカンジの事を
やってみようと思います。