Question

in my app I am using the 'Stripe' gem to setup payments. Everything was going fine but whenever I submit the payment it gives me the error 'You must supply a valid card'. Below is my code.

Ad Controller

class AdsController < ApplicationController
  before_action :set_ad, only: [:show, :edit, :update, :destroy]


  # GET /ads
  # GET /ads.json
  def index
    @ads = Ad.order('created_at DESC').search(params[:search])
    @ads_small = Ad.where(:size => "small").order('created_at DESC')
    @ads_medium = Ad.where(:size => "medium").order('created_at DESC')
    @ads_featured = Ad.where(:size => "featured").order('created_at DESC')

  end

  def myads
    @ads_mine = Ad.where(:user_id => current_user.id )
  end

  # GET /ads/1
  # GET /ads/1.json
  def show
  end

  # GET /ads/new
  def new
    @ad = Ad.new
  end

  # GET /ads/1/edit
  def edit
  end

  # POST /ads
  # POST /ads.json
  def create
    @ad = Ad.new(ad_params)
    @ad.user_id = current_user.id

    respond_to do |format|
      if @ad.save_with_payment
        format.html { redirect_to @ad, notice: 'Ad was successfully created.' }
        format.json { render action: 'show', status: :created, location: @ad }
      else
        format.html { render action: 'new' }
        format.json { render json: @ad.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /ads/1
  # PATCH/PUT /ads/1.json
  def update
    respond_to do |format|
      if @ad.update(ad_params)
        format.html { redirect_to @ad, notice: 'Ad was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @ad.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /ads/1
  # DELETE /ads/1.json
  def destroy
      @ad.destroy
      respond_to do |format|
        format.html { redirect_to ads_url }
        format.json { head :no_content }
      end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_ad
      @ad = Ad.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def ad_params
      params.require(:ad).permit(:title, :url, :preview, :location, :size, :info, :search)
    end
end

Ad Model

class Ad < ActiveRecord::Base

    belongs_to :user
  has_attached_file :preview, :styles => { :medium => "125x125^", :featured => "250x250^", :showpg => "400x400^" }, :convert_options => {:medium => "-gravity center -extent 125x125", :featured => "-gravity center -extent 250x250", :showpg => "-gravity center -extent 400x400"}

  validates :title, length: { maximum: 35 }
  validates :url, length: { maximum: 40 }

  attr_accessor :stripe_card_token

  def self.search(search)
  if search
    find(:all, :conditions => ['LOWER(title) ILIKE ? or LOWER(info) ILIKE ? or LOWER(location) ILIKE ?', ("%#{search.downcase}%"), ("%#{search.downcase}%"), ("%#{search.downcase}%")])
  else
    find(:all)
  end
  end

  def save_with_payment
    if valid?
      customer = Stripe::Customer.create(description: "ad stripe customer", plan: "ad_f", card: stripe_card_token)
      self.stripe_customer_token = customer.id
      save!
    end
  end
end

ads.js.coffee

# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/

jQuery ->
  Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
  ad.setupForm()

 ad = 
    setupForm: ->
        $('#new_ad').submit ->
            $('input[type=submit]').attr('disabled', true)
            ad.processCard()
            false

    processCard: ->
      card =
       number: $('#card_number').val()
       cvc: $('#card_code').val()
       expMonth: $('#card_month').val()
       expYear: $('#card_year').val()
      Stripe.createToken(card, ad.handleStripeResponse)

  handleStripeResponse: (status, response) ->
    if status == 200
        $('#ad_stripe_card_token').val(response.id)
        $('#new_ad')[0].submit()
    else
        alert(response.error.message)
        $('input[type=submit]').attr('disabled', false)

Any help would be greatly appreciated. :)

Était-ce utile?

La solution

In your Ad model, you have:

attr_accessor :stripe_card_token

and then you use the token in save_with_payment:

customer = Stripe::Customer.create(..., card: stripe_card_token)
self.stripe_customer_token = customer.id

So far so good. But you use ad_params to filter params in your controller when you create your Ad:

def ad_params
  params.require(:ad).permit(:title, :url, :preview, :location, :size, :info, :search)
end

and I don't see :stripe_card_token in the permitted list anywhere. Presumably the #ad_stripe_card_token in your HTML looks like this:

<input type="hidden" name="ad[stripe_card_token]">

so you should be able to add :stripe_card_token to the permitted list in ad_params and get things going.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top