Skip to content

Commit

Permalink
Support for latest API version
Browse files Browse the repository at this point in the history
  • Loading branch information
s2t2 authored and alexmamonchik committed Sep 29, 2019
1 parent cfc8846 commit 9c07aa1
Show file tree
Hide file tree
Showing 29 changed files with 901 additions and 537 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ stripe-mock-server.pid
Gemfile.lock
stripe-mock-server.log
.idea
.ruby-version
.ruby-version
9 changes: 4 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ group: deprecated-2017Q2
sudo: required
language: ruby
rvm:
- 2.0.0
- 2.1.10
- 2.2.7
- 2.3.4
- 2.4.6
- 2.5.5
- 2.6.3
before_install:
- rvm 2.1.10 do gem install mime-types -v 2.6.2
- gem install bundler -v '< 2'
Expand All @@ -17,7 +16,7 @@ script: "bundle exec rspec && bundle exec rspec -t live"

env:
global:
- IS_TRAVIS=true STRIPE_TEST_SECRET_KEY_A=sk_test_Ut2MSlZANdT3iDALdGhyLymy STRIPE_TEST_SECRET_KEY_B=sk_test_JXtzss9tHOG1ofIyEZgoUP4Q STRIPE_TEST_SECRET_KEY_C=sk_test_ZR5nVz9p3ivsqVa7mYB0sFep STRIPE_TEST_SECRET_KEY_D=sk_test_ZR5nVz9p3ivsqVa7mYB0sFep
- IS_TRAVIS=true STRIPE_TEST_SECRET_KEY_A=sk_test_BsztzqQjzd7lqkgo1LjEG5DF00KzH7tWKF STRIPE_TEST_SECRET_KEY_B=sk_test_rKCEu0x8jzg6cKPqoey8kUPQ00usQO3KYE STRIPE_TEST_SECRET_KEY_C=sk_test_qeaB7R6Ywp8sC9pzd1ZIABH700YLC7nhmZ

notifications:
webhooks:
Expand Down
3 changes: 3 additions & 0 deletions lib/stripe_mock/api/webhooks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ def self.event_list
'plan.created',
'plan.updated',
'plan.deleted',
'product.created',
'product.updated',
'product.deleted',
'coupon.created',
'coupon.deleted',
'transfer.created',
Expand Down
40 changes: 29 additions & 11 deletions lib/stripe_mock/data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ def self.mock_invoice(lines, params={})
created: 1349738950,
period_end: 1349738950,
period_start: 1349738950,
due_date: nil,
lines: {
object: "list",
total_count: lines.count,
Expand Down Expand Up @@ -385,7 +386,7 @@ def self.mock_invoice(lines, params={})
amount_paid: 0,
currency: currency,
starting_balance: 0,
ending_balance: nil,
ending_balance: 0,
next_payment_attempt: 1349825350,
charge: nil,
discount: nil,
Expand All @@ -399,6 +400,7 @@ def self.mock_invoice(lines, params={})
end
due = invoice[:total] + invoice[:starting_balance]
invoice[:amount_due] = due < 0 ? 0 : due
invoice[:ending_balance] = invoice[:starting_balance] + invoice[:total] if invoice[:amount_due] == 0
invoice
end

Expand Down Expand Up @@ -521,33 +523,49 @@ def self.mock_order_item(params={})
def self.mock_plan(params={})
currency = params[:currency] || StripeMock.default_currency
{
id: "2",
id: "mock_plan_123",
object: "plan",
active: true,
aggregate_usage: nil,
amount: 2300,
billing_scheme: "per_unit",
created: 1466698898,
currency: currency,
interval: "month",
interval_count: 1,
livemode: false,
metadata: {},
name: "The Basic Plan",
statement_descriptor: nil,
trial_period_days: nil
nickname: "My Mock Plan",
product: "mock_prod_NONEXIST", # override this with your own existing product id
tiers: nil,
tiers_mode: nil,
transform_usage: nil,
trial_period_days: nil,
usage_type: "licensed"
}.merge(params)
end

def self.mock_product(params = {})
def self.mock_product(params={})
{
id: "default_test_prod",
id: "mock_prod_abc123",
object: "product",
active: true,
created: 1556896214,
attributes:[],
caption: nil,
created: 1466698000,
deactivate_on: [],
description: nil,
images: [],
livemode: false,
metadata: {},
name: "Default Test Product",
statement_descriptor: "PRODUCT",
name: "The Mock Product",
package_dimensions: nil,
shippable: nil,
statement_descriptor: nil,
type: "service",
updated: 1556918200,
unit_label: "my_unit",
updated: 1537939442,
url: nil
}.merge(params)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/stripe_mock/request_handlers/helpers/token_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def get_card_by_token(token)

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))
@card_tokens[token_id] || @bank_tokens[token_id] || raise(Stripe::InvalidRequestError.new("Invalid token id: #{token_id}", 'tok', http_status: 404))
end

