Adding Bank Account data to stripe not saving to API or database table
up vote
0
down vote
favorite
Issue: The Bank Account data in the form isn't saving to the Stripe API (Stripe::Account), possibly because it's not being correctly or successfully Stripe::Account.retrieve(current_user.stripe_token)
Question: What in my code is causing the retrieve to not work or is the issue something else, such as not having webhooks correctly set up, or incorrect JS?
My Thoughts: I am assuming it's not the controller, but the way the JS is set up as I am not well versed in JS. I found an example application on GitHub using Stripe Connect the way I want it to function and used it as a reference to build my BankAccount controller, view/form, and JS.
This is the sample application for reference I have used to help me set this up: https://stripe-marketplace-demo.herokuapp.com/
How it's set up: I have Users table ; users sign up and get inputted into this User Table. I then have a StripeAccounts table; users (current_user) can create a StripeAccount, the stripe account token is saved as acct_id within StripeAccount >> the user_id (from User table) is associated with the StripeAccount. The stripe_account token is also saved in the User table under stripe_token. Once a stripe_account is created and saved, they are redirected to fill out the BankAccount form << This is where my issues are. The bank account information isn't saving and most likely due to a failure to retrieve. Reasoning below.
Here's the entire Bank Account Controller:
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
I have the stripe_accounts saving correctly with the stripe token saved under "acct_id" in the StripeAccounts table, and the same token saved as "stripe_token" under the Users table in relation to the correct user_id.
I am new to rails (about a month in) and very new to Stripe so the following is only assumption: I am assuming the "@stripe_account = Stripe::Account.retrieve(current_user.stripe_token)" in the new method isn't retrieving anything. Does this rely on webhooks? That I may not have set up correctly? I have tried doing this through ngrok, but to no avail. Although, I receive no errors on page in html.
I would then assume I'm getting stuck at the code in the create method:
unless params[:stripeToken] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
Because when i press submit, the page simply reloads and nothing saves to the API.
Here's the view/form I am submitting along with the 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>
As you see in the JS: // Stripe.setPublishableKey("<%= ENV['PUBLISHABLE_KEY'] %>");
I have tried with that, but apparently it's not up to date anymore. Just for testing purposes, I have simply included the publishable key directly within the JS and not in credentials just yet until I figure it out.
Here is my console when I submit the form:
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)
the e.message reads as follows:
Invalid external_account object: must be a dictionary or a non-empty string. See API docs at https://stripe.com/docs'
but the e.message only appears on page reload and not when the form is submitted. Only once I submit, and then reload the page, it appears.
I having nothing set up within the BankAccount model, either does the example app i used as a reference.
Extra information: For Users and StripeAccount, I have them nested, which is why you will see new_user_stripe_account_path... BankAccount isn't nested to anything.
Message from Browser Console:
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
javascript ruby-on-rails ruby stripe-payments
add a comment |
up vote
0
down vote
favorite
Issue: The Bank Account data in the form isn't saving to the Stripe API (Stripe::Account), possibly because it's not being correctly or successfully Stripe::Account.retrieve(current_user.stripe_token)
Question: What in my code is causing the retrieve to not work or is the issue something else, such as not having webhooks correctly set up, or incorrect JS?
My Thoughts: I am assuming it's not the controller, but the way the JS is set up as I am not well versed in JS. I found an example application on GitHub using Stripe Connect the way I want it to function and used it as a reference to build my BankAccount controller, view/form, and JS.
This is the sample application for reference I have used to help me set this up: https://stripe-marketplace-demo.herokuapp.com/
How it's set up: I have Users table ; users sign up and get inputted into this User Table. I then have a StripeAccounts table; users (current_user) can create a StripeAccount, the stripe account token is saved as acct_id within StripeAccount >> the user_id (from User table) is associated with the StripeAccount. The stripe_account token is also saved in the User table under stripe_token. Once a stripe_account is created and saved, they are redirected to fill out the BankAccount form << This is where my issues are. The bank account information isn't saving and most likely due to a failure to retrieve. Reasoning below.
Here's the entire Bank Account Controller:
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
I have the stripe_accounts saving correctly with the stripe token saved under "acct_id" in the StripeAccounts table, and the same token saved as "stripe_token" under the Users table in relation to the correct user_id.
I am new to rails (about a month in) and very new to Stripe so the following is only assumption: I am assuming the "@stripe_account = Stripe::Account.retrieve(current_user.stripe_token)" in the new method isn't retrieving anything. Does this rely on webhooks? That I may not have set up correctly? I have tried doing this through ngrok, but to no avail. Although, I receive no errors on page in html.
I would then assume I'm getting stuck at the code in the create method:
unless params[:stripeToken] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
Because when i press submit, the page simply reloads and nothing saves to the API.
Here's the view/form I am submitting along with the 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>
As you see in the JS: // Stripe.setPublishableKey("<%= ENV['PUBLISHABLE_KEY'] %>");
I have tried with that, but apparently it's not up to date anymore. Just for testing purposes, I have simply included the publishable key directly within the JS and not in credentials just yet until I figure it out.
Here is my console when I submit the form:
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)
the e.message reads as follows:
Invalid external_account object: must be a dictionary or a non-empty string. See API docs at https://stripe.com/docs'
but the e.message only appears on page reload and not when the form is submitted. Only once I submit, and then reload the page, it appears.
I having nothing set up within the BankAccount model, either does the example app i used as a reference.
Extra information: For Users and StripeAccount, I have them nested, which is why you will see new_user_stripe_account_path... BankAccount isn't nested to anything.
Message from Browser Console:
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
javascript ruby-on-rails ruby stripe-payments
Because you are getting an error like "must be a dictionary or a non-empty string" , I suspect your bank account token is never getting passed to your back-end at all --- in fact i don't see it in the log you sharedParameters: {"authenticity_token"=>"l69UBGkzwcel7JH34+TDbsfQ9Xjkiogu+emWm+8+0iVQfKh9AIxDaXp0yMhjFkUVznHeJYwXeVmdBVSI2XjArg=="}
--- try adding some debugging to your JS --- console.logs in your stripeResponseHandler, a breakpoint before the form submit (check that a hidden stripeToken input really exists in your form using browser dev tools inspector)
– duck
Nov 11 at 19:54
I added the Browser Console when i press submit. Other than that, do you think the rest of the code is okay?
– uno
Nov 11 at 23:56
BTW, "check that a hidden stripetoken input exists"... is that something I'll see in the Browser console...? and in the update, it's not there if so?
– uno
Nov 12 at 0:20
So it looks like, from what i understand, is the JS is for Stripe V2 and not Stripe V3 you can see the differences here: V2:stripe.com/docs/stripe-js/v2#collecting-bank-account-details ----V3:stripe.com/docs/stripe-js/… ----- so im trying to migrate it over to v3
– uno
Nov 12 at 2:53
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
Issue: The Bank Account data in the form isn't saving to the Stripe API (Stripe::Account), possibly because it's not being correctly or successfully Stripe::Account.retrieve(current_user.stripe_token)
Question: What in my code is causing the retrieve to not work or is the issue something else, such as not having webhooks correctly set up, or incorrect JS?
My Thoughts: I am assuming it's not the controller, but the way the JS is set up as I am not well versed in JS. I found an example application on GitHub using Stripe Connect the way I want it to function and used it as a reference to build my BankAccount controller, view/form, and JS.
This is the sample application for reference I have used to help me set this up: https://stripe-marketplace-demo.herokuapp.com/
How it's set up: I have Users table ; users sign up and get inputted into this User Table. I then have a StripeAccounts table; users (current_user) can create a StripeAccount, the stripe account token is saved as acct_id within StripeAccount >> the user_id (from User table) is associated with the StripeAccount. The stripe_account token is also saved in the User table under stripe_token. Once a stripe_account is created and saved, they are redirected to fill out the BankAccount form << This is where my issues are. The bank account information isn't saving and most likely due to a failure to retrieve. Reasoning below.
Here's the entire Bank Account Controller:
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
I have the stripe_accounts saving correctly with the stripe token saved under "acct_id" in the StripeAccounts table, and the same token saved as "stripe_token" under the Users table in relation to the correct user_id.
I am new to rails (about a month in) and very new to Stripe so the following is only assumption: I am assuming the "@stripe_account = Stripe::Account.retrieve(current_user.stripe_token)" in the new method isn't retrieving anything. Does this rely on webhooks? That I may not have set up correctly? I have tried doing this through ngrok, but to no avail. Although, I receive no errors on page in html.
I would then assume I'm getting stuck at the code in the create method:
unless params[:stripeToken] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
Because when i press submit, the page simply reloads and nothing saves to the API.
Here's the view/form I am submitting along with the 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>
As you see in the JS: // Stripe.setPublishableKey("<%= ENV['PUBLISHABLE_KEY'] %>");
I have tried with that, but apparently it's not up to date anymore. Just for testing purposes, I have simply included the publishable key directly within the JS and not in credentials just yet until I figure it out.
Here is my console when I submit the form:
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)
the e.message reads as follows:
Invalid external_account object: must be a dictionary or a non-empty string. See API docs at https://stripe.com/docs'
but the e.message only appears on page reload and not when the form is submitted. Only once I submit, and then reload the page, it appears.
I having nothing set up within the BankAccount model, either does the example app i used as a reference.
Extra information: For Users and StripeAccount, I have them nested, which is why you will see new_user_stripe_account_path... BankAccount isn't nested to anything.
Message from Browser Console:
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
javascript ruby-on-rails ruby stripe-payments
Issue: The Bank Account data in the form isn't saving to the Stripe API (Stripe::Account), possibly because it's not being correctly or successfully Stripe::Account.retrieve(current_user.stripe_token)
Question: What in my code is causing the retrieve to not work or is the issue something else, such as not having webhooks correctly set up, or incorrect JS?
My Thoughts: I am assuming it's not the controller, but the way the JS is set up as I am not well versed in JS. I found an example application on GitHub using Stripe Connect the way I want it to function and used it as a reference to build my BankAccount controller, view/form, and JS.
This is the sample application for reference I have used to help me set this up: https://stripe-marketplace-demo.herokuapp.com/
How it's set up: I have Users table ; users sign up and get inputted into this User Table. I then have a StripeAccounts table; users (current_user) can create a StripeAccount, the stripe account token is saved as acct_id within StripeAccount >> the user_id (from User table) is associated with the StripeAccount. The stripe_account token is also saved in the User table under stripe_token. Once a stripe_account is created and saved, they are redirected to fill out the BankAccount form << This is where my issues are. The bank account information isn't saving and most likely due to a failure to retrieve. Reasoning below.
Here's the entire Bank Account Controller:
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
I have the stripe_accounts saving correctly with the stripe token saved under "acct_id" in the StripeAccounts table, and the same token saved as "stripe_token" under the Users table in relation to the correct user_id.
I am new to rails (about a month in) and very new to Stripe so the following is only assumption: I am assuming the "@stripe_account = Stripe::Account.retrieve(current_user.stripe_token)" in the new method isn't retrieving anything. Does this rely on webhooks? That I may not have set up correctly? I have tried doing this through ngrok, but to no avail. Although, I receive no errors on page in html.
I would then assume I'm getting stuck at the code in the create method:
unless params[:stripeToken] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
Because when i press submit, the page simply reloads and nothing saves to the API.
Here's the view/form I am submitting along with the 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>
As you see in the JS: // Stripe.setPublishableKey("<%= ENV['PUBLISHABLE_KEY'] %>");
I have tried with that, but apparently it's not up to date anymore. Just for testing purposes, I have simply included the publishable key directly within the JS and not in credentials just yet until I figure it out.
Here is my console when I submit the form:
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)
the e.message reads as follows:
Invalid external_account object: must be a dictionary or a non-empty string. See API docs at https://stripe.com/docs'
but the e.message only appears on page reload and not when the form is submitted. Only once I submit, and then reload the page, it appears.
I having nothing set up within the BankAccount model, either does the example app i used as a reference.
Extra information: For Users and StripeAccount, I have them nested, which is why you will see new_user_stripe_account_path... BankAccount isn't nested to anything.
Message from Browser Console:
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
javascript ruby-on-rails ruby stripe-payments
javascript ruby-on-rails ruby stripe-payments
edited Nov 11 at 23:55
asked Nov 11 at 7:57
uno
579
579
Because you are getting an error like "must be a dictionary or a non-empty string" , I suspect your bank account token is never getting passed to your back-end at all --- in fact i don't see it in the log you sharedParameters: {"authenticity_token"=>"l69UBGkzwcel7JH34+TDbsfQ9Xjkiogu+emWm+8+0iVQfKh9AIxDaXp0yMhjFkUVznHeJYwXeVmdBVSI2XjArg=="}
--- try adding some debugging to your JS --- console.logs in your stripeResponseHandler, a breakpoint before the form submit (check that a hidden stripeToken input really exists in your form using browser dev tools inspector)
– duck
Nov 11 at 19:54
I added the Browser Console when i press submit. Other than that, do you think the rest of the code is okay?
– uno
Nov 11 at 23:56
BTW, "check that a hidden stripetoken input exists"... is that something I'll see in the Browser console...? and in the update, it's not there if so?
– uno
Nov 12 at 0:20
So it looks like, from what i understand, is the JS is for Stripe V2 and not Stripe V3 you can see the differences here: V2:stripe.com/docs/stripe-js/v2#collecting-bank-account-details ----V3:stripe.com/docs/stripe-js/… ----- so im trying to migrate it over to v3
– uno
Nov 12 at 2:53
add a comment |
Because you are getting an error like "must be a dictionary or a non-empty string" , I suspect your bank account token is never getting passed to your back-end at all --- in fact i don't see it in the log you sharedParameters: {"authenticity_token"=>"l69UBGkzwcel7JH34+TDbsfQ9Xjkiogu+emWm+8+0iVQfKh9AIxDaXp0yMhjFkUVznHeJYwXeVmdBVSI2XjArg=="}
--- try adding some debugging to your JS --- console.logs in your stripeResponseHandler, a breakpoint before the form submit (check that a hidden stripeToken input really exists in your form using browser dev tools inspector)
– duck
Nov 11 at 19:54
I added the Browser Console when i press submit. Other than that, do you think the rest of the code is okay?
– uno
Nov 11 at 23:56
BTW, "check that a hidden stripetoken input exists"... is that something I'll see in the Browser console...? and in the update, it's not there if so?
– uno
Nov 12 at 0:20
So it looks like, from what i understand, is the JS is for Stripe V2 and not Stripe V3 you can see the differences here: V2:stripe.com/docs/stripe-js/v2#collecting-bank-account-details ----V3:stripe.com/docs/stripe-js/… ----- so im trying to migrate it over to v3
– uno
Nov 12 at 2:53
Because you are getting an error like "must be a dictionary or a non-empty string" , I suspect your bank account token is never getting passed to your back-end at all --- in fact i don't see it in the log you shared
Parameters: {"authenticity_token"=>"l69UBGkzwcel7JH34+TDbsfQ9Xjkiogu+emWm+8+0iVQfKh9AIxDaXp0yMhjFkUVznHeJYwXeVmdBVSI2XjArg=="}
--- try adding some debugging to your JS --- console.logs in your stripeResponseHandler, a breakpoint before the form submit (check that a hidden stripeToken input really exists in your form using browser dev tools inspector)– duck
Nov 11 at 19:54
Because you are getting an error like "must be a dictionary or a non-empty string" , I suspect your bank account token is never getting passed to your back-end at all --- in fact i don't see it in the log you shared
Parameters: {"authenticity_token"=>"l69UBGkzwcel7JH34+TDbsfQ9Xjkiogu+emWm+8+0iVQfKh9AIxDaXp0yMhjFkUVznHeJYwXeVmdBVSI2XjArg=="}
--- try adding some debugging to your JS --- console.logs in your stripeResponseHandler, a breakpoint before the form submit (check that a hidden stripeToken input really exists in your form using browser dev tools inspector)– duck
Nov 11 at 19:54
I added the Browser Console when i press submit. Other than that, do you think the rest of the code is okay?
– uno
Nov 11 at 23:56
I added the Browser Console when i press submit. Other than that, do you think the rest of the code is okay?
– uno
Nov 11 at 23:56
BTW, "check that a hidden stripetoken input exists"... is that something I'll see in the Browser console...? and in the update, it's not there if so?
– uno
Nov 12 at 0:20
BTW, "check that a hidden stripetoken input exists"... is that something I'll see in the Browser console...? and in the update, it's not there if so?
– uno
Nov 12 at 0:20
So it looks like, from what i understand, is the JS is for Stripe V2 and not Stripe V3 you can see the differences here: V2:stripe.com/docs/stripe-js/v2#collecting-bank-account-details ----V3:stripe.com/docs/stripe-js/… ----- so im trying to migrate it over to v3
– uno
Nov 12 at 2:53
So it looks like, from what i understand, is the JS is for Stripe V2 and not Stripe V3 you can see the differences here: V2:stripe.com/docs/stripe-js/v2#collecting-bank-account-details ----V3:stripe.com/docs/stripe-js/… ----- so im trying to migrate it over to v3
– uno
Nov 12 at 2:53
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
accepted
So it looks like the JS was to blame. It was somewhat wrong and out of date, and a few things weren't matched up with my controller.
Here's the correct JS for S v3
JS on view page (i believe this NEEDS TO BE UNDER the form; could be wrong):
var stripe = Stripe('pk_test_WUSo123456789PWU8kh');
function setOutcome(result) {
var successElement = document.querySelector('.success');
var errorElement = document.querySelector('.error');
successElement.classList.remove('visible');
errorElement.classList.remove('visible');
if (result.token) {
// In this example, we're simply displaying the token
successElement.querySelector('.token').textContent = result.token.id;
successElement.classList.add('visible');
// In a real integration, you'd submit the form with the token to your backend server
var form = document.querySelector('form');
form.querySelector('input[name="token"]').setAttribute('value', result.token.id);
form.submit();
} else {
errorElement.textContent = result.error.message;
errorElement.classList.add('visible');
}
}
document.querySelector('form').addEventListener('submit', function(e) {
e.preventDefault();
var bankAccountParams = {
country: document.getElementById('country').value,
currency: document.getElementById('currency').value,
account_number: document.getElementById('account-number').value,
account_holder_name: document.getElementById('account-holder-name').value,
account_holder_type: document.getElementById('account-holder-type').value,
}
if (document.getElementById('routing-number').value != '') {
bankAccountParams['routing_number'] = document.getElementById('routing-number').value;
}
stripe.createToken('bank_account', bankAccountParams).then(setOutcome);
});
And the correct Create for the BankAccount controller:
(or this at least works, i may be fixing this up a bit after this)
def create
unless params[:token] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
begin
token = params[:token]
stripe_account.external_account = params[:token]
stripe_account.save
flash[:success] = "Your bank account has been added!"
redirect_to dashboard_path
rescue Stripe::StripeError => e
# handler_for_rescue(e.message, 'new')
flash[:error] = e.message
# Handle any other exceptions
rescue => e
# handle_error(e.message, 'new')
flash[:error] = e.message
end
end
end
In the form, I also pass the following which may or may not be needed, I will do testing on this later on after i post this.:
<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
<%= hidden_field_tag :stripeToken, current_user.stripe_token -%>
I don't believe :stripeToken is needed... but auth is
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
So it looks like the JS was to blame. It was somewhat wrong and out of date, and a few things weren't matched up with my controller.
Here's the correct JS for S v3
JS on view page (i believe this NEEDS TO BE UNDER the form; could be wrong):
var stripe = Stripe('pk_test_WUSo123456789PWU8kh');
function setOutcome(result) {
var successElement = document.querySelector('.success');
var errorElement = document.querySelector('.error');
successElement.classList.remove('visible');
errorElement.classList.remove('visible');
if (result.token) {
// In this example, we're simply displaying the token
successElement.querySelector('.token').textContent = result.token.id;
successElement.classList.add('visible');
// In a real integration, you'd submit the form with the token to your backend server
var form = document.querySelector('form');
form.querySelector('input[name="token"]').setAttribute('value', result.token.id);
form.submit();
} else {
errorElement.textContent = result.error.message;
errorElement.classList.add('visible');
}
}
document.querySelector('form').addEventListener('submit', function(e) {
e.preventDefault();
var bankAccountParams = {
country: document.getElementById('country').value,
currency: document.getElementById('currency').value,
account_number: document.getElementById('account-number').value,
account_holder_name: document.getElementById('account-holder-name').value,
account_holder_type: document.getElementById('account-holder-type').value,
}
if (document.getElementById('routing-number').value != '') {
bankAccountParams['routing_number'] = document.getElementById('routing-number').value;
}
stripe.createToken('bank_account', bankAccountParams).then(setOutcome);
});
And the correct Create for the BankAccount controller:
(or this at least works, i may be fixing this up a bit after this)
def create
unless params[:token] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
begin
token = params[:token]
stripe_account.external_account = params[:token]
stripe_account.save
flash[:success] = "Your bank account has been added!"
redirect_to dashboard_path
rescue Stripe::StripeError => e
# handler_for_rescue(e.message, 'new')
flash[:error] = e.message
# Handle any other exceptions
rescue => e
# handle_error(e.message, 'new')
flash[:error] = e.message
end
end
end
In the form, I also pass the following which may or may not be needed, I will do testing on this later on after i post this.:
<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
<%= hidden_field_tag :stripeToken, current_user.stripe_token -%>
I don't believe :stripeToken is needed... but auth is
add a comment |
up vote
0
down vote
accepted
So it looks like the JS was to blame. It was somewhat wrong and out of date, and a few things weren't matched up with my controller.
Here's the correct JS for S v3
JS on view page (i believe this NEEDS TO BE UNDER the form; could be wrong):
var stripe = Stripe('pk_test_WUSo123456789PWU8kh');
function setOutcome(result) {
var successElement = document.querySelector('.success');
var errorElement = document.querySelector('.error');
successElement.classList.remove('visible');
errorElement.classList.remove('visible');
if (result.token) {
// In this example, we're simply displaying the token
successElement.querySelector('.token').textContent = result.token.id;
successElement.classList.add('visible');
// In a real integration, you'd submit the form with the token to your backend server
var form = document.querySelector('form');
form.querySelector('input[name="token"]').setAttribute('value', result.token.id);
form.submit();
} else {
errorElement.textContent = result.error.message;
errorElement.classList.add('visible');
}
}
document.querySelector('form').addEventListener('submit', function(e) {
e.preventDefault();
var bankAccountParams = {
country: document.getElementById('country').value,
currency: document.getElementById('currency').value,
account_number: document.getElementById('account-number').value,
account_holder_name: document.getElementById('account-holder-name').value,
account_holder_type: document.getElementById('account-holder-type').value,
}
if (document.getElementById('routing-number').value != '') {
bankAccountParams['routing_number'] = document.getElementById('routing-number').value;
}
stripe.createToken('bank_account', bankAccountParams).then(setOutcome);
});
And the correct Create for the BankAccount controller:
(or this at least works, i may be fixing this up a bit after this)
def create
unless params[:token] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
begin
token = params[:token]
stripe_account.external_account = params[:token]
stripe_account.save
flash[:success] = "Your bank account has been added!"
redirect_to dashboard_path
rescue Stripe::StripeError => e
# handler_for_rescue(e.message, 'new')
flash[:error] = e.message
# Handle any other exceptions
rescue => e
# handle_error(e.message, 'new')
flash[:error] = e.message
end
end
end
In the form, I also pass the following which may or may not be needed, I will do testing on this later on after i post this.:
<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
<%= hidden_field_tag :stripeToken, current_user.stripe_token -%>
I don't believe :stripeToken is needed... but auth is
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
So it looks like the JS was to blame. It was somewhat wrong and out of date, and a few things weren't matched up with my controller.
Here's the correct JS for S v3
JS on view page (i believe this NEEDS TO BE UNDER the form; could be wrong):
var stripe = Stripe('pk_test_WUSo123456789PWU8kh');
function setOutcome(result) {
var successElement = document.querySelector('.success');
var errorElement = document.querySelector('.error');
successElement.classList.remove('visible');
errorElement.classList.remove('visible');
if (result.token) {
// In this example, we're simply displaying the token
successElement.querySelector('.token').textContent = result.token.id;
successElement.classList.add('visible');
// In a real integration, you'd submit the form with the token to your backend server
var form = document.querySelector('form');
form.querySelector('input[name="token"]').setAttribute('value', result.token.id);
form.submit();
} else {
errorElement.textContent = result.error.message;
errorElement.classList.add('visible');
}
}
document.querySelector('form').addEventListener('submit', function(e) {
e.preventDefault();
var bankAccountParams = {
country: document.getElementById('country').value,
currency: document.getElementById('currency').value,
account_number: document.getElementById('account-number').value,
account_holder_name: document.getElementById('account-holder-name').value,
account_holder_type: document.getElementById('account-holder-type').value,
}
if (document.getElementById('routing-number').value != '') {
bankAccountParams['routing_number'] = document.getElementById('routing-number').value;
}
stripe.createToken('bank_account', bankAccountParams).then(setOutcome);
});
And the correct Create for the BankAccount controller:
(or this at least works, i may be fixing this up a bit after this)
def create
unless params[:token] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
begin
token = params[:token]
stripe_account.external_account = params[:token]
stripe_account.save
flash[:success] = "Your bank account has been added!"
redirect_to dashboard_path
rescue Stripe::StripeError => e
# handler_for_rescue(e.message, 'new')
flash[:error] = e.message
# Handle any other exceptions
rescue => e
# handle_error(e.message, 'new')
flash[:error] = e.message
end
end
end
In the form, I also pass the following which may or may not be needed, I will do testing on this later on after i post this.:
<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
<%= hidden_field_tag :stripeToken, current_user.stripe_token -%>
I don't believe :stripeToken is needed... but auth is
So it looks like the JS was to blame. It was somewhat wrong and out of date, and a few things weren't matched up with my controller.
Here's the correct JS for S v3
JS on view page (i believe this NEEDS TO BE UNDER the form; could be wrong):
var stripe = Stripe('pk_test_WUSo123456789PWU8kh');
function setOutcome(result) {
var successElement = document.querySelector('.success');
var errorElement = document.querySelector('.error');
successElement.classList.remove('visible');
errorElement.classList.remove('visible');
if (result.token) {
// In this example, we're simply displaying the token
successElement.querySelector('.token').textContent = result.token.id;
successElement.classList.add('visible');
// In a real integration, you'd submit the form with the token to your backend server
var form = document.querySelector('form');
form.querySelector('input[name="token"]').setAttribute('value', result.token.id);
form.submit();
} else {
errorElement.textContent = result.error.message;
errorElement.classList.add('visible');
}
}
document.querySelector('form').addEventListener('submit', function(e) {
e.preventDefault();
var bankAccountParams = {
country: document.getElementById('country').value,
currency: document.getElementById('currency').value,
account_number: document.getElementById('account-number').value,
account_holder_name: document.getElementById('account-holder-name').value,
account_holder_type: document.getElementById('account-holder-type').value,
}
if (document.getElementById('routing-number').value != '') {
bankAccountParams['routing_number'] = document.getElementById('routing-number').value;
}
stripe.createToken('bank_account', bankAccountParams).then(setOutcome);
});
And the correct Create for the BankAccount controller:
(or this at least works, i may be fixing this up a bit after this)
def create
unless params[:token] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
begin
token = params[:token]
stripe_account.external_account = params[:token]
stripe_account.save
flash[:success] = "Your bank account has been added!"
redirect_to dashboard_path
rescue Stripe::StripeError => e
# handler_for_rescue(e.message, 'new')
flash[:error] = e.message
# Handle any other exceptions
rescue => e
# handle_error(e.message, 'new')
flash[:error] = e.message
end
end
end
In the form, I also pass the following which may or may not be needed, I will do testing on this later on after i post this.:
<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
<%= hidden_field_tag :stripeToken, current_user.stripe_token -%>
I don't believe :stripeToken is needed... but auth is
answered Nov 12 at 8:40
uno
579
579
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53246837%2fadding-bank-account-data-to-stripe-not-saving-to-api-or-database-table%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Because you are getting an error like "must be a dictionary or a non-empty string" , I suspect your bank account token is never getting passed to your back-end at all --- in fact i don't see it in the log you shared
Parameters: {"authenticity_token"=>"l69UBGkzwcel7JH34+TDbsfQ9Xjkiogu+emWm+8+0iVQfKh9AIxDaXp0yMhjFkUVznHeJYwXeVmdBVSI2XjArg=="}
--- try adding some debugging to your JS --- console.logs in your stripeResponseHandler, a breakpoint before the form submit (check that a hidden stripeToken input really exists in your form using browser dev tools inspector)– duck
Nov 11 at 19:54
I added the Browser Console when i press submit. Other than that, do you think the rest of the code is okay?
– uno
Nov 11 at 23:56
BTW, "check that a hidden stripetoken input exists"... is that something I'll see in the Browser console...? and in the update, it's not there if so?
– uno
Nov 12 at 0:20
So it looks like, from what i understand, is the JS is for Stripe V2 and not Stripe V3 you can see the differences here: V2:stripe.com/docs/stripe-js/v2#collecting-bank-account-details ----V3:stripe.com/docs/stripe-js/… ----- so im trying to migrate it over to v3
– uno
Nov 12 at 2:53