mirror of
https://github.com/stripe/stripe-ruby.git
synced 2025-05-30 00:00:47 -04:00
Add support for multiplan subscriptions (#466)
* Add support for multiplan subscriptions: Serialize indexed arrays into hashes with index keys in subscription create, subscription update, and upcoming invoice Add a SubscriptionItem object that supports creation, deletion, update, listing, and retrieval * Remove helpers that convert items array to indexed hash
This commit is contained in:
parent
7637eb48bf
commit
d2f783df34
@ -43,6 +43,7 @@ require 'stripe/recipient'
|
||||
require 'stripe/bank_account'
|
||||
require 'stripe/card'
|
||||
require 'stripe/subscription'
|
||||
require 'stripe/subscription_item'
|
||||
require 'stripe/application_fee'
|
||||
require 'stripe/refund'
|
||||
require 'stripe/reversal'
|
||||
|
12
lib/stripe/subscription_item.rb
Normal file
12
lib/stripe/subscription_item.rb
Normal file
@ -0,0 +1,12 @@
|
||||
module Stripe
|
||||
class SubscriptionItem < APIResource
|
||||
extend Stripe::APIOperations::Create
|
||||
include Stripe::APIOperations::Delete
|
||||
extend Stripe::APIOperations::List
|
||||
include Stripe::APIOperations::Save
|
||||
|
||||
def self.resource_url
|
||||
'/v1/subscription_items'
|
||||
end
|
||||
end
|
||||
end
|
@ -42,6 +42,7 @@ module Stripe
|
||||
'recipient' => Recipient,
|
||||
'refund' => Refund,
|
||||
'subscription' => Subscription,
|
||||
'subscription_item' => SubscriptionItem,
|
||||
'file_upload' => FileUpload,
|
||||
'token' => Token,
|
||||
'transfer' => Transfer,
|
||||
|
@ -44,5 +44,23 @@ module Stripe
|
||||
i.pay
|
||||
assert_equal nil, i.next_payment_attempt
|
||||
end
|
||||
|
||||
should "be able to retrieve upcoming invoices" do
|
||||
base = "#{Stripe.api_base}/v1/invoices/upcoming?"
|
||||
cus_sub = "customer=c_test_customer&subscription=s_test_subscription&"
|
||||
item0 = "subscription_items[][plan]=gold&subscription_items[][quantity]=1&"
|
||||
item1 = "subscription_items[][plan]=silver&subscription_items[][quantity]=2"
|
||||
@mock.expects(:get).once.with(base + cus_sub + item0 + item1, nil, nil).
|
||||
returns(make_response(make_invoice(:customer => 'c_test_customer', :subscription => 's_test_subscription')))
|
||||
|
||||
i = Stripe::Invoice.upcoming(
|
||||
:customer => 'c_test_customer',
|
||||
:subscription => 's_test_subscription',
|
||||
:subscription_items => [{:plan => 'gold', :quantity =>1}, {:plan => 'silver', :quantity =>2}]
|
||||
)
|
||||
|
||||
assert_equal 'c_test_customer', i.customer
|
||||
assert_equal 's_test_subscription', i.subscription
|
||||
end
|
||||
end
|
||||
end
|
||||
|
76
test/stripe/subscription_item_test.rb
Normal file
76
test/stripe/subscription_item_test.rb
Normal file
@ -0,0 +1,76 @@
|
||||
require File.expand_path('../../test_helper', __FILE__)
|
||||
|
||||
module Stripe
|
||||
class SubscriptionItemTest < Test::Unit::TestCase
|
||||
should "subscription items should be retrievable" do
|
||||
@mock.expects(:get).once.with("#{Stripe.api_base}/v1/subscription_items/si_test_subscription_item", nil, nil).
|
||||
returns(make_response(make_subscription_item))
|
||||
|
||||
sub_item = Stripe::SubscriptionItem.retrieve('si_test_subscription_item')
|
||||
|
||||
assert sub_item.kind_of?(Stripe::SubscriptionItem)
|
||||
end
|
||||
|
||||
should "subscription items should be listable" do
|
||||
@mock.expects(:get).once.with("#{Stripe.api_base}/v1/subscription_items?subscription=s_test_subscription&limit=3", nil, nil).
|
||||
returns(make_response(make_subscription_item_array))
|
||||
sub_items = Stripe::SubscriptionItem.list(:subscription => 's_test_subscription', :limit => 3).data
|
||||
|
||||
assert sub_items.kind_of? Array
|
||||
assert sub_items[0].kind_of? Stripe::SubscriptionItem
|
||||
end
|
||||
|
||||
should "subscription items should be deletable" do
|
||||
@mock.expects(:get).once.returns(make_response(make_subscription_item))
|
||||
sub_item = Stripe::SubscriptionItem.retrieve('si_test_subscription_item')
|
||||
|
||||
@mock.expects(:delete).once.with("#{Stripe.api_base}/v1/subscription_items/#{sub_item.id}", nil, nil).
|
||||
returns(make_response(make_subscription_item))
|
||||
sub_item.delete
|
||||
end
|
||||
|
||||
should "subscription items should be updateable" do
|
||||
sid = 'si_test_subscription_item'
|
||||
@mock.expects(:post).once.with do |url, api_key, params|
|
||||
url == "#{Stripe.api_base}/v1/subscription_items/#{sid}" &&
|
||||
api_key.nil? &&
|
||||
CGI.parse(params) == {'plan' => ['silver'], 'quantity' => ['3']}
|
||||
end.returns(make_response(make_subscription_item(:plan => 'silver', :quantity => 3)))
|
||||
|
||||
sub_item = Stripe::SubscriptionItem.update(sid, {:plan => 'silver', :quantity => 3})
|
||||
|
||||
assert_equal 'silver', sub_item.plan.id
|
||||
assert_equal 3, sub_item.quantity
|
||||
end
|
||||
|
||||
should "subscription items should be saveable" do
|
||||
@mock.expects(:get).once.returns(make_response(make_subscription_item))
|
||||
sub_item = Stripe::SubscriptionItem.retrieve('si_test_subscription_item')
|
||||
|
||||
@mock.expects(:post).once.with do |url, api_key, params|
|
||||
url == "#{Stripe.api_base}/v1/subscription_items/#{sub_item.id}" &&
|
||||
api_key.nil? &&
|
||||
CGI.parse(params) == {'plan' => ['silver'], 'quantity' => ['3']}
|
||||
end.returns(make_response(make_subscription_item(:plan => 'silver', :quantity => 3)))
|
||||
|
||||
sub_item.plan = 'silver'
|
||||
sub_item.quantity = 3
|
||||
sub_item.save
|
||||
|
||||
assert_equal 'silver', sub_item.plan.id
|
||||
assert_equal 3, sub_item.quantity
|
||||
end
|
||||
|
||||
should "create should return a new subscription item" do
|
||||
@mock.expects(:post).once.with do |url, api_key, params|
|
||||
url == "#{Stripe.api_base}/v1/subscription_items" && api_key.nil? &&
|
||||
CGI.parse(params) == {'plan' => ['silver'], 'quantity' => ['3']}
|
||||
end.returns(make_response(make_subscription_item(:plan => 'silver', :quantity => 3)))
|
||||
|
||||
sub_item = Stripe::SubscriptionItem.create(:plan => 'silver', :quantity => 3)
|
||||
|
||||
assert_equal 'silver', sub_item.plan.id
|
||||
assert_equal 3, sub_item.quantity
|
||||
end
|
||||
end
|
||||
end
|
@ -87,6 +87,27 @@ module Stripe
|
||||
assert_equal 'active', sub.status
|
||||
end
|
||||
|
||||
should "subscription items should be updateable" do
|
||||
sid = 's_test_subscription'
|
||||
items = {:data => [{:plan => {:id =>'gold'}, :quantity => 1}, {:plan => {:id =>'silver'}, :quantity => 2}]}
|
||||
|
||||
@mock.expects(:post).once.with do |url, api_key, params|
|
||||
url == "#{Stripe.api_base}/v1/subscriptions/#{sid}" &&
|
||||
api_key.nil? &&
|
||||
CGI.parse(params) == {
|
||||
'items[][plan]'=>['gold', 'silver'],
|
||||
'items[][quantity]'=>['1', '2'],
|
||||
}
|
||||
end.returns(make_response(make_subscription(:items => items)))
|
||||
|
||||
sub = Stripe::Subscription.update(sid, :items => [{:plan => 'gold', :quantity =>1}, {:plan => 'silver', :quantity =>2}])
|
||||
|
||||
assert_equal 'gold', sub.items.data[0].plan.id
|
||||
assert_equal 1, sub.items.data[0].quantity
|
||||
assert_equal 'silver', sub.items.data[1].plan.id
|
||||
assert_equal 2, sub.items.data[1].quantity
|
||||
end
|
||||
|
||||
should "subscriptions should be saveable" do
|
||||
@mock.expects(:get).once.returns(make_response(make_subscription))
|
||||
sub = Stripe::Subscription.retrieve('s_test_subscription')
|
||||
@ -113,6 +134,28 @@ module Stripe
|
||||
assert_equal 'gold', sub.plan.identifier
|
||||
end
|
||||
|
||||
should "create with items should return a new subscription" do
|
||||
items = {:data => [{:plan => {:id =>'gold'}, :quantity => 1}, {:plan => {:id =>'silver'}, :quantity => 2}]}
|
||||
|
||||
@mock.expects(:post).once.with do |url, api_key, params|
|
||||
url == "#{Stripe.api_base}/v1/subscriptions" &&
|
||||
api_key.nil? &&
|
||||
CGI.parse(params) == {
|
||||
'customer' => ['c_test_customer'],
|
||||
'items[][plan]'=>['gold', 'silver'],
|
||||
'items[][quantity]'=>['1', '2'],
|
||||
}
|
||||
end.returns(make_response(make_subscription(:items => items, :id => 'test_new_subscription')))
|
||||
|
||||
sub = Stripe::Subscription.create(:customer => 'c_test_customer', :items => [{:plan => 'gold', :quantity =>1}, {:plan => 'silver', :quantity =>2}])
|
||||
|
||||
assert_equal 'test_new_subscription', sub.id
|
||||
assert_equal 'gold', sub.items.data[0].plan.id
|
||||
assert_equal 1, sub.items.data[0].quantity
|
||||
assert_equal 'silver', sub.items.data[1].plan.id
|
||||
assert_equal 2, sub.items.data[1].quantity
|
||||
end
|
||||
|
||||
should "be able to delete a subscriptions's discount" do
|
||||
@mock.expects(:post).once.returns(make_response(make_subscription))
|
||||
sub = Stripe::Subscription.create(:plan => 'gold', :customer => 'c_test_customer', coupon: 'forever')
|
||||
|
@ -277,6 +277,24 @@ module Stripe
|
||||
}.merge(params)
|
||||
end
|
||||
|
||||
def make_subscription_item(params = {})
|
||||
plan = params.delete(:plan) || 'gold'
|
||||
{
|
||||
:id => "si_test_subscription_item",
|
||||
:object => "subscription_item",
|
||||
:created => 1473875521,
|
||||
:plan => {
|
||||
:id => plan,
|
||||
:object => "plan",
|
||||
:amount => 1000,
|
||||
:created => 1468349629,
|
||||
:currency => "usd",
|
||||
:interval => "month",
|
||||
},
|
||||
:quantity => 1
|
||||
}.merge(params)
|
||||
end
|
||||
|
||||
def make_refund(params = {})
|
||||
{
|
||||
:object => 'refund',
|
||||
@ -297,6 +315,14 @@ module Stripe
|
||||
}
|
||||
end
|
||||
|
||||
def make_subscription_item_array
|
||||
{
|
||||
:data => [make_subscription_item, make_subscription_item, make_subscription_item],
|
||||
:object => 'list',
|
||||
:resource_url => '/v1/subscription_items'
|
||||
}
|
||||
end
|
||||
|
||||
def make_customer_subscription_array(customer_id)
|
||||
{
|
||||
:data => [make_subscription, make_subscription, make_subscription],
|
||||
|
Loading…
x
Reference in New Issue
Block a user