Stripe::InvalidRequestError (This customer has no attached payment source) - javascript

There seems to be a problem with sending customer data and token back to Stripe's server. I'm currently using the test api to make dummy transactions. But, I cannot get past this point for no reason at all. I've tried everything to fix this error. I will post the code and error message below.
Subscriptions_Controller.rb
class SubscriptionsController < ApplicationController
before_filter :authenticate_user!, except: [:new]
before_action :redirect_to_signup, only: [:new]
def show
end
def new
#subscription = current_user.subscription
if #subscription.active
#stripe_customer = Stripe::Customer.retrieve(#subscription.stripe_user_id)
#stripe_subscription = #stripe_customer.subscription.first
end
end
def create
token = params[:stripeToken]
customer = Stripe::Customer.create(
:source => token,
:plan => "gbsubscriptionlevel1",
:email => current_user.email
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_subscription_path
current_user.subscription.stripe_user_id = customer.id
current_user.subscription.active = true
current_user.subscription.save
redirect_to users_index_path
end
def cancel_subscription
#stripe_customer = Stripe::Customer.retrieve(
current_user.subscription.stripe_user_id
)
#stripe_subscription = #stripe_customer.subscription.first
end
private
def redirect_to_signup
if !user_signed_in?
session["user_return_to"] = new_subscription_path
redirect_to new_user_registration_path
end
end
end
_stripe_form.html.erb
<div class="container">
<%= form_tag subscription_path, id: 'payment-form' do %>
<form action="/subscription" method="POST" id="payment-form">
<span class="payment-errors"></span>
<div class="row">
<div class="col-xs-4">
<label>
<span>Card Number</span>
<input value="4242 4242 4242 4242" 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 value="123" 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 value="12" class="form-control" type="text" size="2" data-stripe="exp-month" placeholder="01"/>
</div>
<div class="col-xs-1">
<label>YYYY</label>
<input value="2019" 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>
<% end %>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
</div>
subscription.js
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;
});
});
stripe.rb
Stripe.api_key = ENV["STRIPE_API_TEST_SECRET_KEY"]

That response typically arises after you try to attach a Subscription to someone with no card token attached. From your code, I'd hazard a guess that you're running into a CardError and then despite that, trying to attach a Subscription anyway, which will not work.

Related

Saving an html form to a table?

