質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

1799閲覧

PayJPを用いたクレジット決済機能実装のためにtoken_idを取得したい

Kagiya-masahumi

総合スコア0

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2021/06/19 10:50

実現したいこと

ご覧頂きありがとうございます。
現在オリジナルアプリにてPayJPを用いたクレジットカード決済機能を実装しています。
ところが、クレジットカードに情報を記入し、登録しようとすると以下のエラーメッセージが表示されます。

ActiveRecord::NotNullViolation in CardsController#create Mysql2::Error: Field 'token_id' doesn't have a default value

クレジットカードのトークンIDに値が入力されていない旨の内容です。

以下に記述した範囲外で、確認したい箇所がございましたらどうぞ遠慮なくお申し付けください。
どうかお力添えをよろしくお願い申し上げます。

発生しているエラー

イメージ説明
テストカードを用いた挙動

該当のソースコード

ruby

1#cards_controller 2 def create 3 Payjp.api_key = ENV["PAYJP_SECRET_KEY"] 4 customer = Payjp::Customer.create( 5 description: 'test', 6 card: params[:token_id] 7 ) 8 card = Card.new( 9 customer_id: customer.id, 10 token_id: params[:token_id], 11 user_id: current_user.id 12 ) 13 14 if card.save 15 redirect_to root_path 16 else 17 redirect_to new_card_path 18 end 19 end

ruby

1#マイグレーションファイル 2 3 def change 4 create_table :cards do |t| 5 t.string :customer_id, null: false 6 t.string :token_id, null: false 7 t.references :user, foreign_key: true 8 t.timestamps 9 end 10 end

Javascript

1//app/javascript/card.js 2const pay = () => { 3 Payjp.setPublicKey(process.env.PAYJP_PUBLIC_KEY); 4 5 const form = document.getElementById("card_form"); 6 form.addEventListener("submit", function(e) { 7 e.preventDefault(); 8 9 const formResult = document.getElementById("card-form"); 10 const formData = new FormData(formResult); 11 12 const card = { 13 number: formData.get("order[number]"), 14 cvc: formData.get("order[cvc]"), 15 exp_month: formData.get("order[exp_month]"), 16 exp_year: `20${formData.get("order[exp_year]")}`, 17 }; 18 19 Payjp.createToken(card, function(status, response) { 20 if (status === 200) { 21 const token = response.id; 22 const tokenObj = `<input value=${token} name='token_id' type="hidden">`; 23 const cardForm = document.getElementById("card_form"); 24 cardForm.insertAdjacentHTML("beforeend", tokenObj); 25 document.getElementById("number").removeAttribute("name"); 26 document.getElementById("name").removeAttribute("name"); 27 document.getElementById("cvc").removeAttribute("name"); 28 document.getElementById("exp_month").removeAttribute("name"); 29 document.getElementById("exp_year").removeAttribute("name"); 30 document.getElementById("card_form").submit(); 31 } else { 32 alert("カード情報が正しくありません") 33 } 34 }); 35 }); 36}; 37window.addEventListener("load", pay);

ruby

1# app/views/cards/new.html.erb 2 3 <%= form_with url: cards_path, id: 'card-form', class: 'card-form',local: true do |f| %> 4 <div class="Cardpage"> 5 <h1>カード登録</h1> 6 </div><br> 7 <div class="field"> 8 <%= f.label :number, "【カード番号】" %> 9 <%= f.text_field :number, class:"number", placeholder:"カード番号(半角英数字)", maxlength:"16" %> 10 </div> 11 12 <div class="field"> 13 <%= f.label :cvc ,"【CVC】" %> 14 <%= f.text_field :cvc, class:"cvc", placeholder:"カード背面にある3桁の番号", maxlength:"4" %> 15 </div> 16 <div class="field"> 17 <br> 18 <p>【有効期限】</p> 19 <div class='input-expiration-date-wrap'> 20 <%= f.select :exp_month, 1..12, {include_blank: "---"}, class: "exp_month" %> 21 <p>月</p> 22 <%= f.select :exp_year, 20..25, {include_blank: "---"}, class: "exp_year" %> 23 <p></p> 24 </div> 25 </div> 26 <%= f.submit "登録する" , class:"button" %> 27 <% end %> 28

