QrRapido/Controllers/PremiumController.cs
Ricardo Carneiro 2ccd35bb7d
Some checks failed
Deploy QR Rapido / test (push) Successful in 4m58s
Deploy QR Rapido / build-and-push (push) Failing after 1m39s
Deploy QR Rapido / deploy-staging (push) Has been skipped
Deploy QR Rapido / deploy-production (push) Has been skipped
first commit
2025-07-28 11:46:48 -03:00

230 lines
8.0 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using QRRapidoApp.Models.ViewModels;
using QRRapidoApp.Services;
using System.Security.Claims;
namespace QRRapidoApp.Controllers
{
[Authorize]
public class PremiumController : Controller
{
private readonly StripeService _stripeService;
private readonly IUserService _userService;
private readonly AdDisplayService _adDisplayService;
private readonly IConfiguration _config;
private readonly ILogger<PremiumController> _logger;
public PremiumController(StripeService stripeService, IUserService userService, AdDisplayService adDisplayService, IConfiguration config, ILogger<PremiumController> logger)
{
_stripeService = stripeService;
_userService = userService;
_adDisplayService = adDisplayService;
_config = config;
_logger = logger;
}
[HttpGet]
public async Task<IActionResult> Upgrade()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return RedirectToAction("Login", "Account");
}
var user = await _userService.GetUserAsync(userId);
if (user?.IsPremium == true)
{
return RedirectToAction("Dashboard");
}
var model = new UpgradeViewModel
{
CurrentPlan = "Free",
PremiumPrice = _config.GetValue<decimal>("Premium:PremiumPrice"),
Features = _config.GetSection("Premium:Features").Get<Dictionary<string, bool>>() ?? new(),
RemainingQRs = await _userService.GetDailyQRCountAsync(userId),
IsAdFreeActive = !await _adDisplayService.ShouldShowAds(userId),
DaysUntilAdExpiry = (int)((await _adDisplayService.GetAdFreeExpiryDate(userId) - DateTime.UtcNow)?.TotalDays ?? 0)
};
return View(model);
}
[HttpPost]
public async Task<IActionResult> CreateCheckout()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Json(new { success = false, error = "User not authenticated" });
}
var priceId = _config["Stripe:PriceId"];
if (string.IsNullOrEmpty(priceId))
{
return Json(new { success = false, error = "Stripe not configured" });
}
try
{
var checkoutUrl = await _stripeService.CreateCheckoutSessionAsync(userId, priceId);
return Json(new { success = true, url = checkoutUrl });
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error creating checkout session for user {userId}");
return Json(new { success = false, error = ex.Message });
}
}
[HttpGet]
public async Task<IActionResult> Success(string session_id)
{
if (string.IsNullOrEmpty(session_id))
{
return RedirectToAction("Upgrade");
}
try
{
ViewBag.Success = true;
ViewBag.SessionId = session_id;
return View();
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error processing successful payment for session {session_id}");
return RedirectToAction("Upgrade");
}
}
[HttpGet]
public IActionResult Cancel()
{
ViewBag.Cancelled = true;
return View("Upgrade");
}
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> StripeWebhook()
{
try
{
using var reader = new StreamReader(HttpContext.Request.Body);
var json = await reader.ReadToEndAsync();
var signature = Request.Headers["Stripe-Signature"].FirstOrDefault();
if (string.IsNullOrEmpty(signature))
{
return BadRequest("Missing Stripe signature");
}
await _stripeService.HandleWebhookAsync(json, signature);
return Ok();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing Stripe webhook");
return BadRequest(ex.Message);
}
}
[HttpGet]
public async Task<IActionResult> Dashboard()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return RedirectToAction("Login", "Account");
}
var user = await _userService.GetUserAsync(userId);
if (user?.IsPremium != true)
{
return RedirectToAction("Upgrade");
}
var model = new PremiumDashboardViewModel
{
User = user,
QRCodesThisMonth = await _userService.GetQRCountThisMonthAsync(userId),
TotalQRCodes = user.QRHistoryIds?.Count ?? 0,
SubscriptionStatus = await _stripeService.GetSubscriptionStatusAsync(user.StripeSubscriptionId),
RecentQRCodes = await _userService.GetUserQRHistoryAsync(userId, 10)
};
// Calculate next billing date (simplified)
if (user.PremiumExpiresAt.HasValue)
{
model.NextBillingDate = user.PremiumExpiresAt.Value.AddDays(-2); // Approximate
}
// QR type statistics
model.QRTypeStats = model.RecentQRCodes
.GroupBy(q => q.Type)
.ToDictionary(g => g.Key, g => g.Count());
return View(model);
}
[HttpPost]
public async Task<IActionResult> CancelSubscription()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Json(new { success = false, error = "User not authenticated" });
}
try
{
var user = await _userService.GetUserAsync(userId);
if (user?.StripeSubscriptionId == null)
{
return Json(new { success = false, error = "No active subscription found" });
}
var success = await _stripeService.CancelSubscriptionAsync(user.StripeSubscriptionId);
if (success)
{
TempData["Success"] = "Assinatura cancelada com sucesso. Você manterá o acesso premium até o final do período pago.";
return Json(new { success = true });
}
else
{
return Json(new { success = false, error = "Failed to cancel subscription" });
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error canceling subscription for user {userId}");
return Json(new { success = false, error = ex.Message });
}
}
[HttpGet]
public async Task<IActionResult> BillingPortal()
{
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return RedirectToAction("Login", "Account");
}
try
{
// This would create a Stripe billing portal session
// For now, redirect to dashboard
return RedirectToAction("Dashboard");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error creating billing portal for user {userId}");
return RedirectToAction("Dashboard");
}
}
}
}