Issue: I want a way to verify if a user has already connected their bank account. What i have isn't saving to the table so i have no way to verify it from the db.
I want: I want to only save a stripe_account_id to the bankaccount table (which is a column) some way through the forms submit. Have it be unique and allowed to be overridden
This is what I have done so far:
Bank Account Controller:
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)
#bank_account = BankAccount.new
#stripe_account = StripeAccount.find(params[:stripe_account_id])
rescue Stripe::StripeError => e
handle_error(e.message, 'new')
rescue => e
flash[:error] = e.message
end
end
def create
unless params[:token] && current_user.stripe_token
redirect_to new_bank_account_path and return
end
begin
token = params[:token]
stripe_account = Stripe::Account.retrieve(current_user.stripe_token)
stripe_account.external_account = params[:token]
stripe_account.save
flash[:success] = "Your bank account has been added!"
redirect_to dashboard_path
#bank_account = BankAccount.new(bank_account_params)
#bank_account.save!
rescue Stripe::StripeError => e
flash[:error] = e.message
rescue => e
flash[:error] = e.message
end
end
private
def set_bank_account
#bank_account = BankAccount.find(params[:id])
end
def bank_account_params
params.require(:bank_account).permit()
end
end
Routes:
resources :users do
resources :stripe_accounts
end
resources :stripe_accounts do
resources :bank_accounts
end
resources :bank_accounts
Without having the resources by itself, i get an error: "no post /bank_accounts" --- before i realized i had no way to verify a user having a bankaccount connected, it wasn't nested
Here's the gist of the form:
<form action="/bank_accounts" method="POST" id="payment-form-1">
<input type="hidden" name="token" />
<label for="country">Country</label>
<select id="country" class="form-control">
<option value="US">United States</option>
<option value="ES">Spain</option>
</select>
<label for="currency">Currency</label>
<select id="currency" class="form-control">
<option value="EUR">Euro</option>
</select>
<label for="routing-number">Routing Number</label>
<input type="text" class="form-control" id="routing-number" value="110000000" />
<label for="account-number">Account Number</label>
<input type="text" class="form-control" id="account-number" value="000123456789" />
<label for="account-holder-name">Account Holder Name</label>
<input type="text" class="form-control" id="account-holder-name" />
<label for="account-holder-type">Account Holder Type</label>
<select id="account-holder-type" class="form-control">
<option value="individual">Individual</option>
<option value="company">Company</option>
</select>
<%= hidden_field_tag :authenticity_token, form_authenticity_token -%>
<%= hidden_field_tag :stripeToken, current_user.stripe_token -%>
<%= hidden_field_tag :stripe_account_id, :value => #stripe_account_id %>
<button type="submit">Submit</button>
<div class="outcome">
<div class="error"></div>
<div class="success">
Success! Your Stripe token is <span class="token"></span>
</div>
</div>
</form>
The form is then sent using javascript:
<script>
var stripe = Stripe('pk_test_W1234567qTSqQJucPWU8kh');
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);
});
</script>
Ultimately, I am simply wanting to save a reference to the bankaccount table so i know if an end user has filled out their bank account data yet and for view purposes to remind them they have already.
I would like to save to the bankaccount table the stripe_account.id (this is associated with a user in the stripeaccount table), this way ill know which users have already filled this out. (the bankaccount table has a stripe_account_id column, id, created_at, and updated_at).
Is there way to do this from the html form, from the javascript, etc.? Is my controller just wrong?
To save the external accounts ids to the database, you would need to do customer.sources.all(object: "bank_account"), then get the id of each and save it to the associated StripeAccount (I guess) associated to the user (while making sure you are duplicating ids).
https://stripe.com/docs/api/customer_bank_accounts/list
Personally I think you don't need to store the bank account ids in your database, you can just fetch it from Stripe when you need it.

django encountered with ConnectionResetError: [WinError 10054]

I am new to django and would like to write a simple log in web page
frontend: html, css, javascript(using bootstrap and jquery)
After filling the username and password and clicking the sign in button, it is supposed to jump to the home page.
Here is my code:
html:
<form id="sign-form" role="form">
{% csrf_token %}
<div class="form-group">
<label for="name" class="sr-only"> username </label>
<input id="name" type="text" class="form-control" placeholder="Username...">
</div>
<div class="form-group">
<label for="password" class="sr-only"> password </label>
<input id="password" type="password" class="form-control" placeholder="Password...">
</div>
<div class="form-group">
<button class="btn btn-block" id="sign-in-button"> Sign in </button>
</div>
<div class="form-group">
<button class="btn btn-block" id="sign-up-button"> Sign up </button>
</div>
</form>
js:
$("#sign-in-button").click(function () {
var name=$("#name").val();
var word=$("#password").val();
$.post("/login/",
{
'username': name,
'password': word
},
function (result) {
alert(result);
}
);
});
urls:
urlpatterns = [
path('admin/', admin.site.urls),
path(r'landing/', views.landing_page),
path(r'login/', views.login),
path(r'homepage/', views.home_page),
]
views:
def landing_page(request):
return render(request, "landingPage.html")
def login(request):
print("here log in")
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = auth.authenticate(username=username, password=password)
print(username+" out")
if user is not None:
auth.login(request, user)
print(username)
return render(request, "homePage.html", {'username': username})
return render(request, "homePage.html")
return render(request, "homePage.html")
But I encountered this problem(please have a look at the pictures):
The remote host forced the closure of an existing connection
The remote host forced the closure of an existing connection
The remote host forced the closure of an existing connection

