[PM-31040] Add logging to bank account setup process (#6898)

* Add logging to bank account setup process

* Missed test file constructor
This commit is contained in:
Alex Morask
2026-01-26 11:46:08 -06:00
committed by GitHub
parent afb087161a
commit 5104ec5f98
4 changed files with 28 additions and 5 deletions

View File

@@ -9,6 +9,7 @@ namespace Bit.Billing.Services.Implementations;
public class StripeEventService( public class StripeEventService(
GlobalSettings globalSettings, GlobalSettings globalSettings,
ILogger<StripeEventService> logger,
IOrganizationRepository organizationRepository, IOrganizationRepository organizationRepository,
IProviderRepository providerRepository, IProviderRepository providerRepository,
ISetupIntentCache setupIntentCache, ISetupIntentCache setupIntentCache,
@@ -148,26 +149,36 @@ public class StripeEventService(
{ {
var setupIntent = await GetSetupIntent(localStripeEvent); var setupIntent = await GetSetupIntent(localStripeEvent);
logger.LogInformation("Extracted Setup Intent ({SetupIntentId}) from Stripe 'setup_intent.succeeded' event", setupIntent.Id);
var subscriberId = await setupIntentCache.GetSubscriberIdForSetupIntent(setupIntent.Id); var subscriberId = await setupIntentCache.GetSubscriberIdForSetupIntent(setupIntent.Id);
logger.LogInformation("Retrieved subscriber ID ({SubscriberId}) from cache for Setup Intent ({SetupIntentId})", subscriberId, setupIntent.Id);
if (subscriberId == null) if (subscriberId == null)
{ {
logger.LogError("Cached subscriber ID for Setup Intent ({SetupIntentId}) is null", setupIntent.Id);
return null; return null;
} }
var organization = await organizationRepository.GetByIdAsync(subscriberId.Value); var organization = await organizationRepository.GetByIdAsync(subscriberId.Value);
logger.LogInformation("Retrieved organization ({OrganizationId}) via subscriber ID for Setup Intent ({SetupIntentId})", organization?.Id, setupIntent.Id);
if (organization is { GatewayCustomerId: not null }) if (organization is { GatewayCustomerId: not null })
{ {
var organizationCustomer = await stripeFacade.GetCustomer(organization.GatewayCustomerId); var organizationCustomer = await stripeFacade.GetCustomer(organization.GatewayCustomerId);
logger.LogInformation("Retrieved customer ({CustomerId}) via organization ID for Setup Intent ({SetupIntentId})", organization.Id, setupIntent.Id);
return organizationCustomer.Metadata; return organizationCustomer.Metadata;
} }
var provider = await providerRepository.GetByIdAsync(subscriberId.Value); var provider = await providerRepository.GetByIdAsync(subscriberId.Value);
logger.LogInformation("Retrieved provider ({ProviderId}) via subscriber ID for Setup Intent ({SetupIntentId})", provider?.Id, setupIntent.Id);
if (provider is not { GatewayCustomerId: not null }) if (provider is not { GatewayCustomerId: not null })
{ {
return null; return null;
} }
var providerCustomer = await stripeFacade.GetCustomer(provider.GatewayCustomerId); var providerCustomer = await stripeFacade.GetCustomer(provider.GatewayCustomerId);
logger.LogInformation("Retrieved customer ({CustomerId}) via provider ID for Setup Intent ({SetupIntentId})", provider.Id, setupIntent.Id);
return providerCustomer.Metadata; return providerCustomer.Metadata;
} }
} }

View File

@@ -1,11 +1,13 @@
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Bit.Core.Billing.Caches.Implementations; namespace Bit.Core.Billing.Caches.Implementations;
public class SetupIntentDistributedCache( public class SetupIntentDistributedCache(
[FromKeyedServices("persistent")] [FromKeyedServices("persistent")]
IDistributedCache distributedCache) : ISetupIntentCache IDistributedCache distributedCache,
ILogger<SetupIntentDistributedCache> logger) : ISetupIntentCache
{ {
public async Task<string?> GetSetupIntentIdForSubscriber(Guid subscriberId) public async Task<string?> GetSetupIntentIdForSubscriber(Guid subscriberId)
{ {
@@ -17,12 +19,13 @@ public class SetupIntentDistributedCache(
{ {
var cacheKey = GetCacheKeyBySetupIntentId(setupIntentId); var cacheKey = GetCacheKeyBySetupIntentId(setupIntentId);
var value = await distributedCache.GetStringAsync(cacheKey); var value = await distributedCache.GetStringAsync(cacheKey);
if (string.IsNullOrEmpty(value) || !Guid.TryParse(value, out var subscriberId)) if (!string.IsNullOrEmpty(value) && Guid.TryParse(value, out var subscriberId))
{ {
return null;
}
return subscriberId; return subscriberId;
} }
logger.LogError("Subscriber ID value ({Value}) cached for Setup Intent ({SetupIntentId}) is null or not a valid Guid", value, setupIntentId);
return null;
}
public async Task RemoveSetupIntentForSubscriber(Guid subscriberId) public async Task RemoveSetupIntentForSubscriber(Guid subscriberId)
{ {

View File

@@ -94,6 +94,8 @@ public class UpdatePaymentMethodCommand(
await setupIntentCache.Set(subscriber.Id, setupIntent.Id); await setupIntentCache.Set(subscriber.Id, setupIntent.Id);
_logger.LogInformation("{Command}: Successfully cached Setup Intent ({SetupIntentId}) for subscriber ({SubscriberID})", CommandName, setupIntent.Id, subscriber.Id);
await UnlinkBraintreeCustomerAsync(customer); await UnlinkBraintreeCustomerAsync(customer);
return MaskedPaymentMethod.From(setupIntent); return MaskedPaymentMethod.From(setupIntent);

View File

@@ -4,6 +4,7 @@ using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Billing.Caches; using Bit.Core.Billing.Caches;
using Bit.Core.Repositories; using Bit.Core.Repositories;
using Bit.Core.Settings; using Bit.Core.Settings;
using Microsoft.Extensions.Logging;
using NSubstitute; using NSubstitute;
using Stripe; using Stripe;
using Xunit; using Xunit;
@@ -28,7 +29,13 @@ public class StripeEventServiceTests
_providerRepository = Substitute.For<IProviderRepository>(); _providerRepository = Substitute.For<IProviderRepository>();
_setupIntentCache = Substitute.For<ISetupIntentCache>(); _setupIntentCache = Substitute.For<ISetupIntentCache>();
_stripeFacade = Substitute.For<IStripeFacade>(); _stripeFacade = Substitute.For<IStripeFacade>();
_stripeEventService = new StripeEventService(globalSettings, _organizationRepository, _providerRepository, _setupIntentCache, _stripeFacade); _stripeEventService = new StripeEventService(
globalSettings,
Substitute.For<ILogger<StripeEventService>>(),
_organizationRepository,
_providerRepository,
_setupIntentCache,
_stripeFacade);
} }
#region GetCharge #region GetCharge