ruby

1# app/views/layouts/application.html.erb 2 3#省略 4 <%= csrf_meta_tags %> 5 <%= csp_meta_tag %> 6 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" integrity="sha256-UzFD2WYH2U1dQpKDjjZK72VtPeWP50NoJjd26rnAdUI=" crossorigin="anonymous" /> 7 <script type="text/javascript" src="https://js.pay.jp/v1/"></script> 8 <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 9 <%= javascript_include_tag 'application'%> 10 11#省略

ruby

1# log 2app/controllers/cards_controller.rb:19:in `create' 3Started POST "/cards" for ::1 at 2021-06-19 18:52:26 +0900 4  (0.9ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 5Processing by CardsController#create as HTML 6 Parameters: {"authenticity_token"=>"e04vwuk1AcQ2o1/LQUS/oCS0ExTNj89/BHX61QAaFzfAGx1ULeOx7YZyuZbH+n5y30agZ7x3oJCHgU0IXoMOzA==", "number"=>"4242424242424242", "cvc"=>"123", "exp_month"=>"4", "exp_year"=>"24", "commit"=>"登録する"} 7 User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 ORDER BY `users`.`id` ASC LIMIT 1 8 ↳ app/controllers/cards_controller.rb:16:in `create' 9  (0.2ms) BEGIN 10 ↳ app/controllers/cards_controller.rb:19:in `create' 11 User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1 12 ↳ app/controllers/cards_controller.rb:19:in `create' 13 Card Create (0.8ms) INSERT INTO `cards` (`customer_id`, `user_id`, `created_at`, `updated_at`) VALUES ('cus_5ca969407619bdc0991f102e3e00', 3, '2021-06-19 09:52:33.617374', '2021-06-19 09:52:33.617374') 14 ↳ app/controllers/cards_controller.rb:19:in `create' 15  (0.1ms) ROLLBACK 16 ↳ app/controllers/cards_controller.rb:19:in `create' 17Completed 500 Internal Server Error in 7099ms (ActiveRecord: 2.1ms | Allocations: 409797) 18 19 20 21ActiveRecord::NotNullViolation (Mysql2::Error: Field 'token_id' doesn't have a default value): 22 23app/controllers/cards_controller.rb:19:in `create' 24

試したこと

createアクションにbinding,pryをかけ、デバックを行うが生成されたパラメーターにtoken_id自体確認できなかった。
マイグレーションファイルと実際のcard.jsのカラム名を照らし合わせるが、記述ミスは見受けられず。
フォームに入力したクレジットカード情報はパラメーターにあるので、カード情報は取得できている様子。
イメージ説明

参考

【Rails】 PAYJPを使ってクレジットカード決済を導入しよう!
【Rails】PAYJPでトークン生成時のエラー解決
Mysql2::Error: Field '****' doesn't have a default valueに二回もハマった話

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

自己解決しました。
以下、将来の自分へ備忘録です。

①Javascriptの取得するID名が異なっていた。

NG

1const form = document.getElementById("card_form"); 2

OK

1const form = document.getElementById("card-form"); 2

②cardフォームの変数が異なっていた

NG

1 number: formData.get("order[number]"), 2 cvc: formData.get("order[cvc]"), 3 exp_month: formData.get("order[exp_month]"), 4 exp_year: `20${formData.get("order[exp_year]")}`, 5

OK

1 number: formData.get("number"), 2 cvc: formData.get("cvc"), 3 exp_month: formData.get("exp_month"), 4 exp_year: `20${formData.get("exp_year")}`, 5

こんなシンプルでもいいのかと感心した。

あとはJavascriptのファイルが2つあり、使用していないWebpackerのほうで実装していた。

とりあえずは以上で正常に動作致しました。
この解決法がどなたかの問題解決になれば幸いです。

ご覧いただいた皆様に感謝申し上げます。

投稿2021/06/20 11:11

Kagiya-masahumi

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問