Rails 4 Stripe API only working on Refresh

I thought I had the stripe API working. However when I deployed it to Heroku I found that I had to 'refresh' my page or else I would get a javascript in the console when visiting my charging form. The error was
ReferenceError: Stripe is not defined
Now when I refresh the same page this error dissapears and I can continue with my payments. I am not that knowledgeable on JS so that may be the problem I suspect. I have tried adding other stripe libraries but no avail. My code for the form is below:
<h4>Begin your $5.00 a month subscription</h4>
<form action="/users/charge" method="POST" id="payment-form">
<span class="payment-errors"></span>
<div class="row">
<div class="col-md-6">
<label>Card Number</label>
<input class="form-control" type="text" name="Card Number" size="20" data-stripe="number" placeholder="4242424242424242"/>
</div>
</div>
<br />
<div class="row">
<div class="col-xs-2">
<label>CVC</label>
<input type="text" data-stripe="cvc" class="form-control" name="CVC" placeholder="123">
</div>
</div>
<br />
<div class="row">
<div class="col-xs-2">
<label>Expiration</label>
</div>
</div>
<div class="row">
<div class="col-xs-4">
<label>MM</label>
<input type="text" data-stripe="exp-month" class="form-control" name="MM" placeholder="01">
</div>
<div class="col-xs-4">
<label>YYYY</label>
<input type="text" data-stripe="exp-year" class="form-control" name="YYYY" placeholder="2020">
</div>
</div>
<div class="row">
<div class="col-xs-4">
<br/><button class="btn btn-primary" type="submit">Create Subscription</button>
</div>
<div class="col-xs-4">
<br/>
<%= link_to image_tag("big.png"), "https://stripe.com/" %>
</div>
<div class="col-xs-4">
<br/>
<ul>
<li>Reasons To Subscribe:</li>
<li>More tutorials</li>
<li>Personal Contact with A.J.</li>
<li>Request Your own tutorials!</li>
<li>Open Source Help</li>
</ul>
</div>
</div>
<%= token_tag nil %>
</form>
<script src="https://checkout.stripe.com/checkout.js"></script>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
Stripe.setPublishableKey("<%= ENV['STRIPE_PUBLIC_KEY'] %>");
function stripeResponseHandler(status, response) {
// Grab the form:
var $form = $('#payment-form');
if (response.error) { // Problem!
// Show the errors on the form:
$form.find('.payment-errors').text(response.error.message);
$form.find('.submit').prop('disabled', false); // Re-enable submission
} else { // Token was created!
// Get the token ID:
var token = response.id;
// Insert the token ID into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="stripeToken">').val(token));
// Submit the form:
$form.get(0).submit();
}
};
$(function() {
var $form = $('#payment-form');
$form.submit(function(event) {
// Disable the submit button to prevent repeated clicks:
$form.find('.submit').prop('disabled', true);
// Request a token from Stripe:
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from being submitted:
return false;
});
});
</script>
This may be due to Turbolink
Change 'data-turbolinks-track' => false infollowing lines in your application.html.haml or application.html.erb file in views/layouts folder.
%meta{:content => "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no", :name => "viewport"}/
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => 'reload'
= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload'
= csrf_meta_tags
so your code becomes:
%meta{:content => "width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no", :name => "viewport"}/
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => false
= javascript_include_tag 'application', 'data-turbolinks-track' => false
= csrf_meta_tags
I had this right before my checkout page: <a href='/my/checkout'>Purchase Subscription</a>
I had to add data-no-turbolink='true' to the tag:
<a href='/my/checkout' data-no-turbolink='true'>Purchase Subscription</a>

Trouble creating Stripe Token: 402 (Payment Required) error

