Files
tiku-backend.net/Tiku.Infrastructure/PlatformBilling/PlatformBillingPaymentGateway.cs
xiong 33375a38d7
Some checks failed
ci / release-gate (push) Has been cancelled
refactor(architecture): harden module boundaries
2026-08-04 12:10:36 +08:00

118 lines
5.4 KiB
C#

using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Tiku.Application.Commerce;
using Tiku.Application.PlatformBilling;
using Tiku.Application.Security;
using Tiku.Domain.Platform;
using Tiku.Domain.Tenancy;
using Tiku.Infrastructure.Persistence;
namespace Tiku.Infrastructure.PlatformBilling;
internal sealed class PlatformBillingPaymentGateway(
ITenantExecutionScope tenantExecutionScope) : IPlatformBillingPaymentGateway
{
public Task<CreatePaymentProviderResult> CreatePaymentAsync(
string provider,
CreatePaymentProviderRequest request,
CancellationToken cancellationToken = default)
{
return ExecuteAsync(provider, request.OrderNo, async (resolvedProvider, account, token) =>
await resolvedProvider.CreatePaymentAsync(account, request, token), cancellationToken);
}
public Task<PaymentNotificationResult> ParseNotificationAsync(
string provider,
PaymentNotificationRequest request,
CancellationToken cancellationToken = default)
{
return ExecuteAsync(provider, "payment-notification", async (resolvedProvider, account, token) =>
await resolvedProvider.ParsePaymentNotificationAsync(account, request, token), cancellationToken);
}
public Task<CreateRefundProviderResult> CreateRefundAsync(
string provider,
CreateRefundProviderRequest request,
CancellationToken cancellationToken = default)
{
return ExecuteAsync(provider, request.RefundNo, async (resolvedProvider, account, token) =>
await resolvedProvider.CreateRefundAsync(account, request, token), cancellationToken);
}
private Task<TResult> ExecuteAsync<TResult>(
string provider,
string correlationId,
Func<IPaymentProvider, PaymentProviderAccount, CancellationToken, Task<TResult>> operation,
CancellationToken cancellationToken)
{
return tenantExecutionScope.ExecuteAsync(
new SystemScopeRequest(
null,
SystemScopeCallerType.Platform,
nameof(PlatformBillingPaymentGateway),
"Resolve the platform-owned SaaS billing payment account",
correlationId,
true),
async (services, token) =>
{
var dbContext = services.GetRequiredService<IPlatformBillingPersistence>();
var platformTenantId = await dbContext.Tenants.AsNoTracking()
.Where(value => value.Mode == TenantMode.PlatformOwned)
.Select(value => value.Id)
.SingleOrDefaultAsync(token);
if (platformTenantId == Guid.Empty)
throw new PaymentProviderException("Platform-owned tenant is missing.",
"platform_payment_owner_missing");
var normalized = NormalizeProvider(provider);
var resolvedProvider = services.GetServices<IPaymentProvider>()
.SingleOrDefault(value => value.Provider == normalized)
?? throw new PaymentProviderException("Payment provider is not supported.",
"payment_provider_not_supported");
PaymentProviderAccount account;
if (normalized == PaymentProviders.Manual)
{
account = new PaymentProviderAccount(
platformTenantId,
PaymentProviders.Manual,
"PlatformCollect",
JsonDocument.Parse("{}").RootElement.Clone(),
JsonDocument.Parse("{}").RootElement.Clone());
}
else
{
var channel = await dbContext.PlatformPaymentChannels.AsNoTracking()
.Where(value =>
value.Provider == normalized &&
value.Status == PlatformPaymentChannelStatus.Active)
.OrderBy(value => value.Priority)
.FirstOrDefaultAsync(token)
?? throw new PaymentProviderException("Platform payment channel is missing.",
"platform_payment_channel_missing");
account = new PaymentProviderAccount(
platformTenantId,
normalized,
channel.Mode,
channel.ConfigPublic,
JsonDocument.Parse("{}").RootElement.Clone());
}
return await operation(resolvedProvider, account, token);
},
cancellationToken);
}
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,
PaymentProviders.WechatPay or PaymentProviders.Alipay or PaymentProviders.Manual => normalized,
_ => throw new PaymentProviderException("Payment provider is not supported.",
"payment_provider_not_supported")
};
}
}