我目前正在使用他们网站上提供给您的默认条纹表单。在进行交易时,其他一切似乎都在为用户处理适当的授权令牌之外工作。我将在下面发布所有方法和表单的代码。
users_controller.rb
def info
@subscription = current_user.subscription
end
def charge
token = params["stripeToken"]
customer = Stripe::Customer.create(
source: token,
plan: 'gbsubscriptionlevel1',
email: current_user.email
)
current_user.subscription.stripe_user_id = customer.id
current_user.subscription.active = true
current_user.subscription.save
redirect_to users_info_path
end
路线.rb
get '/users/info', to: 'users#info'
post '/users/charge', to: 'users#charge'
_stripe_form.html.erb
<div class="container">
<form action="/users/charge" method="POST" id="payment-form">
<span class="payment-errors"></span>
<div class="row">
<div class="col-xs-4">
<label>
<span>Card Number</span>
<input class="form-control" type="text" size="20" data-stripe="number"/>
</label>
</div>
</div>
<div class="row">
<div class="col-xs-1">
<label>
<span>CVC</span>
<input class="form-control" type="text" size="4" data-stripe="cvc"/>
</label>
</div>
</div>
<div class="row">
<div class="col-xs-1">
<label>MM</label>
<input class="form-control" type="text" size="2" data-stripe="exp-month" placeholder="01"/>
</div>
<div class="col-xs-1">
<label>YYYY</label>
<input class="form-control" type="text" size="3" data-stripe="exp-year" placeholder="2020"/>
</div>
</div>
<div class="row">
<div class="col-xs-1">
<br/>
<button class="btn btn-primary-outline" type="submit">Create Subscription</button>
</div>
</div>
</form>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
// This identifies your website in the createToken call below
Stripe.setPublishableKey('pk_test_tmBNNUvHTmtWXLhSL1q647iH');
//
function stripeResponseHandler(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 {
// response contains id and card, which contains additional card details
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 submit
$form.get(0).submit();
}
}
jQuery(function ($) {
$('#payment-form').submit(function (event) {
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;
});
});
</script>
</div>
堆栈跟踪输出
Started POST "/users/charge" for 127.0.0.1 at 2016-02-10 12:11:07 -0500
Processing by UsersController#charge as HTML
Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 0ms (ActiveRecord: 0.0ms)
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
actionpack (4.2.3) lib/action_controller/metal/request_forgery_protection.rb:181:in `handle_unverified_request'
actionpack (4.2.3) lib/action_controller/metal/request_forgery_protection.rb:209:in `handle_unverified_request'
devise (3.5.6) lib/devise/controllers/helpers.rb:257:in `handle_unverified_request'
actionpack (4.2.3) lib/action_controller/metal/request_forgery_protection.rb:204:in `verify_authenticity_token'
这可能不是最好的解决方案,但您可以忽略错误
protect_from_forgery with: :null_session
放置在控制器中。
更好的解决方案是使用 rails 表单助手构建表单。
form_tag不会自动生成CSRF令牌,除非明确告知这样做,但是form_for标签也不会,因为他们在Rails 4中将其切碎。
我通过在表单中添加隐藏输入来解决此问题。
<input type="hidden" value="<%= form_authenticity_token() %>"name="authenticity_token"/>
下面是一个示例:
<%= form_tag("/payments/create", remote: true) do %>
<%= render partial: "shared/stripe_checkout_button" %>
<%= hidden_field_tag(:product_id, @product.id) %>
<input type="hidden" value="<%= form_authenticity_token() %>"name="authenticity_token"/>
<% end %>
他们砍掉CSRF令牌自动生成的主要原因与人们的片段缓存有关,因为当表单从缓存中提取时,真实性令牌在后续请求中将是错误的。