Mitc.Integrations.Stripe 1.0.4
Mitc.Integrations.Stripe
A turnkey Stripe integration library for ASP.NET Core applications. Handles webhook processing, product/price catalog syncing, subscription management, checkout session creation, and metered usage reporting.
Supported Frameworks
- .NET 8
- .NET 9
- .NET 10
Setup
1. Configuration
Add a StripeOptions section to your appsettings.json:
{
"StripeOptions": {
"ApiKey": "sk_...",
"EndpointSecret": "whsec_...",
"RegistrationCompletedPage": "https://example.com/registration/complete",
"RegistrationCancelledPage": "https://example.com/registration/cancelled",
"AllowLiveEvents": true,
"AllowTestEvents": false,
"SyncInterval": "01:00:00",
"ReportFrequency": "01:00:00",
"ProcessingDelay": "00:00:05",
"ProcessingInterval": "00:00:01",
"EventCleanupInterval": "1.00:00:00",
"EventRetentionPeriod": "30.00:00:00",
"TrialPeriodDays": 14
}
}
| Option | Description |
|---|---|
ApiKey |
Stripe secret API key. Required. |
EndpointSecret |
Stripe webhook signing secret. Required. |
RegistrationCompletedPage |
URL the customer is redirected to after checkout. Required. |
RegistrationCancelledPage |
URL the customer is redirected to if they cancel checkout. Required. |
AllowLiveEvents |
Accept events from Stripe live mode. At least one of AllowLiveEvents / AllowTestEvents must be true. |
AllowTestEvents |
Accept events from Stripe test mode. |
SyncInterval |
How often to poll Stripe for product/price catalog changes (fallback; webhook events are the primary mechanism). |
ReportFrequency |
How often metered usage is reported to Stripe. |
ProcessingDelay |
Grace period before processing an event, allowing out-of-order events to arrive. |
ProcessingInterval |
How often the event processor drains and processes queued events. |
EventCleanupInterval |
How often old processed events are cleaned up from the database. |
EventRetentionPeriod |
How long processed events are retained before deletion. |
TrialPeriodDays |
Optional trial period applied to new subscriptions created through checkout. |
LocalUrlAndPort |
Optional. When set in development, the Stripe CLI is used to forward events to this address. |
2. Register Services
builder.SetupStripeIntegration();
This registers all required services, background workers, and a webhook controller endpoint at POST /stripe/webhook.
3. EF Core Entity Configuration
The library provides entity classes that must be mapped in your DbContext. Add the following DbSet properties and configure them in OnModelCreating:
StripeEventStripeProduct/StripePriceStripeSubscription/StripeSubscriptionItem
4. Implement Required Interfaces
Stores — Inherit from the provided base classes, passing your application's DbContext:
public class MyStripeEventStore(AppDbContext db) : StripeEventStoreBase(db);
public class MyStripeProductStore(AppDbContext db) : StripeProductStoreBase(db);
public class MyStripePriceStore(AppDbContext db) : StripePriceStoreBase(db);
public class MyStripeSubscriptionStore(AppDbContext db) : StripeSubscriptionStoreBase(db);
Checkout session event handler — No default implementation is provided; you must supply one:
public class MyCheckoutHandler : IStripeCheckoutSessionEventHandler
{
public Task HandleCheckoutSessionCompleted(Session session) { /* ... */ }
public Task HandleCheckoutSessionExpired(Session session) { /* ... */ }
}
Usage report generator — Required by the usage reporting service. Return one SubscriberUsage per active subscription item. Only include active, non-cancelled subscriptions; cancelled or ended subscriptions should be filtered out by your query:
public class MyUsageReportGenerator : IStripeUsageReportGenerator
{
public Task<IEnumerable<SubscriberUsage>> GetUsagesAsync() { /* ... */ }
}
Customizing Services
Use the builder callback to override any default store or event handler:
builder.SetupStripeIntegration(stripe => stripe
.AddEventStore<MyStripeEventStore>()
.AddProductStore<MyStripeProductStore>()
.AddPriceStore<MyStripePriceStore>()
.AddSubscriptionStore<MyStripeSubscriptionStore>()
.AddCheckoutSessionEventHandler<MyCheckoutHandler>()
);
Builder overrides are registered before the library's defaults, so TryAddScoped will skip any service you've already configured.
Available Builder Methods
Stores (scoped, depend on DbContext):
| Method | Interface |
|---|---|
AddEventStore<T>() |
IStripeEventStore |
AddProductStore<T>() |
IStripeProductStore |
AddPriceStore<T>() |
IStripePriceStore |
AddSubscriptionStore<T>() |
IStripeSubscriptionStore |
Event handlers (scoped):
| Method | Interface |
|---|---|
AddCheckoutSessionEventHandler<T>() |
IStripeCheckoutSessionEventHandler |
AddProductEventHandler<T>() |
IStripeProductEventHandler |
AddPriceEventHandler<T>() |
IStripePriceEventHandler |
AddSubscriptionEventHandler<T>() |
IStripeSubscriptionEventHandler |
Architecture
Event Processing Pipeline
Stripe webhook
-> StripeController (POST /stripe/webhook)
-> IStripeEventParser (signature verification)
-> IStripeEventDispatcher (deduplication + delay queue)
-> StripeEventProcessor (background service, periodic drain)
-> IStripeEventStore (persist)
-> IStripe*EventHandler (handle by type)
Events are held in a priority queue for ProcessingDelay before processing. This allows out-of-order events to arrive and be grouped by object ID, ensuring related events are processed sequentially.
Background Services
| Service | Responsibility |
|---|---|
StripeEventProcessor |
Drains queued webhook events and dispatches to handlers. |
StripeEventCleanupService |
Deletes processed events older than EventRetentionPeriod. |
StripeOfferingSyncService |
Periodically syncs the product/price catalog from Stripe. Deactivates local products and prices that no longer exist on Stripe. |
StripeUsageReportingService |
Reports metered subscription usage to Stripe. |
Handled Webhook Events
| Category | Events |
|---|---|
| Checkout Session | completed, expired |
| Product | created, updated, deleted |
| Price | created, updated, deleted |
| Subscription | created, updated, deleted, paused, resumed |
Metadata
StripeMetadata provides strongly-typed access to Stripe metadata dictionaries via DataKey<T>:
public static readonly DataKey<Guid> RegistrationId = new("registration_id");
// Writing
var metadata = new StripeMetadata();
metadata.Add(RegistrationId, someGuid);
// Reading
Guid id = metadata.Get(RegistrationId);
Guid? maybeId = metadata.TryGet(RegistrationId);
Includes an EF Core ValueConverter (StripeMetadataValueConverter) for database persistence.
Checkout
IStripeCheckoutService creates Stripe Checkout sessions for subscriptions:
public class MyService(IStripeCheckoutService checkoutService)
{
public async Task StartCheckout(ICheckoutRequest request, StripeMetadata metadata)
{
var session = await checkoutService.CreateCheckoutSessionAsync(request, metadata);
// Redirect user to session.Url
}
}
The provided metadata is attached to both the checkout session and the subscription.
Local Development
When builder.Environment.IsDevelopment() is true, the library:
- Bypasses Stripe webhook signature verification
- Starts a
StripeLocalEventListenerthat uses the Stripe CLI to forward events to your local server (requires the Stripe CLI to be installed andLocalUrlAndPortto be configured)
No packages depend on Mitc.Integrations.Stripe.
.NET 8.0
- CliWrap (>= 3.10.0)
- Microsoft.EntityFrameworkCore (>= 8.0.23)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.2)
- Stripe.net (>= 50.3.0)
.NET 9.0
- CliWrap (>= 3.10.0)
- Microsoft.EntityFrameworkCore (>= 9.0.12)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.2)
- Stripe.net (>= 50.3.0)
.NET 10.0
- CliWrap (>= 3.10.0)
- Microsoft.EntityFrameworkCore (>= 10.0.2)
- Stripe.net (>= 50.3.0)
| Version | Downloads | Last updated |
|---|---|---|
| 1.6.0 | 0 | 4/29/2026 |
| 1.5.0 | 0 | 4/13/2026 |
| 1.4.0 | 0 | 4/13/2026 |
| 1.3.6 | 15 | 2/21/2026 |
| 1.3.5 | 0 | 2/18/2026 |
| 1.3.1 | 27 | 2/18/2026 |
| 1.3.0 | 5 | 2/17/2026 |
| 1.2.9 | 4 | 2/12/2026 |
| 1.2.8 | 7 | 2/11/2026 |
| 1.2.7 | 1 | 2/11/2026 |
| 1.2.6 | 1 | 2/11/2026 |
| 1.2.5 | 1 | 2/11/2026 |
| 1.2.4 | 1 | 2/11/2026 |
| 1.2.3 | 1 | 2/11/2026 |
| 1.2.2 | 2 | 2/11/2026 |
| 1.2.1 | 1 | 2/11/2026 |
| 1.2.0 | 1 | 2/11/2026 |
| 1.1.9 | 1 | 2/10/2026 |
| 1.1.8 | 1 | 2/10/2026 |
| 1.1.7 | 1 | 2/9/2026 |
| 1.1.6 | 1 | 2/9/2026 |
| 1.1.5 | 1 | 2/9/2026 |
| 1.1.4 | 1 | 2/9/2026 |
| 1.1.3 | 1 | 2/9/2026 |
| 1.1.2 | 1 | 2/9/2026 |
| 1.1.1 | 1 | 2/9/2026 |
| 1.1.0 | 1 | 2/9/2026 |
| 1.0.10 | 1 | 2/9/2026 |
| 1.0.9 | 1 | 2/7/2026 |
| 1.0.8 | 1 | 2/7/2026 |
| 1.0.7 | 1 | 2/7/2026 |
| 1.0.6 | 1 | 2/7/2026 |
| 1.0.5 | 1 | 2/7/2026 |
| 1.0.4 | 1 | 2/7/2026 |
| 1.0.3 | 1 | 2/7/2026 |
| 1.0.2 | 1 | 2/6/2026 |
| 1.0.1 | 0 | 2/6/2026 |
| 1.0.0 | 0 | 2/6/2026 |