diff --git a/DysonNetwork.Sphere/Wallet/Subscription.cs b/DysonNetwork.Sphere/Wallet/Subscription.cs index 654ecd9..131363a 100644 --- a/DysonNetwork.Sphere/Wallet/Subscription.cs +++ b/DysonNetwork.Sphere/Wallet/Subscription.cs @@ -7,16 +7,43 @@ namespace DysonNetwork.Sphere.Wallet; public record class SubscriptionTypeData( string Identifier, - decimal BasePrice + string? GroupIdentifier, + string Currency, + decimal BasePrice, + int? RequiredLevel = null ) { public static readonly Dictionary SubscriptionDict = new() { - [SubscriptionType.Twinkle] = new SubscriptionTypeData(SubscriptionType.Twinkle, 0), - [SubscriptionType.Stellar] = new SubscriptionTypeData(SubscriptionType.Stellar, 10), - [SubscriptionType.Nova] = new SubscriptionTypeData(SubscriptionType.Nova, 20), - [SubscriptionType.Supernova] = new SubscriptionTypeData(SubscriptionType.Supernova, 30) + [SubscriptionType.Twinkle] = new SubscriptionTypeData( + SubscriptionType.Twinkle, + SubscriptionType.StellarProgram, + WalletCurrency.SourcePoint, + 0, + 1 + ), + [SubscriptionType.Stellar] = new SubscriptionTypeData( + SubscriptionType.Stellar, + SubscriptionType.StellarProgram, + WalletCurrency.SourcePoint, + 1200, + 3 + ), + [SubscriptionType.Nova] = new SubscriptionTypeData( + SubscriptionType.Nova, + SubscriptionType.StellarProgram, + WalletCurrency.SourcePoint, + 2400, + 6 + ), + [SubscriptionType.Supernova] = new SubscriptionTypeData( + SubscriptionType.Supernova, + SubscriptionType.StellarProgram, + WalletCurrency.SourcePoint, + 3600, + 9 + ) }; public static readonly Dictionary SubscriptionHumanReadable = diff --git a/DysonNetwork.Sphere/Wallet/SubscriptionService.cs b/DysonNetwork.Sphere/Wallet/SubscriptionService.cs index 3259041..88f4e6d 100644 --- a/DysonNetwork.Sphere/Wallet/SubscriptionService.cs +++ b/DysonNetwork.Sphere/Wallet/SubscriptionService.cs @@ -32,16 +32,22 @@ public class SubscriptionService( bool noop = false ) { - var subscriptionTemplate = SubscriptionTypeData + var subscriptionInfo = SubscriptionTypeData .SubscriptionDict.TryGetValue(identifier, out var template) ? template : null; - if (subscriptionTemplate is null) + if (subscriptionInfo is null) throw new ArgumentOutOfRangeException(nameof(identifier), $@"Subscription {identifier} was not found."); + var subscriptionsInGroup = subscriptionInfo.GroupIdentifier is not null + ? SubscriptionTypeData.SubscriptionDict + .Where(s => s.Value.GroupIdentifier == subscriptionInfo.GroupIdentifier) + .Select(s => s.Value.Identifier) + .ToArray() + : [identifier]; cycleDuration ??= Duration.FromDays(30); - var existingSubscription = await GetSubscriptionAsync(account.Id, identifier); + var existingSubscription = await GetSubscriptionAsync(account.Id, subscriptionsInGroup); if (existingSubscription is not null && !noop) throw new InvalidOperationException($"Active subscription with identifier {identifier} already exists."); if (existingSubscription is not null) @@ -77,7 +83,7 @@ public class SubscriptionService( Status = SubscriptionStatus.Unpaid, PaymentMethod = paymentMethod, PaymentDetails = paymentDetails, - BasePrice = subscriptionTemplate.BasePrice, + BasePrice = subscriptionInfo.BasePrice, CouponId = couponData?.Id, Coupon = couponData, RenewalAt = (isFreeTrial || !isAutoRenewal) ? null : now.Plus(cycleDuration.Value), @@ -220,10 +226,16 @@ public class SubscriptionService( .OrderByDescending(s => s.BegunAt) .FirstOrDefaultAsync(); if (subscription is null) throw new InvalidOperationException("No matching subscription found."); + + var subscriptionInfo = SubscriptionTypeData.SubscriptionDict + .TryGetValue(subscription.Identifier, out var template) + ? template + : null; + if (subscriptionInfo is null) throw new InvalidOperationException("No matching subscription found."); return await payment.CreateOrderAsync( null, - WalletCurrency.GoldenPoint, + subscriptionInfo.Currency, subscription.FinalPrice, appIdentifier: SubscriptionOrderIdentifier, meta: new Dictionary() @@ -319,7 +331,7 @@ public class SubscriptionService( { var account = await db.Accounts.FirstOrDefaultAsync(a => a.Id == subscription.AccountId); if (account is null) return; - + AccountService.SetCultureInfo(account); var humanReadableName = @@ -345,10 +357,10 @@ public class SubscriptionService( private const string SubscriptionCacheKeyPrefix = "subscription:"; - public async Task GetSubscriptionAsync(Guid accountId, string identifier) + public async Task GetSubscriptionAsync(Guid accountId, params string[] identifiers) { // Create a unique cache key for this subscription - var cacheKey = $"{SubscriptionCacheKeyPrefix}{accountId}:{identifier}"; + var cacheKey = $"{SubscriptionCacheKeyPrefix}{accountId}:{string.Join(",", identifiers)}"; // Try to get the subscription from cache first var (found, cachedSubscription) = await cache.GetAsyncWithStatus(cacheKey); @@ -359,15 +371,13 @@ public class SubscriptionService( // If not in cache, get from database var subscription = await db.WalletSubscriptions - .Where(s => s.AccountId == accountId && s.Identifier == identifier) + .Where(s => s.AccountId == accountId && identifiers.Contains(s.Identifier)) .OrderByDescending(s => s.BegunAt) .FirstOrDefaultAsync(); // Cache the result if found (with 30 minutes expiry) if (subscription != null) - { await cache.SetAsync(cacheKey, subscription, TimeSpan.FromMinutes(30)); - } return subscription; }