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

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

ただいまの
回答率

88.91%

PAY.JPによるカード登録機能 Uncaught ReferenceError: Payjp is not definedの解決方法

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 272

ki-bo-

score 0

前提・実現したいこと

RailsでPAY.JPを使ったクレジットカードの登録を実装しています。

おそらく、app/views/layouts/application.html.hamlへのscriptタグの記述に問題があるのかなと思っていますが解決しません。

様々なサイトを参照して行っていたのですが、解決に至ることできませんでしたので、お力添えをいただければと思います。

発生している問題・エラーメッセージ

PAY.JPが提供しているテストデータを入力して登録ボタンを押しても、カード登録画面にリダイレクトされる

#cards/new ログのエラー文
GET http://localhost:3000/cards/https//js.pay.jp/ net::ERR_ABORTED 404 (Not Found) new:5

Uncaught ReferenceError: Payjp is not defined.          payjp.self-5f2dd...fbf.js?body=1:4 
    at HTMLDocument.<anonymous> (payjp.self-5f2dd...fbf.js?body=1:4)
(anonymous) @ payjp.self-5f2dd...fbf.js?body=1:4

該当のソースコード

#application.html.haml

!!!
%html
  %head
    %meta{content: "text/html; charset=UTF-8", "http-equiv": "Content-Type"}/
    = javascript_include_tag 'https://ajax.googleapis.com/ajax/libs/d3js/5.15.1/d3.min.js'
    %script{src: "https//js.pay.jp/", type: "text/javascript"}
    = csrf_meta_tags
    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload'
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
  %body

    =render partial: "layouts/notifications", locals:{flash: flash}

    = yield
#cards/new.html.haml

  .card-form
    = form_tag(pay_cards_path, method: :post, id: "charge-form", name: "inputForm") do
      .card-number
        %label.number-label
          カード番号
      .number-field
        = text_field_tag "number", "", class: "number-input", placeholder: "半角数字のみ", id: "card_number", maxlength: "16", type: "text"
      .card-image
        = image_tag(image_path('cards/icon_visa.png'), class: 'visa')
        = image_tag(image_path('cards/icon_mastercard.png'), class: 'master')
        = image_tag(image_path('cards/icon_jcb.png'), class: 'jcb')
        = image_tag(image_path('cards/icon_amex.png'), class: 'amex')
        = image_tag(image_path('cards/icon_diners.png'), class: 'diners')
        = image_tag(image_path('cards/icon_discover.png'), class: 'discover')
      .card-exp
        .exp-details
          %label
            有効期限
          %br
        .exp-choice
          .exp-month
            %select{name: "exp_month", type: "text", id:"exp_month"}
              %option{value: ""} --
              %option{value: "1"}01
              %option{value: "2"}02
              %option{value: "3"}03
              %option{value: "4"}04
              %option{value: "5"}05
              %option{value: "6"}06
              %option{value: "7"}07
              %option{value: "8"}08
              %option{value: "9"}09
              %option{value: "10"}10
              %option{value: "11"}11
              %option{value: "12"}12
            %span 月
            %span.slash /
          .exp-year
            %select{name: "exp_year", type: "text", id: "exp_year"}
              %option{value: ""} --
              %option{value: "2020"}20
              %option{value: "2021"}21
              %option{value: "2022"}22
              %option{value: "2023"}23
              %option{value: "2024"}24
              %option{value: "2025"}25
              %option{value: "2026"}26
              %option{value: "2027"}27
              %option{value: "2028"}28
              %option{value: "2029"}29
            %span 年
            %br
        .security-code
          .code-details
            %label
              セキュリティコード
          .code-field
            = text_field_tag "cvc", "", class: "cvc", placeholder: "カード背面3~4桁の番号", maxlength: "4", id: "cvc"
        #card-token
          = submit_tag "登録する", id: "token_submit", class: "card-btn"
#payjp.js

document.addEventListener(
  "DOMContentLoaded", e => {
    if (document.getElementById("token_submit") != null) { 
      Payjp.setPublicKey("pk_test_1111111111111111");
      let btn = document.getElementById("token_submit"); 
      btn.addEventListener("click", e => { 
        e.preventDefault();
        let card = {
          number: document.getElementById("card_number").value,
          cvc: document.getElementById("cvc").value,
          exp_month: document.getElementById("exp_month").value,
          exp_year: document.getElementById("exp_year").value
        };
        Payjp.createToken(card, (status, response) => {
          if (status === 200) { 
            $("#card_number").removeAttr("name");
            $("#cvc").removeAttr("name");
            $("#exp_month").removeAttr("name");
            $("#exp_year").removeAttr("name"); 
            $("#card_token").append(
              $('<input type="hidden" name="payjpToken">').val(response.id)
            ); 
            document.inputForm.submit();
            alert("登録が完了しました");
          } else {
            alert("カード情報が正しくありません。");
          }
        });
      });
    }
  },
  false
);
#cards_controller.rb

  require "payjp"

  def new
    card = Card.where(user_id: current_user.id)
    redirect_to action: "show" if card.exists?
  end

  def pay
    Payjp.api_key = Rails.application.secrets.payjp_access_key
    if params['payjpToken'].blank?
      flash[:notice] = "カードの情報を確認してください"
      redirect_to action: "new"
    else
      customer = Payjp::Customer.create(
      description: '登録テスト',
      card: params['payjpToken'],
      metadata: {user_id: current_user.id}
      )
      @card = Card.new(user_id: current_user.id, customer_id: customer.id, card_id: customer.default_card)
      if @card.save
        redirect_to action: "show"
        flash[:notice] = 'クレジットカードの登録が完了しました'
      else
        redirect_to action: "pay"
        flash[:notice] = 'クレジットカードの登録に失敗しました'
      end
    end
  end

試したこと

カードの登録に失敗し、登録画面にリダイレクトされた時のフラッシュメッセージは、カード情報を確認してくださいなのでトークンの取得に失敗しているのかなと思います。
秘密鍵の読み込み?ができていないのかとも思いましたが、設定の間違いが見つかりません。

vim ~/.bash_profileで記述し、secrets.ymlのdevelopmentとproductionに記載しました。誤字はありません。

補足情報(FW/ツールのバージョンなど)

Rails 5.0.7.2

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

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

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る