Austin Drysdale

Joined

490 Experience
4 Lessons Completed
0 Questions Solved

Activity

Posted in Stripe Elements Javascript Discussion

To anyone having this same problem, and since Chris doesn't seem to respond to this video's comments. If you are using form_with to render the form, you must add local: true to it. As form_with automatically uses remote: true to submit via XMLHttpRequest. This should stop your server from double submitting.

Posted in Server submitting customer twice to Stripe API

Hi,

I'm following Chris's Stripe Elements and Stripe Subscriptions tutorials. Currently Stripe Elements is working perfectly, but while following the subscriptions tutorial after I create the customer in the controller. Stripe is receiving 2 requests for my customer creation (3 requests total for getting the source token) and is creating one customer with the card information and one without the card information. Oddly enough both are receiving the email associated with that customer from Devise and I receive the correct one (with card details) in the customer variable. The only major differences I made from the tutorials is I converted the Stripe Elements js to coffee. I tried removing the submit action on the stripeTokenHandler function so it doesn't submit the token to the server. But it still creates one customer without card details.

Here's my code. Any help would be appreciated.

Coffee File

stripeTokenHandler = (token) ->
  # Insert the token ID into the form so it gets submitted to the server
  form = document.getElementById('payment-form')
  hiddenInput = document.createElement('input')
  hiddenInput.setAttribute 'type', 'hidden'
  hiddenInput.setAttribute 'name', 'stripeToken'
  hiddenInput.setAttribute 'value', token.id
  form.appendChild hiddenInput
  [
    'brand'
    'exp_month'
    'exp_year'
    'last4'
  ].forEach (field) ->
    addFieldToForm form, token, field
    return
  console.log token
  # Submit the form
  form.submit()
  return

addFieldToForm = (form, token, field) ->
  hiddenInput = document.createElement('input')
  hiddenInput.setAttribute 'type', 'hidden'
  hiddenInput.setAttribute 'name', 'card_' + field
  hiddenInput.setAttribute 'value', token.card[field]
  form.appendChild hiddenInput
  return

document.addEventListener 'turbolinks:load', ->
  public_key = document.querySelector('meta[name=\'stripe-public-key\']').content
  stripe = Stripe(public_key)
  elements = stripe.elements()
  # Custom styling can be passed to options when creating an Element.
  style = base:
    fontSize: '16px'
    color: '#32325d'
  # Create an instance of the card Element.
  card = elements.create('card', style: style)
  # Add an instance of the card Element into the `card-element` <div>.
  card.mount '#card-element'
  card.addEventListener 'change', (event) ->
    displayError = document.getElementById('card-errors')
    if event.error
      displayError.textContent = event.error.message
    else
      displayError.textContent = ''
    return
  # Create a token or display an error when the form is submitted.
  form = document.getElementById('payment-form')
  form.addEventListener 'submit', (event) ->
    event.preventDefault()
    stripe.createToken(card).then (result) ->
      if result.error
        # Inform the customer that there was an error.
        errorElement = document.getElementById('card-errors')
        errorElement.textContent = result.error.message
      else
        # Send the token to your server.
        stripeTokenHandler result.token
      return
    return
  return

Controller

class ChargesController < ApplicationController
  before_action :authenticate_user!, only: [:show, :new, :create]
  before_action :set_user, only: [:create]

  def show
  end

  def new
  end

  def create
    customer = Stripe::Customer.create({
      source: params[:stripeToken],
      email: @user.email
      })

    raise customer
  end

  private

    def set_user
      @user = current_user
    end

end

View:

<%= form_with url: charges_path, id: 'payment-form' do |form| %>
  <div class="form-row">
    <label for="card-element">
      Credit or debit card
    </label>
    <div id="card-element">
      <!-- A Stripe Element will be inserted here. -->
    </div>

    <!-- Used to display Element errors. -->
    <div id="card-errors" role="alert"></div>
  </div>

  <button>Submit Payment</button>
<% end %>

Any thoughts?

Posted in Stripe Elements Javascript Discussion

Hi Chris,

