diff --git a/Editor/QonversionDependencies.xml b/Editor/QonversionDependencies.xml
index 8a11b2a..d41b48b 100644
--- a/Editor/QonversionDependencies.xml
+++ b/Editor/QonversionDependencies.xml
@@ -1,11 +1,11 @@
-
+
-
+
diff --git a/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java b/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java
index 99e7abf..4d2e6b8 100644
--- a/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java
+++ b/Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java
@@ -17,7 +17,6 @@
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
-import io.qonversion.sandwich.PurchaseResultListener;
import io.qonversion.sandwich.QonversionSandwich;
import io.qonversion.sandwich.ResultListener;
import io.qonversion.sandwich.SandwichError;
@@ -117,7 +116,7 @@ public static synchronized void checkEntitlements(String unityCallbackName) {
}
public static synchronized void purchase(String productId, @Nullable String offerId, boolean applyOffer, String unityCallbackName) {
- qonversionSandwich.purchase(productId, offerId, applyOffer, getPurchaseResultListener(unityCallbackName));
+ qonversionSandwich.purchase(productId, offerId, applyOffer, getResultListener(unityCallbackName));
}
public static synchronized void updatePurchase(
@@ -128,7 +127,7 @@ public static synchronized void updatePurchase(
@Nullable String updatePolicyKey,
String unityCallbackName
) {
- qonversionSandwich.updatePurchase(productId, offerId, applyOffer, oldProductId, updatePolicyKey, getPurchaseResultListener(unityCallbackName));
+ qonversionSandwich.updatePurchase(productId, offerId, applyOffer, oldProductId, updatePolicyKey, getResultListener(unityCallbackName));
}
public static synchronized void restore(String unityCallbackName) {
@@ -180,6 +179,10 @@ public static synchronized void detachUserFromRemoteConfiguration(String remoteC
qonversionSandwich.detachUserFromRemoteConfiguration(remoteConfigurationId, getResultListener(unityCallbackName));
}
+ public static synchronized void isFallbackFileAccessible(String unityCallbackName) {
+ qonversionSandwich.isFallbackFileAccessible(getResultListener(unityCallbackName));
+ }
+
public static synchronized void checkTrialIntroEligibility(String productIds, String unityCallbackName) {
try {
ObjectMapper mapper = new ObjectMapper();
@@ -206,24 +209,6 @@ public void onError(@NonNull SandwichError error) {
};
}
- private static PurchaseResultListener getPurchaseResultListener(@NotNull String methodName) {
- return new PurchaseResultListener() {
- @Override
- public void onSuccess(@NonNull Map data) {
- sendMessageToUnity(data, methodName);
- }
-
- @Override
- public void onError(@NonNull SandwichError error, boolean isCancelled) {
- final ObjectMapper mapper = new ObjectMapper();
- final ObjectNode rootNode = Utils.createErrorNode(error);
- final JsonNode isCancelledNode = mapper.convertValue(isCancelled, JsonNode.class);
- rootNode.set("isCancelled", isCancelledNode);
- sendMessageToUnity(rootNode, methodName);
- }
- };
- }
-
private static ResultListener getRemoteConfigResultListener(@Nullable String contextKey, @NotNull String methodName) {
return new ResultListener() {
@Override
diff --git a/Runtime/Android/QonversionWrapperAndroid.cs b/Runtime/Android/QonversionWrapperAndroid.cs
index 08c3172..fd6a51f 100644
--- a/Runtime/Android/QonversionWrapperAndroid.cs
+++ b/Runtime/Android/QonversionWrapperAndroid.cs
@@ -183,6 +183,11 @@ public void DetachUserFromRemoteConfiguration(string remoteConfigurationId, stri
CallQonversion("detachUserFromRemoteConfiguration", remoteConfigurationId, callbackName);
}
+ public void IsFallbackFileAccessible(string callbackName)
+ {
+ CallQonversion("isFallbackFileAccessible", callbackName);
+ }
+
public void CheckTrialIntroEligibility(string productIdsJson, string callbackName)
{
CallQonversion("checkTrialIntroEligibility", productIdsJson, callbackName);
diff --git a/Runtime/Scripts/Dto/Eligibility.cs b/Runtime/Scripts/Dto/Eligibility.cs
index b7da7f0..ba99b30 100644
--- a/Runtime/Scripts/Dto/Eligibility.cs
+++ b/Runtime/Scripts/Dto/Eligibility.cs
@@ -23,7 +23,7 @@ private EligibilityStatus FormatEligibilityStatus(object status)
switch (value)
{
case "non_intro_or_trial_product":
- result = EligibilityStatus.NonIntroProduct;
+ result = EligibilityStatus.NonIntroOrTrialProduct;
break;
case "intro_or_trial_ineligible":
result = EligibilityStatus.Ineligible;
diff --git a/Runtime/Scripts/Dto/EligibilityStatus.cs b/Runtime/Scripts/Dto/EligibilityStatus.cs
index c3815fa..496ac51 100644
--- a/Runtime/Scripts/Dto/EligibilityStatus.cs
+++ b/Runtime/Scripts/Dto/EligibilityStatus.cs
@@ -3,7 +3,7 @@
public enum EligibilityStatus
{
Unknown,
- NonIntroProduct,
+ NonIntroOrTrialProduct,
Ineligible,
Eligible
}
diff --git a/Runtime/Scripts/Dto/ProductStoreDetails/ProductInstallmentPlanDetails.cs b/Runtime/Scripts/Dto/ProductStoreDetails/ProductInstallmentPlanDetails.cs
new file mode 100644
index 0000000..0432345
--- /dev/null
+++ b/Runtime/Scripts/Dto/ProductStoreDetails/ProductInstallmentPlanDetails.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+
+namespace QonversionUnity
+{
+ ///
+ /// This class represents the details about the installment plan for a subscription product.
+ ///
+ public class ProductInstallmentPlanDetails
+ {
+ /// Committed payments count after a user signs up for this subscription plan.
+ public readonly int CommitmentPaymentsCount;
+
+ /// Subsequent committed payments count after this subscription plan renews.
+ ///
+ /// Returns 0 if the installment plan doesn't have any subsequent commitment,
+ /// which means this subscription plan will fall back to a normal
+ /// non-installment monthly plan when the plan renews.
+ public readonly int SubsequentCommitmentPaymentsCount;
+
+ public ProductInstallmentPlanDetails(Dictionary dict)
+ {
+ if (dict.TryGetValue("commitmentPaymentsCount", out object value)) CommitmentPaymentsCount = (int)(long)value;
+ if (dict.TryGetValue("subsequentCommitmentPaymentsCount", out value)) SubsequentCommitmentPaymentsCount = (int)(long)value;
+ }
+
+ public override string ToString()
+ {
+ return $"{nameof(CommitmentPaymentsCount)}: {CommitmentPaymentsCount}, " +
+ $"{nameof(SubsequentCommitmentPaymentsCount)}: {SubsequentCommitmentPaymentsCount}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Scripts/Dto/ProductStoreDetails/ProductInstallmentPlanDetails.cs.meta b/Runtime/Scripts/Dto/ProductStoreDetails/ProductInstallmentPlanDetails.cs.meta
new file mode 100644
index 0000000..c3fdfbb
--- /dev/null
+++ b/Runtime/Scripts/Dto/ProductStoreDetails/ProductInstallmentPlanDetails.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: e15d639930374a54829f77585619d381
+timeCreated: 1719504789
\ No newline at end of file
diff --git a/Runtime/Scripts/Dto/ProductStoreDetails/ProductOfferDetails.cs b/Runtime/Scripts/Dto/ProductStoreDetails/ProductOfferDetails.cs
index c698568..a0f1f6c 100644
--- a/Runtime/Scripts/Dto/ProductStoreDetails/ProductOfferDetails.cs
+++ b/Runtime/Scripts/Dto/ProductStoreDetails/ProductOfferDetails.cs
@@ -29,6 +29,9 @@ public class ProductOfferDetails
/// A base plan phase details.
[CanBeNull] public readonly ProductPricingPhase BasePlan;
+ /// Additional details of an installment plan, if exists.
+ [CanBeNull] public readonly ProductInstallmentPlanDetails InstallmentPlanDetails;
+
/// A trial phase details, if exists.
[CanBeNull] public readonly ProductPricingPhase IntroPhase;
@@ -81,6 +84,11 @@ public ProductOfferDetails(Dictionary dict)
{
BasePlan = new ProductPricingPhase(basePlan);
}
+
+ if (dict.TryGetValue("installmentPlanDetails", out value) && value is Dictionary installmentPlan)
+ {
+ InstallmentPlanDetails = new ProductInstallmentPlanDetails(installmentPlan);
+ }
if (dict.TryGetValue("introPhase", out value) && value is Dictionary introPhase)
{
@@ -117,6 +125,7 @@ public override string ToString()
$"{nameof(Tags)}: {tags}, " +
$"{nameof(PricingPhases)}: {pricingPhases}, " +
$"{nameof(BasePlan)}: {BasePlan}, " +
+ $"{nameof(InstallmentPlanDetails)}: {InstallmentPlanDetails}, " +
$"{nameof(IntroPhase)}: {IntroPhase}, " +
$"{nameof(TrialPhase)}: {TrialPhase}, " +
$"{nameof(HasTrial)}: {HasTrial}, " +
diff --git a/Runtime/Scripts/Dto/ProductStoreDetails/ProductStoreDetails.cs b/Runtime/Scripts/Dto/ProductStoreDetails/ProductStoreDetails.cs
index 0f346c6..49edbeb 100644
--- a/Runtime/Scripts/Dto/ProductStoreDetails/ProductStoreDetails.cs
+++ b/Runtime/Scripts/Dto/ProductStoreDetails/ProductStoreDetails.cs
@@ -74,6 +74,10 @@ public class ProductStoreDetails
/// they will need to make a new payment to extend their plan.
public readonly bool IsPrepaid;
+ /// True, if the subscription product is installment, which means that users commit
+ /// to pay for a specified amount of periods every month.
+ public readonly bool IsInstallment;
+
public ProductStoreDetails(Dictionary dict)
{
if (dict.TryGetValue("productId", out object value)) ProductId = value as string;
@@ -119,6 +123,7 @@ public ProductStoreDetails(Dictionary dict)
if (dict.TryGetValue("isInApp", out value)) IsInApp = (bool)value;
if (dict.TryGetValue("isSubscription", out value)) IsSubscription = (bool)value;
if (dict.TryGetValue("isPrepaid", out value)) IsPrepaid = (bool)value;
+ if (dict.TryGetValue("isInstallment", out value)) IsInstallment = (bool)value;
}
public override string ToString()
@@ -144,7 +149,8 @@ public override string ToString()
$"{nameof(ProductType)}: {ProductType}, " +
$"{nameof(IsInApp)}: {IsInApp}, " +
$"{nameof(IsSubscription)}: {IsSubscription}, " +
- $"{nameof(IsPrepaid)}: {IsPrepaid}";
+ $"{nameof(IsPrepaid)}: {IsPrepaid}" +
+ $"{nameof(IsInstallment)}: {IsInstallment}";
}
}
}
\ No newline at end of file
diff --git a/Runtime/Scripts/Dto/QonversionError.cs b/Runtime/Scripts/Dto/QonversionError.cs
index 98b6e99..93047b9 100644
--- a/Runtime/Scripts/Dto/QonversionError.cs
+++ b/Runtime/Scripts/Dto/QonversionError.cs
@@ -1,15 +1,16 @@
+using System;
using System.Collections.Generic;
namespace QonversionUnity
{
public class QonversionError
{
- public string Code;
+ public QErrorCode Code;
public string Message;
public QonversionError(Dictionary dict)
{
- if (dict.TryGetValue("code", out object value)) Code = value as string;
+ if (dict.TryGetValue("code", out object value)) Code = FormatErrorCode(value);
string message = "";
if (dict.TryGetValue("description", out object description))
{
@@ -27,7 +28,7 @@ public QonversionError(Dictionary dict)
Message = message;
}
- internal QonversionError(string code, string message)
+ internal QonversionError(QErrorCode code, string message)
{
Code = code;
Message = message;
@@ -38,5 +39,54 @@ public override string ToString()
return $"{nameof(Code)}: {Code}, " +
$"{nameof(Message)}: {Message}";
}
+
+ private QErrorCode FormatErrorCode(object code)
+ {
+ return Enum.TryParse(code.ToString(), out QErrorCode parsedSource)
+ ? parsedSource
+ : QErrorCode.Unknown;
+ }
+ }
+
+ public enum QErrorCode
+ {
+ Unknown, // Unknown error
+ ApiRateLimitExceeded, // API requests rate limit exceeded
+ AppleStoreError, // Apple Store error received
+ BackendError, // There was a backend error
+ BillingUnavailable, // The Billing service is unavailable on the device
+ ClientInvalid, // Client is not allowed to issue the request, etc
+ CloudServiceNetworkConnectionFailed, // The device could not connect to the network
+ CloudServicePermissionDenied, // User is not allowed to access cloud service information
+ CloudServiceRevoked, // User has revoked permission to use this cloud service
+ FailedToReceiveData, // Could not receive data
+ FeatureNotSupported, // The requested feature is not supported
+ FraudPurchase, // Fraud purchase was detected
+ IncorrectRequest, // Request failed
+ InternalError, // Internal backend error
+ InvalidClientUid, // Client Uid is invalid or not set
+ InvalidCredentials, // Access token is invalid or not set
+ InvalidStoreCredentials, // This account does not have access to the requested application
+ LaunchError, // There was an error while launching Qonversion SDK
+ NetworkConnectionFailed, // There was a network issue. Make sure that the Internet connection is available on the device
+ OfferingsNotFound, // No offerings found
+ PaymentInvalid, // Purchase identifier was invalid, etc.
+ PaymentNotAllowed, // This device is not allowed to make the payment
+ PlayStoreError, // There was an issue with the Play Store service
+ PrivacyAcknowledgementRequired, // User needs to acknowledge Apple's privacy policy
+ ProductAlreadyOwned, // Failed to purchase since item is already owned
+ ProductNotFound, // Failed to purchase since the Qonversion product was not found
+ ProductNotOwned, // Failed to consume purchase since item is not owned
+ ProjectConfigError, // The project is not configured or configured incorrectly in the Qonversion Dashboard
+ PurchaseCanceled, // User pressed back or canceled a dialog for purchase
+ PurchaseInvalid, // Failure of purchase
+ PurchasePending, // Purchase is pending
+ PurchaseUnspecified, // Unspecified state of the purchase
+ ReceiptValidationError, // Receipt validation error
+ RemoteConfigurationNotAvailable, // Remote configuration is not available for the current user or for the provided context key
+ ResponseParsingFailed, // A problem occurred while serializing or deserializing data
+ StoreProductNotAvailable, // Requested product is not available for purchase or its product id was not found
+ UnauthorizedRequestData, // App is attempting to use SKPayment's requestData property, but does not have the appropriate entitlement
+ UnknownClientPlatform, // The current platform is not supported
}
}
\ No newline at end of file
diff --git a/Runtime/Scripts/IQonversion.cs b/Runtime/Scripts/IQonversion.cs
index 5856c99..6f4362c 100644
--- a/Runtime/Scripts/IQonversion.cs
+++ b/Runtime/Scripts/IQonversion.cs
@@ -137,6 +137,12 @@ public interface IQonversion
/// Callback that will be called when response is received.
public void DetachUserFromRemoteConfiguration(string remoteConfigurationId, Qonversion.OnAttachUserResponseReceived callback);
+ ///
+ /// Call this function to check if the fallback file is accessible.
+ ///
+ /// Callback that will be called when response is received.
+ public void IsFallbackFileAccessible(Qonversion.OnFallbackFileAccessibilityResponseReceived callback);
+
///
/// You can check if a user is eligible for an introductory offer, including a free trial.
/// You can show only a regular price for users who are not eligible for an introductory offer.
diff --git a/Runtime/Scripts/Internal/Mapper.cs b/Runtime/Scripts/Internal/Mapper.cs
index 8441a8e..393ac90 100644
--- a/Runtime/Scripts/Internal/Mapper.cs
+++ b/Runtime/Scripts/Internal/Mapper.cs
@@ -7,17 +7,6 @@ namespace QonversionUnity
{
internal class Mapper
{
- internal static bool GetIsCancelledFromJson(string jsonStr)
- {
- if (!(Json.Deserialize(jsonStr) is Dictionary result))
- {
- Debug.LogError("Could not parse purchase result");
- return false;
- }
-
- return result.TryGetValue("isCancelled", out var isCancelled) && Convert.ToBoolean(isCancelled);
- }
-
internal static Dictionary EntitlementsFromJson(string jsonStr)
{
var result = new Dictionary();
@@ -117,6 +106,19 @@ internal static string ScreenIdFromJson(string jsonStr)
return screenResult.GetString("screenId", "");
}
+ internal static bool IsFallbackFileAccessibleFromJson(string jsonStr)
+ {
+ var isAccessible = false;
+ if (!(Json.Deserialize(jsonStr) is Dictionary rawResult))
+ {
+ Debug.LogError("Could not parse fallback file accessibility");
+ return false;
+ }
+ if (rawResult.TryGetValue("success", out object value)) isAccessible = (bool)value;
+
+ return isAccessible;
+ }
+
internal static Dictionary EligibilitiesFromJson(string jsonStr)
{
var result = new Dictionary();
diff --git a/Runtime/Scripts/Internal/QonversionInternal.cs b/Runtime/Scripts/Internal/QonversionInternal.cs
index 7188ea5..91b5a48 100644
--- a/Runtime/Scripts/Internal/QonversionInternal.cs
+++ b/Runtime/Scripts/Internal/QonversionInternal.cs
@@ -25,8 +25,9 @@ internal class QonversionInternal : MonoBehaviour, IQonversion
private const string OnUserPropertiesMethodName = "OnUserProperties";
private const string OnAttachUserMethodName = "OnAttachUser";
private const string OnDetachUserMethodName = "OnDetachUser";
+ private const string OnIsFallbackFileAccessibleMethodName = "OnIsFallbackFileAccessible";
- private const string SdkVersion = "7.5.0";
+ private const string SdkVersion = "8.0.0";
private const string SdkSource = "unity";
private const string DefaultRemoteConfigContextKey = "";
@@ -53,6 +54,7 @@ internal class QonversionInternal : MonoBehaviour, IQonversion
private Qonversion.OnUserPropertiesReceived UserPropertiesCallback { get; set; }
private Qonversion.OnAttachUserResponseReceived AttachUserCallback { get; set; }
private Qonversion.OnAttachUserResponseReceived DetachUserCallback { get; set; }
+ private Qonversion.OnFallbackFileAccessibilityResponseReceived FallbackFileCallback { get; set; }
public event Qonversion.OnPromoPurchasesReceived PromoPurchasesReceived
{
@@ -205,6 +207,13 @@ public void DetachUserFromRemoteConfiguration(string remoteConfigurationId, Qonv
instance.DetachUserFromRemoteConfiguration(remoteConfigurationId, OnDetachUserMethodName);
}
+ public void IsFallbackFileAccessible(Qonversion.OnFallbackFileAccessibilityResponseReceived callback)
+ {
+ FallbackFileCallback = callback;
+ IQonversionWrapper instance = GetNativeWrapper();
+ instance.IsFallbackFileAccessible(OnIsFallbackFileAccessibleMethodName);
+ }
+
public void CheckTrialIntroEligibility(IList productIds, Qonversion.OnEligibilitiesReceived callback)
{
var productIdsJson = Json.Serialize(productIds);
@@ -494,6 +503,15 @@ private void OnDetachUser(string jsonString)
}
}
+ private void OnIsFallbackFileAccessible(string jsonString)
+ {
+ if (FallbackFileCallback == null) return;
+
+ var isAccessible = Mapper.IsFallbackFileAccessibleFromJson(jsonString);
+
+ FallbackFileCallback(isAccessible);
+ }
+
// Called from the native SDK - Called when eligibilities received from the checkTrialIntroEligibilityForProductIds() method
private void OnEligibilities(string jsonString)
{
@@ -623,7 +641,7 @@ private void HandlePurchaseResult(Qonversion.OnPurchaseResultReceived callback,
var error = Mapper.ErrorFromJson(jsonString);
if (error != null)
{
- var isCancelled = Mapper.GetIsCancelledFromJson(jsonString);
+ var isCancelled = error.Code == QErrorCode.PurchaseCanceled;
callback(null, error, isCancelled);
}
else
diff --git a/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs b/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs
index 861c654..17008ab 100644
--- a/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs
+++ b/Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs
@@ -29,6 +29,7 @@ internal interface IQonversionWrapper
void DetachUserFromExperiment(string experimentId, string callbackName);
void AttachUserToRemoteConfiguration(string remoteConfigurationId, string callbackName);
void DetachUserFromRemoteConfiguration(string remoteConfigurationId, string callbackName);
+ void IsFallbackFileAccessible(string callbackName);
void CheckTrialIntroEligibility(string productIdsJson, string callbackName);
void SetAppleSearchAdsAttributionEnabled(bool enable);
void Identify(string userID, string callbackName);
diff --git a/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs b/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs
index 90e8fb6..1cf461c 100644
--- a/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs
+++ b/Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs
@@ -95,6 +95,10 @@ public void DetachUserFromRemoteConfiguration(string remoteConfigurationId, stri
{
}
+ public void IsFallbackFileAccessible(string callbackName)
+ {
+ }
+
public void StoreSdkInfo(string version, string source)
{
}
diff --git a/Runtime/Scripts/Qonversion.cs b/Runtime/Scripts/Qonversion.cs
index f245c40..554992a 100644
--- a/Runtime/Scripts/Qonversion.cs
+++ b/Runtime/Scripts/Qonversion.cs
@@ -66,6 +66,7 @@ public static IQonversion Initialize(QonversionConfig config)
public delegate void OnAttachUserResponseReceived(bool success, QonversionError error);
public delegate void OnEligibilitiesReceived(Dictionary eligibilities, QonversionError error);
public delegate void OnUserInfoReceived(User userInfo, QonversionError error);
+ public delegate void OnFallbackFileAccessibilityResponseReceived(bool success);
///
/// Delegate fires each time a promo purchase from the App Store happens.
diff --git a/Runtime/iOS/Plugins/Common/UtilityBridge.m b/Runtime/iOS/Plugins/Common/UtilityBridge.m
index bc04293..633cfb6 100644
--- a/Runtime/iOS/Plugins/Common/UtilityBridge.m
+++ b/Runtime/iOS/Plugins/Common/UtilityBridge.m
@@ -37,7 +37,6 @@ + (NSDictionary *)convertError:(SandwichError *)error {
NSMutableDictionary *result = [NSMutableDictionary new];
result[@"error"] = errorDict;
- result[@"isCancelled"] = error.additionalInfo[@"isCancelled"];
return [result copy];
}
diff --git a/Runtime/iOS/Plugins/QonversionBridge.m b/Runtime/iOS/Plugins/QonversionBridge.m
index 93c83ce..84ebb84 100644
--- a/Runtime/iOS/Plugins/QonversionBridge.m
+++ b/Runtime/iOS/Plugins/QonversionBridge.m
@@ -232,6 +232,14 @@ void _detachUserFromRemoteConfiguration(const char* remoteConfigurationId, const
}];
}
+void _isFallbackFileAccessible(const char* unityCallbackName) {
+ NSString *callbackName = [UtilityBridge convertCStringToNSString:unityCallbackName];
+
+ [qonversionSandwich isFallbackFileAccessibleWithCompletion:^(NSDictionary * _Nullable result, SandwichError * _Nullable error) {
+ [UtilityBridge handleResult:result error:error callbackName:callbackName unityListener:unityListenerName];
+ }];
+}
+
void _checkTrialIntroEligibility(const char* productIdsJson, const char* unityCallbackName) {
NSString *callbackName = [UtilityBridge convertCStringToNSString:unityCallbackName];
NSString *productIdsJsonStr = [UtilityBridge convertCStringToNSString:productIdsJson];
diff --git a/Runtime/iOS/QonversionWrapperIOS.cs b/Runtime/iOS/QonversionWrapperIOS.cs
index b17a40b..cc56b04 100644
--- a/Runtime/iOS/QonversionWrapperIOS.cs
+++ b/Runtime/iOS/QonversionWrapperIOS.cs
@@ -3,13 +3,16 @@
#endif
using System;
-using System.Collections.Generic;
+using UnityEngine;
+using System.IO;
namespace QonversionUnity
{
internal class QonversionWrapperIOS : IQonversionWrapper
{
#if UNITY_IOS
+ private const string FallbackFileName = "qonversion_ios_fallbacks.json";
+
[DllImport("__Internal")]
private static extern void _initialize(string gameObjectName);
@@ -88,6 +91,9 @@ internal class QonversionWrapperIOS : IQonversionWrapper
[DllImport("__Internal")]
private static extern void _detachUserFromRemoteConfiguration(string remoteConfigurationId, string callbackName);
+ [DllImport("__Internal")]
+ private static extern void _isFallbackFileAccessible(string callbackName);
+
[DllImport("__Internal")]
private static extern void _checkTrialIntroEligibility(string productIdsJson, string callbackName);
@@ -101,6 +107,21 @@ internal class QonversionWrapperIOS : IQonversionWrapper
public void Initialize(string gameObjectName)
{
#if UNITY_IOS
+ try
+ {
+ string filePath = Path.Combine(Application.streamingAssetsPath, FallbackFileName);
+
+ if (File.Exists(filePath))
+ {
+ string result = System.IO.File.ReadAllText(filePath);
+ File.WriteAllText(Application.persistentDataPath + "/" + FallbackFileName, result);
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.LogWarning("Fallback file is not accessible. " + e);
+ }
+
_initialize(gameObjectName);
#endif
}
@@ -124,14 +145,14 @@ public void SyncHistoricalData()
{
#if UNITY_IOS
_syncHistoricalData();
-#endif
+#endif
}
public void SyncStoreKit2Purchases()
{
#if UNITY_IOS
_syncStoreKit2Purchases();
-#endif
+#endif
}
public void SyncPurchases()
@@ -296,6 +317,13 @@ public void DetachUserFromRemoteConfiguration(string remoteConfigurationId, stri
#endif
}
+ public void IsFallbackFileAccessible(string callbackName)
+ {
+#if UNITY_IOS
+ _isFallbackFileAccessible(callbackName);
+#endif
+ }
+
public void CheckTrialIntroEligibility(string productIdsJson, string callbackName)
{
#if UNITY_IOS
diff --git a/package.json b/package.json
index 9335ea5..070810b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "com.qonversion.unity",
"displayName": "Qonversion",
- "version": "7.5.0",
+ "version": "8.0.0",
"unity": "2018.3",
"description": "Empower your mobile app marketing and product decisions with precise subscription data.",
"author": {