using System.Text.Json; using Microsoft.EntityFrameworkCore; using Tiku.Application.Commerce; using Tiku.Domain.Commerce; using Tiku.Infrastructure.Persistence; namespace Tiku.Infrastructure.Commerce; internal sealed class PaymentProviderConfigService( TikuDbContext dbContext, ITenantSecretService tenantSecretService) : IPaymentProviderConfigService { public async Task GetActiveAccountAsync( Guid tenantId, string provider, CancellationToken cancellationToken = default) { var normalizedProvider = NormalizeProvider(provider); var account = await dbContext.TenantPaymentAccounts .AsNoTracking() .Where(item => item.TenantId == tenantId && item.Provider == normalizedProvider && item.Status == TenantPaymentAccountStatus.Active) .SingleOrDefaultAsync(cancellationToken); if (account is null) { throw new PaymentProviderException( "Payment provider account is not configured.", "payment_provider_not_configured"); } var secretPayload = normalizedProvider == PaymentProviders.Manual ? JsonDocument.Parse("{}").RootElement.Clone() : await tenantSecretService.GetActiveSecretPayloadAsync( tenantId, GetString(account.ConfigPublic, "secretRef", "secret_ref") ?? string.Empty, cancellationToken); return new PaymentProviderAccount( account.TenantId, normalizedProvider, account.Mode.ToString(), account.ConfigPublic, secretPayload); } private static string NormalizeProvider(string provider) { var normalized = provider.Trim().ToLowerInvariant().Replace("-", "_", StringComparison.Ordinal); return normalized switch { "wechat" or "wechatpay" or "wxpay" or "wx_pay" => PaymentProviders.WechatPay, "ali_pay" => PaymentProviders.Alipay, "" => throw new PaymentProviderException("Payment provider is required.", "payment_provider_required"), _ => normalized }; } private static string? GetString(JsonElement element, params string[] keys) { if (element.ValueKind != JsonValueKind.Object) { return null; } foreach (var key in keys) { if (element.TryGetProperty(key, out var property) && property.ValueKind == JsonValueKind.String) { return property.GetString(); } } return null; } }