Search code examples
ruby-on-railsrubymarketplace

Trying to pass/fetch data for stripe api


I'm quite new to Ruby on Rails and I have been following this tutorial on how to implement an online marketplace by using Stripe's Connect API. This tutorial guides you on how to make single item purchases, I have tried to advance myself past this tutorial and create a marketplace where a user can purchase multiple items and put them in a basket and checkout, a nice challenge as the tutorial is focused on one item. However, I am stuck on the checkout _form.html.erb.

Before, to fetch the publishable_key,

<%= form_with model: current_user, local: true, url: subscription_url, method: :post, html: { id: "payment-form", class: "stripe-form" }, **data: { stripe_key: product.user.publishable_key }**  do |form| %>

but now because I am submitting a cart full of products instead of one single item the data: { stripe_key: } is now dysfunctional. Instead, I thought it might be a good idea to do data: { stripe_key: @account.publishable_key } to fetch the publishable_key from the database but it is not working.

I am most likely forgetting something important. Any help would be sound!

http://localhost:3000/subscription/new?account=4&amount=17

The Error

NoMethodError in Subscriptions#new
Showing /Users/kaneandrewgibson/Desktop/Charlie/WOP/app/views/subscriptions/_form.html.erb where line #1 raised:

undefined method `publishable_key' for nil:NilClass

Subscriptions/_form.html.erb

<%= form_with model: current_user, local: true, url: subscription_url, method: :post, html: { id: "payment-form", class: "stripe-form" }, data: { stripe_key: @account.publishable_key }  do |form| %>
  <div>
    <label for="card-element" class="label">
      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" class="text-sm text-red-400"></div>
  </div>

  <input type="hidden" name="account" value="<%= params[:account] %>">

  <button>Back <%= number_to_currency(params[:amount]) %> /mo toward <em><%= %></em></button>
<% end %>

SubscriptionsController

class SubscriptionsController < ApplicationController
  before_action :authenticate_user!

  def new
    @account = User.find_by_id(params[:id])
  end

  # Reference:
  # https://stripe.com/docs/connect/subscriptions
  def create
    @account = User.find_by_id(params[:id])
    key = @account.user.access_code
    Stripe.api_key = key

    plan_id = params[:plan]
    plan = Stripe::Plan.retrieve(plan_id)
    token = params[:stripeToken]


    customer = if current_user.stripe_id?
                Stripe::Customer.retrieve(current_user.stripe_id)
              else
                Stripe::Customer.create(email: current_user.email, source: token)
              end

              Stripe::PaymentIntent.create({
                customer: customer,
                amount: @cart.total_price * 100,
                confirm: true,
                currency: 'gbp',
                payment_method_types: ['card'],
                application_fee_percent: 3,
              }, {
                stripe_account: 'key',
              })


    options = {
      stripe_id: customer.id,
      subscribed: true,
    }

    options.merge!(
      card_last4: params[:user][:card_last4],
      card_exp_month: params[:user][:card_exp_month],
      card_exp_year: params[:user][:card_exp_year],
      card_type: params[:user][:card_brand]
    )

    current_user.perk_subscriptions << plan_id
    current_user.update(options)

    # Update project attributes
    project_updates = {
      backings_count: @project.backings_count.next,
      current_donation_amount: @project.current_donation_amount + (plan.amount/100).to_i,
    }
    @project.update(project_updates)


    redirect_to root_path, notice: "Your subscription was setup successfully!"
  end

  def destroy
    subscription_to_remove = params[:id]
    plan_to_remove = params[:plan_id]
    customer = Stripe::Customer.retrieve(current_user.stripe_id)
    customer.subscriptions.retrieve(subscription_to_remove).delete
    current_user.subscribed = false
    current_user.perk_subscriptions.delete(plan_to_remove)
    current_user.save
    redirect_to root_path, notice: "Your subscription has been cancelled."
  end
end

Solution

  • Kane.

    It looks like your account ID isn't getting into your controller. I would expect the URL to look something like this (account_id instead of account):

    http://localhost:3000/subscription/new?account_id=4&amount=17

    And I would expect the SubscriptionsController#new to be looking in the Account model rather than the User model, and to be using the same account_id param:

    @account = Account.find_by_id(params[:account_id])