I'm building a two sided marketplace, where users are paid out when an item of theirs, sells.
I have a form that a user fills out when wanting to list an item on the marketplace. It includes many inputs, but the important ones for this question are the Stripe COUNTRY, ACCOUNT, and ROUTING inputs. This is so that they can be paid automatically after their items sells.
I'm storing a Stripe recipient ID in the user database, so that they don't have to enter their bank account info every time they post a new item. (Which can be seen in the #create action) Everything that I'm about to post below works perfectly, BUT ONLY ONCE. After posting an item the first time, the user Recipient ID successfully saves to my user database. BUT, if that user attempts to post another item, I get a Stripe error, saying that: "You must supply either a card, customer, or bank account to create a token.", when attempting to submit the form. This error is shown in my Stripe dashboard as well.
I am under the assumption that is has to do with Strong Params? At first, I did not have :Country, :Routing_number, or :Account_number in the params in the listing_controller, so I have added them in, but it did not fix the error. Am I close? Can anyone spot what I'm doing wrong?
_FORM.HTML.ERB:
<%= form_for @listing, :html => { :multipart => true } do |f| %>
<% if @listing.errors.any? %>
<div id="error_explanation" class="alert alert-danger alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">× </button>
<h2><%= pluralize(@listing.errors.count, "error") %> prohibited this listing from being saved:</h2>
<ul>
<% @listing.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div id="stripe_error" class="alert alert-danger" style="display:none">
<noscript> Javascript is disabled. Order cannot be placed. First enable it in your browser.</noscript>
<% if current_user.recipient.blank? %>
<br>
<h1>Bank Account Information</h1>
<p class="sm-message">(You'll only need to enter this once.)</p>
<div class="form-group">
<%= label_tag :country %>
<%= text_field_tag :country, nil, { :name => nil, :'data-stripe' => "country", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :routing_number %>
<%= text_field_tag :routing_number, nil, { :name => nil, :'data-stripe' => "routingNumber", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :account_number %>
<%= text_field_tag :account_number, nil, { :name => nil, :'data-stripe' => "accountNumber", class: "form-control" } %>
</div>
<% end %>
<div class="form-group">
<%= f.submit class: "btn btn-primary btn-lg" %>
</div>
<% end %>
</div>
LISTING_CONTROLLER.RB
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, only: [:seller, :new, :create, :edit, :update, :destroy]
before_filter :check_user, only: [:edit, :update, :destroy]
def seller
@listings = Listing.where(user: current_user).order("created_at DESC")
end
# GET /listings
# GET /listings.json
def index
@listings = Listing.all.order("created_at DESC")
end
# GET /listings/1
# GET /listings/1.json
def show
end
# GET /listings/new
def new
@listing = Listing.new
end
# GET /listings/1/edit
def edit
end
# POST /listings
# POST /listings.json
def create
@listing = Listing.new(listing_params)
@listing.user_id = current_user.id
if current_user.recipient.blank?
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
recipient = Stripe::Recipient.create(
:name => current_user.name,
:type => "individual",
:bank_account => token
)
current_user.recipient = recipient.id
current_user.save
end
respond_to do |format|
if @listing.save
format.html { redirect_to @listing, notice: 'Listing was successfully created.' }
format.json { render :show, status: :created, location: @listing }
else
format.html { render :new }
format.json { render json: @listing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /listings/1
# PATCH/PUT /listings/1.json
def update
respond_to do |format|
if @listing.update(listing_params)
format.html { redirect_to @listing, notice: 'Listing was successfully updated.' }
format.json { render :show, status: :ok, location: @listing }
else
format.html { render :edit }
format.json { render json: @listing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /listings/1
# DELETE /listings/1.json
def destroy
@listing.destroy
respond_to do |format|
format.html { redirect_to listings_url, notice: 'Listing was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing
@listing = Listing.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_params
params.require(:listing).permit(:name, :description, :price, :duration, :street, :city, :state, :image, :duration, :category, :terms,
:country, :account_number, :routing_number, :stripeToken)
end
def check_user
if current_user != @listing.user
redirect_to root_url, alert: "Sorry, that is not your listing."
end
end
end
LISTING.JS.COFFEE
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
listing.setupForm()
listing =
setupForm: ->
$('#new_listing').submit ->
if $('input').length > 8
$('input[type=submit]').attr('disabled', true)
Stripe.bankAccount.createToken($('#new_listing'), listing.handleStripeResponse)
false
handleStripeResponse: (status, response) ->
if status == 200
$('#new_listing').append($('<input type="hidden" name="stripeToken" />').val(response.id))
$('#new_listing')[0].submit()
else
$('#stripe_error').text(response.error.message).show()
$('input[type=submit]').attr('disabled', false)
STRIPE DASHBOARD INFORMATION BEING RETURNED:
key: "pk_test_WgTil6dDhXN6JqzqZI4Gjw0M"
callback: "sjsonp1404518718631"
_method: "POST"
error:
type: "invalid_request_error"
message: "You must supply either a card, customer, or bank account to create a token."
<% end %>
that isn't closing anything. That<% end %>
will break things. I'd start there unless it's a typo. – colinm