Good day everyone,
Below is the error code that is thrown in console:
(index):3 POST https://api.stripe.com/v1/tokens 402 (Payment Required)
(index):3 POST https://api.stripe.com/v1/tokens 402 (Payment Required)c # (index):3e # (index):3a # (index):3Stripe.isDoubleLoaded.Stripe.xhr # (index):3Stripe.a._rawRequest # (index):2Stripe.a.request # (index):2Stripe.token.a.create # (index):2Stripe.card.b.createToken # (index):2Stripe.a._channelListener # (index):2incoming # (index):2f # (index):2
Below is the javascript code
// Generate the user token
$(function() {
// Once the user has submited the form
$(".submit").click(function(e) {
// Prevent the form from submiting by default
e.preventDefault();
// Ensure that checkbox is checked
if($('#checkbox').is(":checked")) {
// Prevent the form from submiting by default
var $form = $('#payment-form');
// Request a token from Stripe:
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from being submitted:
return false;
}
else {
// Display an error message to the user by writting directly into the header error tag
document.getElementById('checkboxError').innerHTML = "You must kindly accept the terms and conditions to continue.";
}
});
// Ensure that checkbox is checked
if($('#checkbox').is(":checked")) {
var appendedStripeToken = false;
function stripeResponseHandler(status, response) {
// Grab the form:
var $form = $('#payment-form');
if (response.error) { // Problem!
// Scroll to the billing section
$("#billingError").scrollTop();
// Show the errors on the form:
$form.find('.payment-errors').text(response.error.message);
$form.find('.submit').prop('disabled', false); // Re-enable submission
} else { // Token was created!
// Get the token ID:
var token = response.id;
handleCall(token);
}
// What to do after the token has been generated.
function handleCall(token) {
var $form = $('#payment-form');
if (!appendedStripeToken) {
// Insert the token into the form so it gets submitted to the server
appendedStripeToken = true;
phpCall();
}
}
// Post the package name, the token, and the user name information to the billing.php page
function phpCall() {
if( appendedStripeToken === true ){
$.ajax({
type: "POST",
data: {run: true, packageName: $('#packageName').val(), token: token, userName: $('#userName').val(),customerName: $('#customerName').val() },
url: '/app/functions/billing.php',
success: function (response) {//response is value returned from php (for your example it's "bye bye"
$('#payment-form').prop('disabled', true); // TODO: give your html-submit-input-tag an "id" attribute
window.location = response;
}
});
}
}
}
}
});
Below is the HTML code
<!-- Package name to be submitted to server -->
<input type="hidden" id="packageName" value="{{ packageName|capitalize }}">
<!-- Username to be submitted to server -->
<input type="hidden" id="userName" value="{{ userName }}">
<input type="hidden" id="customerName" value="{{ customerName }}">
<div class="form-row">
<label for="cardHolder">Cardholder Name</label><br>
<input type="text" id="cardHolder" size="20" data-stripe="name">
</label>
</div>
<br><br>
<div class="form-row">
<label for="cardNumber">Card Number </label><br>
<input type="text" id="cardNumber" size="20" data-stripe="number">
</label>
</div>
<br>
<img src="/public/images/credit-card/visa.png" class="card-visa">
<img src="/public/images/credit-card/mastercard.png" class="card-mastercard">
<img src="/public/images/credit-card/american-express.png" class="card-aexpress">
<br>
<div class="form-row">
<label for="cardExpiration"> Expiration (MM/YY)</label><br>
<input class="expirationNumber" type="text" size="2" id="cardExpiration" data-stripe="exp_month">
</label>
<span> / </span>
<input class="expirationNumber" type="text" size="2" data-stripe="exp_year">
</div>
<br><br>
<div class="form-row">
<label for="cardCVC">CVC</label><br>
<input type="text" id="cardCVC" size="4" data-stripe="cvc">
</label>
</div>
</div>
</div>
<input type="checkbox" id="checkbox">
<label for="checkbox">By purchasing this package you are agreeing to our Terms & Conditions</label><br><br>
<h4 id="checkboxError"></h4>
<button type="submit" class="submit btn-tangerine">Submit Payment</button>
</form>
Any help would be greatly appreciated!
I thnk that the main error lies in the following line:
Stripe.card.createToken($form, stripeResponseHandler);
What is suppose to happen is really simple. Token gets created when all proper information are given, and then the token along with other information are posted via ajax to the server where a PHP code will create the charge using these information.
I was facing same issue when I add test API KEYS for payment, then site was working fine and when I add live key then site shows same error on console.
But problem was, I was testing live key with test credit card number. May be you were doing same mistake
And sorry for bad English.

