我有一个使用Ajax的form_tag,以使用Stripe保存新的用户卡。它呈现Stripe卡形式,将输入传递给控制器方法,然后应提供js文件。它可以在没有Stripe内容的情况下工作,但是有了它,我遇到了身份验证问题。
这是基本代码:
<%= form_tag(save_card_path, id:'payment-form', remote: true) do %>
<div id="card-element">
<!-- A Stripe Element will be inserted here. -->
</div>
<button id="submit-card" class="submit-btn">Save Card</button>
<% end %>
<script type="text/javascript">
var stripe = Stripe('<%= @stripe_public %>');
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
var style = {
base: {
// Add your base input styles here. For example:
fontSize: '20px',
color: "#32325d",
}
};
// Create an instance of the card Element.
var card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Create a token or display an error when the form is submitted.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the customer that there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
</script>
def save_card
respond_to do |format|
format.js
end
end
$("html").hide();
因此,就像我说的那样,没有Stripe代码,一切正常,并且参数中存在authenticity_token
,但是我在上面编写的代码给出了以下错误:
def handle_unverified_request
raise ActionController::InvalidAuthenticityToken
end
仅带有参数:
{"utf8"=>"✓", "stripeToken"=>"<token>"}
当我将选项authenticity_token: true
添加到表单时,参数再次包含authenticity_token
,但是现在当它到达format.js
行时,我得到了错误
ActionController::UnknownFormat
在尝试通过Ajax上载表单文件时,我遇到了类似的问题,但是我发现了remotipart gem,并解决了该问题。但这在这种情况下似乎无济于事。
没有人知道为什么包括Stripe字段会摆脱我的authenticity_token,为什么即使有了authenticity_token,也无法识别js格式?
Jquery-ujs通过我的//= require jquery_ujs
中的行application.js
包括在内,<%= csrf_meta_tags %>
中的行包括在application.html.erb
中,而我的源代码中包括了这些行
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="<TOKEN>" />
无论我的ajax调用是否有效,都是这种情况。
这是我添加选项authenticity_token: true
时的完整日志:
2020年12月20日00:07:04 +0100的127.0.0.1启动POST“ / save_card”
由UsersController#save_card作为HTML处理
参数:{“ utf8” =>“✓”,“ authenticity_token” =>“ [LONG TOKEN]”,“ post” =>“ 47”,“ transaction” =>“ bid”,“ stripeToken” =>“ [STRIPE令牌]”}
用户负载(0.9ms)
选择“用户”。*从“用户”,在“用户”。“ id” = $ 1排序依据“ users”。“ id” ASC LIMIT $ 2 [[“ id”,2],[“ LIMIT”,1]]
(0.3ms)开始SQL
((2.3ms)插入“卡片”(“ stripe_customer_id”,“品牌”,“ last4”,“ exp_month”,“ exp_year”,“ user_id”,“ created_at”,“ updated_at”)值($ 1,$ 2,$ 3,$ 4,$ 5,$ 6,$ 7,$ 8)返回“ id”[[“ stripe_customer_id”,“ [STRIPE TOKEN]”],[“ brand”,“ Visa”],[“ last4”,“ 4242”],[“ exp_month”,“ 4”],[“ exp_year”,“ 2024”],[“ user_id”,2],[“ created_at”,“ 2020-02-19 23:07:05.246789”],[“ updated_at”,“ 2020-02-19 23:07:05.246789”]]
((2.8ms)COMMIT
在672ms内完成406不可接受(ActiveRecord:6.3ms)
ActionController :: UnknownFormat(ActionController :: UnknownFormat):app / controllers / users_controller.rb:485:in'save_card'开始GET2020年2月20日00:07:05 +0100的127.0.0.1的“ /serviceworker.js”在2020-02-20 00:07:21 +0100上获取:: 1的“ /serviceworker.js”:>
这是我删除
authenticity_token: true
时的日志:
2020年12月20日00:33:17 +0100的127.0.0.1启动POST“ / save_card”
由UsersController#save_card作为HTML处理
参数:{“ utf8” =>“✓”,“ post” =>“ 47”,“ transaction” =>“ bid”,“ stripeToken” =>“ [STRIPE TOKEN]”}无法验证CSRF令牌真实性。 1毫秒内完成422个不可处理实体(ActiveRecord:0.0ms)
ActionController :: InvalidAuthenticityToken(ActionController :: InvalidAuthenticityToken):操作包(5.1.7)lib / action_controller / metal / request_forgery_protection.rb:195:in
handle_unverified_request' actionpack (5.1.7) lib/action_controller/metal/request_forgery_protection.rb:227:in
handle_unverified_request'装置(4.7.0)lib / devise / controllers / helpers.rb:255:inhandle_unverified_request' actionpack (5.1.7) lib/action_controller/metal/request_forgery_protection.rb:222:in
verify_authenticity_token'activesupport(5.1.7)lib / active_support / callbacks.rb:413:inblock in make_lambda' activesupport (5.1.7) lib/active_support/callbacks.rb:197:in
block(2级别”中止操作包(5.1.7)lib / abstract_controller / callbacks.rb:12:block (2 levels) in <module:Callbacks>' activesupport (5.1.7) lib/active_support/callbacks.rb:198:in
中的“阻止”activesupport(5.1.7)lib / active_support / callbacks.rb:507:block in invoke_before' activesupport (5.1.7) lib/active_support/callbacks.rb:507:in
每个'activesupport(5.1.7)lib / active_support / callbacks.rb:507:ininvoke_before' activesupport (5.1.7) lib/active_support/callbacks.rb:130:in
run_callbacks'actionpack(5.1.7)lib / abstract_controller / callbacks.rb:19:inprocess_action' actionpack (5.1.7) lib/action_controller/metal/rescue.rb:20:in
process_action'动作包(5.1.7)lib / action_controller / metal / instrumentation.rb:32:inblock in process_action' activesupport (5.1.7) lib/active_support/notifications.rb:166:in
block in instrument'主动支持(5.1.7)lib / active_support / notifications / instrumenter.rb:21:在instrument' activesupport (5.1.7) lib/active_support/notifications.rb:166:in
仪器的操作包(5.1.7)中lib / action_controller / metal / instrumentation.rb:30:inprocess_action' actionpack (5.1.7) lib/action_controller/metal/params_wrapper.rb:252:in
process_action'活动记录(5.1.7)lib / active_record / railties / controller_runtime.rb:22:inprocess_action' actionpack (5.1.7) lib/abstract_controller/base.rb:124:in
流程的操作视图(5.1.7)lib / action_view / rendering.rb:30:process' actionpack (5.1.7) lib/action_controller/metal.rb:189:in
中的“派遣”操作包(5.1.7)lib / action_controller / metal.rb:253:在dispatch' actionpack (5.1.7) lib/action_dispatch/routing/route_set.rb:49:in
派遣'Actionpack中(5.1.7)lib / action_dispatch / routing / route_set.rb:31:serve' actionpack (5.1.7) lib/action_dispatch/journey/router.rb:50:in
block中在发球动作包中(5.1.7)lib / action_dispatch / journey / router.rb:33:each' actionpack (5.1.7) lib/action_dispatch/journey/router.rb:33:in
serve'actionpack(5.1.7)lib / action_dispatch / routing / route_set.rb:844:incall' serviceworker-rails (0.6.0) lib/serviceworker/middleware.rb:35:in
call'remotipart(1.4.3)lib / remotipart / middleware.rb:32:in:call' warden (1.2.8) lib/warden/manager.rb:36:in
block in call'warden(1.2.8)lib / warden / manager.rb:34:incatch' warden (1.2.8) lib/warden/manager.rb:34:in
调用机架(2.0.7)lib / rack / etag.rb:25:incall' rack (2.0.7) lib/rack/conditional_get.rb:38:in
通话架(2.0.7)lib / rack / head.rb:12:call' rack (2.0.7) lib/rack/session/abstract/id.rb:232:in
context'机架(2.0.7)lib / rack / session / abstract / id.rb:226:在call' actionpack (5.1.7) lib/action_dispatch/middleware/cookies.rb:613:in
中调用“ activerecord”(5.1.7)lib / active_record / migration.rb:556:incall' actionpack (5.1.7) lib/action_dispatch/middleware/callbacks.rb:26:in
block in呼叫'activesupport(5.1.7)lib / active_support / callbacks.rb:97:inrun_callbacks' actionpack (5.1.7) lib/action_dispatch/middleware/callbacks.rb:24:in
通话'行动包(5.1.7)lib / action_dispatch / middleware / executor.rb:12:incall' actionpack (5.1.7) lib/action_dispatch/middleware/debug_exceptions.rb:59:in
call'网络控制台(3.7.0)lib / web_console / middleware.rb:135:incall_app' web-console (3.7.0) lib/web_console/middleware.rb:30:in
block in调用“网络控制台(3.7.0)lib / web_console / middleware.rb:20:incatch' web-console (3.7.0) lib/web_console/middleware.rb:20:in
call”动作包(5.1.7)lib / action_dispatch / middleware / show_exceptions.rb:31:在call' railties (5.1.7) lib/rails/rack/logger.rb:36:in
call_app'轨道上(5.1.7)lib / rails / rack / logger.rb:24:inblock in call' activesupport (5.1.7) lib/active_support/tagged_logging.rb:69:in
block in tags'activesupport(5.1.7)lib / active_support / tagged_logging.rb:26:intagged' activesupport (5.1.7) lib/active_support/tagged_logging.rb:69:in
被标记的“杂物”(5.1.7)lib / rails / rack / logger.rb:24:在call' sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in
call'actionpack(5.1.7)中lib / action_dispatch / middleware / remote_ip.rb:79:在call' actionpack (5.1.7) lib/action_dispatch/middleware/request_id.rb:25:in
调用机架中(2.0.7)lib / rack / method_override.rb:22:call' rack (2.0.7) lib/rack/runtime.rb:22:in
中的调用“ activesupport”(5.1.7)lib / active_support / cache / strategy / local_cache_middleware.rb:27:incall' actionpack (5.1.7) lib/action_dispatch/middleware/executor.rb:12:in
通话'行动包(5.1.7)lib / action_dispatch / middleware / static.rb:125:在call' rack (2.0.7) lib/rack/sendfile.rb:111:in
call'栏杆中(5.1.7)lib / rails / engine.rb:522:incall' puma (3.12.1) lib/puma/configuration.rb:227:in
call'puma(3.12.1)lib / puma / server.rb:660:inhandle_request' puma (3.12.1) lib/puma/server.rb:474:in
process_client'puma(3.12.1)lib / puma / server.rb:334:在spawn_thread的block in run' puma (3.12.1) lib/puma/thread_pool.rb:135:in
块中'开始GET2020年2月20日00:33:18 +0100的127.0.0.1的“ /serviceworker.js”
我有一个使用Ajax的form_tag,以使用Stripe保存新的用户卡。它呈现Stripe卡形式,将输入传递给控制器方法,然后应提供js文件。它不需要...
您可以尝试以下操作吗,
假设您在Rails 5.X上并且//= require rails-ujs
文件中有application.js
保留所有内容,然后更新.submit()