RailsでPAY.JP APIを利用する 〜実装準備編〜（payjp.js v2）

# 概要
PAY.JP APIでのカード登録/変更/削除機能実装の覚書です。
今回は実装のための準備としてトークンの取得までの手順をまとめていきます。
※簡潔にするため実装のために必要な最低限のコードのみ書いています。

なにか間違い等あれば編集リクエストをいただけると幸いです。

ちなみにpayjp.jsはv1に関する記事は多いですが現行のv2とは異なる部分が多いので注意が必要です。

実装準備編←今ここ
https://qiita.com/nissy7ok/items/9790ef5ee1dec2863a62
カード登録編
https://qiita.com/nissy7ok/items/cea6789fe3b99654e473
カード更新・削除編
https://qiita.com/nissy7ok/items/0ed52954f8fdad772da3

# 環境
```
# OS Version
ProductName:	Mac OS X
ProductVersion:	10.15.7
BuildVersion:	19H2

# Ruby Version
ruby:           2.6.5p114
Rails:          6.0.3.3
```

# 手順
## PAY.JPへ登録
登録・ログイン後の画面で`API`を選択。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672627/3864b610-2de8-fb05-8ece-2da908454971.png" width=75%>
`テスト鍵`と`本番鍵`が用意されていますが、`テスト鍵`の方を使用します。


## 必要なgemをインストール

```ruby:Gemfile
gem 'payjp'
gem 'dotenv-rails'
```
`dotenv-rails`は環境変数を管理するgemなので、必須ではありませんが、秘密鍵を直接コードに記述するようなことがない形をとりましょう。
記述後は`bundle install`も忘れずにしておきましょう。

## 環境変数を定義

アプリのディレクトリに`.env`ファイルを作成し、以下のように記述します。

```:.env
PAYJP_SECRET_KEY = '先ほど確認したテスト秘密鍵'
PAYJP_PUBLIC_KEY = '先ほど確認したテスト公開鍵'
```
こうすることで鍵を変数化でき、たとえば`ENV[PAYJP_SECRET_KEY]`と記述することでテスト鍵を表せます。
`rails console`で動作を確認できます。

```terminal:terminal
[1] pry(main)> require 'dotenv-rails'
=> true
[2] pry(main)> ENV['PAYJP_SECRET_KEY']
=> "sk_test_hogehoge"
```

ちなみにファイル名を`.env.development`とすれば開発環境、`.env.production`とすれば本番環境といった形でコードはそのままで環境ごとに変数を使い分けることができます。
そのあたりの詳細は公式github （ https://github.com/bkeepers/dotenv ）を参照。

<font color="Red">※.envファイルはgithubにpushしないこと。.gitignoreに設定しておきましょう。</font>

## モデルを作成
Cardモデルを作成します。

```terminal:terminal
$ rails g model card
```

PAY.JPから受け取るデータとして保存する必要があるのは`顧客ID`と`カードID`を保存するカラムです。
この2つがあれば大体のデータは持ってくることができます。
下記コードでは`Userモデル`との紐付けも行っています。

```Ruby:migrationfile
class CreateCards < ActiveRecord::Migration[6.0]
  def change
    create_table :cards do |t|
      t.reference :user, null: false
      t.string :customer_id, null: false
      t.string :card_id, null: false
      t.timestamps
    end
  end
end
```
忘れずマイグレーションを行いましょう。

```terminal:terminal
$ rails db:migrate
```

## JSファイルを記述
公式ガイド（ https://pay.jp/docs/payjs-guidance ） のほぼ丸写しです。
公式ではトークン生成の発火にonclickを使用していますが、私の場合はうまく動作しなかったのでAddEventListenerを使用しました。
とりあえずトークンを表示させて動作を確認します。

```javascript:card_form.js
// DOM読み込みが完了したら実行
document.addEventListener('DOMContentLoaded', () => {
  // 公開鍵を登録し、起点となるオブジェクトを取得します
  var payjp = Payjp('pk_test_hogehoge')

  // elementsを取得します。ページ内に複数フォーム用意する場合は複数取得ください
  var elements = payjp.elements()

  // element(入力フォームの単位)を生成します
  var numberElement = elements.create('cardNumber', {style: style})
  var expiryElement = elements.create('cardExpiry', {style: style})
  var cvcElement = elements.create('cardCvc', {style: style})

  // elementをDOM上に配置します
  numberElement.mount('#number-form')
  expiryElement.mount('#expiry-form')
  cvcElement.mount('#cvc-form')
  
  // ボタンが押されたらtokenを生成する関数を用意します
  create_token.addEventListener("click", function() {
    payjp.createToken(numberElement).then(function(r) {
      document.querySelector('#token').innerText = r.error ? r.error.message : r.id
    })
  });
})
```

## ビューファイルを記述
とりあえずフォームを表示させるため最低限の記述をします。後でお好みで書き換えましょう。

```haml:_card_form.html.haml
:css
  .Payjs__outer {
    border: solid 1px;
  }

-# 実際はapplication.html.haml等のヘッダー部分に書いたほうが良いです。
= javascript_include_tag 'https://js.pay.jp/v2/pay.js'

.Payjs
  .Payjs__outer{id: "number-form"}
  .Payjs__outer{id: "expiry-form"}
  .Payjs__outer{id: "cvc-form"}
  %button{id: "create_token"}
    トークン作成
  %span#token
    トークン：
```

## 動作確認
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672627/f38b24ad-a06a-95b4-f390-0105f3e3d25d.png" width=75%>
こんな感じのフォームができるので、テストカード ( https://pay.jp/docs/testcard )から好きなカード番号を入力して動作を確認します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672627/44fac341-488e-c9ce-1166-ed7c8a6caf24.png" width=75%>
トークンの生成が確認できました。

今回はここまで、次回はカード登録機能の実装についてまとめていきたいと思います。

# 参考
結局の所公式APIとガイドが最強です。
ただ読み慣れないうちはQiita等で実際の実装手順を見ながら感覚を掴むと理解が早まると思います。

PAY.JP API リファレンス
https://pay.jp/docs/api/

PAY.JP API 利用ガイド | PAY.JP
https://pay.jp/docs/started
<br>
公式ブログも参考になりますが、情報が古くv1準拠で書かれている場合が多いので注意が必要です。

ごく基本的なPAY.JPの使い方（Ruby編） - PAY.JP Engineering Blog
https://payjp.hatenablog.com/entry/2017/11/21/191916
<br>
その他参考にした記事等

Railsで　Payjp.js V2　でクレジットカード登録機能実装　フリマアプリ - Qiita
https://qiita.com/ta9301/items/6b736390c49c3f40edb6

[HowTo]Pay.jpを用いた商品購入機能実装から商品購入後の設定まで
https://qiita.com/Tatsu88/items/eb420e372077939a4627