From e2055e503f21b21dcf933d6fd066a715531419ef Mon Sep 17 00:00:00 2001 From: Toni Rico Date: Thu, 1 Aug 2024 13:53:07 +0200 Subject: [PATCH] Update to latest native majors --- AMAZON-INSTRUCTIONS.md | 4 +- .../Assets/APITests/PurchasesAPITests.cs | 8 +- .../APITests/SubscriptionOptionAPITests.cs | 3 + .../Plugins/Android/PurchasesWrapper.java | 9 +- .../Plugins/Editor/RevenueCatDependencies.xml | 4 +- RevenueCat/Plugins/iOS/PurchasesUnityHelper.m | 19 ----- RevenueCat/Scripts/Purchases.cs | 82 +++++++++---------- RevenueCat/Scripts/PurchasesAreCompletedBy.cs | 31 +++++++ RevenueCat/Scripts/PurchasesConfiguration.cs | 54 ++++++------ RevenueCat/Scripts/PurchasesWrapper.cs | 12 +-- RevenueCat/Scripts/PurchasesWrapperAndroid.cs | 20 ++--- RevenueCat/Scripts/PurchasesWrapperNoop.cs | 22 ++--- RevenueCat/Scripts/PurchasesWrapperiOS.cs | 36 ++++---- RevenueCat/Scripts/StoreKitVersion.cs | 34 ++++++++ RevenueCat/Scripts/SubscriptionOption.cs | 35 +++++++- .../Plugins/Android/mainTemplate.gradle | 2 +- .../AndroidResolverDependencies.xml | 2 +- 17 files changed, 220 insertions(+), 157 deletions(-) create mode 100644 RevenueCat/Scripts/PurchasesAreCompletedBy.cs create mode 100644 RevenueCat/Scripts/StoreKitVersion.cs diff --git a/AMAZON-INSTRUCTIONS.md b/AMAZON-INSTRUCTIONS.md index 7ad6b1d9..3a1b282f 100644 --- a/AMAZON-INSTRUCTIONS.md +++ b/AMAZON-INSTRUCTIONS.md @@ -38,7 +38,7 @@ public void OnInitialized(IStoreController controller, IExtensionProvider extens if (product.hasReceipt) { var amazonExtensions = storeExtensionProvider.GetExtension(); var userId = amazonExtensions.amazonUserId; - purchases.SyncObserverModeAmazonPurchase( + purchases.SyncAmazonPurchase( product.definition.id, product.transactionID, userId, @@ -55,7 +55,7 @@ public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) var amazonExtensions = storeExtensionProvider.GetExtension(); var userId = amazonExtensions.amazonUserId; - purchases.SyncObserverModeAmazonPurchase( + purchases.SyncAmazonPurchase( e.purchasedProduct.definition.id, e.purchasedProduct.transactionID, userId, diff --git a/IntegrationTests/Assets/APITests/PurchasesAPITests.cs b/IntegrationTests/Assets/APITests/PurchasesAPITests.cs index 170ce271..7582c49f 100644 --- a/IntegrationTests/Assets/APITests/PurchasesAPITests.cs +++ b/IntegrationTests/Assets/APITests/PurchasesAPITests.cs @@ -147,7 +147,6 @@ private void Start() receivedError = error; }); - purchases.SetFinishTransactions(true); #pragma warning disable CS0618 // Type or member is obsolete purchases.SetAllowSharingStoreAccount(false); #pragma warning restore CS0618 // Type or member is obsolete @@ -170,7 +169,6 @@ private void Start() }); purchases.SyncPurchases(); - purchases.SetAutomaticAppleSearchAdsAttributionCollection(true); purchases.EnableAdServicesAttributionTokenCollection(); Dictionary receivedEligibilities; purchases.CheckTrialOrIntroductoryPriceEligibility(new string[] { "a", "b" }, @@ -220,16 +218,18 @@ private void Start() Purchases.PurchasesConfiguration purchasesConfiguration = builder.SetUserDefaultsSuiteName("user_default") .SetDangerousSettings(new Purchases.DangerousSettings(false)) - .SetObserverMode(true) + .SetPurchasesAreCompletedBy(Purchases.PurchasesAreCompletedBy.MyApp, Purchases.StoreKitVersion.StoreKit2) .SetUseAmazon(false) .SetAppUserId(appUserId) - .SetUsesStoreKit2IfAvailable(false) + .SetStoreKitVersion(Purchases.StoreKitVersion.StoreKit2) .SetShouldShowInAppMessagesAutomatically(false) .SetEntitlementVerificationMode(Purchases.EntitlementVerificationMode.Informational) + .SetPendingTransactionsForPrepaidPlansEnabled(true) .Build(); purchases.Configure(purchasesConfiguration); purchases.SyncObserverModeAmazonPurchase("product_id", "receipt_id", "amazon_user_id", "iso_currency_code", 1.99); + purchases.SyncAmazonPurchase("product_id", "receipt_id", "amazon_user_id", "iso_currency_code", 1.99); purchases.ShowInAppMessages(new Purchases.InAppMessageType[] { Purchases.InAppMessageType.BillingIssue, Purchases.InAppMessageType.PriceIncreaseConsent, Purchases.InAppMessageType.Generic }); diff --git a/IntegrationTests/Assets/APITests/SubscriptionOptionAPITests.cs b/IntegrationTests/Assets/APITests/SubscriptionOptionAPITests.cs index 94242fd6..596bcb1a 100644 --- a/IntegrationTests/Assets/APITests/SubscriptionOptionAPITests.cs +++ b/IntegrationTests/Assets/APITests/SubscriptionOptionAPITests.cs @@ -29,6 +29,9 @@ private void Start() bool IsBasePlan = subscriptionOption.IsBasePlan; bool IsPrepaid = subscriptionOption.IsPrepaid; string PresentedOfferingIdentifier = subscriptionOption.PresentedOfferingIdentifier; + Purchases.SubscriptionOption.InstallmentsInfo installmentsInfo = subscriptionOption.InstallmentsInfo; + int commitmentPaymentsCount = installmentsInfo.CommitmentPaymentsCount; + int renewalCommitmentPaymentsCount = installmentsInfo.RenewalCommitmentPaymentsCount; } } } \ No newline at end of file diff --git a/RevenueCat/Plugins/Android/PurchasesWrapper.java b/RevenueCat/Plugins/Android/PurchasesWrapper.java index de039513..b7e01878 100644 --- a/RevenueCat/Plugins/Android/PurchasesWrapper.java +++ b/RevenueCat/Plugins/Android/PurchasesWrapper.java @@ -312,14 +312,14 @@ public void onError(ErrorContainer errorContainer) { }); } - public static void syncObserverModeAmazonPurchase( + public static void syncAmazonPurchase( String productID, String receiptID, String amazonUserID, String isoCurrencyCode, double price ) { - Purchases.getSharedInstance().syncObserverModeAmazonPurchase(productID, receiptID, + Purchases.getSharedInstance().syncAmazonPurchase(productID, receiptID, amazonUserID, isoCurrencyCode, price); } @@ -357,11 +357,6 @@ public static void getCustomerInfo() { CommonKt.getCustomerInfo(getCustomerInfoListener(GET_CUSTOMER_INFO)); } - public static void setFinishTransactions(boolean enabled) { - CommonKt.setPurchasesAreCompletedBy(enabled ? - PurchasesAreCompletedBy.REVENUECAT : PurchasesAreCompletedBy.MY_APP); - } - public static void syncPurchases() { CommonKt.syncPurchases(); } diff --git a/RevenueCat/Plugins/Editor/RevenueCatDependencies.xml b/RevenueCat/Plugins/Editor/RevenueCatDependencies.xml index 602a0686..ed66c7c8 100644 --- a/RevenueCat/Plugins/Editor/RevenueCatDependencies.xml +++ b/RevenueCat/Plugins/Editor/RevenueCatDependencies.xml @@ -1,10 +1,10 @@ - + - + diff --git a/RevenueCat/Plugins/iOS/PurchasesUnityHelper.m b/RevenueCat/Plugins/iOS/PurchasesUnityHelper.m index 4266096f..c8ed2dd1 100644 --- a/RevenueCat/Plugins/iOS/PurchasesUnityHelper.m +++ b/RevenueCat/Plugins/iOS/PurchasesUnityHelper.m @@ -236,18 +236,6 @@ - (void)getCustomerInfo { [RCCommonFunctionality getCustomerInfoWithCompletionBlock:[self getCustomerInfoCompletionBlockFor:GET_CUSTOMER_INFO]]; } -- (void)setFinishTransactions:(BOOL)finishTransactions { - if (finishTransactions) { - [RCCommonFunctionality setPurchasesAreCompletedBy:RCPurchasesAreCompletedByRevenueCat]; - } else { - [RCCommonFunctionality setPurchasesAreCompletedBy:RCPurchasesAreCompletedByMyApp]; - } -} - -- (void)setAutomaticAppleSearchAdsAttributionCollection:(BOOL)enabled { - [RCCommonFunctionality setAutomaticAppleSearchAdsAttributionCollection:enabled]; -} - - (void)enableAdServicesAttributionTokenCollection { if (@available(iOS 14.3, macOS 11.1, macCatalyst 14.3, *)) { [RCCommonFunctionality enableAdServicesAttributionTokenCollection]; @@ -571,9 +559,6 @@ void _RCLogOut() { [_RCUnityHelperShared() logOut]; } -void _RCSetFinishTransactions(const BOOL finishTransactions) { - [_RCUnityHelperShared() setFinishTransactions:finishTransactions]; -} void _RCSetAllowSharingStoreAccount(const BOOL allow) { [_RCUnityHelperShared() setAllowSharingStoreAccount:allow]; } @@ -618,10 +603,6 @@ void _RCGetCustomerInfo() { return [_RCUnityHelperShared() getAppUserID]; } -void _RCSetAutomaticAppleSearchAdsAttributionCollection(const BOOL enabled) { - [_RCUnityHelperShared() setAutomaticAppleSearchAdsAttributionCollection:enabled]; -} - void _RCEnableAdServicesAttributionTokenCollection() { [_RCUnityHelperShared() enableAdServicesAttributionTokenCollection]; } diff --git a/RevenueCat/Scripts/Purchases.cs b/RevenueCat/Scripts/Purchases.cs index de14f56d..c1c3ea1f 100644 --- a/RevenueCat/Scripts/Purchases.cs +++ b/RevenueCat/Scripts/Purchases.cs @@ -60,12 +60,6 @@ public partial class Purchases : MonoBehaviour "Use your custom subclass to define how to handle updated customer information.")] public UpdatedCustomerInfoListener listener; - [Tooltip("An optional boolean. Set this to true if you have your own IAP implementation " + - "and want to use only RevenueCat's backend.\nDefault is false.\n" + - "NOTE: This value will be ignored if \"Use Runtime Setup\" is true. For Runtime Setup, you can configure " + - "it through PurchasesConfiguration instead")] - public bool observerMode; - [Tooltip("An optional string. iOS only.\n" + "Set this to use a specific NSUserDefaults suite for RevenueCat. " + "This might be handy if you are deleting all NSUserDefaults in your app " + @@ -74,6 +68,16 @@ public partial class Purchases : MonoBehaviour "it through PurchasesConfiguration instead")] public string userDefaultsSuiteName; + [Tooltip("Set this to MyApp and provide a StoreKitVersion if you have your own IAP implementation and\n" + + "want to only use RevenueCat's backend. Defaults to PurchasesAreCompletedBy.RevenueCat\n." + + "If you are on Android and setting this to MyApp, you will have to acknowledge the purchases yourself.\n" + + "If your app is only on Android, you may specify any StoreKit version, as it is ignored by the Android SDK.")] + public PurchasesAreCompletedBy purchasesAreCompletedBy = PurchasesAreCompletedBy.RevenueCat; + + [Tooltip("Version of StoreKit to use in iOS. By default, RevenueCat will decide for you.\n" + + "Set this if you're setting PurchasesAreCompletedBy to MyApp.")] + public StoreKitVersion storeKitVersion = StoreKitVersion.Default; + [Tooltip("Whether we should show store in-app messages automatically. Both Google Play and the App Store provide in-app " + "messages for some situations like billing issues. By default, those messages will be shown automatically.\n" + "This allows to disable that behavior, so you can display those messages at your convenience. For more information, " + @@ -83,6 +87,10 @@ public partial class Purchases : MonoBehaviour [Tooltip("The entitlement verification mode to use. For more information, check: https://rev.cat/trusted-entitlements")] public EntitlementVerificationMode entitlementVerificationMode = EntitlementVerificationMode.Disabled; + [Tooltip("Enable this setting if you want to allow pending purchases for prepaid subscriptions (only supported " + + "in Google Play). Note that entitlements are not granted until payment is done. Disabled by default.")] + public bool pendingTransactionsForPrepaidPlansEnabled = false; + [Header("Advanced")] [Tooltip("Set this property to your proxy URL before configuring Purchases *only* if you've received " + "a proxy key value from your RevenueCat contact.\n" + @@ -90,23 +98,6 @@ public partial class Purchases : MonoBehaviour "it through PurchasesConfiguration instead")] public string proxyURL; - [Header("⚠️ Deprecated")] - [Tooltip("⚠️ RevenueCat currently uses StoreKit 1 for purchases, as its stability in production " + - "scenarios has proven to be more performant than StoreKit 2.\n" + - "We're collecting more data on the best approach, but StoreKit 1 vs StoreKit 2 is \n" + - "an implementation detail that you shouldn't need to care about.\n" + - "We recommend not using this parameter, letting RevenueCat decide for " + - "you which StoreKit implementation to use.\n" + - "NOTE: This value will be ignored if \"Use Runtime Setup\" is true. For Runtime Setup, you can configure " + - "it through PurchasesConfiguration instead")] - [Obsolete("RevenueCat currently uses StoreKit 1 for purchases, as its stability in production " + - "scenarios has proven to be more performant than StoreKit 2.\n" + - "We're collecting more data on the best approach, but StoreKit 1 vs StoreKit 2 is \n" + - "an implementation detail that you shouldn't need to care about.\n" + - "We recommend not using this parameter, letting RevenueCat decide for " + - "you which StoreKit implementation to use.", false)] - public bool usesStoreKit2IfAvailable; - private IPurchasesWrapper _wrapper; private void Start() @@ -143,11 +134,11 @@ private void Configure(string newUserId) var dangerousSettings = new DangerousSettings(autoSyncPurchases); var builder = PurchasesConfiguration.Builder.Init(apiKey) .SetAppUserId(newUserId) - .SetObserverMode(observerMode) + .SetPurchasesAreCompletedBy(purchasesAreCompletedBy, storeKitVersion) .SetUserDefaultsSuiteName(userDefaultsSuiteName) .SetUseAmazon(useAmazon) .SetDangerousSettings(dangerousSettings) - .SetUsesStoreKit2IfAvailable(usesStoreKit2IfAvailable) + .SetStoreKitVersion(storeKitVersion) .SetShouldShowInAppMessagesAutomatically(shouldShowInAppMessagesAutomatically) .SetEntitlementVerificationMode(entitlementVerificationMode); @@ -193,9 +184,9 @@ public void Configure(PurchasesConfiguration purchasesConfiguration) { var dangerousSettings = purchasesConfiguration.DangerousSettings.Serialize().ToString(); _wrapper.Setup(gameObject.name, purchasesConfiguration.ApiKey, purchasesConfiguration.AppUserId, - purchasesConfiguration.ObserverMode, purchasesConfiguration.UsesStoreKit2IfAvailable, purchasesConfiguration.UserDefaultsSuiteName, + purchasesConfiguration.PurchasesAreCompletedBy, purchasesConfiguration.StoreKitVersion, purchasesConfiguration.UserDefaultsSuiteName, purchasesConfiguration.UseAmazon, dangerousSettings, purchasesConfiguration.ShouldShowInAppMessagesAutomatically, - purchasesConfiguration.EntitlementVerificationMode); + purchasesConfiguration.EntitlementVerificationMode, purchasesConfiguration.PendingTransactionsForPrepaidPlansEnabled); } private bool IsAndroidEmulator() @@ -513,22 +504,6 @@ public void LogOut(CustomerInfoFunc callback) _wrapper.LogOut(); } - // ReSharper disable once UnusedMember.Global - /// - /// Whether transactions should be finished automatically. `true` by default. - /// - /// - /// Warning: Setting this value to `false` will prevent the SDK from finishing transactions. - /// In this case, you *must* finish transactions in your app, otherwise they will remain in the queue and - /// will turn up every time the app is opened. - /// More information on finishing transactions manually [is available here](https://rev.cat/finish-transactions). - /// - /// Whether transactions should be finished automatically. - public void SetFinishTransactions(bool finishTransactions) - { - _wrapper.SetFinishTransactions(finishTransactions); - } - // ReSharper disable once UnusedMember.Global [Obsolete("Deprecated, configure behavior through the RevenueCat Dashboard instead.")] public void SetAllowSharingStoreAccount(bool allow) @@ -726,10 +701,29 @@ public void SyncPurchases() /// Amazon's userID. /// Product's currency code in ISO 4217 format. /// Product's price. + [Obsolete("Deprecated, use SyncAmazonPurchase instead.")] public void SyncObserverModeAmazonPurchase(string productID, string receiptID, string amazonUserID, string isoCurrencyCode, double price) { - _wrapper.SyncObserverModeAmazonPurchase(productID, receiptID, amazonUserID, isoCurrencyCode, price); + _wrapper.SyncAmazonPurchase(productID, receiptID, amazonUserID, isoCurrencyCode, price); + } + + /// + /// Android only. Noop in iOS. + /// + /// This method will send a purchase to the RevenueCat backend. This function should only be called if you are + /// in Amazon observer mode or performing a client side migration of your current users to RevenueCat. + /// The receipt IDs are cached if successfully posted so they are not posted more than once. + /// + /// Product ID associated to the purchase. + /// ReceiptId that represents the Amazon purchase. + /// Amazon's userID. + /// Product's currency code in ISO 4217 format. + /// Product's price. + public void SyncAmazonPurchase(string productID, string receiptID, string amazonUserID, + string isoCurrencyCode, double price) + { + _wrapper.SyncAmazonPurchase(productID, receiptID, amazonUserID, isoCurrencyCode, price); } // ReSharper disable once UnusedMember.Global diff --git a/RevenueCat/Scripts/PurchasesAreCompletedBy.cs b/RevenueCat/Scripts/PurchasesAreCompletedBy.cs new file mode 100644 index 00000000..93a9d176 --- /dev/null +++ b/RevenueCat/Scripts/PurchasesAreCompletedBy.cs @@ -0,0 +1,31 @@ +using System; +using System.ComponentModel; + +public partial class Purchases +{ + public enum PurchasesAreCompletedBy + { + /// RevenueCat will automatically acknowledge verified purchases. No action is required by you. + [Description("REVENUECAT")] + RevenueCat, + + /// RevenueCat will **not** automatically acknowledge any purchases. You will have to do so manually. + /// **Note:** failing to acknowledge a purchase within 3 days will lead to Google Play automatically issuing a + /// refund to the user. + /// For more info, see [revenuecat.com](https://docs.revenuecat.com/docs/observer-mode#option-2-client-side). + [Description("MY_APP")] + MyApp, + } +} + +internal static class StoreKitVersionExtensions +{ + internal static string Name(this Purchases.PurchasesAreCompletedBy purchasesAreCompletedBy) + { + var type = purchasesAreCompletedBy.GetType(); + var memInfo = type.GetMember(purchasesAreCompletedBy.ToString()); + var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); + var stringValue = ((DescriptionAttribute) attributes[0]).Description; + return stringValue; + } +} diff --git a/RevenueCat/Scripts/PurchasesConfiguration.cs b/RevenueCat/Scripts/PurchasesConfiguration.cs index 91c6f4eb..642b59f5 100644 --- a/RevenueCat/Scripts/PurchasesConfiguration.cs +++ b/RevenueCat/Scripts/PurchasesConfiguration.cs @@ -25,26 +25,29 @@ public class PurchasesConfiguration public readonly string ApiKey; public readonly string AppUserId; public readonly bool ObserverMode; + public readonly PurchasesAreCompletedBy PurchasesAreCompletedBy; public readonly string UserDefaultsSuiteName; public readonly bool UseAmazon; public readonly DangerousSettings DangerousSettings; - public readonly bool UsesStoreKit2IfAvailable; + public readonly StoreKitVersion StoreKitVersion; public readonly bool ShouldShowInAppMessagesAutomatically; public readonly EntitlementVerificationMode EntitlementVerificationMode; + public readonly bool PendingTransactionsForPrepaidPlansEnabled; - private PurchasesConfiguration(string apiKey, string appUserId, bool observerMode, string userDefaultsSuiteName, - bool useAmazon, DangerousSettings dangerousSettings, bool usesStoreKit2IfAvailable, bool shouldShowInAppMessagesAutomatically, - EntitlementVerificationMode entitlementVerificationMode) + private PurchasesConfiguration(string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, string userDefaultsSuiteName, + bool useAmazon, DangerousSettings dangerousSettings, StoreKitVersion storeKitVersion, bool shouldShowInAppMessagesAutomatically, + EntitlementVerificationMode entitlementVerificationMode, bool pendingTransactionsForPrepaidPlansEnabled) { ApiKey = apiKey; AppUserId = appUserId; - ObserverMode = observerMode; + PurchasesAreCompletedBy = purchasesAreCompletedBy; UserDefaultsSuiteName = userDefaultsSuiteName; UseAmazon = useAmazon; DangerousSettings = dangerousSettings; - UsesStoreKit2IfAvailable = usesStoreKit2IfAvailable; + StoreKitVersion = storeKitVersion; ShouldShowInAppMessagesAutomatically = shouldShowInAppMessagesAutomatically; EntitlementVerificationMode = entitlementVerificationMode; + PendingTransactionsForPrepaidPlansEnabled = pendingTransactionsForPrepaidPlansEnabled; } /// @@ -70,13 +73,14 @@ public class Builder { private readonly string _apiKey; private string _appUserId; - private bool _observerMode; + private PurchasesAreCompletedBy _purchasesAreCompletedBy; private string _userDefaultsSuiteName; private bool _useAmazon; private DangerousSettings _dangerousSettings; - private bool _usesStoreKit2IfAvailable; + private StoreKitVersion _storeKitVersion; private bool _shouldShowInAppMessagesAutomatically; private EntitlementVerificationMode _entitlementVerificationMode; + private bool _pendingTransactionsForPrepaidPlansEnabled; private Builder(string apiKey) { @@ -91,9 +95,9 @@ public static Builder Init(string apiKey) public PurchasesConfiguration Build() { _dangerousSettings = _dangerousSettings ?? new DangerousSettings(false); - return new PurchasesConfiguration(_apiKey, _appUserId, _observerMode, _userDefaultsSuiteName, - _useAmazon, _dangerousSettings, _usesStoreKit2IfAvailable, _shouldShowInAppMessagesAutomatically, - _entitlementVerificationMode); + return new PurchasesConfiguration(_apiKey, _appUserId, _purchasesAreCompletedBy, _userDefaultsSuiteName, + _useAmazon, _dangerousSettings, _storeKitVersion, _shouldShowInAppMessagesAutomatically, + _entitlementVerificationMode, _pendingTransactionsForPrepaidPlansEnabled); } public Builder SetAppUserId(string appUserId) @@ -102,9 +106,10 @@ public Builder SetAppUserId(string appUserId) return this; } - public Builder SetObserverMode(bool observerMode) + public Builder SetPurchasesAreCompletedBy(PurchasesAreCompletedBy purchasesAreCompletedBy, StoreKitVersion storeKitVersion) { - _observerMode = observerMode; + _purchasesAreCompletedBy = purchasesAreCompletedBy; + _storeKitVersion = storeKitVersion; return this; } @@ -126,15 +131,9 @@ public Builder SetDangerousSettings(DangerousSettings dangerousSettings) return this; } - [Obsolete("RevenueCat currently uses StoreKit 1 for purchases, as its stability in production " + - "scenarios has proven to be more performant than StoreKit 2.\n" + - "We're collecting more data on the best approach, but StoreKit 1 vs StoreKit 2 is \n" + - "an implementation detail that you shouldn't need to care about.\n" + - "We recommend not using this parameter, letting RevenueCat decide for " + - "you which StoreKit implementation to use.", false)] - public Builder SetUsesStoreKit2IfAvailable(bool usesStoreKit2IfAvailable) + public Builder SetStoreKitVersion(StoreKitVersion storeKitVersion) { - _usesStoreKit2IfAvailable = usesStoreKit2IfAvailable; + _storeKitVersion = storeKitVersion; return this; } @@ -150,6 +149,12 @@ public Builder SetEntitlementVerificationMode(EntitlementVerificationMode entitl return this; } + public Builder SetPendingTransactionsForPrepaidPlansEnabled(bool pendingTransactionsForPrepaidPlansEnabled) + { + _pendingTransactionsForPrepaidPlansEnabled = pendingTransactionsForPrepaidPlansEnabled; + return this; + } + } public override string ToString() @@ -157,13 +162,14 @@ public override string ToString() return $"{nameof(ApiKey)}: {ApiKey}\n" + $"{nameof(AppUserId)}: {AppUserId}\n" + - $"{nameof(ObserverMode)}: {ObserverMode}\n" + + $"{nameof(PurchasesAreCompletedBy)}: {PurchasesAreCompletedBy}\n" + $"{nameof(UserDefaultsSuiteName)}: {UserDefaultsSuiteName}\n" + $"{nameof(UseAmazon)}: {UseAmazon}\n" + $"{nameof(DangerousSettings)}: {DangerousSettings}\n" + - $"{nameof(UsesStoreKit2IfAvailable)}: {UsesStoreKit2IfAvailable}\n" + + $"{nameof(StoreKitVersion)}: {StoreKitVersion}\n" + $"{nameof(ShouldShowInAppMessagesAutomatically)}: {ShouldShowInAppMessagesAutomatically}\n" + - $"{nameof(EntitlementVerificationMode)}: {EntitlementVerificationMode}"; + $"{nameof(EntitlementVerificationMode)}: {EntitlementVerificationMode}\n" + + $"{nameof(PendingTransactionsForPrepaidPlansEnabled)}: {PendingTransactionsForPrepaidPlansEnabled}\n"; } } } diff --git a/RevenueCat/Scripts/PurchasesWrapper.cs b/RevenueCat/Scripts/PurchasesWrapper.cs index 03549af9..e5cceb61 100644 --- a/RevenueCat/Scripts/PurchasesWrapper.cs +++ b/RevenueCat/Scripts/PurchasesWrapper.cs @@ -3,12 +3,13 @@ public interface IPurchasesWrapper { - void Setup(string gameObject, string apiKey, string appUserId, bool observerMode, bool usesStoreKit2IfAvailable, - string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically); + void Setup(string gameObject, string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, StoreKitVersion storeKitVersion, + string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically, + bool pendingTransactionsForPrepaidPlansEnabled); - void Setup(string gameObject, string apiKey, string appUserId, bool observerMode, bool usesStoreKit2IfAvailable, + void Setup(string gameObject, string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, StoreKitVersion storeKitVersion, string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically, - Purchases.EntitlementVerificationMode entitlementVerificationMode); + Purchases.EntitlementVerificationMode entitlementVerificationMode, bool pendingTransactionsForPrepaidPlansEnabled); void GetProducts(string[] productIdentifiers, string type = "subs"); @@ -27,7 +28,6 @@ void PurchaseSubscriptionOption(Purchases.SubscriptionOption subscriptionOption, void RestorePurchases(); void LogIn(string appUserId); void LogOut(); - void SetFinishTransactions(bool finishTransactions); void SetAllowSharingStoreAccount(bool allow); void SetDebugLogsEnabled(bool enabled); void SetLogLevel(Purchases.LogLevel level); @@ -40,7 +40,7 @@ void PurchaseSubscriptionOption(Purchases.SubscriptionOption subscriptionOption, void SyncAttributesAndOfferingsIfNeeded(); void SyncPurchases(); - void SyncObserverModeAmazonPurchase(string productID, string receiptID, string amazonUserID, string isoCurrencyCode, + void SyncAmazonPurchase(string productID, string receiptID, string amazonUserID, string isoCurrencyCode, double price); void SetAutomaticAppleSearchAdsAttributionCollection(bool enabled); diff --git a/RevenueCat/Scripts/PurchasesWrapperAndroid.cs b/RevenueCat/Scripts/PurchasesWrapperAndroid.cs index f6a9ed10..4d179b87 100644 --- a/RevenueCat/Scripts/PurchasesWrapperAndroid.cs +++ b/RevenueCat/Scripts/PurchasesWrapperAndroid.cs @@ -81,18 +81,19 @@ public void PurchaseSubscriptionOption(Purchases.SubscriptionOption subscription } } - public void Setup(string gameObject, string apiKey, string appUserId, bool observerMode, bool usesStoreKit2IfAvailable, - string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically) + public void Setup(string gameObject, string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, StoreKitVersion storeKitVersion, + string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically, + bool pendingTransactionsForPrepaidPlansEnabled) { Setup(gameObject, apiKey, appUserId, observerMode, usesStoreKit2IfAvailable, userDefaultsSuiteName, useAmazon, dangerousSettingsJson, shouldShowInAppMessagesAutomatically, Purchases.EntitlementVerificationMode.Disabled); } - public void Setup(string gameObject, string apiKey, string appUserId, bool observerMode, bool usesStoreKit2IfAvailable, + public void Setup(string gameObject, string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, StoreKitVersion storeKitVersion, string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically, - Purchases.EntitlementVerificationMode entitlementVerificationMode) + Purchases.EntitlementVerificationMode entitlementVerificationMode, bool pendingTransactionsForPrepaidPlansEnabled) { - CallPurchases("setup", apiKey, appUserId, gameObject, observerMode, userDefaultsSuiteName, useAmazon, shouldShowInAppMessagesAutomatically, + CallPurchases("setup", apiKey, appUserId, gameObject, purchasesAreCompletedBy.Name(), userDefaultsSuiteName, useAmazon, shouldShowInAppMessagesAutomatically, dangerousSettingsJson, entitlementVerificationMode.Name()); } @@ -111,11 +112,6 @@ public void LogOut() CallPurchases("logOut"); } - public void SetFinishTransactions(bool finishTransactions) - { - CallPurchases("setFinishTransactions", finishTransactions); - } - public void SetAllowSharingStoreAccount(bool allow) { CallPurchases("setAllowSharingStoreAccount", allow); @@ -171,10 +167,10 @@ public void SyncPurchases() CallPurchases("syncPurchases"); } - public void SyncObserverModeAmazonPurchase(string productID, string receiptID, string amazonUserID, + public void SyncAmazonPurchase(string productID, string receiptID, string amazonUserID, string isoCurrencyCode, double price) { - CallPurchases("syncObserverModeAmazonPurchase", productID, receiptID, amazonUserID, isoCurrencyCode, price); + CallPurchases("syncAmazonPurchase", productID, receiptID, amazonUserID, isoCurrencyCode, price); } public void SetAutomaticAppleSearchAdsAttributionCollection(bool enabled) diff --git a/RevenueCat/Scripts/PurchasesWrapperNoop.cs b/RevenueCat/Scripts/PurchasesWrapperNoop.cs index f32f73b4..7d066a1b 100644 --- a/RevenueCat/Scripts/PurchasesWrapperNoop.cs +++ b/RevenueCat/Scripts/PurchasesWrapperNoop.cs @@ -4,14 +4,16 @@ public partial class Purchases { private class PurchasesWrapperNoop : IPurchasesWrapper { - public void Setup(string gameObject, string apiKey, string appUserId, bool observerMode, bool usesStoreKit2IfAvailable, - string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically) + public void Setup(string gameObject, string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, + StoreKitVersion storeKitVersion, string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, + bool shouldShowInAppMessagesAutomatically, bool pendingTransactionsForPrepaidPlansEnabled) { } - public void Setup(string gameObject, string apiKey, string appUserId, bool observerMode, bool usesStoreKit2IfAvailable, - string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically, - EntitlementVerificationMode entitlementVerificationMode) + public void Setup(string gameObject, string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, + StoreKitVersion storeKitVersion, string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, + bool shouldShowInAppMessagesAutomatically, EntitlementVerificationMode entitlementVerificationMode, + bool pendingTransactionsForPrepaidPlansEnabled) { } @@ -53,10 +55,6 @@ public void LogOut() { } - public void SetFinishTransactions(bool finishTransactions) - { - } - public void SetAllowSharingStoreAccount(bool allow) { } @@ -102,15 +100,11 @@ public void SyncPurchases() { } - public void SyncObserverModeAmazonPurchase(string productID, string receiptID, string amazonUserID, + public void SyncAmazonPurchase(string productID, string receiptID, string amazonUserID, string isoCurrencyCode, double price) { } - public void SetAutomaticAppleSearchAdsAttributionCollection(bool enabled) - { - } - public void EnableAdServicesAttributionTokenCollection() { } diff --git a/RevenueCat/Scripts/PurchasesWrapperiOS.cs b/RevenueCat/Scripts/PurchasesWrapperiOS.cs index 053faf05..6016c757 100644 --- a/RevenueCat/Scripts/PurchasesWrapperiOS.cs +++ b/RevenueCat/Scripts/PurchasesWrapperiOS.cs @@ -7,24 +7,27 @@ public class PurchasesWrapperiOS : IPurchasesWrapper { [DllImport("__Internal")] - private static extern void _RCSetupPurchases(string gameObject, string apiKey, string appUserId, bool observerMode, - bool usesStoreKit2IfAvailable, string userDefaultsSuiteName, + private static extern void _RCSetupPurchases(string gameObject, string apiKey, string appUserId, string purchasesAreCompletedBy, + string storeKitVersion, string userDefaultsSuiteName, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically, - string entitlementVerificationMode); - public void Setup(string gameObject, string apiKey, string appUserId, bool observerMode, bool usesStoreKit2IfAvailable, - string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically) + string entitlementVerificationMode, bool pendingTransactionsForPrepaidPlansEnabled); + public void Setup(string gameObject, string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, + StoreKitVersion storeKitVersion, string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, + bool shouldShowInAppMessagesAutomatically, bool pendingTransactionsForPrepaidPlansEnabled) { - Setup(gameObject, apiKey, appUserId, observerMode, usesStoreKit2IfAvailable, + Setup(gameObject, apiKey, appUserId, purchasesAreCompletedBy, storeKitVersion, userDefaultsSuiteName, useAmazon, dangerousSettingsJson, shouldShowInAppMessagesAutomatically, - Purchases.EntitlementVerificationMode.Disabled); + Purchases.EntitlementVerificationMode.Disabled, pendingTransactionsForPrepaidPlansEnabled); } - public void Setup(string gameObject, string apiKey, string appUserId, bool observerMode, bool usesStoreKit2IfAvailable, - string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, bool shouldShowInAppMessagesAutomatically, - Purchases.EntitlementVerificationMode entitlementVerificationMode) + public void Setup(string gameObject, string apiKey, string appUserId, PurchasesAreCompletedBy purchasesAreCompletedBy, + StoreKitVersion storeKitVersion, string userDefaultsSuiteName, bool useAmazon, string dangerousSettingsJson, + bool shouldShowInAppMessagesAutomatically, Purchases.EntitlementVerificationMode entitlementVerificationMode, + bool pendingTransactionsForPrepaidPlansEnabled) { - _RCSetupPurchases(gameObject, apiKey, appUserId, observerMode, usesStoreKit2IfAvailable, - userDefaultsSuiteName, dangerousSettingsJson, shouldShowInAppMessagesAutomatically, entitlementVerificationMode.Name()); + _RCSetupPurchases(gameObject, apiKey, appUserId, purchasesAreCompletedBy.Name(), storeKitVersion.Name(), + userDefaultsSuiteName, dangerousSettingsJson, shouldShowInAppMessagesAutomatically, entitlementVerificationMode.Name(), + pendingTransactionsForPrepaidPlansEnabled); } [SuppressMessage("ReSharper", "NotAccessedField.Local")] @@ -95,7 +98,7 @@ public void SyncPurchases() _RCSyncPurchases(); } - public void SyncObserverModeAmazonPurchase(string productID, string receiptID, string amazonUserID, + public void SyncAmazonPurchase(string productID, string receiptID, string amazonUserID, string isoCurrencyCode, double price) { // No-Op @@ -115,13 +118,6 @@ public void LogOut() _RCLogOut(); } - [DllImport("__Internal")] - private static extern void _RCSetFinishTransactions(bool finishTransactions); - public void SetFinishTransactions(bool finishTransactions) - { - _RCSetFinishTransactions(finishTransactions); - } - [DllImport("__Internal")] private static extern void _RCSetAllowSharingStoreAccount(bool allow); public void SetAllowSharingStoreAccount(bool allow) diff --git a/RevenueCat/Scripts/StoreKitVersion.cs b/RevenueCat/Scripts/StoreKitVersion.cs new file mode 100644 index 00000000..445c52d9 --- /dev/null +++ b/RevenueCat/Scripts/StoreKitVersion.cs @@ -0,0 +1,34 @@ +using System; +using System.ComponentModel; + +public partial class Purchases +{ + public enum StoreKitVersion + { + /// Always use StoreKit 1. + [Description("STOREKIT_1")] + StoreKit1, + + /// Always use StoreKit 2 (StoreKit 1 will be used if StoreKit 2 is not available in the current device.) + /// - Warning: Make sure you have an In-App Purchase Key configured in your app. + /// Please see https://rev.cat/in-app-purchase-key-configuration for more info. + [Description("STOREKIT_2")] + StoreKit2, + + /// Let RevenueCat use the most appropiate version of StoreKit. + [Description("DEFAULT")] + Default, + } +} + +internal static class StoreKitVersionExtensions +{ + internal static string Name(this Purchases.StoreKitVersion storeKitVersion) + { + var type = storeKitVersion.GetType(); + var memInfo = type.GetMember(storeKitVersion.ToString()); + var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); + var stringValue = ((DescriptionAttribute) attributes[0]).Description; + return stringValue; + } +} diff --git a/RevenueCat/Scripts/SubscriptionOption.cs b/RevenueCat/Scripts/SubscriptionOption.cs index 7ecebb70..18a59c1e 100644 --- a/RevenueCat/Scripts/SubscriptionOption.cs +++ b/RevenueCat/Scripts/SubscriptionOption.cs @@ -81,6 +81,11 @@ public class SubscriptionOption [Obsolete("Deprecated, use PresentedOfferingContext instead.", false)] [CanBeNull] public readonly string PresentedOfferingIdentifier; + /** + * Information about the installment subscription. Currently only supported in Google Play. + */ + [CanBeNull] public readonly InstallmentsInfo InstallmentsInfo; + public SubscriptionOption(JSONNode response) { Id = response["id"]; @@ -129,6 +134,12 @@ public SubscriptionOption(JSONNode response) PresentedOfferingContext = new PresentedOfferingContext(presentedOfferingContexNode); PresentedOfferingIdentifier = PresentedOfferingContext.OfferingIdentifier; } + + var installmentsInfoNode = response["installmentsInfo"]; + if (installmentsInfoNode != null && !installmentsInfoNode.IsNull) + { + InstallmentsInfo = new InstallmentsInfo(installmentsInfoNode); + } } public override string ToString() @@ -144,7 +155,8 @@ public override string ToString() $"{nameof(FullPricePhase)}: {FullPricePhase}\n" + $"{nameof(FreePhase)}: {FreePhase}\n" + $"{nameof(IntroPhase)}: {IntroPhase}\n" + - $"{nameof(PresentedOfferingIdentifier)}: {PresentedOfferingIdentifier}"; + $"{nameof(PresentedOfferingIdentifier)}: {PresentedOfferingIdentifier}\n" + + $"{nameof(InstallmentsInfo)}: {InstallmentsInfo}\n"; } public class PricingPhase @@ -326,5 +338,26 @@ public override string ToString() $"{nameof(CurrencyCode)}: {CurrencyCode}\n"; } } + + /// Type containing information of installment subscriptions. Currently only supported in Google Play. + public class InstallmentsInfo { + /// Number of payments the customer commits to in order to purchase the subscription. + public readonly int CommitmentPaymentsCount; + + /// After the commitment payments are complete, the number of payments the user commits to upon a renewal. + public readonly int RenewalCommitmentPaymentsCount; + + public InstallmentsInfo(JSONNode response) + { + CommitmentPaymentsCount = response["commitmentPaymentsCount"]; + RenewalCommitmentPaymentsCount = response["renewalCommitmentPaymentsCount"]; + } + + public override string ToString() + { + return $"{nameof(CommitmentPaymentsCount)}: {CommitmentPaymentsCount}\n" + + $"{nameof(RenewalCommitmentPaymentsCount)}: {RenewalCommitmentPaymentsCount}\n"; + } + } } } diff --git a/Subtester/Assets/Plugins/Android/mainTemplate.gradle b/Subtester/Assets/Plugins/Android/mainTemplate.gradle index 00e50149..dea55060 100644 --- a/Subtester/Assets/Plugins/Android/mainTemplate.gradle +++ b/Subtester/Assets/Plugins/Android/mainTemplate.gradle @@ -19,7 +19,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // Android Resolver Dependencies Start implementation 'androidx.annotation:annotation:[1.2.0]' // Packages/com.revenuecat.purchases-unity/Plugins/Editor/RevenueCatDependencies.xml:5 - implementation 'com.revenuecat.purchases:purchases-hybrid-common:[11.1.0]' // Packages/com.revenuecat.purchases-unity/Plugins/Editor/RevenueCatDependencies.xml:4 + implementation 'com.revenuecat.purchases:purchases-hybrid-common:[13.0.0]' // Packages/com.revenuecat.purchases-unity/Plugins/Editor/RevenueCatDependencies.xml:4 // Android Resolver Dependencies End **DEPS**} diff --git a/Subtester/ProjectSettings/AndroidResolverDependencies.xml b/Subtester/ProjectSettings/AndroidResolverDependencies.xml index 6bcd9d84..95d98e93 100644 --- a/Subtester/ProjectSettings/AndroidResolverDependencies.xml +++ b/Subtester/ProjectSettings/AndroidResolverDependencies.xml @@ -1,7 +1,7 @@ androidx.annotation:annotation:[1.2.0] - com.revenuecat.purchases:purchases-hybrid-common:[11.1.0] + com.revenuecat.purchases:purchases-hybrid-common:[13.0.0]