using System.Text.Json; namespace Tiku.Application.Commerce; public sealed record CommerceActor(Guid TenantId, Guid UserId); public sealed record CreateCommerceOrderCommand( Guid PlanId, int Quantity, string? PayMethod, string? PayProvider, Guid? RegionId, string? CouponCode); public sealed record CommerceOrderQuery(int? Limit = null, string? Status = null); public sealed record CreateCommercePaymentCommand( string OrderNo, string Provider, string Method, string? OpenId, string? ReturnUrl, string? QuitUrl); public sealed record CommerceOrderItem( Guid Id, string OrderNo, string Status, Guid? PlanId, Guid? RegionId, string? ProductType, string? ProductName, int AmountCents, string Price, string? PayMethod, string? PayProvider, string? TradeNo, int? Days, DateTimeOffset? PaidAt, DateTimeOffset CreatedAt, JsonElement RawPayload); public sealed record CommerceOrderList(IReadOnlyCollection Items); public sealed record CommercePaymentItem( Guid Id, Guid OrderId, string OrderNo, string Provider, string? Method, string Status, int AmountCents, string Price, string? ProviderTradeNo, DateTimeOffset? PaidAt, JsonElement ClientPayload, JsonElement RawPayload); public sealed record CurrentEntitlementItem( bool IsActive, string EntitlementType, DateTimeOffset? StartsAt, DateTimeOffset? ExpiresAt, string Status, int? DaysLeft); public sealed record PaymentNotificationProcessResult( string Provider, string EventId, string OrderNo, string Status, bool Idempotent); public interface ICommerceService { Task CreateOrderAsync( CommerceActor actor, CreateCommerceOrderCommand command, CancellationToken cancellationToken = default); Task GetOrdersAsync( CommerceActor actor, CommerceOrderQuery query, CancellationToken cancellationToken = default); Task GetOrderAsync( CommerceActor actor, string orderNo, CancellationToken cancellationToken = default); Task CreatePaymentAsync( CommerceActor actor, CreateCommercePaymentCommand command, CancellationToken cancellationToken = default); Task GetCurrentEntitlementAsync( CommerceActor actor, CancellationToken cancellationToken = default); Task ProcessPaymentNotificationAsync( Guid tenantId, string provider, IReadOnlyDictionary headers, string rawBody, JsonElement body, CancellationToken cancellationToken = default); } public sealed class CommerceException(string message, string code) : Exception(message) { public string Code { get; } = code; }