与使用Stripe付款的其他人一样,我收到错误“无法向没有活动卡的客户收费”。表单没有附加令牌,因为javascript在表单中没有匹配的ID,但现在我收到rails错误并且卡没有收费,客户被创建,错误表明存在无效行item,当没有运行创建客户和充值卡的代码时,创建的订单没有错误。
订单视图
<script type="text/javascript" src="https://js.stripe.com/v2/">
$(function(){
Stripe.setPublishableKey('<%= Rails.configuration.stripe[:PUBLISHABLE_KEY] %>');
});
</script>
<div class = "Power Me" >
<fieldset>
<legend> Please enter your details </legend>
<%= render 'form', object: @object %>
</fieldset>
</div>
呈现订单表格
<%= form_for(@order, :html => {:id => 'payment-form'}) do |f| %>
<% if @order.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@order.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% @order.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= "Order Total: #{order_total.to_s}" %>
<%= "Order Currency: #{order_currency.to_s}" %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :Address_line_1 %><br>
<%= f.text_area :address_line_1 %>
</div>
<div class="field">
<%= f.label :Address_Line_2 %><br>
<%= f.text_area :address_line_2 %>
</div>
<div class="field">
<%= f.label :City %><br>
<%= f.text_area :address_city %>
</div>
<div class="field">
<%= f.label :Region %><br>
<%= f.text_area :address_state %>
</div>
<div class="field">
<%= f.label :Postcode %><br>
<%= f.text_area :address_zip %>
</div>
<div class="field">
<%= f.label :Country %><br>
<%= f.select :address_country, Order::CC_COUNTRIES, prompt: 'Select the country' %>
</div>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email, :placeholder => "you@example.com" %>
</div>
<div class="field">
<%= f.label :Payment_Type %><br>
<%= f.select :pay_type, Order::PAYMENT_TYPES, prompt: 'Select a payment method' %>
</div>
<div class="form-row">
<label>Card Number</label>
<input type="text" size="20" autocomplete="off" data-stripe="number" id="number" class="credit-number", placeholder = "**** **** **** ****" pattern="[\d ]*" />
</div>
<div class="form-row">
<label>Security Code/CVC</label>
<input type="text" size="4" autocomplete="off" data-stripe="cvc" id="cvc" class="credit-scurity" placeholder="***" pattern="\d*" />
</div>
<div class="form-row">
<label>Expiration (MM/YYYY)</label>
<input type="text" size="2" data-stripe="exp-month" id="exp-month" class="card-expiry-month" placeholder="MM" pattern="\d*" />
<span> / </span>
<input type="text" size="4" data-stripe="exp-year" id="exp-year" class="card-expiry-year" placeholder="YYYY" pattern="\d*" />
</div>
<div class="actions">
<%= f.submit 'Pay', :class =>"stripe-button" %>
</div>
<% end %>
订单型号
class Order < ActiveRecord::Base
# attr_accessor :stripeToken
PAYMENT_TYPES = ["credit card"]
CC_COUNTRIES = ["United Kingdom", "France", "Italy"]
validates :name, :address_line_1, :address_zip, :email, presence: true
# validates :pay_type, inclusion: PAYMENT_TYPES
has_many :line_items, dependent: :destroy
def add_line_items_from_cart(cart)
cart.line_items.each do |item|
item.cart_id = nil
line_items << item
end
end
end
订单控制器
class OrdersController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
before_action :set_order, only: [:show, :edit, :update, :destroy]
# GET /orders
# GET /orders.json
def index
@orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
if @cart.line_items.empty?
redirect_to store_url, notice: "Your cart is empty"
return
end
@order = Order.new
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
@order = Order.new(order_params)
@order.add_line_items_from_cart(@cart)
respond_to do |format|
if @order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
format.html { redirect_to @order, notice: 'Order was successfully created.' }
format.json { render action: 'show', status: :created, location: @order }
else
format.html { render action: 'new' }
format.json { render json: @order.errors, status: :unprocessable_entity }
end
end
Stripe.api_key = "sk_test_BsdqHq0SQuPqHIsm46lcpX4v"
@amount = order_total.to_i * 100
token = params[:stripeToken]
=begin
begin
customer = Stripe::Customer.create(
:email => order_params[:email]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => @amount, # amount in cents, again
:currency => order_currency,
:card => token,
:description => order_params[:email]
)
redirect_to root_path
rescue Stripe::CardError => e
@error = e
end
=end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if @order.update(order_params)
format.html { redirect_to @order, notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
@order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
@order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:name, :email, :pay_type, :address_line_1, :address_line_2, :address_city, :address_state, :address_zip, :address_country)
end
end
我的申请助手
module ApplicationHelper
def order_total
total = LineItem.joins(:product).select("sum(line_items.quantity * products.price) as total").where("cart_id = ?", session[:cart_id]).first.total
end
def order_currency
currency = LineItem.joins(:product).joins(:currency).select("currencies.name as iso_name").where("cart_id = ?", session[:cart_id]).first.iso_name
end
# Returns the full title on a per-page basis.
def full_title(page_title)
base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?
base_title
else
"#{base_title} | #{page_title}"
end
end
def bootstrap_class_for flash_type
{ success: "alert-success", error: "alert-danger", alert: "alert-warning", notice: "alert-info" }[flash_type] || flash_type.to_s
end
def flash_messages(opts = {})
flash.each do |msg_type, message|
concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} fade in") do
concat message
end)
end
nil
end
# before filters
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
Orders.js
$('#payment-form').submit(function(event) {
var form = $(this);
form.find('button').prop('disabled', true);
Stripe.createToken(form, stripeResponseHandler);
return false;
});
答案 0 :(得分:0)
下面的工作订单表单,你不能将字段传递给Stripe并在rails表单中使用它们来保存在db中,它的任一个或(前面的例子试图在db中保存地址字段并将它们作为一部分传递给条带交易验证。
<%= form_for(@order, :html => {:id => 'payment-form'}) do |f| %>
<% if @order.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@order.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% @order.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= "Order Total: #{order_total.to_s}" %>
<%= "Order Currency: #{order_currency.to_s}" %>
</div>
<div class="form-row">
<label>Full Name</label>
<input type="text" size="20" autocomplete="off" data-stripe="name" />
</div>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email, :placeholder => "you@example.com" %>
</div>
<div class="field">
<%= f.label :Payment_Type %><br>
<%= f.select :pay_type, Order::PAYMENT_TYPES, prompt: 'Select a payment method', :selected => "credit card" %>
</div>
<div class="form-row">
<label>Address Line 1</label>
<input type="text" size="20" autocomplete="off" data-stripe="address_line1" />
</div>
<div class="form-row">
<label>Address Line 2</label>
<input type="text" size="20" autocomplete="off" />
</div>
<div class="form-row">
<label>Address City</label>
<input type="text" size="20" autocomplete="off" />
</div>
<div class="form-row">
<label>Address State</label>
<input type="text" size="20" autocomplete="off" />
</div>
<div class="form-row">
<label>Zip/Postcode</label>
<input type="text" size="20" autocomplete="off" data-stripe="address_zip" />
</div>
<div class="form-row">
<label>Country</label>
<input type="text" size="20" autocomplete="off" data-stripe="address_country" />
</div>
<div class="form-row">
<label>Card Number</label>
<input type="text" size="20" autocomplete="off" data-stripe="number" placeholder = "**** **** **** ****" pattern="[\d ]*" />
</div>
<div class="form-row">
<label>Security Code/CVC</label>
<input type="text" size="4" autocomplete="off" data-stripe="cvc" placeholder="***" pattern="\d*" />
</div>
<div class="form-row">
<label>Expiration (MM/YYYY)</label>
<input type="text" size="2" data-stripe="exp-month" placeholder="MM" pattern="\d*" />
<span> / </span>
<input type="text" size="4" data-stripe="exp-year" placeholder="YYYY" pattern="\d*" />
</div>
<div class="actions">
<%= f.submit 'Pay', :class => "button" %>
</div>
<% end %>
表单需要在下面的javascript中引用的id
var stripeResponseHandler = function(status, response) {
var $form = $('#payment-form');
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('button').prop('disabled', false);
} else {
// token contains id, last4, and card type
var token = response.id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// and re-submit
$form.get(0).submit();
}
};
jQuery(function($) {
$('#payment-form').submit(function(e) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
});
订单型号,已删除字段
class Order < ActiveRecord::Base
PAYMENT_TYPES = ["credit card"]
CC_COUNTRIES = ["United Kingdom", "France", "Italy"]
validates :email, presence: true
validates :pay_type, inclusion: PAYMENT_TYPES
has_many :line_items, dependent: :destroy
def add_line_items_from_cart(cart)
cart.line_items.each do |item|
item.cart_id = nil
line_items << item
end
end
end
申请表标题
<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<%= stylesheet_link_tag "application", media: "all",
"data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
$(function(){
Stripe.setPublishableKey('<%= Rails.configuration.stripe[:publishable_key] %>');
});
</script>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>
</head>
<body>
订单控制器
class OrdersController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
before_action :set_order, only: [:show,:edit, :update, :destroy]
# before_action :admin_user, only: [:destroy, :show]
# GET /orders
# GET /orders.json
def index
@orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
if @cart.line_items.empty?
redirect_to store_url, notice: "Your cart is empty"
return
end
@order = Order.new
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
begin
@order = Order.new(order_params)
@order.add_line_items_from_cart(@cart)
Stripe.api_key = "sk_test_xxxxxxxxxxxxxxx"
@amount = order_total.to_i * 100
token = params[:stripeToken]
# Create a Customer
customer = Stripe::Customer.create(
:description => order_params[:email],
:card => token,
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => @amount, # amount in cents, again
:currency => order_currency,
# :card => token,
:description => order_params[:email]
)
respond_to do |format|
if @order.save
puts "saving now"
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
format.html { redirect_to @order, notice: 'Order was successfully created.' }
format.json { render action: 'show', status: :created, location: @order }
else
format.html { render action: 'new' }
format.json { render json: @order.errors, status: :unprocessable_entity }
end
end
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to root_path
end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if @order.update(order_params)
format.html { redirect_to @order, notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
@order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
@order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:email, :pay_type)
end
end