Элемент Stripe card не отображается в моем приложении Rails

Я создаю простое приложение rails, которое использует Stripe для оплаты картой, но поле ввода карты не отображается, когда я запускаю приложение. У меня все нормально, но почему-то не показывает. я использую Rails 5.2.4.4, Ruby 2.7. Вот мой код:

/app/views/layout/application.html.erb :

    <!DOCTYPE html>
<html>
  <head>
    <title><%= Rails.configuration.application_name %></title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <meta name = "viewport" content = "width=device-width, initial-scale=1">
    <%= stylesheet_link_tag 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'https://js.stripe.com/v3/', 'data-turbolinks-track': 'reload' %>
    <%= tag :meta, name: "stripe-key:", content: Rails.application.credentials.stripe_publishable_key %>
  </head>

  <body class = "<%= yield (:body_class) %>">
    <% if flash[:notice] %>
      <div class = "notification is-success global-notification">
        <p class = "notice"><%= notice %></p>
      </div>
    <% end %>

    <% if flash[:alert] %>
    <div class = "notification is-danger global-notification">
      <p class = "alert"><%= alert %></p>
    </div>
    <% end %>

     <nav class = "navbar is-light" role = "navigation" aria-label = "main navigation">
      <div class = "navbar-brand">
        <%= link_to root_path, class:"navbar-item" do %>
          <h1 class = "title is-5"><%= Rails.configuration.application_name %></h1>
        <% end  %>
        <div class = "navbar-burger burger" data-target = "navbar">
          <span></span>
          <span></span>
          <span></span>
        </div>
      </div>

      <div id = "navbar" class = "navbar-menu">
        <div class = "navbar-start">
          <% if subscribed? %>
            <div class = "navbar-item">
              <%= link_to library_index_path, class: 'navbar-item button is-dark' do %>
                <i class = "fa fa-book"></i> &nbsp;&nbsp; My Bookcase
              <% end %>
            </div>
          <% end %>
        </div>
        <div class = "navbar-end">
          <div class = "navbar-item">
            <% if admin? %>
              <%= link_to 'New Book', new_book_path, class:'button is-dark' %>
            <% end%>
            <div class = "field is-grouped">
            <% if user_signed_in? %>

              <div class = "navbar-item has-dropdown is-hoverable">
                <%= link_to 'Account', edit_user_registration_path, class: "navbar-link" %>
                <div class = "navbar-dropdown is-right">
                  <%= link_to edit_user_registration_path, class:"navbar-item" do %>
                    <%= current_user.name %> <% if admin? %> &nbsp; <span class = "tag is-warrning">ADMIN</span> <% end %>
                  <% end %>
                  <%= link_to "Log Out", destroy_user_session_path, method: :delete, class:"navbar-item" %>
                </div>
              </div>
            <% else %>
            <p class = "control">
              <%= link_to 'Pricing', pricing_index_path, class: 'navbar-item button is-light' %>
            </p>
            <p class = "control">
              <%= link_to "Sign In", new_user_session_path, class:"navbar-item button is-light" %>
            </p>
            <p class = "control">
              <%= link_to "Sign up", new_user_registration_path, class:"navbar-item button is-light"%>
            </p>
            <% end %>

          </div>
        </div>
      </div>
    </div>
  </nav>

    <div class = "container">
      <%= yield %>
    </div>

  </body>
</html>

/app/views/layout/subscribe.html.erb :

<!DOCTYPE html>
<html>
  <head>
    <title><%= Rails.configuration.application_name %></title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <meta name = "viewport" content = "width=device-width, initial-scale=1">
    <%= stylesheet_link_tag 'https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css' %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'https://js.stripe.com/v3/', 'data-turbolinks-track': 'reload' %>
    <%= tag :meta, name: "stripe-key:", content: Rails.application.credentials.stripe_publishable_key %>
  </head>

  <body class = "<%= yield (:body_class) %>">
    <% if flash[:notice] %>
      <div class = "notification is-success global-notification">
        <p class = "notice"><%= notice %></p>
      </div>
    <% end %>

    <% if flash[:alert] %>
    <div class = "notification is-danger global-notification">
      <p class = "alert"><%= alert %></p>
    </div>
    <% end %>

     <nav class = "navbar is-light" role = "navigation" aria-label = "main navigation">
      <div class = "navbar-brand">
        <div class = "navbar-item">
        <h1 class = "title is-5"><%= Rails.configuration.application_name %></h1>
          </div>
        </div>
      </nav>

    <div class = "container">
      <%= yield %>
    </div>
  </body>

