diff --git a/Editor/QonversionDependencies.xml b/Editor/QonversionDependencies.xml index 26816ae..708b462 100644 --- a/Editor/QonversionDependencies.xml +++ b/Editor/QonversionDependencies.xml @@ -1,11 +1,11 @@ - + - + diff --git a/Runtime/Scripts/Constants.cs b/Runtime/Scripts/Constants.cs index da6bbe0..a24ba20 100644 --- a/Runtime/Scripts/Constants.cs +++ b/Runtime/Scripts/Constants.cs @@ -5,5 +5,6 @@ static class Constants public const string KeyPrefix = "com.qonversion.keys"; public const string SourceKey = KeyPrefix + ".source"; public const string VersionKey = KeyPrefix + ".sourceVersion"; + public const int SkuDetailsPriceRatio = 1000000; } } \ No newline at end of file diff --git a/Runtime/Scripts/Models/Product.cs b/Runtime/Scripts/Models/Product.cs index 0c67f16..d76a592 100644 --- a/Runtime/Scripts/Models/Product.cs +++ b/Runtime/Scripts/Models/Product.cs @@ -38,6 +38,21 @@ public class Product /// Available for Android only. [CanBeNull] public readonly SkuDetails SkuDetails; + /// Store product title + [CanBeNull] public readonly string StoreTitle; + + /// Store product description + [CanBeNull] public readonly string StoreDescription; + + /// Price of the product + [CanBeNull] public readonly double Price; + + /// Store Product currency code, such as USD + [CanBeNull] public readonly string CurrencyCode; + + /// Formatted introductory price of a subscription, including its currency sign, such as €2.99 + [CanBeNull] public readonly string PrettyIntroductoryPrice; + public Product(Dictionary dict) { if (dict.TryGetValue("id", out object value)) QonversionId = value as string; @@ -51,11 +66,31 @@ public Product(Dictionary dict) { if (Application.platform == RuntimePlatform.Android) { - if (value is Dictionary skuDetails) SkuDetails = new SkuDetails(skuDetails); + if (value is Dictionary skuDetails) + { + SkuDetails = new SkuDetails(skuDetails); + + Price = (double)SkuDetails.PriceAmountMicros / Constants.SkuDetailsPriceRatio; + CurrencyCode = SkuDetails.PriceCurrencyCode; + StoreTitle = SkuDetails.Title; + StoreDescription = SkuDetails.Description; + + string introPrice = SkuDetails.IntroductoryPrice; + PrettyIntroductoryPrice = (introPrice.Length != 0) ? introPrice : null; + } } else { - if (value is Dictionary skProduct) SkProduct = new SKProduct(skProduct); + if (value is Dictionary skProduct) + { + SkProduct = new SKProduct(skProduct); + + Price = double.Parse(SkProduct.Price); + CurrencyCode = SkProduct.CurrencyCode; + StoreTitle = SkProduct.LocalizedTitle; + StoreDescription = SkProduct.LocalizedDescription; + PrettyIntroductoryPrice = SkProduct.IntroductoryPrice.CurrencySymbol + SkProduct.IntroductoryPrice.Price; + } } } } @@ -69,7 +104,12 @@ public override string ToString() $"{nameof(TrialDuration)}: {TrialDuration}, " + $"{nameof(PrettyPrice)}: {PrettyPrice}, " + $"{nameof(SkProduct)}: {SkProduct}, " + - $"{nameof(SkuDetails)}: {SkuDetails}"; + $"{nameof(SkuDetails)}: {SkuDetails}" + + $"{nameof(StoreTitle)}: {StoreTitle}" + + $"{nameof(StoreDescription)}: {StoreDescription}" + + $"{nameof(Price)}: {Price}" + + $"{nameof(CurrencyCode)}: {CurrencyCode}" + + $"{nameof(PrettyIntroductoryPrice)}: {PrettyIntroductoryPrice}"; } private QProductType FormatType(object productType) => diff --git a/Runtime/Scripts/Models/SkProduct/SKProductDiscount.cs b/Runtime/Scripts/Models/SkProduct/SKProductDiscount.cs index 95d5dc6..3a1e58e 100644 --- a/Runtime/Scripts/Models/SkProduct/SKProductDiscount.cs +++ b/Runtime/Scripts/Models/SkProduct/SKProductDiscount.cs @@ -13,6 +13,7 @@ public class SKProductDiscount public readonly SKProductDiscountPaymentMode PaymentMode; public readonly int NumberOfPeriods; [CanBeNull] public readonly SKProductSubscriptionPeriod SubscriptionPeriod; + public readonly string CurrencySymbol; public SKProductDiscount(Dictionary dict) { @@ -22,6 +23,7 @@ public SKProductDiscount(Dictionary dict) if (dict.TryGetValue("localeIdentifier", out value)) LocaleIdentifier = value as string; if (dict.TryGetValue("paymentMode", out value)) PaymentMode = FormatPaymentMode(value); if (dict.TryGetValue("numberOfPeriods", out value)) NumberOfPeriods = Convert.ToInt32(value); + if (dict.TryGetValue("currencySymbol", out value)) CurrencySymbol = value as string; if (dict.TryGetValue("subscriptionPeriod", out value)) { @@ -38,7 +40,8 @@ public override string ToString() $"{nameof(Price)}: {Price} , " + $"{nameof(PaymentMode)}: {PaymentMode}, " + $"{nameof(NumberOfPeriods)}: {NumberOfPeriods}, " + - $"{nameof(SubscriptionPeriod)}: {SubscriptionPeriod}"; + $"{nameof(SubscriptionPeriod)}: {SubscriptionPeriod}" + + $"{nameof(CurrencySymbol)}: {CurrencySymbol}"; } private SKProductDiscountType FormatDiscountType(object discountType) => diff --git a/Runtime/Scripts/Qonversion.cs b/Runtime/Scripts/Qonversion.cs index 1e8fea5..1403953 100644 --- a/Runtime/Scripts/Qonversion.cs +++ b/Runtime/Scripts/Qonversion.cs @@ -20,7 +20,7 @@ public class Qonversion : MonoBehaviour private const string OnOfferingsMethodName = "OnOfferings"; private const string OnEligibilitiesMethodName = "OnEligibilities"; - private const string SdkVersion = "3.0.0"; + private const string SdkVersion = "3.1.0"; private const string SdkSource = "unity"; private static IQonversionWrapper _Instance; diff --git a/Runtime/iOS/Plugins/Common/UtilityBridge.m b/Runtime/iOS/Plugins/Common/UtilityBridge.m index 5b51936..2594bf8 100644 --- a/Runtime/iOS/Plugins/Common/UtilityBridge.m +++ b/Runtime/iOS/Plugins/Common/UtilityBridge.m @@ -43,10 +43,16 @@ + (NSNumber *)convertProperty:(NSString *)propertyStr { } + (NSDictionary *)convertError:(NSError *)error{ - NSDictionary *errorDict = [@{ - @"code": [@(error.code) stringValue], - @"message": [NSString stringWithFormat:@"%@. Domain: %@", error.localizedDescription, error.domain], - } mutableCopy]; + NSString *errorMessage = [NSString stringWithFormat:@"%@. Domain: %@", error.localizedDescription, error.domain]; + NSMutableDictionary *errorDict = [NSMutableDictionary new]; + errorDict[@"code"] = @(error.code).stringValue; + + NSString *debugMessage = error.userInfo[NSDebugDescriptionErrorKey]; + if (debugMessage.length > 0) { + errorMessage = [NSString stringWithFormat:@"%@\nDebugInfo:%@", errorMessage, debugMessage]; + } + + errorDict[@"message"] = errorMessage; NSMutableDictionary *result = [NSMutableDictionary new]; result[@"error"] = errorDict; @@ -160,6 +166,7 @@ + (NSDictionary *)convertDiscount:(SKProductDiscount *)discount API_AVAILABLE(io introductoryPrice[@"subscriptionPeriod"] = [subscriptionPeriod copy]; introductoryPrice[@"paymentMode"] = @(discount.paymentMode); + introductoryPrice[@"currencySymbol"] = discount.priceLocale.currencySymbol; if (@available(iOS 12.2, *)) { introductoryPrice[@"identifier"] = discount.identifier; diff --git a/package.json b/package.json index bb0ea13..210d524 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.qonversion.unity", "displayName": "Qonversion", - "version": "3.0.0", + "version": "3.1.0", "unity": "2018.3", "description": "Empower your mobile app marketing and product decisions with precise subscription data.", "author": {