【发布时间】:2019-04-14 06:27:57
【问题描述】:
问题:表单中的银行账户数据没有保存到 Stripe API (Stripe::Account),可能是因为它没有正确或成功 Stripe::Account.retrieve(current_user .stripe_token)
问题:我的代码中的什么原因导致检索无法正常工作,或者是其他问题,例如没有正确设置 webhook,或者 JS 不正确?
我的想法:我假设它不是控制器,而是 JS 的设置方式,因为我不精通 JS。我在 GitHub 上找到了一个示例应用程序,它按照我希望的方式使用 Stripe Connect,并将其用作构建我的 BankAccount 控制器、视图/表单和 JS 的参考。
这是我用来帮助我设置它的参考示例应用程序:https://stripe-marketplace-demo.herokuapp.com/
如何设置:我有用户表;用户注册并输入到此用户表中。然后我有一个 StripeAccounts 表; users (current_user) 可以创建一个 StripeAccount,stripe 帐户令牌在 StripeAccount 中保存为 acct_id >> user_id(来自 User 表)与 StripeAccount 相关联。 stripe_account 令牌也保存在 stripe_token 下的 User 表中。创建并保存 stripe_account 后,它们将被重定向以填写 BankAccount 表单
这是整个银行账户控制器:
class BankAccountsController < ApplicationController
before_action :authenticate_user!
def new
unless current_user.stripe_token
redirect_to new_user_stripe_account_path and return
end
begin
@stripe_account = Stripe::Account.retrieve(current_user.stripe_token)
rescue Stripe::StripeError => e
handle_error(e.message, 'new')
rescue => e
flash[:error] = e.message
end
end
def create
unless params[:stripeToken] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
begin
stripe_account = Stripe::Account.retrieve(current_user.stripe_token)
stripe_account.external_account = params[:stripeToken]
stripe_account.save
flash[:success] = "Your bank account has been added!"
redirect_to dashboard_path
rescue Stripe::StripeError => e
flash[:error] = e.message
rescue => e
flash[:error] = e.message
end
end
end
我使用 StripeAccounts 表中的“acct_id”下保存的条带令牌正确保存了 stripe_accounts,并且与正确的 user_id 相关的用户表下保存为“stripe_token”的相同令牌。
我是 Rails 新手(大约一个月)并且对 Stripe 非常陌生,所以以下只是假设:我假设新方法中的“@stripe_account = Stripe::Account.retrieve(current_user.stripe_token)”没有检索任何东西。这是否依赖于 webhook?那我可能没有正确设置?我曾尝试通过 ngrok 执行此操作,但无济于事。虽然,我在 html 页面上没有收到任何错误。 然后我会假设我陷入了 create 方法中的代码:
unless params[:stripeToken] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
因为当我按下提交时,页面只是重新加载并且没有任何内容保存到 API。
这是我与 JS 一起提交的视图/表单:
<%= content_for :page_title, "Add a new bank account" %>
<% content_for(:header) do %>
<script src="https://js.stripe.com/v3/"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.payment/1.4.1/jquery.payment.js"></script>
<script>
// Set your Stripe publishable API key here
// Stripe.setPublishableKey("<%= ENV['PUBLISHABLE_KEY'] %>");
var stripe = Stripe('pk_test_3v1234567896LyWMYKE1f0B8');
$(function() {
var $form = $('#payment-form');
$form.submit(function(event) {
// Clear any errors
$form.find('.has-error').removeClass('has-error');
// Disable the submit button to prevent repeated clicks:
$form.find('.submit').prop('disabled', true).html("<i class='fa fa-spinner fa-spin'></i> Adding bank account...");
// Request a token from Stripe:
Stripe.bankAccount.createToken($form, stripeResponseHandler);
return false;
});
});
function stripeResponseHandler(status, response) {
var $form = $('#payment-form');
if (response.error) {
$form.find('.errors').text(response.error.message).addClass('alert alert-danger');
$form.find('.' + response.error.param).parent('.form-group').addClass('has-error');
$form.find('button').prop('disabled', false).text('Add Bank Account'); // Re-enable submission
}
else { // Token was created!
$form.find('.submit').html("<i class='fa fa-check'></i> Account added");
var token = response.id;
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
$form.get(0).submit();
}
}
</script>
<% end %>
<div class="panel panel-default">
<div class="panel-body">
<form action="/bank_accounts" method="POST" id="payment-form">
<div class="errors"></div>
<div class="row">
<div class="col-md-8">
<div class="form-group">
<label>Country</label>
<select class="form-control input-lg" id="country" data-stripe="country">
<option value="US">United States</option>
</select>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>Currency</label>
<select class="form-control input-lg" id="currency" data-stripe="currency">
<option value="usd">USD</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6" id="routing_number_div">
<div class="form-group">
<label id="routing_number_label">Routing Number</label>
<input class="form-control input-lg bank_account" id="routing_number" type="tel" size="12" data-stripe="routing_number" value="110000000" autocomplete="off">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label id="account_number_label">Account Number</label>
<input class="form-control input-lg bank_account" id="account_number" type="tel" size="20" data-stripe="account_number" value="000123456789" autocomplete="off">
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-lg btn-block btn-primary btn-custom submit" type="submit">Add Bank Account</button>
</div>
</div>
<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
</form>
</div>
</div>
正如您在 JS 中看到的:// Stripe.setPublishableKey("<%= ENV['PUBLISHABLE_KEY'] %>");
我已经尝试过了,但显然它不再是最新的了。仅出于测试目的,我只是将可发布密钥直接包含在 JS 中,而不是在凭据中,直到我弄明白为止。
这是我提交表单时的控制台:
Started POST "/bank_accounts" for 127.0.0.1 at 2018-11-10 14:32:11 -0500
Processing by BankAccountsController#create as HTML
Parameters: {"authenticity_token"=>"l69UBGkzwcel7JH34+TDbsfQ9Xjkiogu+emWm+8+0iVQfKh9AIxDaXp0yMhjFkUVznHeJYwXeVmdBVSI2XjArg=="}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 2], ["LIMIT", 1]]
↳ /home/bob/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
Redirected to http://localhost:3000/bank_accounts/new
Completed 302 Found in 4ms (ActiveRecord: 0.3ms)
Started GET "/bank_accounts/new" for 127.0.0.1 at 2018-11-10 14:32:11 -0500
Processing by BankAccountsController#new as HTML
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 2], ["LIMIT", 1]]
↳ /home/bob/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
StripeAccount Load (0.2ms) SELECT "stripe_accounts".* FROM "stripe_accounts" WHERE "stripe_accounts"."user_id" = ? LIMIT ? [["user_id", 2], ["LIMIT", 1]]
↳ app/controllers/bank_accounts_controller.rb:6
Rendering bank_accounts/new.html.erb within layouts/application
Rendered bank_accounts/_bank_account_form.html.erb (1.0ms)
Rendered bank_accounts/new.html.erb within layouts/application (4.2ms)
Rendered layouts/_navbar.html.erb (3.0ms)
Rendered layouts/_footer.html.erb (0.3ms)
Completed 200 OK in 218ms (Views: 212.4ms | ActiveRecord: 0.5ms)
e.message 内容如下:
Invalid external_account object: must be a dictionary or a non-empty string. See API docs at https://stripe.com/docs'
但 e.message 仅在页面重新加载时出现,而不是在提交表单时出现。只有当我提交,然后重新加载页面时,它才会出现。
我没有在 BankAccount 模型中设置任何内容,我用作参考的示例应用程序也是如此。
额外信息:对于用户和 StripeAccount,我将它们嵌套,这就是为什么你会看到 new_user_stripe_account_path...BankAccount 没有嵌套到任何东西。
来自浏览器控制台的消息:
Error: The selector you specified (#card-element) applies to no DOM elements that are currently on the page.
Make sure the element exists on the page before calling mount(). v3:1:10186
t
https://js.stripe.com/v3/:1:10186
oi/this.mount<
https://js.stripe.com/v3/:1:79868
Gt/<
https://js.stripe.com/v3/:1:23367
<anonymous>
http://localhost:3000/assets/stripejs.self-8c2ad75855f867e5280e1a173e994f83fb5afc997847456669b8cbe0b24fae1f.js:31:1
[Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIContentSniffer.getMIMETypeFromContent]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: resource:///modules/FaviconLoader.jsm :: onStopRequest :: line 181" data: no]
onStopRequest
resource:///modules/FaviconLoader.jsm:181:16
InterpretGeneratorResume self-hosted:1257:8 next self-hosted:1212:9
【问题讨论】:
-
因为您收到诸如“必须是字典或非空字符串”之类的错误,我怀疑您的银行帐户令牌根本不会传递到您的后端 --- 事实上我在您共享的日志中看不到它
Parameters: {"authenticity_token"=>"l69UBGkzwcel7JH34+TDbsfQ9Xjkiogu+emWm+8+0iVQfKh9AIxDaXp0yMhjFkUVznHeJYwXeVmdBVSI2XjArg=="}--- 尝试在您的 JS 中添加一些调试 --- console.logs 在您的stripeResponseHandler 中,这是表单提交之前的断点(检查隐藏的stripeToken 输入是否确实存在于您的表单使用浏览器开发工具检查器) -
我在按下提交时添加了浏览器控制台。除此之外,你觉得剩下的代码还可以吗?
-
顺便说一句,“检查是否存在隐藏的 stripetoken 输入”...这是我将在浏览器控制台中看到的内容...?而在更新中,如果是这样,它就不存在了吗?
-
所以,据我了解,JS 是用于 Stripe V2 而不是 Stripe V3,您可以在这里看到差异:V2:stripe.com/docs/stripe-js/v2#collecting-bank-account-details ----V3:stripe.com/docs/stripe-js/… ----- 所以我试图将它迁移到 v3
标签: javascript ruby-on-rails ruby stripe-payments