module StripeMock::RequestHandlers::Helpers

Public Instance Methods

add_card_to(type, type_id, params, objects) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/card_helpers.rb, line 104
def add_card_to(type, type_id, params, objects)
  resource = assert_existence type, type_id, objects[type_id]

  card = card_from_params(params[:card] || params[:source] || params[:external_accounts])
  add_card_to_object(type, card, resource)
end
add_card_to_object(type, card, object, replace_current=false) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/card_helpers.rb, line 37
def add_card_to_object(type, card, object, replace_current=false)
  card[type] = object[:id]
  cards_or_sources = object[:cards] || object[:sources] || object[:external_accounts]

  is_customer = object.has_key?(:sources)

  if replace_current && cards_or_sources[:data]
    cards_or_sources[:data].delete_if {|card| card[:id] == object[:default_card]}
    object[:default_card]   = card[:id] unless is_customer
    object[:default_source] = card[:id] if is_customer
    cards_or_sources[:data] = [card]
  else
    cards_or_sources[:total_count] = (cards_or_sources[:total_count] || 0) + 1
    (cards_or_sources[:data] ||= []) << card
  end

  object[:default_card]   = card[:id] if !is_customer && object[:default_card].nil?
  object[:default_source] = card[:id] if is_customer  && object[:default_source].nil?

  card
end
add_coupon_to_object(object, coupon) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb, line 4
def add_coupon_to_object(object, coupon)
  discount_attrs = {}.tap do |attrs|
    attrs[object[:object]]         = object[:id]
    attrs[:coupon]                 = coupon
    attrs[:start]                  = Time.now.to_i
    attrs[:end]                    = (DateTime.now >> coupon[:duration_in_months].to_i).to_time.to_i if coupon[:duration] == 'repeating'
  end

  object[:discount] = Stripe::Discount.construct_from(discount_attrs)
  object
end
add_external_account_to(type, type_id, params, objects) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb, line 5
def add_external_account_to(type, type_id, params, objects)
  resource = assert_existence type, type_id, objects[type_id]

  source =
    if params[:card]
      card_from_params(params[:card])
    elsif params[:bank_account]
      bank_from_params(params[:bank_account])
    else
      begin
        get_card_by_token(params[:external_account])
      rescue Stripe::InvalidRequestError
        bank_from_params(params[:external_account])
      end
    end
  add_external_account_to_object(type, source, resource)
end
add_external_account_to_object(type, source, object, replace_current=false) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb, line 23
def add_external_account_to_object(type, source, object, replace_current=false)
  source[type] = object[:id]
  accounts = object[:external_accounts]

  if replace_current && accounts[:data]
    accounts[:data].delete_if {|source| source[:id] == object[:default_source]}
    object[:default_source] = source[:id]
    accounts[:data] = [source]
  else
    accounts[:total_count] = (accounts[:total_count] || 0) + 1
    (accounts[:data] ||= []) << source
  end
  object[:default_source] = source[:id] if object[:default_source].nil?

  source
end
add_refund_to_charge(refund, charge) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/charge_helpers.rb, line 5
def add_refund_to_charge(refund, charge)
  refunds = charge[:refunds]
  refunds[:data] << refund
  refunds[:total_count] = refunds[:data].count

  charge[:amount_refunded] = refunds[:data].reduce(0) {|sum, r| sum + r[:amount].to_i }
  charge[:refunded] = true
end
add_source_to(type, type_id, params, objects) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/card_helpers.rb, line 85
def add_source_to(type, type_id, params, objects)
  resource = assert_existence type, type_id, objects[type_id]

  source =
    if params[:card]
      card_from_params(params[:card])
    elsif params[:bank_account]
      get_bank_by_token(params[:bank_account])
    else
      begin
        get_card_by_token(params[:source])
      rescue Stripe::InvalidRequestError
        get_bank_by_token(params[:source])
      end
    end
  source[:metadata].merge!(params[:metadata]) if params[:metadata]
  add_source_to_object(type, source, resource)
end
add_source_to_object(type, source, object, replace_current=false) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/card_helpers.rb, line 20
def add_source_to_object(type, source, object, replace_current=false)
  source[type] = object[:id]
  sources = object[:sources]

  if replace_current && sources[:data]
    sources[:data].delete_if {|source| source[:id] == object[:default_source]}
    object[:default_source] = source[:id]
    sources[:data] = [source]
  else
    sources[:total_count] = (sources[:total_count] || 0) + 1
    (sources[:data] ||= []) << source
  end
  object[:default_source] = source[:id] if object[:default_source].nil?

  source
