Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flexible/Metered Billing API support #1150

Merged
merged 4 commits into from
Apr 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@
.vs

project.lock.json

.DS_Store
.idea/
9 changes: 5 additions & 4 deletions src/Stripe.Tests.XUnit/plans/_cache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public static partial class Cache
{
private static Object cacheLock = new Object();

public static StripePlan GetPlan(string planName = "plan")
public static StripePlan GetPlan(string planName = "plan", string planUsageType = "licensed")
{
// Ensures that creating a new plan only happens synchronously
// Avoids parallel calls to end up with the same options (and id) twice.
Expand All @@ -17,14 +17,14 @@ public static StripePlan GetPlan(string planName = "plan")
return (StripePlan) Items[planName];
}

var plan = new StripePlanService(ApiKey).Create(GetPlanCreateOptions(planName));
var plan = new StripePlanService(ApiKey).Create(GetPlanCreateOptions(planName, planUsageType));
Items.Add(planName, plan);

return plan;
}
}

public static StripePlanCreateOptions GetPlanCreateOptions(string planName = "plan")
public static StripePlanCreateOptions GetPlanCreateOptions(string planName = "plan", string planUsageType = "licensed")
{
if (Items.ContainsKey($"{planName}_create_options")) return (StripePlanCreateOptions) Items[$"{planName}_create_options"];

Expand All @@ -39,7 +39,8 @@ public static StripePlanCreateOptions GetPlanCreateOptions(string planName = "pl
{
Name = "Test Product",
StatementDescriptor = "TEST THIS PRODUCT"
}
},
UsageType = planUsageType,
};
Items.Add($"{planName}_create_options", options);

Expand Down
91 changes: 91 additions & 0 deletions src/Stripe.Tests.XUnit/plans/_fixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,95 @@ public add_plan_to_product_fixture()

public void Dispose() { }
}

public class tiered_plan_fixture : IDisposable
{
public StripeProductCreateOptions ProductCreateOptions { get; set; }
public StripePlanCreateOptions PlanCreateOptions { get; set; }

public StripePlan Plan { get; set; }
public StripePlan PlanRetrieved { get; set; }

public tiered_plan_fixture()
{
ProductCreateOptions = new StripeProductCreateOptions
{
Name = $"test-product-{ Guid.NewGuid() }",
Type = "service"
};

var productService = new StripeProductService(Cache.ApiKey);
var product = productService.Create(ProductCreateOptions);
var tiers = new List<StripePlanTierOptions>
{
new StripePlanTierOptions()
{
Amount = 1000,
UpTo = new StripePlanTierOptions.UpToBound() {Bound = 10}
},
new StripePlanTierOptions()
{
Amount = 2000,
UpTo = new StripePlanTierOptions.UpToInf()
}
};

PlanCreateOptions = new StripePlanCreateOptions() {
Nickname = "tiered-plan-name",
BillingScheme = "tiered",
TiersMode = "volume",
Tiers = tiers,
Currency = "usd",
Interval = "month",
ProductId = product.Id
};

var planService = new StripePlanService(Cache.ApiKey);
Plan = planService.Create(PlanCreateOptions);
PlanRetrieved = planService.Get(Plan.Id);
}

public void Dispose() { }
}

public class transform_usage_plan_fixture : IDisposable
{
public StripeProductCreateOptions ProductCreateOptions { get; set; }
public StripePlanCreateOptions PlanCreateOptions { get; set; }

public StripePlan Plan { get; set; }
public StripePlan PlanRetrieved { get; set; }

public transform_usage_plan_fixture()
{
ProductCreateOptions = new StripeProductCreateOptions
{
Name = $"test-product-{ Guid.NewGuid() }",
Type = "service"
};

var productService = new StripeProductService(Cache.ApiKey);
var product = productService.Create(ProductCreateOptions);
var transformUsage = new StripePlanTransformUsageOptions()
{
DivideBy = 100,
Round = "up"
};

PlanCreateOptions = new StripePlanCreateOptions() {
Nickname = "tiered-plan-name",
Amount = 1000,
Currency = "usd",
Interval = "month",
ProductId = product.Id,
TransformUsage = transformUsage,
};

var planService = new StripePlanService(Cache.ApiKey);
Plan = planService.Create(PlanCreateOptions);
PlanRetrieved = planService.Get(Plan.Id);
}

public void Dispose() { }
}
}
46 changes: 46 additions & 0 deletions src/Stripe.Tests.XUnit/plans/when_creating_tiered_plans.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Xunit;

