Dloizides.Subscriptions.AspNetCore
1.0.5
See the version list below for details.
dotnet add package Dloizides.Subscriptions.AspNetCore --version 1.0.5
NuGet\Install-Package Dloizides.Subscriptions.AspNetCore -Version 1.0.5
<PackageReference Include="Dloizides.Subscriptions.AspNetCore" Version="1.0.5" />
<PackageVersion Include="Dloizides.Subscriptions.AspNetCore" Version="1.0.5" />
<PackageReference Include="Dloizides.Subscriptions.AspNetCore" />
paket add Dloizides.Subscriptions.AspNetCore --version 1.0.5
#r "nuget: Dloizides.Subscriptions.AspNetCore, 1.0.5"
#:package Dloizides.Subscriptions.AspNetCore@1.0.5
#addin nuget:?package=Dloizides.Subscriptions.AspNetCore&version=1.0.5
#tool nuget:?package=Dloizides.Subscriptions.AspNetCore&version=1.0.5
Subscriptions.AspNetCore
Reusable platform-subscription billing for multi-tenant ASP.NET Core SaaS.
Pairs Stripe Subscriptions + a plan/feature catalog + a [RequiresPlan]
attribute + a webhook handler. The consuming product brings the persistence
layer (ISubscriptionStore) and the routes; everything else is wired in
~10 lines of Program.cs.
Concepts
- Plan catalog loaded from configuration. Each plan has a code (
"free","pro","business"), a rank, a Stripe Price id (free is null), and a feature list. TenantSubscriptionSnapshotis the immutable per-tenant record the feature gates consult.ISubscriptionStoreis the per-product persistence layer. Each product implements it against its own DbContext.ISubscriptionServiceis the high-level API the product calls from endpoints:GetForTenant,CreateCheckoutSession,CreateCustomerPortalSession.[RequiresPlan("pro")]returns 402 Payment Required when the caller's plan rank is below the required tier. The 402 body carries{ currentPlan, requiredPlan, upgradePath }so the SPA can route the user to /pricing.- Stripe webhook handler verifies the HMAC + upserts the snapshot
via the store on
checkout.session.completed+customer.subscription.*events.
Wiring (consumer side)
Program.cs:
builder.Services.AddPlatformSubscriptions(builder.Configuration);
builder.Services.AddScoped<ISubscriptionStore, MyEfSubscriptionStore>();
// after app.UseAuthorization():
app.MapPlatformSubscriptionsWebhook(); // POST /api/webhooks/stripe-subscriptions
appsettings.json:
{
"PlatformSubscriptions": {
"Stripe": {
"SecretKey": "sk_test_...",
"WebhookSecret": "whsec_..."
},
"Plans": {
"free": { "DisplayName": "Free", "MonthlyPriceEur": 0, "Rank": 0, "Features": ["1-event"] },
"pro": { "DisplayName": "Pro", "MonthlyPriceEur": 19, "Rank": 10, "StripePriceId": "price_...", "Features": ["unlimited-events", "no-branding", "editor"] },
"business": { "DisplayName": "Business", "MonthlyPriceEur": 49, "Rank": 20, "StripePriceId": "price_...", "Features": ["unlimited-events", "no-branding", "editor", "team", "priority-support"] }
}
}
}
Gate an endpoint:
[Authorize(Roles = "tenant-owner")]
[RequiresPlan(PlanCode.Pro)]
public class PublishLandingConfig : EndpointWithoutRequest<...> { ... }
What the consumer owns
ISubscriptionStore— read + upsert via EF Core (or any persistence). AlsoFindTenantByStripeCustomerAsyncso the webhook can route by customer id.- The Stripe Products / Prices in their Stripe dashboard. The package reads the Price ids from config.
- The Checkout success/cancel URL design (typically per-product).
- Caching the snapshot if your feature gates fire on every request (the default store is consulted live).
Free / paid tiers
The free tier has no Stripe Subscription — TenantSubscriptionSnapshot.Status
stays None. Stripe is involved only when the tenant clicks Upgrade.
Security
- Webhook signature is verified with
Stripe.EventUtility.ConstructEvent. - The package does NOT log the Stripe secret key.
- 402 responses leak only
{ currentPlan, requiredPlan, upgradePath }— no Stripe ids, no internal state.
Stripe dashboard one-time setup
- Create Products: "Pro", "Business".
- Add a recurring Price to each (€19/mo, €49/mo). Copy the Price ids.
- Configure a Webhook endpoint:
https://<your-api>/api/webhooks/stripe-subscriptions. Subscribe to:checkout.session.completed,customer.subscription.created,customer.subscription.updated,customer.subscription.deleted. - Copy the Webhook signing secret.
- Drop the four values into the K8s Secret backing
PlatformSubscriptions:Stripe:SecretKey,PlatformSubscriptions:Stripe:WebhookSecret,PlatformSubscriptions:Plans:Pro:StripePriceId,PlatformSubscriptions:Plans:Business:StripePriceId.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Stripe.net (>= 47.4.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.