end
Expand Down
7 changes: 6 additions & 1 deletion lib/stripe_mock/request_handlers/invoices.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,12 @@ def upcoming_invoice(route, method_url, params, headers)
invoice_lines = []

if prorating
unused_amount = subscription[:plan][:amount] * subscription[:quantity] * (subscription[:current_period_end] - subscription_proration_date.to_i) / (subscription[:current_period_end] - subscription[:current_period_start])
unused_amount = (
subscription[:plan][:amount].to_f *
subscription[:quantity] *
(subscription[:current_period_end] - subscription_proration_date.to_i) / (subscription[:current_period_end] - subscription[:current_period_start])
).ceil

invoice_lines << Data.mock_line_item(
id: new_id('ii'),
amount: -unused_amount,
Expand Down
1 change: 1 addition & 0 deletions lib/stripe_mock/request_handlers/products.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def self.included(base)

def create_product(_route, _method_url, params, _headers)
params[:id] ||= new_id('prod')
validate_create_product_params(params)
products[params[:id]] = Data.mock_product(params)
end

Expand Down
20 changes: 16 additions & 4 deletions lib/stripe_mock/request_handlers/subscriptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def create_subscription(route, method_url, params, headers)
customer[:default_source] = new_card[:id]
end

allowed_params = %w(customer application_fee_percent coupon items metadata plan quantity source tax_percent trial_end trial_period_days current_period_start created prorate billing_cycle_anchor billing days_until_due idempotency_key)
allowed_params = %w(customer application_fee_percent coupon items metadata plan quantity source tax_percent trial_end trial_period_days current_period_start created prorate billing_cycle_anchor billing days_until_due idempotency_key enable_incomplete_payments cancel_at_period_end)
unknown_params = params.keys - allowed_params.map(&:to_sym)
if unknown_params.length > 0
raise Stripe::InvalidRequestError.new("Received unknown parameter: #{unknown_params.join}", unknown_params.first.to_s, http_status: 400)
Expand Down Expand Up @@ -133,6 +133,11 @@ def create_subscription(route, method_url, params, headers)
end
end

if params[:cancel_at_period_end]
subscription[:cancel_at_period_end] = true
subscription[:canceled_at] = Time.now.utc.to_i
end

subscriptions[subscription[:id]] = subscription
add_subscription_to_customer(customer, subscription)

Expand Down Expand Up @@ -191,17 +196,24 @@ def update_subscription(route, method_url, params, headers)
raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', http_status: 400)
end
end
verify_card_present(customer, subscription_plans.first, subscription)

if subscription[:cancel_at_period_end]
if params[:cancel_at_period_end]
subscription[:cancel_at_period_end] = true
subscription[:canceled_at] = Time.now.utc.to_i
elsif params.has_key?(:cancel_at_period_end)
subscription[:cancel_at_period_end] = false
subscription[:canceled_at] = nil
end

params[:current_period_start] = subscription[:current_period_start]
params[:trial_end] = params[:trial_end] || subscription[:trial_end]

plan_amount_was = subscription.dig(:plan, :amount)

subscription = resolve_subscription_changes(subscription, subscription_plans, customer, params)

verify_card_present(customer, subscription_plans.first, subscription, params) if plan_amount_was == 0 && subscription.dig(:plan, :amount) && subscription.dig(:plan, :amount) > 0

# delete the old subscription, replace with the new subscription
customer[:subscriptions][:data].reject! { |sub| sub[:id] == subscription[:id] }
customer[:subscriptions][:data] << subscription
Expand Down Expand Up @@ -281,7 +293,7 @@ def verify_card_present(customer, plan, subscription, params={})

return if params[:billing] == 'send_invoice'

raise Stripe::InvalidRequestError.new('You must supply a valid card xoxo', nil, http_status: 400)
raise Stripe::InvalidRequestError.new('This customer has no attached payment source', nil, http_status: 400)
end

def verify_active_status(subscription)
Expand Down
107 changes: 97 additions & 10 deletions lib/stripe_mock/request_handlers/validators/param_validators.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,28 @@ module StripeMock
module RequestHandlers
module ParamValidators

def validate_create_plan_params(params)
def already_exists_message(obj_class)
"#{obj_class.to_s.split("::").last} already exists."
end

def not_found_message(obj_class, obj_id)
"No such #{obj_class.to_s.split("::").last.downcase}: #{obj_id}"
end

def missing_param_message(attr_name)
"Missing required param: #{attr_name}."
end

def invalid_integer_message(my_val)
"Invalid integer: #{my_val}"
end

#
# ProductValidator
#


def validate_create_product_params(params)
params[:id] = params[:id].to_s
required_product_fields = @base_strategy.create_plan_params[:product].keys

Expand All @@ -14,25 +35,91 @@ def validate_create_plan_params(params)
raise Stripe::InvalidRequestError.new(message, name) if params[:product][name].nil?
end

@base_strategy.create_plan_params.keys.each do |name|
@base_strategy.create_product_params.keys.reject{ |k,_| k == :id }.each do |k|
raise Stripe::InvalidRequestError.new(missing_param_message(k), k) if params[k].nil?
end

if !%w[good service].include?(params[:type])
raise Stripe::InvalidRequestError.new("Invalid type: must be one of good or service", :type)
end

if products[ params[:id] ]
raise Stripe::InvalidRequestError.new(already_exists_message(Stripe::Product), :id)
end
end

#
# PlanValidator
#

def missing_plan_amount_message
"Plans require an `amount` parameter to be set."
end

SUPPORTED_PLAN_INTERVALS = ["month", "year", "week", "day"]

def invalid_plan_interval_message
"Invalid interval: must be one of month, year, week, or day"
end

SUPPORTED_CURRENCIES = [
"usd", "aed", "afn", "all", "amd", "ang", "aoa", "ars", "aud", "awg", "azn", "bam", "bbd", "bdt", "bgn",
"bif", "bmd", "bnd", "bob", "brl", "bsd", "bwp", "bzd", "cad", "cdf", "chf", "clp", "cny", "cop", "crc",
"cve", "czk", "djf", "dkk", "dop", "dzd", "egp", "etb", "eur", "fjd", "fkp", "gbp", "gel", "gip", "gmd",
"gnf", "gtq", "gyd", "hkd", "hnl", "hrk", "htg", "huf", "idr", "ils", "inr", "isk", "jmd", "jpy", "kes",
"kgs", "khr", "kmf", "krw", "kyd", "kzt", "lak", "lbp", "lkr", "lrd", "lsl", "mad", "mdl", "mga", "mkd",
"mmk", "mnt", "mop", "mro", "mur", "mvr", "mwk", "mxn", "myr", "mzn", "nad", "ngn", "nio", "nok", "npr",
"nzd", "pab", "pen", "pgk", "php", "pkr", "pln", "pyg", "qar", "ron", "rsd", "rub", "rwf", "sar", "sbd",
"scr", "sek", "sgd", "shp", "sll", "sos", "srd", "std", "szl", "thb", "tjs", "top", "try", "ttd", "twd",
"tzs", "uah", "ugx", "uyu", "uzs", "vnd", "vuv", "wst", "xaf", "xcd", "xof", "xpf", "yer", "zar", "zmw",
"eek", "lvl", "svc", "vef"
]

def invalid_currency_message(my_val)
"Invalid currency: #{my_val.downcase}. Stripe currently supports these currencies: #{SUPPORTED_CURRENCIES.join(", ")}"
end

def validate_create_plan_params(params)
plan_id = params[:id].to_s
product_id = params[:product]

@base_strategy.create_plan_params.keys.each do |attr_name|
message =
if name == :amount
"Plans require an `#{name}` parameter to be set."
elsif name == :product
if attr_name == :amount
"Plans require an `#{attr_name}` parameter to be set."
elsif attr_name == :product
"Missing required param: name."
else
"Missing required param: #{name}."
"Missing required param: #{attr_name}."
end
raise Stripe::InvalidRequestError.new(message, name) if params[name].nil?
raise Stripe::InvalidRequestError.new(message, attr_name) if params[attr_name].nil?
end

if plans[ params[:id] ]
raise Stripe::InvalidRequestError.new("Plan already exists.", :id)
if plans[plan_id]
message = already_exists_message(Stripe::Plan)
raise Stripe::InvalidRequestError.new(message, :id)
end

unless products[product_id]
message = not_found_message(Stripe::Product, product_id)
raise Stripe::InvalidRequestError.new(message, :product)
end

unless SUPPORTED_PLAN_INTERVALS.include?(params[:interval])
message = invalid_plan_interval_message
raise Stripe::InvalidRequestError.new(message, :interval)
end

unless SUPPORTED_CURRENCIES.include?(params[:currency])
message = invalid_currency_message(params[:currency])
raise Stripe::InvalidRequestError.new(message, :currency)
end

unless params[:amount].integer?
raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", :amount)
message = invalid_integer_message(params[:amount])
raise Stripe::InvalidRequestError.new(message, :amount)
end

end

def require_param(param_name)
Expand Down
Loading

0 comments on commit 9c07aa1

Please sign in to comment.