fix: log com delay temporario para logar pagamento
All checks were successful
BCards Deployment Pipeline / Run Tests (push) Successful in 2s
BCards Deployment Pipeline / PR Validation (push) Has been skipped
BCards Deployment Pipeline / Build and Push Image (push) Successful in 15m41s
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (push) Successful in 1m14s
BCards Deployment Pipeline / Deploy to Staging (x86 - Local) (push) Has been skipped
BCards Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
BCards Deployment Pipeline / Deployment Summary (push) Successful in 0s

This commit is contained in:
Ricardo Carneiro 2025-08-31 22:28:20 -03:00
parent 406c298afb
commit 6042eb59e6
4 changed files with 132 additions and 73 deletions

View File

@ -18,6 +18,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Pipeline", "Pipeline", "{3F
.gitea\workflows\deploy-bcards.yml = .gitea\workflows\deploy-bcards.yml .gitea\workflows\deploy-bcards.yml = .gitea\workflows\deploy-bcards.yml
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}"
ProjectSection(SolutionItems) = preProject
Conexoes.txt = Conexoes.txt
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU

4
Conexoes.txt Normal file
View File

@ -0,0 +1,4 @@
bcards
ssh ubuntu@141.148.162.114
convert-it
ssh ubuntu@129.146.116.218

View File

