feat: implement Stripe product configuration and add token-based input validation using Microsoft.ML.Tokenizers
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NexusReader.Application.Abstractions.Services;
|
||||
using NexusReader.Domain.Entities;
|
||||
using NexusReader.Infrastructure.Configuration;
|
||||
using NexusReader.Infrastructure.Persistence;
|
||||
|
||||
namespace NexusReader.Infrastructure.Services;
|
||||
@@ -10,44 +13,83 @@ public class BillingService : IBillingService
|
||||
{
|
||||
private readonly AppDbContext _dbContext;
|
||||
private readonly UserManager<NexusUser> _userManager;
|
||||
private readonly StripeSettings _stripeSettings;
|
||||
private readonly ILogger<BillingService> _logger;
|
||||
|
||||
public BillingService(AppDbContext dbContext, UserManager<NexusUser> userManager)
|
||||
public BillingService(
|
||||
AppDbContext dbContext,
|
||||
UserManager<NexusUser> userManager,
|
||||
IOptions<StripeSettings> stripeSettings,
|
||||
ILogger<BillingService> logger)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_userManager = userManager;
|
||||
_stripeSettings = stripeSettings.Value;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<bool> HandleSubscriptionUpdatedAsync(string customerEmail, string stripeProductId)
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(customerEmail);
|
||||
if (user == null) return false;
|
||||
if (user == null)
|
||||
{
|
||||
_logger.LogWarning("Attempted to update subscription for non-existent user: {Email}", customerEmail);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Map Stripe Product IDs to Nexus Plans
|
||||
// These IDs would typically come from configuration
|
||||
if (stripeProductId.Contains("pro"))
|
||||
if (stripeProductId == _stripeSettings.ProProductId)
|
||||
{
|
||||
user.CurrentPlan = "Pro";
|
||||
user.AITokenLimit = 50000;
|
||||
}
|
||||
else if (stripeProductId.Contains("basic"))
|
||||
else if (stripeProductId == _stripeSettings.BasicProductId)
|
||||
{
|
||||
user.CurrentPlan = "Basic";
|
||||
user.AITokenLimit = 10000;
|
||||
}
|
||||
else if (stripeProductId == _stripeSettings.FreeProductId || string.IsNullOrEmpty(stripeProductId))
|
||||
{
|
||||
user.CurrentPlan = "Free";
|
||||
user.AITokenLimit = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("Unrecognized Stripe Product ID: {ProductId} for user {Email}. Falling back to Free tier.", stripeProductId, customerEmail);
|
||||
user.CurrentPlan = "Free";
|
||||
user.AITokenLimit = 1000;
|
||||
}
|
||||
|
||||
var result = await _userManager.UpdateAsync(user);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
_logger.LogError("Failed to update user {Email} after subscription change: {Errors}",
|
||||
customerEmail, string.Join(", ", result.Errors.Select(e => e.Description)));
|
||||
return false;
|
||||
}
|
||||
|
||||
await _userManager.UpdateAsync(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> HandleSubscriptionDeletedAsync(string customerEmail)
|
||||
{
|
||||
var user = await _userManager.FindByEmailAsync(customerEmail);
|
||||
if (user == null) return false;
|
||||
if (user == null)
|
||||
{
|
||||
_logger.LogWarning("Attempted to delete subscription for non-existent user: {Email}", customerEmail);
|
||||
return false;
|
||||
}
|
||||
|
||||
user.CurrentPlan = "Free";
|
||||
user.AITokenLimit = 1000; // Reset to free limit
|
||||
|
||||
await _userManager.UpdateAsync(user);
|
||||
var result = await _userManager.UpdateAsync(user);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
_logger.LogError("Failed to reset user {Email} to Free tier after subscription deletion: {Errors}",
|
||||
customerEmail, string.Join(", ", result.Errors.Select(e => e.Description)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user