namespace Stripe.Tests.Xunit
{
public class creating_tiered_plans : IClassFixture<tiered_plan_fixture>
{
private readonly tiered_plan_fixture fixture;

public creating_tiered_plans(tiered_plan_fixture fixture)
{
this.fixture = fixture;
}

[Fact]
public void has_the_correct_billing_scheme()
{
fixture.Plan.BillingScheme.Should().Be(fixture.PlanCreateOptions.BillingScheme);
}

[Fact]
public void has_the_correct_tiers_mode()
{
fixture.Plan.TiersMode.Should().Be(fixture.PlanCreateOptions.TiersMode);
}

[Fact]
public void has_the_correct_first_tier()
{
fixture.Plan.Tiers[0].Amount.Should().Be(fixture.PlanCreateOptions.Tiers[0].Amount);

StripePlanTierOptions.UpToOption upTo = fixture.PlanCreateOptions.Tiers[0].UpTo;
StripePlanTierOptions.UpToBound upBound = (StripePlanTierOptions.UpToBound) upTo;
fixture.Plan.Tiers[0].UpTo.Should().Be(upBound.Bound);
}

[Fact]
public void has_the_correct_second_tier()
{
fixture.Plan.Tiers[1].Amount.Should().Be(fixture.PlanCreateOptions.Tiers[1].Amount);
fixture.Plan.Tiers[1].UpTo.Should().Be(null);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Xunit;

namespace Stripe.Tests.Xunit
{
public class creating_transform_usage_plans : IClassFixture<transform_usage_plan_fixture>
{
private readonly transform_usage_plan_fixture fixture;

public creating_transform_usage_plans(transform_usage_plan_fixture fixture)
{
this.fixture = fixture;
}

[Fact]
public void has_the_currect_divide_by()
{
fixture.Plan.TransformUsage.DivideBy.Should().Be(fixture.PlanCreateOptions.TransformUsage.DivideBy);
}

[Fact]
public void has_the_currect_rouding()
{
fixture.Plan.TransformUsage.Round.Should().Be(fixture.PlanCreateOptions.TransformUsage.Round);
}
}
}
39 changes: 39 additions & 0 deletions src/Stripe.Tests.XUnit/usage_records/_fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;

namespace Stripe.Tests.Xunit
{
public class usage_record_fixture : IDisposable
{
public StripeUsageRecordCreateOptions UsageRecordCreateOptions { get; set; }

public StripeUsageRecord UsageRecord { get; set; }

public usage_record_fixture()
{
var subOptions = new StripeSubscriptionCreateOptions
{
Items = new List<StripeSubscriptionItemOption>
{
new StripeSubscriptionItemOption { PlanId = Cache.GetPlan("Metered Plan", "metered").Id }
}
};

var service = new StripeSubscriptionService(Cache.ApiKey);
var customer_id = Cache.GetCustomer().Id;
var subscription = service.Create(customer_id, subOptions);
var subscription_item_id = subscription.Items.Data[0].Id;

UsageRecordCreateOptions = new StripeUsageRecordCreateOptions() {
SubscriptionItem = subscription_item_id,
Timestamp = DateTime.Now,
Quantity = 2000
};

var usageRecordService = new StripeUsageRecordService(Cache.ApiKey);
UsageRecord = usageRecordService.Create(UsageRecordCreateOptions);
}

public void Dispose() { }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Xunit;
using Stripe.Infrastructure;

namespace Stripe.Tests.Xunit
{
public class creating_a_usage_record : IClassFixture<usage_record_fixture>
{
private readonly usage_record_fixture fixture;

public creating_a_usage_record(usage_record_fixture fixture)
{
this.fixture = fixture;
}

[Fact]
public void has_the_correct_quantity()
{
fixture.UsageRecord.Quantity.Should().Be(fixture.UsageRecordCreateOptions.Quantity);
}

[Fact]
public void has_the_correct_timestamp()
{
fixture.UsageRecord.Timestamp.ConvertDateTimeToEpoch().Should().Be(
fixture.UsageRecordCreateOptions.Timestamp.ConvertDateTimeToEpoch());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ public class when_getting_an_upcoming_invoice_with_options
_stripeInvoice.StripeInvoiceLineItems.Data.First().Plan.Id.ShouldEqual(_stripePlan.Id);

It should_have_the_correct_plan_amount = () =>
_stripeInvoice.StripeInvoiceLineItems.Data.First().Amount.ShouldEqual(_stripePlan.Amount);
_stripeInvoice.StripeInvoiceLineItems.Data.First().Amount.ShouldEqual(_stripePlan.Amount.Value);
}
}
17 changes: 16 additions & 1 deletion src/Stripe.net/Entities/StripePlan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ public class StripePlan : StripeEntityWithId, ISupportMetadata
public string Object { get; set; }

[JsonProperty("amount")]
public int Amount { get; set; }
public int? Amount { get; set; }

[JsonProperty("billing_scheme")]
public string BillingScheme { get; set; }

[JsonProperty("created")]
[JsonConverter(typeof(StripeDateTimeConverter))]
Expand Down Expand Up @@ -55,7 +58,19 @@ internal object InternalProduct
}
#endregion

[JsonProperty("tiers")]
public List<StripePlanTier> Tiers { get; set; }

[JsonProperty("tiers_mode")]
public string TiersMode { get; set; }

[JsonProperty("transform_usage")]
public StripePlanTransformUsage TransformUsage { get; set; }

[JsonProperty("trial_period_days")]
public int? TrialPeriodDays { get; set; }

[JsonProperty("usage_type")]
public string UsageType { get; set; }
}
}
13 changes: 13 additions & 0 deletions src/Stripe.net/Entities/StripePlanTier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Newtonsoft.Json;

namespace Stripe
{
public class StripePlanTier
{
[JsonProperty("amount")]
public int Amount { get; set; }

[JsonProperty("up_to")]
public int? UpTo { get; set; }
}
}
13 changes: 13 additions & 0 deletions src/Stripe.net/Entities/StripePlanTransformUsage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Newtonsoft.Json;

namespace Stripe
{
public class StripePlanTransformUsage
{
[JsonProperty("divide_by")]
public int DivideBy { get; set; }

[JsonProperty("round")]
public string Round { get; set; }
}
}
25 changes: 25 additions & 0 deletions src/Stripe.net/Entities/StripeUsageRecord.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using Newtonsoft.Json;
using Stripe.Infrastructure;

namespace Stripe
{
public class StripeUsageRecord : StripeEntityWithId
{
[JsonProperty("object")]
public string Object { get; set; }

[JsonProperty("livemode")]
public bool LiveMode { get; set; }

[JsonProperty("subscription_item")]
public string SubscriptionItem { get; set; }

[JsonProperty("timestamp")]
[JsonConverter(typeof(StripeDateTimeConverter))]
public DateTime Timestamp { get; set; }

[JsonProperty("quantity")]
public int Quantity { get; set; }
}
}
Loading