end
add_subscription_to_customer(cus, sub) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb, line 57
def add_subscription_to_customer(cus, sub)
  if sub[:trial_end].nil? || sub[:trial_end] == "now"
    id = new_id('ch')
    charges[id] = Data.mock_charge(
      :id => id,
      :customer => cus[:id],
      :amount => (sub[:plan] ? sub[:plan][:amount] : total_items_amount(sub[:items][:data]))
    )
  end

  if cus[:currency].nil?
    cus[:currency] = sub[:items][:data][0][:plan][:currency]
  elsif cus[:currency] != sub[:items][:data][0][:plan][:currency]
    raise Stripe::InvalidRequestError.new( "Can't combine currencies on a single customer. This customer has had a subscription, coupon, or invoice item with currency #{cus[:currency]}", 'currency', http_status: 400)
  end
  cus[:subscriptions][:total_count] = (cus[:subscriptions][:total_count] || 0) + 1
  cus[:subscriptions][:data].unshift sub
end
bank_from_params(attrs_or_token) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb, line 40
def bank_from_params(attrs_or_token)
  if attrs_or_token.is_a? Hash
    attrs_or_token = generate_bank_token(attrs_or_token)
  end
  get_bank_by_token(attrs_or_token)
end
card_from_params(attrs_or_token) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/card_helpers.rb, line 118
def card_from_params(attrs_or_token)
  if attrs_or_token.is_a? Hash
    attrs_or_token = generate_card_token(attrs_or_token)
  end
  card = get_card_by_token(attrs_or_token)
  validate_card(card)
end
custom_subscription_params(plans, cus, options = {}) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb, line 25
def custom_subscription_params(plans, cus, options = {})
  verify_trial_end(options[:trial_end]) if options[:trial_end]

  plan = plans.first if plans.size == 1

  now = Time.now.utc.to_i
  created_time = options[:created] || now
  start_time = options[:current_period_start] || now
  params = { customer: cus[:id], current_period_start: start_time, created: created_time }
  params.merge!({ :plan => (plans.size == 1 ? plans.first : nil) })
  keys_to_merge = /application_fee_percent|quantity|metadata|tax_percent|billing|days_until_due|default_tax_rates|pending_invoice_item_interval/
  params.merge! options.select {|k,v| k =~ keys_to_merge}

  if options[:cancel_at_period_end] == true
    params.merge!(cancel_at_period_end: true, canceled_at: now)
  elsif options[:cancel_at_period_end] == false
    params.merge!(cancel_at_period_end: false, canceled_at: nil)
  end

  # TODO: Implement coupon logic

  if (((plan && plan[:trial_period_days]) || 0) == 0 && options[:trial_end].nil?) || options[:trial_end] == "now"
    end_time = options[:billing_cycle_anchor] || get_ending_time(start_time, plan)
    params.merge!({status: 'active', current_period_end: end_time, trial_start: nil, trial_end: nil, billing_cycle_anchor: options[:billing_cycle_anchor]})
  else
    end_time = options[:trial_end] || (Time.now.utc.to_i + plan[:trial_period_days]*86400)
    params.merge!({status: 'trialing', current_period_end: end_time, trial_start: start_time, trial_end: end_time, billing_cycle_anchor: nil})
  end

  params
end
delete_card_from(type, type_id, card_id, objects) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/card_helpers.rb, line 66
def delete_card_from(type, type_id, card_id, objects)
  resource = assert_existence type, type_id, objects[type_id]

  assert_existence :card, card_id, get_card(resource, card_id)

  card = { id: card_id, deleted: true }
  cards_or_sources = resource[:cards] || resource[:sources] || resource[:external_accounts]
  cards_or_sources[:data].reject!{|cc|
    cc[:id] == card[:id]
  }

  is_customer = resource.has_key?(:sources)
  new_default = cards_or_sources[:data].count > 0 ? cards_or_sources[:data].first[:id] : nil
  resource[:default_card]   = new_default unless is_customer
  resource[:sources][:total_count] = cards_or_sources[:data].count if is_customer
  resource[:default_source] = new_default if is_customer
  card
end
delete_coupon_from_object(object) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb, line 16
def delete_coupon_from_object(object)
  object[:discount] = nil
  object
end
delete_subscription_from_customer(cus, subscription) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb, line 76
def delete_subscription_from_customer(cus, subscription)
  cus[:subscriptions][:data].reject!{|sub|
    sub[:id] == subscription[:id]
  }
  cus[:subscriptions][:total_count] -=1
end
generate_bank_token(bank_params = {}) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/token_helpers.rb, line 5
def generate_bank_token(bank_params = {})
  token = new_id 'btok'
  bank_params[:id] = new_id 'bank_account'
  @bank_tokens[token] = Data.mock_bank_account bank_params
  token
end
generate_card_token(card_params = {}) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/token_helpers.rb, line 12
def generate_card_token(card_params = {})
  token = new_id 'tok'
  card_params[:id] = new_id 'cc'
  @card_tokens[token] = Data.mock_card symbolize_names(card_params)
  token
end
get_bank_by_token(token) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/token_helpers.rb, line 19
def get_bank_by_token(token)
  if token.nil? || @bank_tokens[token].nil?
    Data.mock_bank_account
  else
    @bank_tokens.delete(token)
  end
