Handling of paddle purchases and add-ons.
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
namespace Wino.Core.Domain.Enums;
|
||||
|
||||
public enum WinoAddOnProductType
|
||||
{
|
||||
AI_PACK,
|
||||
UNLIMITED_ACCOUNTS
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Store;
|
||||
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
|
||||
public interface IStoreManagementService
|
||||
@@ -9,10 +7,10 @@ public interface IStoreManagementService
|
||||
/// <summary>
|
||||
/// Checks whether user has the type of an add-on purchased.
|
||||
/// </summary>
|
||||
Task<bool> HasProductAsync(StoreProductType productType);
|
||||
Task<bool> HasProductAsync(WinoAddOnProductType productType);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to purchase the given add-on.
|
||||
/// </summary>
|
||||
Task<StorePurchaseResult> PurchaseAsync(StoreProductType productType);
|
||||
Task<StorePurchaseResult> PurchaseAsync(WinoAddOnProductType productType);
|
||||
}
|
||||
|
||||
@@ -2,21 +2,25 @@
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
using Wino.Mail.Api.Contracts.Ai;
|
||||
using Wino.Mail.Api.Contracts.Auth;
|
||||
using Wino.Mail.Api.Contracts.Billing;
|
||||
using Wino.Mail.Api.Contracts.Common;
|
||||
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
|
||||
public interface IWinoAccountApiClient
|
||||
{
|
||||
Task<ApiEnvelope<AuthResultDto>> RegisterAsync(string email, string password, CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<AuthResultDto>> LoginAsync(string email, string password, CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<AuthResultDto>> RefreshAsync(string refreshToken, CancellationToken cancellationToken = default);
|
||||
Task<WinoAccountApiResult<AuthResultDto>> RegisterAsync(string email, string password, CancellationToken cancellationToken = default);
|
||||
Task<WinoAccountApiResult<AuthResultDto>> LoginAsync(string email, string password, CancellationToken cancellationToken = default);
|
||||
Task<WinoAccountApiResult<AuthResultDto>> RefreshAsync(string refreshToken, CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<JsonElement>> LogoutAsync(string refreshToken, CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<AuthUserDto>> GetCurrentUserAsync(CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<AiStatusResultDto>> GetAiStatusAsync(CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<string>> CreateCheckoutSessionAsync(string productId, CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<CheckoutSessionResultDto>> CreateCheckoutSessionAsync(WinoAddOnProductType productId, CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<CustomerPortalResultDto>> CreateCustomerPortalSessionAsync(CancellationToken cancellationToken = default);
|
||||
Task<string?> GetSettingsAsync(CancellationToken cancellationToken = default);
|
||||
Task<bool> SaveSettingsAsync(string settingsJson, CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
using Wino.Mail.Api.Contracts.Ai;
|
||||
using Wino.Mail.Api.Contracts.Auth;
|
||||
using Wino.Mail.Api.Contracts.Billing;
|
||||
using Wino.Mail.Api.Contracts.Common;
|
||||
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
@@ -17,8 +19,10 @@ public interface IWinoAccountProfileService
|
||||
Task<WinoAccount?> GetActiveAccountAsync();
|
||||
Task<WinoAccount?> GetAuthenticatedAccountAsync(CancellationToken cancellationToken = default);
|
||||
Task<bool> HasActiveAccountAsync();
|
||||
Task<bool> HasAddOnAsync(WinoAddOnProductType productId, CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<AuthUserDto>> GetCurrentUserAsync(CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<AiStatusResultDto>> GetAiStatusAsync(CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<string>> CreateCheckoutSessionAsync(string productId, CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<CheckoutSessionResultDto>> CreateCheckoutSessionAsync(WinoAddOnProductType productId, CancellationToken cancellationToken = default);
|
||||
Task<ApiEnvelope<CustomerPortalResultDto>> CreateCustomerPortalSessionAsync(CancellationToken cancellationToken = default);
|
||||
Task SignOutAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#nullable enable
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
|
||||
public interface IWinoAddOnService
|
||||
{
|
||||
Task<IReadOnlyList<WinoAddOnInfo>> GetAvailableAddOnsAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#nullable enable
|
||||
|
||||
namespace Wino.Core.Domain.Models.Accounts;
|
||||
|
||||
public sealed class WinoAccountApiResult<T>
|
||||
{
|
||||
public bool IsSuccess { get; init; }
|
||||
public string? ErrorCode { get; init; }
|
||||
public string? ErrorMessage { get; init; }
|
||||
public T? Result { get; init; }
|
||||
|
||||
public static WinoAccountApiResult<T> Success(T result)
|
||||
=> new()
|
||||
{
|
||||
IsSuccess = true,
|
||||
Result = result
|
||||
};
|
||||
|
||||
public static WinoAccountApiResult<T> Failure(string? errorCode, string? errorMessage = null)
|
||||
=> new()
|
||||
{
|
||||
IsSuccess = false,
|
||||
ErrorCode = errorCode,
|
||||
ErrorMessage = errorMessage
|
||||
};
|
||||
}
|
||||
@@ -7,6 +7,7 @@ public sealed class WinoAccountOperationResult
|
||||
{
|
||||
public bool IsSuccess { get; init; }
|
||||
public string? ErrorCode { get; init; }
|
||||
public string? ErrorMessage { get; init; }
|
||||
public WinoAccount? Account { get; init; }
|
||||
|
||||
public static WinoAccountOperationResult Success(WinoAccount account)
|
||||
@@ -16,10 +17,11 @@ public sealed class WinoAccountOperationResult
|
||||
Account = account
|
||||
};
|
||||
|
||||
public static WinoAccountOperationResult Failure(string? errorCode)
|
||||
public static WinoAccountOperationResult Failure(string? errorCode, string? errorMessage = null)
|
||||
=> new()
|
||||
{
|
||||
IsSuccess = false,
|
||||
ErrorCode = errorCode
|
||||
ErrorCode = errorCode,
|
||||
ErrorMessage = errorMessage
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Accounts;
|
||||
|
||||
public sealed record WinoAddOnInfo(
|
||||
WinoAddOnProductType ProductType,
|
||||
bool IsPurchased,
|
||||
int? UsageCount = null,
|
||||
int? UsageLimit = null,
|
||||
double UsagePercentage = 0,
|
||||
DateTimeOffset? RenewalDateUtc = null);
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Wino.Core.Domain.Models.Store;
|
||||
|
||||
public enum StoreProductType
|
||||
{
|
||||
UnlimitedAccounts
|
||||
}
|
||||
@@ -84,6 +84,7 @@
|
||||
"Buttons_SyncAliases": "Synchronize Aliases",
|
||||
"Buttons_TryAgain": "Try Again",
|
||||
"Buttons_Yes": "Yes",
|
||||
"Purchased": "Purchased",
|
||||
"Sync_SynchronizingFolder": "Synchronizing {0} {1}%",
|
||||
"Sync_DownloadedMessages": "Downloaded {0} messages from {1}",
|
||||
"SyncAction_Archiving": "Archiving {0} mail(s)",
|
||||
@@ -860,7 +861,7 @@
|
||||
"WinoAccount_Management_SignedOutTitle": "Sign in to Wino Mail",
|
||||
"WinoAccount_Management_SignedOutDescription": "Sign in or create an account to sync your email, access AI features, and manage your settings across devices.",
|
||||
"WinoAccount_Management_ProfileSectionHeader": "Profile",
|
||||
"WinoAccount_Management_AiPackSectionHeader": "AI Pack",
|
||||
"WinoAccount_Management_AddOnsSectionHeader": "Wino Add-Ons",
|
||||
"WinoAccount_Management_DataSectionHeader": "Data",
|
||||
"WinoAccount_Management_AccountActionsSectionHeader": "Account actions",
|
||||
"WinoAccount_Management_AccountCardTitle": "Account",
|
||||
@@ -887,14 +888,10 @@
|
||||
"WinoAccount_Management_AiPackFeatureTranslate": "Translate",
|
||||
"WinoAccount_Management_AiPackFeatureRewrite": "Rewrite",
|
||||
"WinoAccount_Management_AiPackFeatureSummarize": "Summarize",
|
||||
"WinoAccount_Management_ImportSettingsTitle": "Import settings",
|
||||
"WinoAccount_Management_ImportSettingsDescription": "Restore your preferences from cloud.",
|
||||
"WinoAccount_Management_ExportSettingsTitle": "Export settings",
|
||||
"WinoAccount_Management_ExportSettingsDescription": "Save your preferences to cloud.",
|
||||
"WinoAccount_Management_SyncPreferencesTitle": "Synchronize Preferences",
|
||||
"WinoAccount_Management_SyncPreferencesDescription": "Import or export your preferences to cloud. Import them across devices.",
|
||||
"WinoAccount_Management_SignOutTitle": "Sign out",
|
||||
"WinoAccount_Management_SignOutDescription": "Sign out of your account on this device",
|
||||
"WinoAccount_Management_SettingsCardTitle": "Settings sync",
|
||||
"WinoAccount_Management_SettingsCardDescription": "Export your current settings to your Wino Account or import them back on this device.",
|
||||
"WinoAccount_Management_StatusLabel": "Status: {0}",
|
||||
"WinoAccount_Management_NoRemoteSettings": "There are no synchronized settings stored for this account yet.",
|
||||
"WinoAccount_Management_ExportSucceeded": "Your settings were exported to your Wino Account.",
|
||||
@@ -905,6 +902,12 @@
|
||||
"WinoAccount_Management_ImportEmpty": "The synchronized settings payload does not contain any values to restore.",
|
||||
"WinoAccount_Management_LoadFailed": "Wino could not load the latest Wino Account information.",
|
||||
"WinoAccount_Management_ActionFailed": "The Wino Account request could not be completed.",
|
||||
"WinoAddOn_AI_PACK_Name": "AI Pack",
|
||||
"WinoAddOn_AI_PACK_Description": "Translate, rewrite, and summarize emails with Wino AI.",
|
||||
"WinoAddOn_AI_PACK_Keywords": "Translate · Rewrite · Summarize",
|
||||
"WinoAddOn_UNLIMITED_ACCOUNTS_Name": "Unlimited Accounts",
|
||||
"WinoAddOn_UNLIMITED_ACCOUNTS_Description": "Remove the 3-account limit and add as many accounts as you need.",
|
||||
"WinoAddOn_UNLIMITED_ACCOUNTS_Keywords": "More accounts · No limit · One-time purchase",
|
||||
"SettingsSearch_MessageList_Keywords": "message;messages;list;threading;threads;avatar;preview;sender",
|
||||
"SettingsSearch_ReadComposePane_Keywords": "reader;compose;composer;font;fonts;external content;display;reading",
|
||||
"SettingsSearch_SignatureAndEncryption_Keywords": "signature;signatures;encryption;certificate;certificates;s mime;smime;security",
|
||||
|
||||
Reference in New Issue
Block a user