Receiving GUID Null Status on create for Payola Stripe Subscription Model

111 views Asked by At

I'm having trouble figuring out why I am receiving {"guid":null,"status":"pending","error":"Email can't be blank"} after I attempt to create a user. Even though, all of the input fields are correct. I cannot get past this point. My server log information is below. Can you help me figure out what the problem is? Lastly, the user is actually saved to the database, but I get a blank screen right after creating one...It doesn't redirect to the target controller. I have a mailing job hooked to the user create model that is meant to fire off an email to the new user. On Stripe, it says I have no active subscribers, even though the user was created. I added the registrations_controller below. I'm trying not to break the code while manipulating the logic.

Plan.rb

class Plan < ApplicationRecord
  include Payola::Plan

  has_many :users
  validates :stripe_id, inclusion: {in: Plan.pluck('DISTINCT stripe_id'),
  message: 'not a valid subscription plan'}

  def redirect_path(subscription)
    '/'
  end
end

User.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  enum role: [:user, :admin, :full_suite, :ultimate]
  after_initialize :set_default_role, :if => :new_record?
  after_initialize :set_default_plan, :if => :new_record?
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  after_initialize :create_login, :if => :new_record?
  # after_create :sign_up_for_mailing_list
  has_many :clients
  has_many :client_profiles

  belongs_to :plan
  validates_associated :plan
  attr_accessor :login
  has_one :user_profile
  before_create :build_user_profile
  accepts_nested_attributes_for :user_profile
  validate :validate_username
  validates :terms_and_conditions, acceptance: true

  validates :username,
            :presence => true,
            :uniqueness => {
                :case_sensitive => false
            }
  validates_associated :plan

  def set_default_role
    self.role ||= :user
  end

  def set_default_plan
    self.plan ||= Plan.last
  end

  def sign_up_for_mailing_list
    MailingListSignupJob.perform_later(self)
  end

  def validate_username
    if User.where(email: username).exists?
      errors.add(:username, :invalid)
    end
  end

  def subscribe
    mailchimp = Gibbon::Request.new(api_key: Rails.application.secrets.mailchimp_api_key)
    list_id = Rails.application.secrets.mailchimp_list_id
    result = mailchimp.lists(list_id).members.create(
        body: {
            email_address: self.email,
            status: 'subscribed'
        })
    Rails.logger.info("Subscribed #{self.email} to MailChimp") if result
  end

  def create_login
    if self.username.blank?
      email = self.email.split(/@/)
      login_taken = User.where(:username => email[0]).first
      unless login_taken
        self.username = email[0]
      else
        self.username = self.email
      end
    end
  end

  def self.find_first_by_auth_conditions(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:login)
      where(conditions).where(["lower(username) = :value OR lower(email) = :value", {:value => login.downcase}]).first
    else
      if conditions[:username].nil?
        where(conditions).first
      else
        where(username: conditions[:username]).first
      end
    end
  end
end

Server Log

Started POST "/" for 127.0.0.1 at 2017-03-02 21:33:09 -0500
Processing by Users::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"cZqJL55nm/CDUEoe4K+opEtIG/hS+eztoIOCoH85KsTbKBRQgz41YKcszUnD2uwlrqzrtUE2L6ENPzRikfcDcQ==", "user"=>{"plan_id"=>"2", "email"=>"[email protected]", "username"=>"TestDoctor100", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "full_name"=>"David Wright", "terms_and_conditions"=>"1"}, "commit"=>"Sign up"}
Plan Load (0.0ms) SELECT "plans".* FROM "plans" WHERE "plans"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
CACHE (0.0ms) SELECT "plans".* FROM "plans" WHERE "plans"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
(1.0ms) begin transaction
User Exists (1.0ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "[email protected]"], ["LIMIT", 1]]
Plan Exists (0.0ms) SELECT 1 AS one FROM "plans" WHERE "plans"."stripe_id" = ? AND ("plans"."id" != ?) LIMIT ? [["stripe_id", "ultimate_suite"], ["id", 2], ["LIMIT", 1]]
User Exists (0.0ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "TestDoctor100"], ["LIMIT", 1]]
User Exists (15.8ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."username") = LOWER(?) LIMIT ? [["username", "TestDoctor100"], ["LIMIT", 1]]
Plan Exists (0.0ms) SELECT 1 AS one FROM "plans" WHERE "plans"."stripe_id" = ? AND ("plans"."id" != ?) LIMIT ? [["stripe_id", "ultimate_suite"], ["id", 2], ["LIMIT", 1]]
SQL (2.0ms) INSERT INTO "users" ("email", "username", "encrypted_password", "created_at", "updated_at", "plan_id", "full_name") VALUES (?, ?, ?, ?, ?, ?, ?) [["email", "[email protected]"], ["username", "TestDoctor100"], ["encrypted_password", "$2a$11$fvyCFGmPyaMHKLrJgU9C.eccFiyyIuP/CxoIZsqJNUZ2KTI8qdbSS"], ["created_at", 2017-03-03 02:33:10 UTC], ["updated_at", 2017-03-03 02:33:10 UTC], ["plan_id", 2], ["full_name", "David Wright"]]
SQL (1.0ms) INSERT INTO "user_profiles" ("user_id", "created_at", "updated_at") VALUES (?, ?, ?) [["user_id", 2], ["created_at", 2017-03-03 02:33:10 UTC], ["updated_at", 2017-03-03 02:33:10 UTC]]
(98.4ms) commit transaction
(0.0ms) begin transaction
SQL (2.0ms) UPDATE "users" SET "sign_in_count" = ?, "current_sign_in_at" = ?, "last_sign_in_at" = ?, "current_sign_in_ip" = ?, "last_sign_in_ip" = ?, "updated_at" = ? WHERE "users"."id" = ? [["sign_in_count", 1], ["current_sign_in_at", 2017-03-03 02:33:10 UTC], ["last_sign_in_at", 2017-03-03 02:33:10 UTC], ["current_sign_in_ip", "127.0.0.1"], ["last_sign_in_ip", "127.0.0.1"], ["updated_at", 2017-03-03 02:33:10 UTC], ["id", 2]]
(98.5ms) commit transaction
(0.0ms) begin transaction
Payola::Subscription Exists (0.0ms) SELECT 1 AS one FROM "payola_subscriptions" WHERE "payola_subscriptions"."guid" IS NULL LIMIT ? [["LIMIT", 1]]
(0.0ms) rollback transaction
(0.0ms) begin transaction
Plan Exists (0.0ms) SELECT 1 AS one FROM "plans" WHERE "plans"."stripe_id" = ? AND ("plans"."id" != ?) LIMIT ? [["stripe_id", "ultimate_suite"], ["id", 2], ["LIMIT", 1]]
User Exists (0.0ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "TestDoctor100"], ["LIMIT", 1]]
User Exists (0.0ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."username") = LOWER(?) AND ("users"."id" != ?) LIMIT ? [["username", "TestDoctor100"], ["id", 2], ["LIMIT", 1]]
Plan Exists (0.0ms) SELECT 1 AS one FROM "plans" WHERE "plans"."stripe_id" = ? AND ("plans"."id" != ?) LIMIT ? [["stripe_id", "ultimate_suite"], ["id", 2], ["LIMIT", 1]]
(0.0ms) commit transaction
Completed 400 Bad Request in 1441ms (Views: 0.3ms | ActiveRecord: 223.7ms)

