Интеграция полосы с направляющими 6 - PullRequest
0 голосов
/ 01 августа 2020

У меня есть функция регистрации с использованием devise и расширенная регистрация devise с использованием вложенных атрибутов, т.е. я вложил атрибуты класса Payment в класс пользователя. Мой payment.rb

class Payment < ApplicationRecord
attr_accessor :card_number, :card_cvv, :card_expires_month, :card_expires_year #These are actually instance variables
#We cannot access instance variables outside of class so to overcome that we use attr_accessor which is inclusive of attr_reader and attr_writer
belongs_to :user

def self.month_options
    Date::MONTHNAMES.compact.each_with_index.map { |name, i| ["#{i+1} - #{name}", i+1]} 
end

def self.year_options
    (Date.today.year..(Date.today.year+10)).to_a    
end

def process_payment
    
    customer = Stripe::Customer.create email: email, card: token
    Stripe::Charge.create customer: customer.id,
    amount: 1000,
    description: 'Premium',
    currency: 'usd'    
end

end

, а мой user.rb -

class User < ApplicationRecord
    devise :database_authenticatable, :registerable, :confirmable,
           :recoverable, :rememberable, :validatable
    has_one :payment 
    accepts_nested_attributes_for :payment      
 end

В моем файле application.rb я добавил тег javascript для полосы

<%= javascript_include_tag "https://js.stripe.com/v3/" %>

мой вид т.е. новый. html .erb. есть form_for, в котором я добавил класс «cc», который я позже определил для запуска javascript

<script language="Javascript">

Stripe.setPublishableKey("<%= ENV['STRIPE_TEST_PUBLISHABLE_KEY']%>");

</script>
<h1><%= t('.sign_up') %></h1>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { role: "form", class: 'cc_form' }) do |f| %>
  <%= bootstrap_devise_error_messages! %>

  <div class="form-group">
    <%= f.label :email %>
    <%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control' %>
  </div>

  <div class="form-group">
    <%= f.label :password %>
    <%= f.password_field :password, autocomplete: 'current-password', class: 'form-control' %>

    <% if @minimum_password_length %>
      <small class="form-text text-muted"><%= t('devise.shared.minimum_password_length', count: @minimum_password_length) %></small>
    <% end %>
  </div>

  <div class="form-group">
    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation, autocomplete: 'current-password', class: 'form-control' %>
  </div>

  <%= fields_for( :payment ) do |p| %>
  <div class="row col-md-12">
  <div class="form-group col-md-4 no-left-padding">
  <%= p.label :card_number, "Card Number", data: { stripe: 'label'} %>
  <%= p.text_field :card_number, class: "form-control", required: true, data: { stripe: 'number'} %>
</div>
<div class="form-group col-md-2">
  <%= p.label :card_cvv, "Card CVV", data: { stripe: 'label'} %>
  <%= p.text_field :card_cvv, class: "form-control", required: true, data: { stripe: 'cvc'} %>
</div>
<div class="form-group col-md-6">
  <div class="col-md-12">
    <%= p.label :card_expires, "Card Expires", data: { stripe: 'label'} %>
</div>
<div class="row">
  <div class="col-md-3 form-group">
    <%= p.select :card_expires_month, options_for_select(Payment.month_options),
    { include_blank: 'Month' },
    "data-stripe" => "exp-month",
    class: "form-control", required: true %>
  </div>
  <div class="col-md-3 form-group">
    <%= p.select :card_expires_year, options_for_select(Payment.year_options.push),   
    { include_blank: 'Year' },  
    class: "form-control",
   "data-stripe" => "exp-year", required: true %>
</div>   
</div>
</div>
</div>
<% end %>
  <div class="form-group">
    <%= f.submit t('.sign_up'), class: 'btn btn-primary' %>
  </div>
<% end %>

<%= render 'devise/shared/links' %>

и мой registration_controller.rb, т.е. расширенную регистрацию устройства

class RegistrationsController < Devise::RegistrationsController

    def create
        build_resource(sign_up_params)
        resource.class.transaction do
        resource.save
        yield resource if block_given?
        if resource.persisted?
            @payment = Payment.new({email: params["user"]["email"], token: params[:payment]["token"], user_id: resource.id})
            flash[:error]="Please check registration errors" unless @payment.valid?

            begin
                @payment.process_payment
            rescue => exception e
            flash[:error]=e.message
            resource.destroy
            puts 'Payment failed'
            render :new and return
            end
            if resource.active_for_authentication?
                set_flash_message! :notice, :signed_up
                sign_up(resource_name, resource)
                respond_with resource, location: after_sign_up_path_for(resource)
              else
                set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
                expire_data_after_sign_in!
                respond_with resource, location: after_inactive_sign_up_path_for(resource)
              end
        else
            clean_up_passwords resource
            set_minimum_password_length
            respond_with resource
        end      

    end

    protected

    def configure_permitted_parameters
        devise_parameter_sanitizer.for(:sign_up).push(:payment)
    end
    


end

Я сохранил свои учетные данные, т.е. тестовый публикуемый ключ и тестовый секретный ключ полосы в credentials.yml.enc. У меня есть этот пользовательский javascript credit_card_form. js, в котором будет обрабатываться процесс оплаты полосы через это поле класса «cc»

$(document).on('ready turbolinks:load', function() {

    var show_error, stripeResponseHandler, submitHandler;
    submitHandler = function (event) {
    var $form = $(event.target);
    $form.find("input[type=submit]").prop("disabled", true);
    //If Stripe was initialized correctly this will create a token using the credit card info
    if(Stripe){
    Stripe.card.createToken($form, stripeResponseHandler);
    } else {
    show_error("Failed to load credit card processing functionality. Please reload this page in your browser.")
    }
    return false;    
    };

    $(".cc_form").on('submit', submitHandler);
    stripeResponseHandler = function (status, response) {
    var token, $form;
    $form = $('.cc_form');
    if (response.error) {
    console.log(response.error.message);
    show_error(response.error.message);
    $form.find("input[type=submit]").prop("disabled", false);
    } else {
    token = response.id;
    $form.append($("<input type=\"hidden\" name=\"payment[token]\" />").val(token));
    $("[data-stripe=number]").remove();
    $("[data-stripe=cvc]").remove();
    $("[data-stripe=exp-year]").remove();
    $("[data-stripe=exp-month]").remove();
    $("[data-stripe=label]").remove();
    $form.get(0).submit();
    }
    return false;    
    };

    show_error = function (message) {
    if($("#flash-messages").size() < 1){
    $('div.container.main div:first').prepend("<div id='flash-messages'></div>")
    }
    $("#flash-messages").html('<div class="alert alert-warning"><a class="close" data-dismiss="alert">×</a><div id="flash_alert">' + message + '</div></div>');
    $('.alert').delay(5000).fadeOut(3000);
    return false;
    };
    });

Итак, этот javascript в основном сначала обращается к серверу rails и сначала обрабатывает полосу оплаты. У меня есть эти два маршрута в моих маршрутах. Rb

devise_for :users , :controller =>{:registrations =>'registrations'}
  root to: "welcome#index"

но когда я подписываю Ссылка для подтверждения правильного электронного письма отправлена ​​на мою учетную запись Gmail через sendgrid. но когда я нажимаю эту ссылку подтверждения, локальный хост не отвечает. Я не могу найти ошибку. Пожалуйста, помогите мне.

...