#1.どのような状態だったか
javascriptでpayjp-token
取得はコンソールで確認すると全て成功しており、ページ遷移の部分でもエラーは出ず、validationに関するエラーも出ないのに、コントローラーでpayjp-token
の値が取り出せないという状態でした。(エラー文が出ず、正常にnewアクションに戻るという症状でした。)
下記の二つの記事を参考にpay.jp機能を実装をしていました。(大元が上の方で、それの詳細まで記述されていたのが下記の方でした。)
https://qiita.com/takachan_coding/items/f7e70794b9ca03b559dd
https://qiita.com/emincoring/items/ce29dbbd182aa3c49c6b
なのでとりあえず動作を見るべく細部まで記述のあった下記のブログを参考に下記のようにviewを作成しました
※今回はviewの記述によるエラーだったので、その部分についてのみ記述します
.content__title
%h2 クレジットカード情報入力
.content__credit-card
.content__credit-card__inner
= form_with url: cards_path, method: :post, html: { name: "inputForm" } do |f| -# createアクションのパスを指定
= f.label :カード番号, class: 'label'
%span 必須
= f.text_field :card_number, type: 'text', class: 'input-number', placeholder: '半角数字のみ', maxlength: "16"
.cards-expire
= f.label :有効期限, class: 'label'
%span 必須
%br
.cards-expire__wrap
= f.select :exp_month, [["01",1],["02",2],["03",3],["04",4],["05",5],["06",6],["07",7],["08",8],["09",9],["10",10],["11",11],["12",12]],{} , class: 'input-expire'
%span.expire-text 月
%br
.cards-expire__wrap
= f.select :exp_year, [["19",2019],["20",2020],["21",2021],["22",2022],["23",2023],["24",2024],["25",2025],["26",2026],["27",2027],["28",2028],["29",2029]],{} , class: 'input-expire'
%span.expire-text 年
.cards-expire
= f.label :セキュリティコード, class: 'label'
%span 必須
= f.text_field :cvc, type: 'text', class: 'input-number', placeholder: 'カード背面4桁もしくは3桁の番号', maxlength: "4"
.content-bottom#card_token
= f.submit '追加する', class: 'content-bottom--add-btn', id: 'token_submit'
#2.原因
payjp-token
の受け渡しを図解すると、
submitを押してjavascriptに入力情報送信→javascriptでpayjp-token
に変換→form_withの実行でcontrollerにpayjp-token
受け渡し
となります。
この時、数値の受け渡し毎にそれぞれidが1つずつ必要になるのですが、自分は1つしか用意していませんでした。
そのため、受け取りid=受け渡しid
となり、入力情報(カードの期日など)を素のままでform_withで受け取り、コントローラに値を返してしまっていたというのが原因でした。
#3.解決方法
form_withにも新たにidを定義すれば希望通りの挙動をしました
〜前略〜
= form_with url: pay_cards_path, method: :post, id: 'charge-form',html: { name: "inputForm" }do |f|
# idの名前はどのようなものでも大丈夫です。筆者はpayjpのホームページで記述のあったid名を引用しました。
〜後略〜
#4.(補足)エラーの見つけ方
まず今回のように、railsのエラー文やjavascriptのエラー文(Google Chromeの検証のconsole上のもの)が出なければ数値の受け取りミスであることがほとんどだと思われます。
したがって筆者はまずコントローラでbinding.pryを挟んでどこまで数字が取れているか確認し、次にjavascriptにもconsole.log();を挟んで確認しました。結果、javascriptは問題ないということがわかり、コントローラとビューの確認を行いました。
その結果、javascriptには送れているから、そのあとの受け取りのタイミングで間違いがあると考え、submitの後に処理されるのはなにかと考えた時、残るのはform_withだけなのでその記述に関する資料を検索していたところ、このメソッドもid指定できることがわかり解決に至りました。
このようにエラー文が出なくて困ったら、デバックのコードを1行ずつ挟んで確認すれば原因を特定しやすくなり、エラーを見つけることができます。