mywork1868
@mywork1868

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Payjpを使用したクレカ情報入力ができない

解決したいこと

クレカ入力画面を作っています。
クレカ情報入力欄が入力フォームとして認識されず、入力ができない状態です。

発生している問題・エラー

エラーメッセージらしきものは、検証で出てくる二つです

Uncaught (in promise) Error: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received


A <label> isn't associated with a form field.
To fix this issue, nest the <input> in the <label> or provide a for attribute on the <label> that matches a form field id.

こちらの画像のオレンジの欄にカーソルを合わせても矢印状態のままで入力できません。
image.png

該当するソースコード

<%# カード情報の入力 %>
<div class='credit-card-form'>
  <h1 class='info-input-haedline'>
    クレジットカード情報入力
  </h1>
  <div class="form-group">
    <div class='form-text-wrap'>
      <label class="form-text">カード情報</label>
      <span class="indispensable">必須</span>
      <div class='available-card'>
        <%= image_tag 'card-visa.gif', class: 'card-logo'%>
        <%= image_tag 'card-mastercard.gif', class: 'card-logo'%>
        <%= image_tag 'card-jcb.gif', class: 'card-logo'%>
        <%= image_tag 'card-amex.gif', class: 'card-logo'%>
      </div>
    <div id="number-form" class="input-default"></div>
    </div>
    
  </div>
  <div class="form-group">
    <div class='form-text-wrap'>
      <label class="form-text">有効期限</label>
      <span class="indispensable">必須</span>
      <div id="expiry-form" class="input-default"></div>
    </div>
  </div>
  <div class="form-group">
    <div class='form-text-wrap'>
      <label class="form-text">セキュリティコード</label>
      <span class="indispensable">必須</span>
      <div id="cvc-form" class="input-default"></div>
    </div>
  </div>
</div>
<%# /カード情報の入力 %>
const pay = () => {
  const payjp = Payjp("pk_test_************************");
  const elements = payjp.elements();
  const numberElement = elements.create('cardNumber');
  const expiryElement = elements.create('cardExpiry');
  const cvcElement = elements.create('cardCvc');

  numberElement.mount('#number-form');
  expiryElement.mount('#expiry-form');
  cvcElement.mount('#cvc-form');
  
  const submit = document.getElementById("button");
  submit.addEventListener("click", (e) => {
    e.preventDefault();
    payjp.createToken(numberElement).then(function (response) {
      if (response.error) {
      } else {
        const token = response.id;
        const renderDom = document.getElementById("charge-form");
        const tokenObj = `<input value=${token} name='token' type="hidden">`;
        renderDom.insertAdjacentHTML("beforeend", tokenObj);
        debugger;
      }
      numberElement.clear();
      expiryElement.clear();
      cvcElement.clear();
      document.getElementById("charge-form").submit();
    });
  });
};

window.addEventListener("load", pay);

****には公開鍵が入っています

自分で試したこと

Javascriptを無効にする記述をapplication.jsからコメントアウトした。

payjpのサイトにあるv2トークン化の記述(下記URLより)を入れてみたが、カードナンバー・有効期限・セキュリティーコードが一体となっているときのみ入力ができた。
3つを分割したものも掲載されていたが、入力できない状態だった。

うまく質問できていないかもしれませんので、不明な情報等ございましたらお知らせください。

0

1Answer

回答ではなくデバッグ方針の提案ですが、numberElement, expiryElement, cvcElementをconsole.logで確認して何が出力されていますか?
何も出力されていなければ、div内に本来生成されるはずだった要素が生成できていないことになります。

0Like

Comments

  1. @mywork1868

    Questioner

    コメントありがとうございます。
    なにも出力されませんでしたので、本来生成される要素が生成できていないようです。

  2. なるほど...
    では、elementspayjsもconsole.logしてみてどうなるでしょうか?
    もしpayjsが想定していない値になっているようであれば、引数の公開鍵が間違っていたり無効になっている可能性もあると思います。


    また、発生しているエラーについて、
    Uncaught (in promise) Error: A listener indicated ...はChromeの拡張機能が影響しているようなので、一度すべてOFFにしてみてください。

    A <label> isn't associated with a form field. ...については、おそらくinput要素がpayjsによって追加されていないため発生していると思われます。
    なので、本事象が解消すればエラーも出なくなると思います。
    (つまり、本事象を解消する手がかりになるエラーではないと思います。)

  3. @mywork1868

    Questioner

    elements, payjpをconsole.logしてみましたが、なにも出ませんでした。

    試しに、console.log("hello");を記述しましたが出力されなかったので、
    そもそもjsを読み込めていないようです。

    application.jsには

    //= require jquery3
    //= require jquery_ujs
    //= require_tree .
    
    require("@rails/ujs").start()
    /* require("turbolinks").start() */
    require("@rails/activestorage").start()
    require("channels")
    require("./card")
    

    と記述しています。

    application.html.erbには

    <script type="text/javascript" src="https://js.pay.jp/v2/pay.js"></script>
    
    <%= stylesheet_link_tag 'application', media: 'all'  %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    

    とHeadに記述しています。
    足りない部分がありましたらご教授いただけますと幸いです。

  4. rubyを使われていたんですね。
    すいません、rubyは詳しくないのでちょっと分からないですね...
    例えば、erbでpayjsの読み込みをやめて素のjavascriptだけでconsole.logするとどうなりますでしょうか?

    また、書ける範囲で良いのでrubyのコードなど関連するコードを載せて頂けるとより回答しやすくなると思います。

  5. @mywork1868

    Questioner

    ありがとうございます。

Your answer might help someone💌