はじめに
Payjpの決済方法の記事はたくさんありますが、default_card設定方法はなかったので書かせていただきます。
トークン化については他の方が書かれているので、javascriptの記述は割愛します。
開発環境
ruby 2.6.5
Rails 6.0.3.3
参考
説明不足なところはこちらで補ってください。
リファレンス:
https://pay.jp/docs/api/#customer-%E9%A1%A7%E5%AE%A2
https://pay.jp/docs/customer
Cardモデル
自分の場合はCardモデルで下記のカラムを保存しています。
id | user_id | card_token | customer_token |
---|---|---|---|
integer | tok_~ | cus_~ |
Customer作成
Customer作成にはcard_token(tok_~)が必要になります。
javascriptで受け取ったtokenをコントローラーに渡して、下記の記述をします。
def create
# card_tokenが正しいか確認
if params[:card_token] == nil
redirect_to new_user_card_path
return
end
# ユーザーのcustomer_tokenが存在する場合
if Card.find_by(user_id: current_user.id)
card = current_user.card
customer = Payjp::Customer.retrieve(card[0][:customer_token])
customer.cards.create(
card: params[:card_token]
)
else
# ユーザーがcustomer_tokenが存在していない場合
customer = Payjp::Customer.create(
description: "test",
card: params[:card_token],)
end
# cardテーブルに保存
card = Card.new(
user_id: current_user.id,
card_token: params[:card_token],
customer_token: customer.id)
end
Customer情報取得
配列@cards
を定義して、customer_tokenをもとにcard情報を入れます
cards = Card.where(user_id: current_user.id)
@cards = []
cards.each do |card|
@customer = Payjp::Customer.retrieve(card.customer_token)
@cards << @customer.cards
end
ユーザーにカードを選択してもらい、引数「i」で選択されたindexを受け取れるようにフォームを作成します。
ビューで@cards
に対してeach_with_indexで下記の記述でカード情報を表示させられます。
<%= form_with url: set_default_card_path, method: :post, local: true do |f| %>
<% @cards.each_with_index do |card, i| %>
<%=f.radio_button :selected, :"#{i}" ,id: "check_card", checked: (card.data[i] [:id] == @customer[:default_card]) %>
<%= "**** **** **** #{ + card.data[i][:last4]}" %>
<%= "#{card.data[i][:exp_year]}年#{+ card.data[i][:exp_month]}月" %>
<% end %>
<%= f.submit "次へ進む" %>
<% end %>
default_cardの設定方法
select.html.erbのform_withの中でradio_buttonを使い、params[:selected]に#{i}の値を受け取っています。
@customer
の[:default_card]に代入して、@customer.saveで完了します。
※@customer.saveをしないと更新されません。
def set_default_card
cards = Card.where(user_id: current_user.id)
@cards = []
cards.each do |card|
@customer = Payjp::Customer.retrieve(card.customer_token)
@cards << @customer.cards
end
@customer = Payjp::Customer.retrieve(card.customer_token)
index = params[:selected].to_i
@customer[:default_card] = @cards[0].data[index][:id]
@customer.save
end
念のため
- customerを作成していない場合、card_token(tok_~)があれば、Payjp::Charge.createができます。
- customerを作成した場合、cardのid(car_~)、もしくはcustomerのid(cus_~)があればPayjp::Charge.createができます。
- customerのidを渡した場合はcustomerのdefault_cardが使われます。
(指定しない場合は最後に登録したカードがdefault_cardになります。)
最後に
もっと簡便な記述もあるかも知れませんが、これで実装することはできます。
あとは、各々アレンジしてください。