using System.Text.Json; namespace Tiku.Application.Commerce; public static class PaymentProviders { public const string WechatPay = "wechat_pay"; public const string Alipay = "alipay"; public const string Manual = "manual"; } public sealed record PaymentProviderAccount( Guid TenantId, string Provider, string Mode, JsonElement ConfigPublic, JsonElement SecretPayload); public sealed record CreatePaymentProviderRequest( Guid TenantId, string OrderNo, string Subject, int AmountCents, string Method, string? OpenId, string? ReturnUrl, string? QuitUrl, string NotifyUrl, JsonElement Metadata); public sealed record CreatePaymentProviderResult( string Provider, string Method, string Status, string? ProviderTradeNo, JsonElement ClientPayload, JsonElement RawPayload); public sealed record PaymentNotificationRequest( Guid TenantId, string Provider, IReadOnlyDictionary Headers, string RawBody, JsonElement Body); public sealed record PaymentNotificationResult( string Provider, string EventType, string EventId, string OrderNo, string? ProviderTradeNo, int AmountCents, bool Paid, bool SignatureValid, DateTimeOffset? PaidAt, JsonElement RawPayload); public interface IPaymentProvider { string Provider { get; } Task CreatePaymentAsync( PaymentProviderAccount account, CreatePaymentProviderRequest request, CancellationToken cancellationToken = default); Task ParsePaymentNotificationAsync( PaymentProviderAccount account, PaymentNotificationRequest request, CancellationToken cancellationToken = default); } public interface IPaymentProviderGateway { Task CreatePaymentAsync( string provider, CreatePaymentProviderRequest request, CancellationToken cancellationToken = default); Task ParsePaymentNotificationAsync( string provider, PaymentNotificationRequest request, CancellationToken cancellationToken = default); } public interface IPaymentProviderConfigService { Task GetActiveAccountAsync( Guid tenantId, string provider, CancellationToken cancellationToken = default); } public interface ITenantSecretService { Task GetActiveSecretPayloadAsync( Guid tenantId, string secretRef, CancellationToken cancellationToken = default); } public sealed class PaymentProviderException(string message, string code) : Exception(message) { public string Code { get; } = code; }