Django JQuery AJAX submit form POST request refreshes the page

I have a login form for which I want the client to send AJAX POST request as below with error handling. In case of validation/authentication errors, I don't the page to be reloaded or refreshed to the url corresponding to POST request Handler(/users/login/) with the JSON string received from login view's response. I tried using event.preventDefault() as suggested by many answer on SO but could not make it work. Any clue as to what is going wrong here? I don't think this to be a Django issue. I know that the onsubmit is triggerred because the window redirects to the POST handler URL /users/login/ with the expected JSON string response - {"error": ["Entered mobile number is not registered"]}
JQuery code
$("#loginform").on('submit', function(event) {
event.preventDefault();
alert("Was preventDefault() called: " + event.isDefaultPrevented());
console.log("form submitted!");
var url = "/users/login/";
$.ajax({
type: "POST",
url:url,
data: $("#loginform").serialize(),
success: function(data)
{
console.log(data);
var result = JSON.stringify(data);
if(result.indexOf('errors')!=-1 ){
console.log(data);
if(data.errors[0] == "Mobile number and password don't match")
{
$('.login-error').text("Mobile number and password don't match");
}
else if(data.errors[0] == "Entered mobile number is not registered")
{
$('.login-error').text("Entered mobile number is not registered");
}
}
else
{
window.open("/users/profile/");
}
//var result = JSON.stringify(data);
// console.log(result);
}
})
});
View Handler
def login(request):
if request.method == 'POST':
mobile_number = request.POST.get('mobile_number', '')
password = request.POST.get('password', '')
data = {}
user_queryset = User.objects.filter(mobile_number=mobile_number)
if len(user_queryset) == 0:
data['error'] = []
data['error'].append("Entered mobile number is not registered")
# return JsonResponse(data)
elif len(user_queryset) == 1:
email = user_queryset[0].email
user = auth.authenticate(email=email, password=password)
if user is not None:
auth.login(request, user)
else:
data['error'] = []
data['error'].append("Mobile number and password don't match")
return JsonResponse(data)
HTML code
<div class="container-fluid bg-primary" id="login">
<div class="row">
<div class="col-lg-3 text-center">
</div>
<div class="col-lg-6 text-center">
<h1> </h1><h3> </h3>
<h2 class="section-heading">Login to your profile</h2>
<hr>
</div>
<div class="col-lg-3 text-center">
</div>
<h2> </h2>
<h2> </h2>
<h2> </h2>
</div>
<div class="col-md-4 col-md-offset-4 ">
<form id='loginform' action='/users/login/' method='post' accept-charset='UTF-8'>
{% csrf_token %}
<fieldset >
<div class="form-group">
<input type="text" name="mobile_number" id="mobile_number" tabindex="1" class="form-control" placeholder="Mobile Number" value="">
</div>
<div class="form-group">
<input type="password" name="password" id="password" tabindex="2" class="form-control" placeholder="Enter Password">
</div>
</fieldset>
<button type="submit" class="btn btn-primary btn-xl btn-block">LOG IN</button><br><br>
<span class="login-error"></span>
<h1> </h1><h1> </h1>
</form>
</div>
</div>
In addition to event.preventDefault();, it might be a good idea to also call event.stopPropagation() in this case.
Use : 'event.preventDefault()' or 'return false' after the ajax call.

Categories

Resources