I'm following your Stripe Elements and Stripe Subscriptions tutorials. Currently Stripe Elements is working perfectly, but while following the subscriptions tutorial after I create the customer in the controller. Stripe is receiving 2 requests for my customer creation (3 requests total for getting the source token) and is creating one customer with the card information and one without the card information. Oddly enough both are receiving the email associated with that customer from Devise and I receive the correct one (with card details) in the customer variable. The only major differences I made from the tutorials is I converted the Stripe Elements js to coffee. I tried removing the submit action on the stripeTokenHandler function so it doesn't submit the token to the server. But it still creates one customer without card details.

Here's my code. Any help would be appreciated.

Coffee File

stripeTokenHandler = (token) ->
  # Insert the token ID into the form so it gets submitted to the server
  form = document.getElementById('payment-form')
  hiddenInput = document.createElement('input')
  hiddenInput.setAttribute 'type', 'hidden'
  hiddenInput.setAttribute 'name', 'stripeToken'
  hiddenInput.setAttribute 'value', token.id
  form.appendChild hiddenInput
  [
    'brand'
    'exp_month'
    'exp_year'
    'last4'
  ].forEach (field) ->
    addFieldToForm form, token, field
    return
  console.log token
  # Submit the form
  form.submit()
  return

addFieldToForm = (form, token, field) ->
  hiddenInput = document.createElement('input')
  hiddenInput.setAttribute 'type', 'hidden'
  hiddenInput.setAttribute 'name', 'card_' + field
  hiddenInput.setAttribute 'value', token.card[field]
  form.appendChild hiddenInput
  return

document.addEventListener 'turbolinks:load', ->
  public_key = document.querySelector('meta[name=\'stripe-public-key\']').content
  stripe = Stripe(public_key)
  elements = stripe.elements()
  # Custom styling can be passed to options when creating an Element.
  style = base:
    fontSize: '16px'
    color: '#32325d'
  # Create an instance of the card Element.
  card = elements.create('card', style: style)
  # Add an instance of the card Element into the `card-element` <div>.
  card.mount '#card-element'
  card.addEventListener 'change', (event) ->
    displayError = document.getElementById('card-errors')
    if event.error
      displayError.textContent = event.error.message
    else
      displayError.textContent = ''
    return
  # Create a token or display an error when the form is submitted.
  form = document.getElementById('payment-form')
  form.addEventListener 'submit', (event) ->
    event.preventDefault()
    stripe.createToken(card).then (result) ->
      if result.error
        # Inform the customer that there was an error.
        errorElement = document.getElementById('card-errors')
        errorElement.textContent = result.error.message
      else
        # Send the token to your server.
        stripeTokenHandler result.token
      return
    return
  return

Controller

class ChargesController < ApplicationController
  before_action :authenticate_user!, only: [:show, :new, :create]
  before_action :set_user, only: [:create]

  def show
  end

  def new
  end

  def create
    customer = Stripe::Customer.create({
      source: params[:stripeToken],
      email: @user.email
      })

    raise customer
  end

  private

    def set_user
      @user = current_user
    end

end

View:

<%= form_with url: charges_path, id: 'payment-form' do |form| %>
  <div class="form-row">
    <label for="card-element">
      Credit or debit card
    </label>
    <div id="card-element">
      <!-- A Stripe Element will be inserted here. -->
    </div>

    <!-- Used to display Element errors. -->
    <div id="card-errors" role="alert"></div>
  </div>

  <button>Submit Payment</button>
<% end %>

Any thoughts?

Posted in Liking Posts Discussion

Appreciate the speedy response. Thanks again.

Posted in Liking Posts Discussion

Hi Chris,

I want to ask you a question, I got stuck at the part of implementing the likes? method in the user controller. Except my method was named saved? as was my table and related files. I kept getting the error unitialized constant Item::Safe, for hours I tried to fix this and my code all seemed fine. I finally just renamed my table and related files to bookmarks instead of saves. After updating all the models, controllers, routes, ect. It worked... Do you have any insight on this? Is it possible to be a naming conflict?

Thanks in advance.

logo Created with Sketch.

Ruby on Rails tutorials, guides, and screencasts for web developers learning Ruby, Rails, Javascript, Turbolinks, Stimulus.js, Vue.js, and more. Icons by Icons8

© 2020 GoRails, LLC. All rights reserved.