feat: Add Stripe payment integration and subscription management

- Add Stripe.net SDK for payment processing
- Implement StripeService with checkout sessions, customer portal, webhooks
- Implement SubscriptionService for quota management
- Add quota enforcement to CVCheckService
- Create Pricing, Billing, Settings pages
- Add checkout success/cancel pages
- Update Check and Dashboard with usage indicators
- Add ResetMonthlyUsageJob for billing cycle resets
- Add database migration for subscription fields

Plan tiers: Free (3 checks), Professional £49/mo (30), Enterprise £199/mo (unlimited)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 12:03:24 +00:00
parent 6f384f8d09
commit 28d7d41b25
27 changed files with 2427 additions and 1 deletions

View File

@@ -5,6 +5,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.Extensions.Http;
using Stripe;
using TrueCV.Application.Interfaces;
using TrueCV.Infrastructure.Configuration;
using TrueCV.Infrastructure.Data;
@@ -74,6 +75,16 @@ public static class DependencyInjection
services.Configure<LocalStorageSettings>(
configuration.GetSection(LocalStorageSettings.SectionName));
services.Configure<StripeSettings>(
configuration.GetSection(StripeSettings.SectionName));
// Configure Stripe API key
var stripeSettings = configuration.GetSection(StripeSettings.SectionName).Get<StripeSettings>();
if (!string.IsNullOrEmpty(stripeSettings?.SecretKey))
{
StripeConfiguration.ApiKey = stripeSettings.SecretKey;
}
// Configure HttpClient for CompaniesHouseClient with retry policy
services.AddHttpClient<CompaniesHouseClient>((serviceProvider, client) =>
{
@@ -97,6 +108,8 @@ public static class DependencyInjection
services.AddScoped<ICVCheckService, CVCheckService>();
services.AddScoped<IUserContextService, UserContextService>();
services.AddScoped<IAuditService, AuditService>();
services.AddScoped<IStripeService, StripeService>();
services.AddScoped<ISubscriptionService, Services.SubscriptionService>();
// Register file storage - use local storage if configured, otherwise Azure
var useLocalStorage = configuration.GetValue<bool>("UseLocalStorage");
@@ -111,6 +124,7 @@ public static class DependencyInjection
// Register Hangfire jobs
services.AddTransient<ProcessCVCheckJob>();
services.AddTransient<ResetMonthlyUsageJob>();
return services;
}