</html>

/app/assets/javascripts/subscriptions.jss

    document.addEventListener("turbolinks:load", function() {
  const publishableKey = document.querySelector("meta[name='stripe-key']").content;
  const stripe = Stripe(publishableKey);

  const elements = stripe.elements({
    fonts: [{
      cssSrc: "https://rsms.me/inter/inter-ui.css"
    }],
    locale: 'auto'
  });

  // Custom styling can be passed to options when creating an Element.
  const style = {
    base: {
      color: "#32325D",
      fontWeight: 500,
      fontFamily: "Inter UI, Open Sans, Segoe UI, sans-serif",
      fontSize: "16px",
      fontSmoothing: "antialiased",

      "::placeholder": {
        color: "#CFD7DF"
      }
    },
    invalid: {
      color: "#E25950"
    }
  };

  // Create an instance of the card Element.
  const card = elements.create('card', { style });

  // Add an instance of the card Element into the `card-element` <div>.


    card.mount('#card-element');

    card.addEventListener('change', ({ error }) => {

      const displayError = document.getElementById('card-errors');
      if (error) {
        displayError.textContent = error.message;
      } else {
        displayError.textContent = '';
      }
    });

    // Create a token or display an error when the form is submitted.
    const form = document.getElementById('payment-form');

    form.addEventListener('submit', async(event) => {
      event.preventDefault();

      const { token, error } = await stripe.createToken(card);

      if (error) {
        // Inform the customer that there was an error.
        const errorElement = document.getElementById('card-errors');
        errorElement.textContent = error.message;
      } else {
        // Send the token to your server.
        stripeTokenHandler(token);
      }
    });

    const stripeTokenHandler = (token) => {
      // Insert the token ID into the form so it gets submitted to the server
      const form = document.getElementById('payment-form');
      const hiddenInput = document.createElement('input');
      hiddenInput.setAttribute('type', 'hidden');
      hiddenInput.setAttribute('name', 'stripeToken');
      hiddenInput.setAttribute('value', token.id);
      form.appendChild(hiddenInput);

      ["type", "last4", "exp_month", "exp_year"].forEach(function(field) {
        addCardField(form, token, field);
      });

      // Submit the form
      form.submit();
    }

    function addCardField(form, token, field) {
      let hiddenInput = document.createElement('input');
      hiddenInput.setAttribute('type', 'hidden');
      hiddenInput.setAttribute('name', "user[card_" + field + "]");
      hiddenInput.setAttribute('value', token.card[field]);
      form.appendChild(hiddenInput);
    }

});

/приложение/контроллеры/subscriptions_controller.rb

class SubscriptionsController < ApplicationController
  layout "subscribe"
  before_action :authenticate_user!, except: [:new, :create]

  def new
    if user_signed_in? && current_user.subscribed?
      redirect_to root_path, notice: "You are already a subscriber!"
    end
  end

  def create
    Stripe.api_key = Rails.application.credentials.stripe_api_key

    plan_id = params[:plan_id]
    plan = Stripe::Plan.retrieve(plan_id)
    token = params[:stripeToken]

    product = Stripe::Product.retrieve(Rails.application.credentials.book_library)

    customer = if current_user.stripe_id?
                 Stripe::Customer.retrieve(current_user.stripe_id)
               else
                 Stripe::Customer.create(email: current_user.email, source: token)
               end

    subscription = customer.subscriptions.create(plan: plan.id)

    options = {
      stripe_id: customer.id,
      stripe_subscription_id: subscription.id,
      subscribed: true,
    }

    options.merge!(
      card_last4: params[:user][:card_last4],
      card_exp_month: params[:user][:card_exp_month],
      card_exp_year: params[:user][:card_exp_year],
      card_type: params[:user][:card_type]
    ) if params[:user][:card_last4]

    current_user.update(options)

    redirect_to root_path, notice: "&#x1f389; Your subscription was set up successfully!"
  end

  def destroy
    customer = Stripe::Customer.retrieve(current_user.stripe_id)
    customer.subscriptions.retrieve(current_user.stripe_subscription_id).delete
    current_user.update(stripe_subscription_id: nil)

    redirect_to root_path, notice: "Your subscription has been cancelled."
  end