registrations_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController
  include Payola::StatusBehavior
  before_action :cancel_subscription, only: [:destroy]
  def new
    build_resource({})
    unless params[:plan].nil?
      @plan = Plan.find_by!(stripe_id: params[:plan])
      resource.plan = @plan
    end
    yield resource if block_given?
    respond_with self.resource
  end

  def create
    build_resource(sign_up_params)
    plan = Plan.find_by!(id: params[:user][:plan_id].to_i)
    resource.role = User.roles[plan.stripe_id] unless resource.admin?
    resource.save
    yield resource if block_given?
    if resource.persisted?
      if resource.active_for_authentication?
        set_flash_message :notice, :signed_up if is_flashing_format?
        sign_up(resource_name, resource)
        subscribe
      else
        set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
        expire_data_after_sign_in!
        subscribe
      end
    else
      clean_up_passwords resource
      render json:
          {error: resource.errors.full_messages.to_sentence},
          status: 400
    end
  end

  def change_plan
    plan = Plan.find_by!(id: params[:user][:plan_id].to_i)
    unless plan == current_user.plan
      role = User.roles[plan.stripe_id]
      if current_user.update_attributes!(plan: plan, role: role)
        subscription = Payola::Subscription.find_by!(owner_id: current_user.id)
        Payola::ChangeSubscriptionPlan.call(subscription, plan)
        redirect_to edit_user_registration_path, :notice => "Plan changed."
      else
        flash[:alert] = 'Unable to change plan.'
        build_resource
        render :edit
      end
    end
  end

  private
  def subscribe
     return if resource.admin?
params[:plan] = current_user.plan
params[:stripeEmail] = current_user.email
subscription = Payola::CreateSubscription.call(params, current_user)
current_user.save
render_payola_status(subscription)
  end

  def sign_up_params
    params.require(:user).permit(:email, :password, :password_confirmation, :plan_id, :terms_and_conditions, :full_name)
  end

  def cancel_subscription
    subscription = Payola::Subscription.find_by!(owner_id: current_user.id, state: 'active')
    Payola::CancelSubscription.call(subscription)
  end

  def update_card
    @subscription = Subscription.find_by!(guid: params[:guid])
    Payola::UpdateCard.call(@subscription, params[:stripeToken])

    confirm_with_message("Card updated")
  end

  protected
  def after_sign_up_path_for(resource)
    authenticated_root_path(resource)
  end

  def after_update_path_for(resource)
    user_path(resource)
  end
end

payola.rb

 config.secret_key = Rails.application.secrets.stripe_api_key
  config.publishable_key = Rails.application.secrets.stripe_publishable_key
  Payola.subscribe 'customer.subscription.deleted' do |event|
    sale = Sale.find_by(stripe_id: event.data.object.id)
    user = User.find_by(email: sale.email)
    UserMailer.expire_email(user).deliver
    user.destroy
  end

  config.subscribe 'charge.refunded' do |event|
    sale = Payola::Sale.find_by(stripe_id: event.data.object.id)
    sale.refund! unless sale.refunded?
  end
1

There are 1 answers

0
Eliot Sykes On

The response is:

{"guid":null,"status":"pending","error":"Email can't be blank"}

This can happen when params[:stripeEmail] is not submitted in the request.

Payola's CreateSubscription assumes the email is available as params[:stripeEmail]:

module Payola
  class CreateSubscription
    def self.call(params, owner=nil)
      ...

      if params[:stripe_customer_id].present?
        ...
      else
        email = params[:stripeEmail]
      end

      sub = Payola::Subscription.new do |s|
        s.plan = plan
        s.email = email
        ...
      end

      ...

    end
  end
end

Try adding a stripeEmail field to the registration form.