end
get_card(object, card_id, class_name='Customer') click to toggle source
# File lib/stripe_mock/request_handlers/helpers/card_helpers.rb, line 5
def get_card(object, card_id, class_name='Customer')
  cards = object[:cards] || object[:sources] || object[:external_accounts]
  card = cards[:data].find{|cc| cc[:id] == card_id }
  if card.nil?
    if class_name == 'Recipient'
      msg = "#{class_name} #{object[:id]} does not have a card with ID #{card_id}"
      raise Stripe::InvalidRequestError.new(msg, 'card', http_status: 404)
    else
      msg = "There is no source with ID #{card_id}"
      raise Stripe::InvalidRequestError.new(msg, 'id', http_status: 404)
    end
  end
  card
end
get_card_by_token(token) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/token_helpers.rb, line 27
def get_card_by_token(token)
  if token.nil? || @card_tokens[token].nil?
    # TODO: Make this strict
    msg = "Invalid token id: #{token}"
    raise Stripe::InvalidRequestError.new(msg, 'tok', http_status: 404)
  else
    @card_tokens.delete(token)
  end
end
get_card_or_bank_by_token(token) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/token_helpers.rb, line 37
def get_card_or_bank_by_token(token)
  token_id = token['id'] || token
  @card_tokens[token_id] || @bank_tokens[token_id] || raise(Stripe::InvalidRequestError.new("Invalid token id: #{token_id}", 'tok', http_status: 404))
end
get_customer_subscription(customer, sub_id) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb, line 5
def get_customer_subscription(customer, sub_id)
  customer[:subscriptions][:data].find{|sub| sub[:id] == sub_id }
end
get_ending_time(start_time, plan, intervals = 1) click to toggle source

`intervals` is set to 1 when calculating current_period_end from current_period_start & plan `intervals` is set to 2 when calculating Stripe::Invoice.upcoming end from current_period_start & plan

# File lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb, line 85
def get_ending_time(start_time, plan, intervals = 1)
  return start_time unless plan

  case plan[:interval]
  when "week"
    start_time + (604800 * (plan[:interval_count] || 1) * intervals)
  when "month"
    (Time.at(start_time).to_datetime >> ((plan[:interval_count] || 1) * intervals)).to_time.to_i
  when "year"
    (Time.at(start_time).to_datetime >> (12 * intervals)).to_time.to_i # max period is 1 year
  else
    start_time
  end
end
resolve_subscription_changes(subscription, plans, customer, options = {}) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb, line 9
def resolve_subscription_changes(subscription, plans, customer, options = {})
  subscription.merge!(custom_subscription_params(plans, customer, options))
  items = options[:items]
  items = items.values if items.respond_to?(:values)
  subscription[:items][:data] = plans.map do |plan|
    if items && items.size == plans.size
      quantity = items &&
        items.detect { |item| item[:plan] == plan[:id] }[:quantity] || 1
      Data.mock_subscription_item({ plan: plan, quantity: quantity })
    else
      Data.mock_subscription_item({ plan: plan })
    end
  end
  subscription
end
retrieve_object_cards(type, type_id, objects) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/card_helpers.rb, line 59
def retrieve_object_cards(type, type_id, objects)
  resource = assert_existence type, type_id, objects[type_id]
  cards = resource[:cards] || resource[:sources] || resource[:external_accounts]

  Data.mock_list_object(cards[:data])
end
total_items_amount(items) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb, line 112
def total_items_amount(items)
  total = 0
  items.each { |i| total += (i[:quantity] || 1) * i[:plan][:amount] }
  total
end
validate_card(card) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/card_helpers.rb, line 111
def validate_card(card)
  [:exp_month, :exp_year].each do |field|
    card[field] = card[field].to_i
  end
  card
end
verify_bank_account(object, bank_account_id, class_name='Customer') click to toggle source
# File lib/stripe_mock/request_handlers/helpers/bank_account_helpers.rb, line 5
def verify_bank_account(object, bank_account_id, class_name='Customer')
  bank_accounts = object[:external_accounts] || object[:bank_accounts] || object[:sources]
  bank_account = bank_accounts[:data].find{|acc| acc[:id] == bank_account_id }
  return if bank_account.nil?
  bank_account['status'] = 'verified'
  bank_account
end
verify_trial_end(trial_end) click to toggle source
# File lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb, line 100
def verify_trial_end(trial_end)
  if trial_end != "now"
    if !trial_end.is_a? Integer
      raise Stripe::InvalidRequestError.new('Invalid timestamp: must be an integer', nil, http_status: 400)
    elsif trial_end < Time.now.utc.to_i
      raise Stripe::InvalidRequestError.new('Invalid timestamp: must be an integer Unix timestamp in the future', nil, http_status: 400)
    elsif trial_end > Time.now.utc.to_i + 31557600*5 # five years
      raise Stripe::InvalidRequestError.new('Invalid timestamp: can be no more than five years in the future', nil, http_status: 400)
    end
  end
end