end

/app/views/subscriptions/new.html.erb

<div class = "section">
  <div class = "columns is-centered">
    <div class = "column is-6 border pa5">
      <h1 class = "title is-3">Subscribe</h1>
      <hr />
      <p>Chosen plan: <strong><%= params[:plan] %>
      <hr/>
      <%= form_tag subscriptions_path, id: "payment-form" do |form| %>

        <div class = "field">
          <label for = "card-element" class = "label">Enter credit or debit card</label>

          <div id = "card-element">
            <!-- A Stripe element will be intserted here !-->
          </div>

          <div id = "card-errors" role = "alert"></div>

          <%= hidden_field_tag :plan_id, params[:plan_id] %>

          <button class = "button is-fullwidth is-link mt4">Submit</button>
        </div>

      <% end %>
    </div>
  </div>
</div>

консоль: (указывает на «контент» из строки 2 в subscribes.jss)

Uncaught TypeError: Cannot read property 'content' of null
    at HTMLDocument.<anonymous> (subscriptions.self-16b0862fbc44d0ce1a2c1d499b9e65be153010612892033690c2ee948affcab0.js?body=1:2)
    at Object.e.dispatch (turbolinks.self-569ee74eaa15c1e2019317ff770b8769b1ec033a0f572a485f64c82ddc8f989e.js?body=1:6)
    at r.notifyApplicationAfterPageLoad (turbolinks.self-569ee74eaa15c1e2019317ff770b8769b1ec033a0f572a485f64c82ddc8f989e.js?body=1:7)
    at r.pageLoaded (turbolinks.self-569ee74eaa15c1e2019317ff770b8769b1ec033a0f572a485f64c82ddc8f989e.js?body=1:7)
    at turbolinks.self-569ee74eaa15c1e2019317ff770b8769b1ec033a0f572a485f64c82ddc8f989e.js?body=1:6

Можете ли вы проверить представление и убедиться, что есть метаэлемент, соответствующий <%= tag :meta, name: "stripe-key:", content: Rails.application.credentials.stripe_publishable_key %>. Это на самом деле на странице, когда вы ее проверяете?

Rockwell Rice 10.12.2020 03:34

Кажется, есть одно да, здесь <script src = "/assets/application.self-66347cf0a4cb1f26f76868b4697a9e‌​ee457c8c3a6da80c6fdd‌​76ff77e911715e.js?bo‌​dy=1" data-turbolinks-track = "reload"></script> <script src = "https://js.stripe.com/v3/" data-turbolinks-track = "reload"></script> <meta name = "stripe-key:" content = "pk_test_51Hvsl0H0jrWUklo94ZerOcqYvCT45O3zX19pq4dlCZ‌​6Cd9JVzmj1DXDz1LcsFu‌​YhcaUcOX7gPcKsaC0vLB‌​q3GtqG006ehhnrqL" /> </head>

Abdul Kadi 10.12.2020 04:35

Может показаться странным, но если вы переместите этот метатег так, чтобы он был над файлами javascript, он сработает?

Rockwell Rice 10.12.2020 04:42

Только что попробовал переместить метатег над javascript, а также попробовал над таблицами стилей, но все равно не повезло :(

Abdul Kadi 10.12.2020 04:56

Отладить их может быть сложно. По моему опыту, эти cannot read content of null ошибки JS, как правило, возникают, когда он ищет элемент, который еще не загружен на страницу, поэтому он равен нулю. Похоже, это исходит из файла subscriptions.js.

Rockwell Rice 10.12.2020 16:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
466
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Было ли это проблемой неправильного селектора запросов? Я заметил, что вы объявляете имя метатега как «полосатый ключ:» (с двоеточием в конце), но выбираете элемент с помощью document.querySelector("meta[name='stripe-key']") (без двоеточия в конце имени элемента)

Вы убедились, что ваш ответ работает, или это просто не уверенная мысль от вас?

Lakshman Kambam 18.04.2021 20:02

Другие вопросы по теме