92 lines
4.2 KiB
C#
92 lines
4.2 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.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) =>
|
|
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) =>
|
|
ExecuteAsync(provider, "payment-notification", async (resolvedProvider, account, token) =>
|
|
await resolvedProvider.ParsePaymentNotificationAsync(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,
|
|
IsGlobal: true),
|
|
async (services, token) =>
|
|
{
|
|
var dbContext = services.GetRequiredService<TikuDbContext>();
|
|
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
|
|
{
|
|
account = await services.GetRequiredService<IPaymentProviderConfigService>()
|
|
.GetActiveAccountAsync(platformTenantId, normalized, token);
|
|
}
|
|
|
|
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")
|
|
};
|
|
}
|
|
}
|