@ -50,6 +50,7 @@ public class StripeWebhookController : ControllerBase
return BadRequest("Missing Stripe signature"); return BadRequest("Missing Stripe signature");
} }
_logger.LogInformation($"Contruir evento Stripe: {json}");
var stripeEvent = EventUtility.ConstructEvent( var stripeEvent = EventUtility.ConstructEvent(
json, json,
stripeSignature, stripeSignature,
@ -82,15 +83,18 @@ public class StripeWebhookController : ControllerBase
break; break;
} }
await Task.Delay(2000); // 2 segundos
return Ok(); return Ok();
} }
catch (StripeException ex) catch (StripeException ex)
{ {
await Task.Delay(2000); // 2 segundos
_logger.LogError(ex, "Stripe webhook error"); _logger.LogError(ex, "Stripe webhook error");
return BadRequest($"Stripe error: {ex.Message}"); return BadRequest($"Stripe error: {ex.Message}");
} }
catch (Exception ex) catch (Exception ex)
{ {
await Task.Delay(2000); // 2 segundos
_logger.LogError(ex, "Webhook processing error"); _logger.LogError(ex, "Webhook processing error");
return StatusCode(500, "Internal server error"); return StatusCode(500, "Internal server error");
} }
@ -98,116 +102,164 @@ public class StripeWebhookController : ControllerBase
private async Task HandlePaymentSucceeded(Event stripeEvent) private async Task HandlePaymentSucceeded(Event stripeEvent)
{ {
if (stripeEvent.Data.Object is Invoice invoice) try
{ {
_logger.LogInformation($"Payment succeeded for customer: {invoice.CustomerId}"); if (stripeEvent.Data.Object is Invoice invoice)
var subscriptionId = GetSubscriptionId(stripeEvent);
var subscription = await _subscriptionRepository.GetByStripeSubscriptionIdAsync(subscriptionId);
if (subscription != null)
{ {
subscription.Status = "active"; _logger.LogInformation($"Payment succeeded for customer: {invoice.CustomerId}");
subscription.UpdatedAt = DateTime.UtcNow;
await _subscriptionRepository.UpdateAsync(subscription);
// Reactivate user pages var subscriptionId = GetSubscriptionId(stripeEvent);
var userPages = await _userPageService.GetUserPagesAsync(subscription.UserId); var subscription = await _subscriptionRepository.GetByStripeSubscriptionIdAsync(subscriptionId);
foreach (var page in userPages.Where(p => p.Status == ViewModels.PageStatus.PendingPayment)) if (subscription != null)
{ {
page.Status = ViewModels.PageStatus.Active; subscription.Status = "active";
page.UpdatedAt = DateTime.UtcNow; subscription.UpdatedAt = DateTime.UtcNow;
await _userPageService.UpdatePageAsync(page); await _subscriptionRepository.UpdateAsync(subscription);
}
_logger.LogInformation($"Reactivated {userPages.Count} pages for user {subscription.UserId}"); // Reactivate user pages
var userPages = await _userPageService.GetUserPagesAsync(subscription.UserId);
foreach (var page in userPages.Where(p => p.Status == ViewModels.PageStatus.PendingPayment))
{
page.Status = ViewModels.PageStatus.Active;
page.UpdatedAt = DateTime.UtcNow;
await _userPageService.UpdatePageAsync(page);
}
_logger.LogInformation($"Reactivated {userPages.Count} pages for user {subscription.UserId}");
}
} }
else
{
_logger.LogWarning($"Unexpected event type on HandlePaymentSucceeded: {stripeEvent.Type}");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error handling payment succeeded event");
throw new Exception("Error handling payment succeeded event", ex);
} }
} }
private async Task HandlePaymentFailed(Event stripeEvent) private async Task HandlePaymentFailed(Event stripeEvent)
{ {
if (stripeEvent.Data.Object is Invoice invoice) try
{ {
_logger.LogInformation($"Payment failed for customer: {invoice.CustomerId}"); if (stripeEvent.Data.Object is Invoice invoice)
var subscriptionId = GetSubscriptionId(stripeEvent);
var subscription = await _subscriptionRepository.GetByStripeSubscriptionIdAsync(subscriptionId);
if (subscription != null)
{ {
subscription.Status = "past_due"; _logger.LogInformation($"Payment failed for customer: {invoice.CustomerId}");
subscription.UpdatedAt = DateTime.UtcNow;
await _subscriptionRepository.UpdateAsync(subscription);
// Set pages to pending payment var subscriptionId = GetSubscriptionId(stripeEvent);
var userPages = await _userPageService.GetUserPagesAsync(subscription.UserId); var subscription = await _subscriptionRepository.GetByStripeSubscriptionIdAsync(subscriptionId);
foreach (var page in userPages.Where(p => p.Status == ViewModels.PageStatus.Active)) if (subscription != null)
{ {
page.Status = ViewModels.PageStatus.PendingPayment; subscription.Status = "past_due";
page.UpdatedAt = DateTime.UtcNow; subscription.UpdatedAt = DateTime.UtcNow;
await _userPageService.UpdatePageAsync(page); await _subscriptionRepository.UpdateAsync(subscription);
}
_logger.LogInformation($"Set {userPages.Count} pages to pending payment for user {subscription.UserId}"); // Set pages to pending payment
var userPages = await _userPageService.GetUserPagesAsync(subscription.UserId);
foreach (var page in userPages.Where(p => p.Status == ViewModels.PageStatus.Active))
{
page.Status = ViewModels.PageStatus.PendingPayment;
page.UpdatedAt = DateTime.UtcNow;
await _userPageService.UpdatePageAsync(page);
}
_logger.LogInformation($"Set {userPages.Count} pages to pending payment for user {subscription.UserId}");
}
} }
else
{
_logger.LogWarning($"Unexpected event type on HandlePaymentFailed: {stripeEvent.Type}");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error handling payment failed event");
throw new Exception("Error handling payment failed event", ex);
} }
} }
private async Task HandleSubscriptionDeleted(Event stripeEvent) private async Task HandleSubscriptionDeleted(Event stripeEvent)
{ {
if (stripeEvent.Data.Object is Subscription stripeSubscription) try
{ {
_logger.LogInformation($"Subscription cancelled: {stripeSubscription.Id}"); if (stripeEvent.Data.Object is Subscription stripeSubscription)
var subscription = await _subscriptionRepository.GetByStripeSubscriptionIdAsync(stripeSubscription.Id);
if (subscription != null)
{ {
subscription.Status = "cancelled"; _logger.LogInformation($"Subscription cancelled: {stripeSubscription.Id}");
subscription.UpdatedAt = DateTime.UtcNow;
await _subscriptionRepository.UpdateAsync(subscription);
// Downgrade to trial or deactivate pages var subscription = await _subscriptionRepository.GetByStripeSubscriptionIdAsync(stripeSubscription.Id);
var userPages = await _userPageService.GetUserPagesAsync(subscription.UserId); if (subscription != null)
foreach (var page in userPages.Where(p => p.Status == ViewModels.PageStatus.Active))
{ {
page.Status = ViewModels.PageStatus.Expired; subscription.Status = "cancelled";
page.UpdatedAt = DateTime.UtcNow; subscription.UpdatedAt = DateTime.UtcNow;
await _userPageService.UpdatePageAsync(page); await _subscriptionRepository.UpdateAsync(subscription);
}
_logger.LogInformation($"Deactivated {userPages.Count} pages for cancelled subscription {subscription.UserId}"); // Downgrade to trial or deactivate pages
var userPages = await _userPageService.GetUserPagesAsync(subscription.UserId);
foreach (var page in userPages.Where(p => p.Status == ViewModels.PageStatus.Active))
{
page.Status = ViewModels.PageStatus.Expired;
page.UpdatedAt = DateTime.UtcNow;
await _userPageService.UpdatePageAsync(page);
}
_logger.LogInformation($"Deactivated {userPages.Count} pages for cancelled subscription {subscription.UserId}");
}
} }
else
{
_logger.LogWarning($"Unexpected event type on HandlePaymentFailed: {stripeEvent.Type}");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error handling subscription deleted failed event");
throw new Exception("Error handling subscription deleted failed event", ex);
} }
} }
private async Task HandleSubscriptionUpdated(Event stripeEvent) private async Task HandleSubscriptionUpdated(Event stripeEvent)
{ {
if (stripeEvent.Data.Object is Subscription stripeSubscription) try
{ {
_logger.LogInformation($"Subscription updated: {stripeSubscription.Id}"); if (stripeEvent.Data.Object is Subscription stripeSubscription)
var subscription = await _subscriptionRepository.GetByStripeSubscriptionIdAsync(stripeSubscription.Id);
if (subscription != null)
{ {
var service = new SubscriptionItemService(); _logger.LogInformation($"Subscription updated: {stripeSubscription.Id}");
var subItem = service.Get(stripeSubscription.Items.Data[0].Id);
subscription.Status = stripeSubscription.Status; var subscription = await _subscriptionRepository.GetByStripeSubscriptionIdAsync(stripeSubscription.Id);
subscription.CurrentPeriodStart = subItem.CurrentPeriodStart; if (subscription != null)
subscription.CurrentPeriodEnd = subItem.CurrentPeriodEnd;
subscription.CancelAtPeriodEnd = stripeSubscription.CancelAtPeriodEnd;
subscription.UpdatedAt = DateTime.UtcNow;
// Update plan type based on Stripe price ID
var priceId = stripeSubscription.Items.Data.FirstOrDefault()?.Price.Id;
if (!string.IsNullOrEmpty(priceId))
{ {
subscription.PlanType = MapPriceIdToPlanType(priceId); var service = new SubscriptionItemService();
var subItem = service.Get(stripeSubscription.Items.Data[0].Id);
subscription.Status = stripeSubscription.Status;
subscription.CurrentPeriodStart = subItem.CurrentPeriodStart;
subscription.CurrentPeriodEnd = subItem.CurrentPeriodEnd;
subscription.CancelAtPeriodEnd = stripeSubscription.CancelAtPeriodEnd;
subscription.UpdatedAt = DateTime.UtcNow;
// Update plan type based on Stripe price ID
var priceId = stripeSubscription.Items.Data.FirstOrDefault()?.Price.Id;
if (!string.IsNullOrEmpty(priceId))
{
subscription.PlanType = MapPriceIdToPlanType(priceId);
}
await _subscriptionRepository.UpdateAsync(subscription);
_logger.LogInformation($"Updated subscription for user {subscription.UserId}");
} }
await _subscriptionRepository.UpdateAsync(subscription);
_logger.LogInformation($"Updated subscription for user {subscription.UserId}");
} }
else
{
_logger.LogWarning($"Unexpected event type on HandlePaymentFailed: {stripeEvent.Type}");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error handling subscription updated failed event");
throw new Exception("Error handling subscription updated failed event", ex);
} }
} }

View File

@ -45,7 +45,6 @@ if (isDevelopment)
.WriteTo.Async(a => a.Console( .WriteTo.Async(a => a.Console(
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] [{Hostname}] {Message:lj} {Properties:j}{NewLine}{Exception}")); outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] [{Hostname}] {Message:lj} {Properties:j}{NewLine}{Exception}"));
// Also send to Seq if configured (for local development with Seq)
var seqUrl = builder.Configuration["Serilog:SeqUrl"]; var seqUrl = builder.Configuration["Serilog:SeqUrl"];
if (!string.IsNullOrEmpty(seqUrl)) if (!string.IsNullOrEmpty(seqUrl))
{ {
@ -64,7 +63,6 @@ else
restrictedToMinimumLevel: LogEventLevel.Error, restrictedToMinimumLevel: LogEventLevel.Error,
outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] [{Hostname}] {Message:lj}{NewLine}{Exception}")); outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] [{Hostname}] {Message:lj}{NewLine}{Exception}"));
// Production: Send detailed logs to Seq
var seqUrl = builder.Configuration["Serilog:SeqUrl"]; var seqUrl = builder.Configuration["Serilog:SeqUrl"];
if (!string.IsNullOrEmpty(seqUrl)) if (!string.IsNullOrEmpty(seqUrl))
{ {