├── .github └── workflows │ ├── manual_minor_prerelease.yml │ ├── manual_patch_prerelease.yml │ ├── prerelease_github.yml │ ├── release_pull_requests.yml │ ├── stale_issues.yml │ └── upgrade_sandwich.yml ├── .gitignore ├── Editor.meta ├── Editor ├── QonversionDependencies.xml └── QonversionDependencies.xml.meta ├── README.md ├── README.md.meta ├── Runtime.meta ├── Runtime ├── Android.meta ├── Android │ ├── AutomationsWrapperAndroid.cs │ ├── AutomationsWrapperAndroid.cs.meta │ ├── Plugins.meta │ ├── Plugins │ │ ├── com.meta │ │ └── com │ │ │ ├── qonversion.meta │ │ │ └── qonversion │ │ │ ├── unitywrapper.meta │ │ │ └── unitywrapper │ │ │ ├── AutomationsWrapper.java │ │ │ ├── AutomationsWrapper.java.meta │ │ │ ├── MessageSender.java │ │ │ ├── MessageSender.java.meta │ │ │ ├── QonversionWrapper.java │ │ │ ├── QonversionWrapper.java.meta │ │ │ ├── Utils.java │ │ │ └── Utils.java.meta │ ├── QonversionWrapperAndroid.cs │ └── QonversionWrapperAndroid.cs.meta ├── Common.meta ├── Common │ ├── MiniJSON.meta │ ├── MiniJSON │ │ ├── Json.cs │ │ ├── Json.cs.meta │ │ ├── MiniJsonExtensions.cs │ │ └── MiniJsonExtensions.cs.meta │ ├── MiniJson.cs │ └── MiniJson.cs.meta ├── Qonversion.Unity.Sdk.asmdef ├── Qonversion.Unity.Sdk.asmdef.meta ├── Scripts.meta ├── Scripts │ ├── .idea │ │ └── .idea.Scripts.dir │ │ │ └── .idea │ │ │ ├── .gitignore │ │ │ ├── encodings.xml │ │ │ ├── indexLayout.xml │ │ │ └── vcs.xml │ ├── Automations.cs │ ├── Automations.cs.meta │ ├── Dto.meta │ ├── Dto │ │ ├── ActionResult.cs │ │ ├── ActionResult.cs.meta │ │ ├── ActionResultType.cs │ │ ├── ActionResultType.cs.meta │ │ ├── AttributionProvider.cs │ │ ├── AttributionProvider.cs.meta │ │ ├── AutomationsDelegate.cs │ │ ├── AutomationsDelegate.cs.meta │ │ ├── AutomationsEvent.cs │ │ ├── AutomationsEvent.cs.meta │ │ ├── AutomationsEventType.cs │ │ ├── AutomationsEventType.cs.meta │ │ ├── Eligibility.cs │ │ ├── Eligibility.cs.meta │ │ ├── EligibilityStatus.cs │ │ ├── EligibilityStatus.cs.meta │ │ ├── Entitlement.cs │ │ ├── Entitlement.cs.meta │ │ ├── EntitlementsCacheLifetime.cs │ │ ├── EntitlementsCacheLifetime.cs.meta │ │ ├── Environment.cs │ │ ├── Environment.cs.meta │ │ ├── Experiment.cs │ │ ├── Experiment.cs.meta │ │ ├── ExperimentGroup.cs │ │ ├── ExperimentGroup.cs.meta │ │ ├── LaunchMode.cs │ │ ├── LaunchMode.cs.meta │ │ ├── Offering.cs │ │ ├── Offering.cs.meta │ │ ├── Offerings.cs │ │ ├── Offerings.cs.meta │ │ ├── Product.cs │ │ ├── Product.cs.meta │ │ ├── ProductStoreDetails.meta │ │ ├── ProductStoreDetails │ │ │ ├── PricingPhaseRecurrenceMode.cs │ │ │ ├── PricingPhaseRecurrenceMode.cs.meta │ │ │ ├── PricingPhaseType.cs │ │ │ ├── PricingPhaseType.cs.meta │ │ │ ├── ProductInAppDetails.cs │ │ │ ├── ProductInAppDetails.cs.meta │ │ │ ├── ProductInstallmentPlanDetails.cs │ │ │ ├── ProductInstallmentPlanDetails.cs.meta │ │ │ ├── ProductOfferDetails.cs │ │ │ ├── ProductOfferDetails.cs.meta │ │ │ ├── ProductPrice.cs │ │ │ ├── ProductPrice.cs.meta │ │ │ ├── ProductPricingPhase.cs │ │ │ ├── ProductPricingPhase.cs.meta │ │ │ ├── ProductStoreDetails.cs │ │ │ └── ProductStoreDetails.cs.meta │ │ ├── ProductType.cs │ │ ├── ProductType.cs.meta │ │ ├── PromotionalOffer.cs │ │ ├── PromotionalOffer.cs.meta │ │ ├── PurchaseModel.cs │ │ ├── PurchaseModel.cs.meta │ │ ├── PurchaseOptions.cs │ │ ├── PurchaseOptions.cs.meta │ │ ├── PurchaseOptionsBuilder.cs │ │ ├── PurchaseOptionsBuilder.cs.meta │ │ ├── PurchaseUpdateModel.cs │ │ ├── PurchaseUpdateModel.cs.meta │ │ ├── PurchaseUpdatePolicy.cs │ │ ├── PurchaseUpdatePolicy.cs.meta │ │ ├── QonversionError.cs │ │ ├── QonversionError.cs.meta │ │ ├── RemoteConfig.cs │ │ ├── RemoteConfig.cs.meta │ │ ├── RemoteConfigList.cs │ │ ├── RemoteConfigList.cs.meta │ │ ├── RemoteConfigurationSource.cs │ │ ├── RemoteConfigurationSource.cs.meta │ │ ├── ScreenPresentationConfig.cs │ │ ├── ScreenPresentationConfig.cs.meta │ │ ├── ScreenPresentationStyle.cs │ │ ├── ScreenPresentationStyle.cs.meta │ │ ├── SkProduct.meta │ │ ├── SkProduct │ │ │ ├── SKPraymentDiscount.cs │ │ │ ├── SKPraymentDiscount.cs.meta │ │ │ ├── SKProduct.cs │ │ │ ├── SKProduct.cs.meta │ │ │ ├── SKProductDiscount.cs │ │ │ ├── SKProductDiscount.cs.meta │ │ │ ├── SKProductSubscriptionPeriod.cs │ │ │ └── SKProductSubscriptionPeriod.cs.meta │ │ ├── SkuDetails.cs │ │ ├── SkuDetails.cs.meta │ │ ├── SubscriptionPeriod.cs │ │ ├── SubscriptionPeriod.cs.meta │ │ ├── SubscriptionPeriodUnit.cs │ │ ├── SubscriptionPeriodUnit.cs.meta │ │ ├── Transaction.cs │ │ ├── Transaction.cs.meta │ │ ├── User.cs │ │ ├── User.cs.meta │ │ ├── UserProperties.cs │ │ ├── UserProperties.cs.meta │ │ ├── UserProperty.cs │ │ ├── UserProperty.cs.meta │ │ ├── UserPropertyKey.cs │ │ └── UserPropertyKey.cs.meta │ ├── IAutomations.cs │ ├── IAutomations.cs.meta │ ├── IQonversion.cs │ ├── IQonversion.cs.meta │ ├── Internal.meta │ ├── Internal │ │ ├── AutomationsInternal.cs │ │ ├── AutomationsInternal.cs.meta │ │ ├── Constants.cs │ │ ├── Constants.cs.meta │ │ ├── Mapper.cs │ │ ├── Mapper.cs.meta │ │ ├── QonversionInternal.cs │ │ ├── QonversionInternal.cs.meta │ │ ├── Utils.cs │ │ ├── Utils.cs.meta │ │ ├── wrappers.meta │ │ └── wrappers │ │ │ ├── automations.meta │ │ │ ├── automations │ │ │ ├── AutomationsWrapperNoop.cs │ │ │ ├── AutomationsWrapperNoop.cs.meta │ │ │ ├── IAutomationsWrapper.cs │ │ │ └── IAutomationsWrapper.cs.meta │ │ │ ├── qonversion.meta │ │ │ └── qonversion │ │ │ ├── IQonversionWrapper.cs │ │ │ ├── IQonversionWrapper.cs.meta │ │ │ ├── QonversionWrapperNoop.cs │ │ │ └── QonversionWrapperNoop.cs.meta │ ├── Qonversion.cs │ ├── Qonversion.cs.meta │ ├── QonversionConfig.cs │ ├── QonversionConfig.cs.meta │ ├── QonversionConfigBuilder.cs │ └── QonversionConfigBuilder.cs.meta ├── iOS.meta └── iOS │ ├── AutomationsWrapperIOS.cs │ ├── AutomationsWrapperIOS.cs.meta │ ├── Plugins.meta │ ├── Plugins │ ├── AutomationsBridge.m │ ├── AutomationsBridge.m.meta │ ├── Common.meta │ ├── Common │ │ ├── QNUAutomationsDelegate.h │ │ ├── QNUAutomationsDelegate.h.meta │ │ ├── QNUAutomationsDelegate.m │ │ ├── QNUAutomationsDelegate.m.meta │ │ ├── UtilityBridge.h │ │ ├── UtilityBridge.h.meta │ │ ├── UtilityBridge.m │ │ └── UtilityBridge.m.meta │ ├── QonversionBridge.m │ └── QonversionBridge.m.meta │ ├── QonversionWrapperIOS.cs │ └── QonversionWrapperIOS.cs.meta ├── fastlane.meta ├── fastlane ├── Appfile ├── Appfile.meta ├── Fastfile ├── README.md ├── README.md.meta ├── fastfile.meta ├── report.xml └── report.xml.meta ├── img.meta ├── img ├── UnityQonversionLauncher.png └── UnityQonversionLauncher.png.meta ├── package.json └── package.json.meta /.github/workflows/manual_minor_prerelease.yml: -------------------------------------------------------------------------------- 1 | name: Manual Minor Prerelease 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | patch-minor: 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | ref: develop 14 | 15 | - name: Minor 16 | run: | 17 | fastlane minor 18 | -------------------------------------------------------------------------------- /.github/workflows/manual_patch_prerelease.yml: -------------------------------------------------------------------------------- 1 | name: Manual Patch Prerelease 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | patch-prerelease: 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | ref: develop 14 | 15 | - name: Patch 16 | run: | 17 | fastlane patch 18 | -------------------------------------------------------------------------------- /.github/workflows/prerelease_github.yml: -------------------------------------------------------------------------------- 1 | name: Pre-release Github 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | 8 | jobs: 9 | pre-release: 10 | runs-on: macos-latest 11 | 12 | steps: 13 | - uses: "marvinpinto/action-automatic-releases@latest" 14 | with: 15 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 16 | automatic_release_tag: "latest" 17 | prerelease: true 18 | title: "Development Build" 19 | files: | 20 | LICENSE.txt 21 | *.jar -------------------------------------------------------------------------------- /.github/workflows/release_pull_requests.yml: -------------------------------------------------------------------------------- 1 | name: Release pull requests from dev by tag 2 | on: 3 | push: 4 | tags: 5 | - prerelease/* 6 | 7 | jobs: 8 | handle_prerelease: 9 | uses: qonversion/shared-sdk-workflows/.github/workflows/prerelease_handling.yml@main 10 | -------------------------------------------------------------------------------- /.github/workflows/stale_issues.yml: -------------------------------------------------------------------------------- 1 | name: Close stale issues 2 | on: 3 | schedule: 4 | - cron: '30 1 * * *' 5 | 6 | jobs: 7 | stale_issues: 8 | uses: qonversion/shared-sdk-workflows/.github/workflows/stale_issues.yml@main -------------------------------------------------------------------------------- /.github/workflows/upgrade_sandwich.yml: -------------------------------------------------------------------------------- 1 | name: Upgrade Sandwich 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | sandwich_version: 6 | description: 'Sandwich version' 7 | required: true 8 | default: '0.0.0' 9 | 10 | jobs: 11 | upgrade: 12 | uses: qonversion/shared-sdk-workflows/.github/workflows/upgrade_sandwich.yml@main 13 | with: 14 | sandwich_version: ${{ github.event.inputs.sandwich_version }} 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Uu]ser[Ss]ettings/ 12 | 13 | # MemoryCaptures can get excessive in size. 14 | # They also could contain extremely sensitive data 15 | /[Mm]emoryCaptures/ 16 | 17 | # Recordings can get excessive in size 18 | /[Rr]ecordings/ 19 | 20 | # Uncomment this line if you wish to ignore the asset store tools plugin 21 | # /[Aa]ssets/AssetStoreTools* 22 | 23 | # Autogenerated Jetbrains Rider plugin 24 | /[Aa]ssets/Plugins/Editor/JetBrains* 25 | 26 | # Visual Studio cache directory 27 | .vs/ 28 | 29 | # Gradle cache directory 30 | .gradle/ 31 | 32 | # Autogenerated VS/MD/Consulo solution and project files 33 | ExportedObj/ 34 | .consulo/ 35 | *.csproj 36 | *.unityproj 37 | *.sln 38 | *.suo 39 | *.tmp 40 | *.user 41 | *.userprefs 42 | *.pidb 43 | *.booproj 44 | *.svd 45 | *.pdb 46 | *.mdb 47 | *.opendb 48 | *.VC.db 49 | .idea 50 | 51 | # Unity3D generated meta files 52 | *.pidb.meta 53 | *.pdb.meta 54 | *.mdb.meta 55 | 56 | # Unity3D generated file on crash reports 57 | sysinfo.txt 58 | 59 | # Builds 60 | *.apk 61 | *.aab 62 | *.unitypackage 63 | *.app 64 | 65 | # Crashlytics generated file 66 | crashlytics-build.properties 67 | 68 | # Packed Addressables 69 | /[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin* 70 | 71 | # Temporary auto-generated Android Assets 72 | /[Aa]ssets/[Ss]treamingAssets/aa.meta 73 | /[Aa]ssets/[Ss]treamingAssets/aa/* -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 00dca6be949bd4393bfdbb3bc85e201a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/QonversionDependencies.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Editor/QonversionDependencies.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e8f49b3053cb24b62a0793a238b95380 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Qonversion 3 |

4 | 5 | Qonversion - In-app subscription monetization: implement subscriptions and grow your app’s revenue with A/B experiments 6 | 7 | * In-app subscription management SDK 8 | * API and webhooks to make your subscription data available where you need it 9 | * Seamless Stripe integration to enable cross-platform access management 10 | * Subscribers CRM with user-level transactions 11 | * Instant access to real-time subscription analytics 12 | * Built-in A/B experiments for subscription business model 13 | 14 |

15 | 16 | 17 |

18 | 19 | [![openupm](https://img.shields.io/npm/v/com.qonversion.unity?label=openupm®istry_uri=https://package.openupm.com)](https://openupm.com/packages/com.qonversion.unity/) 20 | [![MIT License](http://img.shields.io/cocoapods/l/Qonversion.svg?style=flat)](https://qonversion.io) 21 | 22 | 23 | ## In-App Subscription Implementation & Management 24 | 25 |

26 | 27 | 28 |

29 | 30 | 1. Qonversion SDK provides three simple methods to manage subscriptions: 31 | * Get in-app product details 32 | * Make purchases 33 | * Check subscription status to manage premium access 34 | 2. Qonversion communicates with Apple or Google platforms both through SDK and server-side to process native in-app payments and keep subscription statuses up to date. 35 | 3. You can use Qonversion webhooks and API in addition to SDK to get user-level data where you need it. 36 | 37 | See the [quick start guide documentation](https://documentation.qonversion.io/docs/quickstart). 38 | 39 | ## Analytics 40 | 41 | Qonversion provides advanced subscription analytics out-of-the-box. You can monitor real-time metrics from new users and trial-to-paid conversions to revenue, MRR, ARR, cohort retention and more. Understand your customers and make better decisions with precise subscription analytics. 42 | 43 |

44 | 45 | 46 |

47 | 48 | 49 | ## A/B Experiments 50 | 51 | Qonversion's A/B Experiments feature provides everything required to quickly launch paywall and other monetization experiments, analyze results and roll out winning versions without releasing a new app build. Qonversion A/B Experiments include: 52 | 53 | * User segmentation by country, install date, app version, free/paying user 54 | * Traffic allocation 55 | * Advanced subscription analytics 56 | * Visualization of A/B experiments results 57 | * Statistical significance of the results 58 | * Roll out winning versions without app release with remote config 59 | 60 | 61 |

62 | 63 | 64 |

65 | 66 | See more details [here](https://documentation.qonversion.io/docs/paywall-experiments). 67 | 68 | ## Integrations 69 | 70 | Send user-level subscription data to your favorite platforms. 71 | 72 | * Amplitude 73 | * Mixpanel 74 | * Appsflyer 75 | * Adjust 76 | * Singular 77 | * CleverTap 78 | * [All other integrations here](qonversion.io/integrations) 79 | 80 |

81 | 82 | 83 |

84 | 85 | ## Why Qonversion? 86 | 87 | * **No headaches with Apple's StoreKit & Google Billing.** Qonversion provides simple methods to handle Apple StoreKit & Google Billing purchase flow. 88 | * **Receipt validation.** Qonversion validates user receipts with Apple and Google to provide 100% accurate purchase information and subscription statuses. It also prevents unauthorized access to the premium features of your app. 89 | * **Track and increase your revenue.** Qonversion provides detailed real-time revenue analytics including cohort analysis, trial conversion rates, country segmentation, and much more. 90 | * **Integrations with the leading mobile platforms.** Qonversion allows sending data to platforms like AppsFlyer, Adjust, Branch, Tenjin, Facebook Ads, Amplitude, Mixpanel, and many others. 91 | * **Change promoted in-app products.** Change promoted in-app products anytime without app releases. 92 | * **A/B test** and identify winning in-app purchases, subscriptions or paywals. 93 | * **Cross-device and cross-platform access management.** If you provide user authorization in your app, you can easily set Qonversion to provide premium access to authorized users across devices and operating systems. 94 | * **SDK caches the data.** Qonversion SDK caches purchase data including in-app products and entitlements, so the user experience is not affected even with the slow or interrupting network connection. 95 | * **Webhooks.** You can easily send all of the data to your server with Qonversion webhooks. 96 | * **Customer support.** You can always reach out to our customer support and get the help required. 97 | 98 | Convinced? Let's go! 99 | 100 | ## Documentation 101 | 102 | Check the [full documentation](https://documentation.qonversion.io/docs/quickstart) to learn about implementation details and available features. 103 | 104 | #### Help us improve the documentation 105 | 106 | Whether you’re a core user or trying it out for the first time, you can make a valuable contribution to Qonversion by improving the documentation. Help us by: 107 | 108 | * sending us feedback about something you thought was confusing or simply missing 109 | * sending us a pull request via GitHub 110 | * suggesting better wording or ways of explaining certain topics in the [Qonversion documentation](http://documentation.qonversion.io). Use `SUGGEST EDITS` button in the top right corner. 111 | 112 | ## Contributing 113 | 114 | Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. 115 | 116 | 1. Fork the Project 117 | 2. Create your Feature Branch (`git checkout -b feature/SuperFeature`) 118 | 3. Commit your Changes. Use small commits with separate logic. (`git commit -m 'Add some super feature'`) 119 | 4. Push to the Branch (`git push origin feature/SuperFeature`) 120 | 5. Open a Pull Request 121 | 122 | 123 | ## Have a question? 124 | 125 | Contact us via [issues on GitHub](https://github.com/qonversion/unity-sdk/issues) or [ask a question](https://documentation.qonversion.io/discuss-new) on the site. 126 | 127 | ## License 128 | 129 | Qonversion SDK is available under the MIT license. -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5a66fc8572b164d4da7665448ad88ea5 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 76f61b2fdd3f42d4a83f044b683016db 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Android.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68d19869c54f9764d855135c11d2ab00 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Android/AutomationsWrapperAndroid.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace QonversionUnity 4 | { 5 | internal class AutomationsWrapperAndroid : IAutomationsWrapper 6 | { 7 | public void Initialize(string gameObjectName) 8 | { 9 | CallAutomations("initialize", gameObjectName); 10 | } 11 | 12 | public void SetNotificationsToken(string token) 13 | { 14 | CallAutomations("setNotificationsToken", token); 15 | } 16 | 17 | public bool HandleNotification(string notification) 18 | { 19 | return CallAutomations("handleNotification", notification); 20 | } 21 | 22 | public string GetNotificationCustomPayload(string notification) 23 | { 24 | return CallAutomations("getNotificationCustomPayload", notification); 25 | } 26 | 27 | public void SubscribeOnAutomationEvents() 28 | { 29 | CallAutomations("subscribeOnAutomationEvents"); 30 | } 31 | 32 | public void ShowScreen(string screenId, string callbackName) 33 | { 34 | CallAutomations("showScreen", screenId, callbackName); 35 | } 36 | 37 | public void SetScreenPresentationConfig(string configJson, string screenId) 38 | { 39 | CallAutomations("setScreenPresentationConfig", configJson, screenId); 40 | } 41 | 42 | private const string AutomationsWrapper = "com.qonversion.unitywrapper.AutomationsWrapper"; 43 | 44 | private static T CallAutomations(string methodName, params object[] args) 45 | { 46 | using (var automations = new AndroidJavaClass(AutomationsWrapper)) 47 | { 48 | return automations.CallStatic(methodName, args); 49 | } 50 | } 51 | 52 | private static void CallAutomations(string methodName, params object[] args) 53 | { 54 | using (var automations = new AndroidJavaClass(AutomationsWrapper)) 55 | { 56 | automations.CallStatic(methodName, args); 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Runtime/Android/AutomationsWrapperAndroid.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bf1469979a8544c5b531368ea34cec2f 3 | timeCreated: 1668776137 -------------------------------------------------------------------------------- /Runtime/Android/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d7df7b917c788e84aaff9c56bab04ced 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a28459d5e109a944794b5a7a64aaabcd 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com/qonversion.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dcef5ddb5c68df540ae5468498f4a949 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com/qonversion/unitywrapper.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 06b40e5048253d04ab06b66f9d2452d2 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com/qonversion/unitywrapper/AutomationsWrapper.java: -------------------------------------------------------------------------------- 1 | package com.qonversion.unitywrapper; 2 | 3 | import android.util.Log; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | 8 | import com.fasterxml.jackson.core.JsonProcessingException; 9 | import com.fasterxml.jackson.core.type.TypeReference; 10 | import com.fasterxml.jackson.databind.ObjectMapper; 11 | import com.fasterxml.jackson.databind.node.ObjectNode; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | import io.qonversion.sandwich.AutomationsEventListener; 19 | import io.qonversion.sandwich.AutomationsSandwich; 20 | import io.qonversion.sandwich.ResultListener; 21 | import io.qonversion.sandwich.SandwichError; 22 | 23 | @SuppressWarnings("UnnecessaryLocalVariable") 24 | public class AutomationsWrapper { 25 | private static final String EVENT_SCREEN_SHOWN = "OnAutomationsScreenShown"; 26 | private static final String EVENT_ACTION_STARTED = "OnAutomationsActionStarted"; 27 | private static final String EVENT_ACTION_FAILED = "OnAutomationsActionFailed"; 28 | private static final String EVENT_ACTION_FINISHED = "OnAutomationsActionFinished"; 29 | private static final String EVENT_AUTOMATIONS_FINISHED = "OnAutomationsFinished"; 30 | 31 | public static String TAG = "AutomationsDelegate"; 32 | private static MessageSender messageSender; 33 | private static AutomationsSandwich automationsSandwich; 34 | 35 | public static synchronized void initialize(String unityListener) { 36 | messageSender = new MessageSender(unityListener); 37 | automationsSandwich = new AutomationsSandwich(); 38 | } 39 | 40 | public static synchronized void subscribeOnAutomationEvents() { 41 | automationsSandwich.setDelegate(new EventListener()); 42 | } 43 | 44 | public static synchronized void setNotificationsToken(String token) { 45 | automationsSandwich.setNotificationToken(token); 46 | } 47 | 48 | public static synchronized boolean handleNotification(String notification) { 49 | try { 50 | ObjectMapper mapper = new ObjectMapper(); 51 | 52 | TypeReference> typeRef 53 | = new TypeReference>() { 54 | }; 55 | Map notificationInfo = mapper.readValue(notification, typeRef); 56 | 57 | boolean result = automationsSandwich.handleNotification(notificationInfo); 58 | 59 | return result; 60 | } catch (Exception e) { 61 | return false; 62 | } 63 | } 64 | 65 | @Nullable 66 | public static synchronized String getNotificationCustomPayload(String notification) { 67 | try { 68 | final ObjectMapper mapper = new ObjectMapper(); 69 | 70 | final TypeReference> typeRef 71 | = new TypeReference>() { 72 | }; 73 | final Map notificationInfo = mapper.readValue(notification, typeRef); 74 | 75 | final Map payload = automationsSandwich.getNotificationCustomPayload(notificationInfo); 76 | final String json = mapper.writeValueAsString(payload); 77 | 78 | return json; 79 | } catch (Exception e) { 80 | return null; 81 | } 82 | } 83 | 84 | public static synchronized void showScreen(String screenId, String unityCallbackName) { 85 | automationsSandwich.showScreen(screenId, new ResultListener() { 86 | @Override 87 | public void onSuccess(@NonNull Map data) { 88 | sendMessageToUnity(data, unityCallbackName); 89 | } 90 | 91 | @Override 92 | public void onError(@NonNull SandwichError error) { 93 | handleErrorResponse(error, unityCallbackName); 94 | } 95 | }); 96 | } 97 | 98 | public static synchronized void setScreenPresentationConfig(String configJson, @Nullable String screenId) { 99 | try { 100 | ObjectMapper mapper = new ObjectMapper(); 101 | 102 | TypeReference> typeRef 103 | = new TypeReference>() {}; 104 | Map configData = mapper.readValue(configJson, typeRef); 105 | 106 | automationsSandwich.setScreenPresentationConfig(configData, screenId); 107 | } catch (JsonProcessingException e) { 108 | handleSerializationException(e); 109 | } 110 | } 111 | 112 | private static void handleErrorResponse(@NotNull SandwichError error, @NotNull String methodName) { 113 | final ObjectNode rootNode = Utils.createErrorNode(error); 114 | 115 | sendMessageToUnity(rootNode, methodName); 116 | } 117 | 118 | static class EventListener implements AutomationsEventListener { 119 | @Override 120 | public void onAutomationEvent(@NonNull Event event, @Nullable Map data) { 121 | String methodName; 122 | switch (event) { 123 | case ScreenShown: 124 | methodName = EVENT_SCREEN_SHOWN; 125 | break; 126 | case ActionStarted: 127 | methodName = EVENT_ACTION_STARTED; 128 | break; 129 | case ActionFinished: 130 | methodName = EVENT_ACTION_FINISHED; 131 | break; 132 | case ActionFailed: 133 | methodName = EVENT_ACTION_FAILED; 134 | break; 135 | case AutomationsFinished: 136 | methodName = EVENT_AUTOMATIONS_FINISHED; 137 | break; 138 | default: 139 | return; 140 | } 141 | 142 | sendMessageToUnity(data == null ? new HashMap<>() : data, methodName); 143 | } 144 | } 145 | 146 | private static void sendMessageToUnity(@NotNull Object objectToConvert, @NotNull String methodName) { 147 | try { 148 | messageSender.sendMessageToUnity(objectToConvert, methodName); 149 | } catch (JsonProcessingException e) { 150 | handleException(e); 151 | } 152 | } 153 | 154 | private static void handleException(Exception e) { 155 | Log.e(TAG, "An error occurred while processing automations flow: " + e.getLocalizedMessage()); 156 | } 157 | 158 | private static void handleSerializationException(JsonProcessingException e) { 159 | Log.e(TAG, "An error occurred while serializing data: " + e.getLocalizedMessage()); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com/qonversion/unitywrapper/AutomationsWrapper.java.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c343db7cc54e542d39f73bd2228012e6 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Android: Android 16 | second: 17 | enabled: 1 18 | settings: {} 19 | - first: 20 | Any: 21 | second: 22 | enabled: 0 23 | settings: {} 24 | - first: 25 | Editor: Editor 26 | second: 27 | enabled: 0 28 | settings: 29 | DefaultValueInitialized: true 30 | userData: 31 | assetBundleName: 32 | assetBundleVariant: 33 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com/qonversion/unitywrapper/MessageSender.java: -------------------------------------------------------------------------------- 1 | package com.qonversion.unitywrapper; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.unity3d.player.UnityPlayer; 6 | 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public class MessageSender { 10 | private final String unityListenerName; 11 | 12 | public MessageSender(String unityListenerName) { 13 | this.unityListenerName = unityListenerName; 14 | } 15 | 16 | void sendMessageToUnity(@NotNull Object objectToConvert, @NotNull String methodName) throws JsonProcessingException { 17 | final ObjectMapper mapper = new ObjectMapper(); 18 | final String json = mapper.writeValueAsString(objectToConvert); 19 | UnityPlayer.UnitySendMessage(unityListenerName, methodName, json); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com/qonversion/unitywrapper/MessageSender.java.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 684884a01eddd4f10aa3ab971380605e 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Android: Android 16 | second: 17 | enabled: 1 18 | settings: {} 19 | - first: 20 | Any: 21 | second: 22 | enabled: 0 23 | settings: {} 24 | - first: 25 | Editor: Editor 26 | second: 27 | enabled: 0 28 | settings: 29 | DefaultValueInitialized: true 30 | userData: 31 | assetBundleName: 32 | assetBundleVariant: 33 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com/qonversion/unitywrapper/QonversionWrapper.java.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9b3bcac970bd57249a19f97cb4621515 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Android: Android 16 | second: 17 | enabled: 1 18 | settings: {} 19 | - first: 20 | Any: 21 | second: 22 | enabled: 0 23 | settings: {} 24 | - first: 25 | Editor: Editor 26 | second: 27 | enabled: 0 28 | settings: 29 | DefaultValueInitialized: true 30 | userData: 31 | assetBundleName: 32 | assetBundleVariant: 33 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com/qonversion/unitywrapper/Utils.java: -------------------------------------------------------------------------------- 1 | package com.qonversion.unitywrapper; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.fasterxml.jackson.databind.node.ObjectNode; 5 | 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import io.qonversion.sandwich.SandwichError; 10 | 11 | public class Utils { 12 | 13 | public static ObjectNode createErrorNode(@NotNull SandwichError error) { 14 | return createErrorNode(error.getCode(), error.getDescription(), error.getAdditionalMessage()); 15 | } 16 | 17 | public static ObjectNode createErrorNode(String code, String description, @Nullable String additionalMessage) { 18 | ObjectMapper mapper = new ObjectMapper(); 19 | ObjectNode errorNode = mapper.createObjectNode(); 20 | errorNode.put("code", code); 21 | errorNode.put("description", description); 22 | if (additionalMessage != null) { 23 | errorNode.put("additionalMessage", additionalMessage); 24 | } 25 | 26 | ObjectNode rootNode = mapper.createObjectNode(); 27 | rootNode.set("error", errorNode); 28 | return rootNode; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Runtime/Android/Plugins/com/qonversion/unitywrapper/Utils.java.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1b5c0dd49367425db4e808bbc38580bf 3 | timeCreated: 1670833335 -------------------------------------------------------------------------------- /Runtime/Android/QonversionWrapperAndroid.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ac748a0eedddf7f48bf78bd60d0d8b40 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Common.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9f8f248a64639f24d88b5cf8823ed8e0 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Common/MiniJSON.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fae5ccf0682f6754ea6da63d7ffe7e54 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Common/MiniJSON/Json.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9d3ee7b76aed97e4a94ba457376993fd 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Common/MiniJSON/MiniJsonExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace QonversionUnity.MiniJSON 5 | { 6 | public static class MiniJsonExtensions 7 | { 8 | public static Dictionary GetHash(this Dictionary dic, string key) 9 | { 10 | return (Dictionary)dic[key]; 11 | } 12 | 13 | public static T GetEnum(this Dictionary dic, string key) 14 | { 15 | if (dic.ContainsKey(key)) 16 | { 17 | return (T)Enum.Parse(typeof(T), dic[key].ToString(), ignoreCase: true); 18 | } 19 | return default(T); 20 | } 21 | 22 | public static string GetString(this Dictionary dic, string key, string defaultValue = "") 23 | { 24 | if (dic.ContainsKey(key)) 25 | { 26 | return dic[key].ToString(); 27 | } 28 | return defaultValue; 29 | } 30 | 31 | public static long GetLong(this Dictionary dic, string key) 32 | { 33 | if (dic.ContainsKey(key)) 34 | { 35 | return long.Parse(dic[key].ToString()); 36 | } 37 | return 0L; 38 | } 39 | 40 | public static List GetStringList(this Dictionary dic, string key) 41 | { 42 | if (dic.ContainsKey(key)) 43 | { 44 | List list = new List(); 45 | List list2 = (List)dic[key]; 46 | foreach (object item in list2) 47 | { 48 | list.Add(item.ToString()); 49 | } 50 | return list; 51 | } 52 | return new List(); 53 | } 54 | 55 | public static bool GetBool(this Dictionary dic, string key) 56 | { 57 | if (dic.ContainsKey(key)) 58 | { 59 | return bool.Parse(dic[key].ToString()); 60 | } 61 | return false; 62 | } 63 | 64 | public static T Get(this Dictionary dic, string key) 65 | { 66 | if (dic.ContainsKey(key)) 67 | { 68 | return (T)dic[key]; 69 | } 70 | return default(T); 71 | } 72 | 73 | public static string toJson(this Dictionary obj) 74 | { 75 | return MiniJson.JsonEncode(obj); 76 | } 77 | 78 | public static string toJson(this Dictionary obj) 79 | { 80 | return MiniJson.JsonEncode(obj); 81 | } 82 | 83 | public static string toJson(this string[] array) 84 | { 85 | List list = new List(); 86 | foreach (string item in array) 87 | { 88 | list.Add(item); 89 | } 90 | return MiniJson.JsonEncode(list); 91 | } 92 | 93 | public static List ArrayListFromJson(this string json) 94 | { 95 | return MiniJson.JsonDecode(json) as List; 96 | } 97 | 98 | public static Dictionary HashtableFromJson(this string json) 99 | { 100 | return MiniJson.JsonDecode(json) as Dictionary; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Runtime/Common/MiniJSON/MiniJsonExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9c6171f44828f1f4c9629916a99e6b32 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Common/MiniJson.cs: -------------------------------------------------------------------------------- 1 | using QonversionUnity.MiniJSON; 2 | 3 | namespace QonversionUnity 4 | { 5 | public class MiniJson 6 | { 7 | public static string JsonEncode(object json) 8 | { 9 | return Json.Serialize(json); 10 | } 11 | 12 | public static object JsonDecode(string json) 13 | { 14 | return Json.Deserialize(json); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Runtime/Common/MiniJson.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5fe28a6970fb6864a9081f9e960ab07a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Qonversion.Unity.Sdk.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Qonversion.Unity.Sdk" 3 | } 4 | -------------------------------------------------------------------------------- /Runtime/Qonversion.Unity.Sdk.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7997463b3dbb27245a8ff4616b271e67 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 43b724a4537ec484ab8c8e7d293af0e0 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Rider ignored files 5 | /.idea.Scripts.iml 6 | /projectSettingsUpdater.xml 7 | /contentModel.xml 8 | /modules.xml 9 | # Editor-based HTTP Client requests 10 | /httpRequests/ 11 | # Datasource local storage ignored files 12 | /dataSources/ 13 | /dataSources.local.xml 14 | -------------------------------------------------------------------------------- /Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/indexLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Runtime/Scripts/.idea/.idea.Scripts.dir/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Runtime/Scripts/Automations.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | public static class Automations 7 | { 8 | [CanBeNull] private static IAutomations _backingInstance; 9 | 10 | /// 11 | /// Use this variable to get a current initialized instance of the Qonversion Automations. 12 | /// Please, use Automations only after calling . 13 | /// Otherwise, trying to access the variable will cause an error. 14 | /// 15 | /// Current initialized instance of the Qonversion Automations. 16 | /// throws exception if Qonversion has not been initialized. 17 | public static IAutomations GetSharedInstance() 18 | { 19 | if (_backingInstance == null) 20 | { 21 | try 22 | { 23 | Qonversion.GetSharedInstance(); 24 | } 25 | catch (Exception e) 26 | { 27 | throw new Exception("Qonversion has not been initialized. " + 28 | "Automations should be used after Qonversion is initialized."); 29 | } 30 | 31 | _backingInstance = AutomationsInternal.CreateInstance(); 32 | } 33 | 34 | return _backingInstance; 35 | } 36 | 37 | public delegate void OnShowScreenResponseReceived(QonversionError error); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Runtime/Scripts/Automations.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb9026ffe23714e4094aebd9d036c9c2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6941a58d609fd49ffac95120213d64a3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ActionResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class ActionResult 7 | { 8 | public readonly ActionResultType Type; 9 | [CanBeNull] public readonly Dictionary Parameters; 10 | [CanBeNull] public readonly QonversionError Error; 11 | 12 | public ActionResult(Dictionary dict) 13 | { 14 | if (dict.TryGetValue("error", out var rawError ) && rawError != null) Error = new QonversionError((Dictionary)rawError); 15 | if (dict.TryGetValue("value", out var rawParams) && rawParams != null) Parameters = (Dictionary)rawParams; 16 | if (dict.TryGetValue("type", out var actionType)) Type = FormatActionResultType(actionType); 17 | } 18 | 19 | public override string ToString() 20 | { 21 | return $"{nameof(Type)}: {Type}, " + 22 | $"{nameof(Parameters)}: {Parameters}, " + 23 | $"{nameof(Error)}: {Error}"; 24 | } 25 | 26 | private ActionResultType FormatActionResultType(object type) 27 | { 28 | string value = type as string; 29 | ActionResultType result; 30 | switch (value) 31 | { 32 | case "url": 33 | result = ActionResultType.URL; 34 | break; 35 | case "deeplink": 36 | result = ActionResultType.Deeplink; 37 | break; 38 | case "navigate": 39 | result = ActionResultType.Navigation; 40 | break; 41 | case "purchase": 42 | result = ActionResultType.Purchase; 43 | break; 44 | case "restore": 45 | result = ActionResultType.Restore; 46 | break; 47 | case "close": 48 | result = ActionResultType.Close; 49 | break; 50 | default: 51 | result = ActionResultType.Unknown; 52 | break; 53 | } 54 | 55 | return result; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ActionResult.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e27480d33c0774d5f9f7ce5a1d7c6c56 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ActionResultType.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum ActionResultType 4 | { 5 | Unknown, 6 | URL, 7 | Deeplink, 8 | Navigation, 9 | Purchase, 10 | Restore, 11 | Close 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ActionResultType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 25342fbb35e8a4dce81d44d56b414766 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/AttributionProvider.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum AttributionProvider 4 | { 5 | AppsFlyer = 0, 6 | Branch, 7 | Adjust, 8 | AppleSearchAds, // ios only 9 | AppleAdServices // ios only 10 | } 11 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/AttributionProvider.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4b91d281dc6374342b819965b3694d4e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/AutomationsDelegate.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace QonversionUnity 4 | { 5 | /// 6 | /// Delegate fires each time an automations event happens 7 | /// 8 | public abstract class AutomationsDelegate : MonoBehaviour 9 | { 10 | /// 11 | /// Called when Automations screen is shown 12 | /// 13 | /// shown screen Id 14 | public abstract void OnAutomationsScreenShown(string screenId); 15 | 16 | /// 17 | /// Called when Automations flow starts executing an action 18 | /// 19 | /// executed action 20 | public abstract void OnAutomationsActionStarted(ActionResult actionResult); 21 | 22 | /// 23 | /// Called when Automations flow fails executing an action 24 | /// 25 | /// executed action 26 | public abstract void OnAutomationsActionFailed(ActionResult actionResult); 27 | 28 | /// 29 | /// Called when Automations flow finishes executing an action 30 | /// For instance, if the user made a purchase then action.type == QONActionResultTypePurchase 31 | /// Then you can use the method to get available permissions 32 | /// 33 | /// executed action 34 | public abstract void OnAutomationsActionFinished(ActionResult actionResult); 35 | 36 | /// 37 | /// Called when Automations flow is finished and the Automations screen is closed 38 | /// 39 | public abstract void OnAutomationsFinished(); 40 | } 41 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/AutomationsDelegate.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a59920bdf2fc14ac1a37e77eb3f4d7b2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/AutomationsEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class AutomationsEvent 7 | { 8 | public readonly AutomationsEventType Type; 9 | public readonly DateTime Date; 10 | 11 | public AutomationsEvent(Dictionary dict) 12 | { 13 | if (dict.TryGetValue("timestamp", out object time)) Date = Utils.FormatDate(Convert.ToInt64((double)time)); 14 | if (dict.TryGetValue("type", out object eventType)) Type = FormatAutomationsEventType(eventType); 15 | } 16 | 17 | public override string ToString() 18 | { 19 | return $"{nameof(Type)}: {Type}, " + 20 | $"{nameof(Date)}: {Date}"; 21 | } 22 | 23 | private AutomationsEventType FormatAutomationsEventType(object type) 24 | { 25 | string value = type as string; 26 | AutomationsEventType result; 27 | switch (value) 28 | { 29 | case "trial_started": 30 | result = AutomationsEventType.TrialStarted; 31 | break; 32 | case "trial_converted": 33 | result = AutomationsEventType.TrialConverted; 34 | break; 35 | case "trial_canceled": 36 | result = AutomationsEventType.TrialCanceled; 37 | break; 38 | case "trial_billing_retry_entered": 39 | result = AutomationsEventType.TrialBillingRetry; 40 | break; 41 | case "subscription_started": 42 | result = AutomationsEventType.SubscriptionStarted; 43 | break; 44 | case "subscription_renewed": 45 | result = AutomationsEventType.SubscriptionRenewed; 46 | break; 47 | case "subscription_refunded": 48 | result = AutomationsEventType.SubscriptionRefunded; 49 | break; 50 | case "subscription_canceled": 51 | result = AutomationsEventType.SubscriptionCanceled; 52 | break; 53 | case "subscription_billing_retry_entered": 54 | result = AutomationsEventType.SubscriptionBillingRetry; 55 | break; 56 | case "in_app_purchase": 57 | result = AutomationsEventType.InAppPurchase; 58 | break; 59 | case "subscription_upgraded": 60 | result = AutomationsEventType.SubscriptionUpgraded; 61 | break; 62 | case "trial_still_active": 63 | result = AutomationsEventType.TrialStillActive; 64 | break; 65 | case "trial_expired": 66 | result = AutomationsEventType.TrialExpired; 67 | break; 68 | case "subscription_expired": 69 | result = AutomationsEventType.SubscriptionExpired; 70 | break; 71 | case "subscription_downgraded": 72 | result = AutomationsEventType.SubscriptionDowngraded; 73 | break; 74 | case "subscription_product_changed": 75 | result = AutomationsEventType.SubscriptionProductChanged; 76 | break; 77 | default: 78 | result = AutomationsEventType.Unknown; 79 | break; 80 | } 81 | 82 | return result; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/AutomationsEvent.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 687d028d5e04c4ad88e7995bfbf808c0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/AutomationsEventType.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum AutomationsEventType 4 | { 5 | Unknown, 6 | TrialStarted, 7 | TrialConverted, 8 | TrialCanceled, 9 | TrialBillingRetry, 10 | SubscriptionStarted, 11 | SubscriptionRenewed, 12 | SubscriptionRefunded, 13 | SubscriptionCanceled, 14 | SubscriptionBillingRetry, 15 | InAppPurchase, 16 | SubscriptionUpgraded, 17 | TrialStillActive, 18 | TrialExpired, 19 | SubscriptionExpired, 20 | SubscriptionDowngraded, 21 | SubscriptionProductChanged 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/AutomationsEventType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d069be0d69cf1482da59364bce07633d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Eligibility.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace QonversionUnity 4 | { 5 | public class Eligibility 6 | { 7 | public readonly EligibilityStatus Status; 8 | 9 | public Eligibility(Dictionary dict) 10 | { 11 | if (dict.TryGetValue("status", out object value)) Status = FormatEligibilityStatus(value); 12 | } 13 | 14 | public override string ToString() 15 | { 16 | return $"{nameof(Status)}: {Status}"; 17 | } 18 | 19 | private EligibilityStatus FormatEligibilityStatus(object status) 20 | { 21 | string value = status as string; 22 | EligibilityStatus result; 23 | switch (value) 24 | { 25 | case "non_intro_or_trial_product": 26 | result = EligibilityStatus.NonIntroOrTrialProduct; 27 | break; 28 | case "intro_or_trial_ineligible": 29 | result = EligibilityStatus.Ineligible; 30 | break; 31 | case "intro_or_trial_eligible": 32 | result = EligibilityStatus.Eligible; 33 | break; 34 | default: 35 | result = EligibilityStatus.Unknown; 36 | break; 37 | } 38 | 39 | return result; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Eligibility.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e5734643decb54c5b891603130ab213e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/EligibilityStatus.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum EligibilityStatus 4 | { 5 | Unknown, 6 | NonIntroOrTrialProduct, 7 | Ineligible, 8 | Eligible 9 | } 10 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/EligibilityStatus.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eb95a37986ad54d139d16c3bc624e387 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Entitlement.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8721b4598de3343a28465afe8261afe7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/EntitlementsCacheLifetime.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum EntitlementsCacheLifetime 4 | { 5 | Week, 6 | TwoWeeks, 7 | Month, 8 | TwoMonths, 9 | ThreeMonths, 10 | SixMonths, 11 | Year, 12 | Unlimited 13 | } 14 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/EntitlementsCacheLifetime.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7a565dd602ce74950a70927782a8f4fe 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Environment.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum Environment 4 | { 5 | Sandbox, 6 | Production 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Environment.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1b02fbe89ab349a59491d47e9ca2329d 3 | timeCreated: 1668682691 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Experiment.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace QonversionUnity 4 | { 5 | public class Experiment 6 | { 7 | public readonly string Id; 8 | public readonly string Name; 9 | public readonly ExperimentGroup Group; 10 | 11 | 12 | public Experiment(Dictionary dict) 13 | { 14 | if (dict.TryGetValue("id", out object value)) Id = value as string; 15 | if (dict.TryGetValue("name", out value)) Name = value as string; 16 | if (dict.TryGetValue("group", out value) && value is Dictionary group) 17 | { 18 | Group = new ExperimentGroup(group); 19 | } 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return $"{nameof(Id)}: {Id}, " + 25 | $"{nameof(Name)}: {Name}, " + 26 | $"{nameof(Group)}: {Group}"; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Experiment.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26f8b4a30f24045028e51326a03fb1e9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ExperimentGroup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using JetBrains.Annotations; 4 | 5 | namespace QonversionUnity 6 | { 7 | public class ExperimentGroup 8 | { 9 | public readonly string Id; 10 | public readonly string Name; 11 | public readonly ExperimentGroupType Type; 12 | 13 | public ExperimentGroup(Dictionary dict) 14 | { 15 | if (dict.TryGetValue("id", out object value)) Id = value as string; 16 | if (dict.TryGetValue("name", out value)) Name = value as string; 17 | if (dict.TryGetValue("type", out value)) Type = FormatGroupType(value); 18 | } 19 | 20 | public ExperimentGroupType FormatGroupType(object typeValue) 21 | { 22 | string type = typeValue as string; 23 | if (type == "control") 24 | { 25 | return ExperimentGroupType.Control; 26 | } 27 | else if (type == "treatment") 28 | { 29 | return ExperimentGroupType.Treatment; 30 | } 31 | 32 | return ExperimentGroupType.Unknown; 33 | } 34 | 35 | public override string ToString() 36 | { 37 | return $"{nameof(Id)}: {Id}, " + 38 | $"{nameof(Name)}: {Name}, " + 39 | $"{nameof(Type)}: {Type}"; 40 | } 41 | } 42 | 43 | public enum ExperimentGroupType 44 | { 45 | Unknown = -1, 46 | Control = 0, 47 | Treatment = 1 48 | } 49 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ExperimentGroup.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3bea57f1886414de79be7bf2ea23f74b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/LaunchMode.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum LaunchMode 4 | { 5 | Analytics, 6 | SubscriptionManagement 7 | } 8 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/LaunchMode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 24dcbe0f097a40c59733cfbd46312398 3 | timeCreated: 1668682749 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Offering.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using JetBrains.Annotations; 4 | using UnityEngine.Scripting; 5 | 6 | namespace QonversionUnity 7 | { 8 | public class Offering 9 | { 10 | public readonly string Id; 11 | public readonly QOfferingTag Tag; 12 | public readonly List Products; 13 | 14 | // Informs compiler to save this method from removal via optimization, 15 | // as even if it has no direct calls, it is called via reflection while mapping. 16 | [Preserve] 17 | public Offering(Dictionary dict) 18 | { 19 | if (dict.TryGetValue("id", out object value)) Id = value as string; 20 | if (dict.TryGetValue("tag", out value)) Tag = FormatOfferingTag(value); 21 | if (dict.TryGetValue("products", out value)) 22 | { 23 | if (value is List products) Products = Mapper.ConvertObjectsList(products); 24 | } 25 | } 26 | 27 | [CanBeNull] 28 | public Product ProductForID(string id) 29 | { 30 | return Products.Find(product => product.QonversionId == id); 31 | } 32 | 33 | public QOfferingTag FormatOfferingTag(object tag) => 34 | (QOfferingTag)Convert.ToInt32(tag); 35 | 36 | public override string ToString() 37 | { 38 | return $"{nameof(Id)}: {Id}, " + 39 | $"{nameof(Tag)}: {Tag}, " + 40 | $"{nameof(Products)}: {Utils.PrintObjectList(Products)}"; 41 | } 42 | } 43 | 44 | public enum QOfferingTag 45 | { 46 | Unknown = -1, 47 | None = 0, 48 | Main = 1 49 | } 50 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Offering.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad8db728bf4fd489b8a8a65677f0089b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Offerings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class Offerings 7 | { 8 | [CanBeNull] public readonly Offering Main; 9 | public readonly List AvailableOfferings; 10 | 11 | public Offerings(Dictionary dict) 12 | { 13 | if (dict.TryGetValue("main", out object value) && value is Dictionary offering) 14 | { 15 | Main = new Offering(offering); 16 | } 17 | if (dict.TryGetValue("availableOfferings", out value) && value is List offerings) 18 | { 19 | AvailableOfferings = Mapper.ConvertObjectsList(offerings); 20 | } 21 | } 22 | 23 | [CanBeNull] 24 | public Offering OfferingForID(string id) 25 | { 26 | return AvailableOfferings.Find(offering => offering.Id == id); 27 | } 28 | 29 | public override string ToString() 30 | { 31 | return $"{nameof(Main)}: {Main}, " + 32 | $"{nameof(AvailableOfferings)}: {Utils.PrintObjectList(AvailableOfferings)}"; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Offerings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b48e5e74dc2dc416881ccb7e3030bc3e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Product.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f7fdfa6fc70dc4ac08162a1886f1539a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9fbc1f954cf3c4c02b065ab4eccdc1ac 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/PricingPhaseRecurrenceMode.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | /// 4 | /// Recurrence mode of the pricing phase. 5 | /// 6 | public enum PricingPhaseRecurrenceMode 7 | { 8 | /// The billing plan payment recurs for infinite billing periods unless canceled. 9 | InfiniteRecurring, 10 | 11 | /// The billing plan payment recurs for a fixed number of billing periods 12 | /// set in . 13 | FiniteRecurring, 14 | 15 | /// The billing plan payment is a one-time charge that does not repeat. 16 | NonRecurring, 17 | 18 | /// Unknown recurrence mode. 19 | Unknown, 20 | } 21 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/PricingPhaseRecurrenceMode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c9d02b7b4c0a14d14840c161828aea94 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/PricingPhaseType.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | /// 4 | /// Type of the pricing phase. 5 | /// 6 | public enum PricingPhaseType 7 | { 8 | /// Regular subscription without any discounts like trial or intro offers. 9 | Regular, 10 | 11 | /// A free phase. 12 | FreeTrial, 13 | 14 | /// A phase with a discounted payment for a single period. 15 | DiscountedSinglePayment, 16 | 17 | /// A phase with a discounted payment for several periods, described in . 18 | DiscountedRecurringPayment, 19 | 20 | /// Unknown pricing phase type. 21 | Unknown, 22 | } 23 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/PricingPhaseType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 65730d53808e4455d9c80ab2981353fa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductInAppDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace QonversionUnity 5 | { 6 | /// 7 | /// This class contains all the information about the Google in-app product details. 8 | /// 9 | public class ProductInAppDetails 10 | { 11 | /// The price of the in-app product. 12 | public readonly ProductPrice Price; 13 | 14 | public ProductInAppDetails(Dictionary dict) 15 | { 16 | if (dict.TryGetValue("price", out object value) && value is Dictionary price) 17 | { 18 | Price = new ProductPrice(price); 19 | } 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return $"{nameof(Price)}: {Price}"; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductInAppDetails.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f770c2c584a6456baee470c99f6f44d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductInstallmentPlanDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace QonversionUnity 5 | { 6 | /// 7 | /// This class represents the details about the installment plan for a subscription product. 8 | /// 9 | public class ProductInstallmentPlanDetails 10 | { 11 | /// Committed payments count after a user signs up for this subscription plan. 12 | public readonly int CommitmentPaymentsCount; 13 | 14 | /// Subsequent committed payments count after this subscription plan renews. 15 | /// 16 | /// Returns 0 if the installment plan doesn't have any subsequent commitment, 17 | /// which means this subscription plan will fall back to a normal 18 | /// non-installment monthly plan when the plan renews. 19 | public readonly int SubsequentCommitmentPaymentsCount; 20 | 21 | public ProductInstallmentPlanDetails(Dictionary dict) 22 | { 23 | if (dict.TryGetValue("commitmentPaymentsCount", out object value)) CommitmentPaymentsCount = (int)(long)value; 24 | if (dict.TryGetValue("subsequentCommitmentPaymentsCount", out value)) SubsequentCommitmentPaymentsCount = (int)(long)value; 25 | } 26 | 27 | public override string ToString() 28 | { 29 | return $"{nameof(CommitmentPaymentsCount)}: {CommitmentPaymentsCount}, " + 30 | $"{nameof(SubsequentCommitmentPaymentsCount)}: {SubsequentCommitmentPaymentsCount}"; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductInstallmentPlanDetails.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e15d639930374a54829f77585619d381 3 | timeCreated: 1719504789 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductOfferDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using JetBrains.Annotations; 4 | 5 | namespace QonversionUnity 6 | { 7 | /// 8 | /// This class contains all the information about the Google subscription offer details. 9 | /// It might be either a plain base plan details or a base plan with the concrete offer details. 10 | /// 11 | public class ProductOfferDetails 12 | { 13 | /// The identifier of the current base plan. 14 | public readonly string BasePlanId; 15 | 16 | /// The identifier of the concrete offer, to which these details belong. 17 | /// Null, if these are plain base plan details. 18 | [CanBeNull] public readonly string OfferId; 19 | 20 | /// A token to purchase the current offer. 21 | public readonly string OfferToken; 22 | 23 | /// List of tags set for the current offer. 24 | public readonly string[] Tags; 25 | 26 | /// A time-ordered list of pricing phases for the current offer. 27 | public readonly ProductPricingPhase[] PricingPhases; 28 | 29 | /// A base plan phase details. 30 | [CanBeNull] public readonly ProductPricingPhase BasePlan; 31 | 32 | /// Additional details of an installment plan, if exists. 33 | [CanBeNull] public readonly ProductInstallmentPlanDetails InstallmentPlanDetails; 34 | 35 | /// A trial phase details, if exists. 36 | [CanBeNull] public readonly ProductPricingPhase IntroPhase; 37 | 38 | /// An intro phase details, if exists. 39 | /// The intro phase is one of single or recurrent discounted payments. 40 | [CanBeNull] public readonly ProductPricingPhase TrialPhase; 41 | 42 | /// True, if there is a trial phase in the current offer. False otherwise. 43 | public readonly bool HasTrial; 44 | 45 | /// True, if there is any intro phase in the current offer. False otherwise. 46 | /// The intro phase is one of single or recurrent discounted payments. 47 | public readonly bool HasIntro; 48 | 49 | /// True, if there is any trial or intro phase in the current offer. False otherwise. 50 | /// The intro phase is one of single or recurrent discounted payments. 51 | public readonly bool HasTrialOrIntro; 52 | 53 | public ProductOfferDetails(Dictionary dict) 54 | { 55 | if (dict.TryGetValue("basePlanId", out object value)) BasePlanId = value as string; 56 | if (dict.TryGetValue("offerId", out value)) OfferId = value as string; 57 | if (dict.TryGetValue("offerToken", out value)) OfferToken = value as string; 58 | if (dict.TryGetValue("tags", out value) && value is List tags) { 59 | List result = new List(); 60 | foreach (object tag in tags) 61 | { 62 | result.Add(tag.ToString()); 63 | } 64 | 65 | Tags = result.ToArray(); 66 | } 67 | 68 | if (dict.TryGetValue("pricingPhases", out value) && value is List pricingPhases) 69 | { 70 | List result = new List(); 71 | foreach (object pricingPhase in pricingPhases) 72 | { 73 | if (pricingPhase is Dictionary) 74 | { 75 | ProductPricingPhase phase = new ProductPricingPhase(pricingPhase as Dictionary); 76 | result.Add(phase); 77 | } 78 | } 79 | 80 | PricingPhases = result.ToArray(); 81 | } 82 | 83 | if (dict.TryGetValue("basePlan", out value) && value is Dictionary basePlan) 84 | { 85 | BasePlan = new ProductPricingPhase(basePlan); 86 | } 87 | 88 | if (dict.TryGetValue("installmentPlanDetails", out value) && value is Dictionary installmentPlan) 89 | { 90 | InstallmentPlanDetails = new ProductInstallmentPlanDetails(installmentPlan); 91 | } 92 | 93 | if (dict.TryGetValue("introPhase", out value) && value is Dictionary introPhase) 94 | { 95 | IntroPhase = new ProductPricingPhase(introPhase); 96 | } 97 | 98 | if (dict.TryGetValue("trialPhase", out value) && value is Dictionary trialPhase) 99 | { 100 | TrialPhase = new ProductPricingPhase(trialPhase); 101 | } 102 | 103 | if (dict.TryGetValue("hasTrial", out value)) HasTrial = (bool)value; 104 | if (dict.TryGetValue("hasIntro", out value)) HasIntro = (bool)value; 105 | if (dict.TryGetValue("hasTrialOrIntro", out value)) HasTrialOrIntro = (bool)value; 106 | } 107 | 108 | public override string ToString() 109 | { 110 | string tags = ""; 111 | if (Tags != null) 112 | { 113 | tags = string.Join(", ", Tags.Select(tag => tag)); 114 | } 115 | 116 | string pricingPhases = ""; 117 | if (PricingPhases != null) 118 | { 119 | pricingPhases = string.Join(", ", PricingPhases.Select(phase => phase.ToString())); 120 | } 121 | 122 | return $"{nameof(BasePlanId)}: {BasePlanId}, " + 123 | $"{nameof(OfferId)}: {OfferId}, " + 124 | $"{nameof(OfferToken)}: {OfferToken}, " + 125 | $"{nameof(Tags)}: {tags}, " + 126 | $"{nameof(PricingPhases)}: {pricingPhases}, " + 127 | $"{nameof(BasePlan)}: {BasePlan}, " + 128 | $"{nameof(InstallmentPlanDetails)}: {InstallmentPlanDetails}, " + 129 | $"{nameof(IntroPhase)}: {IntroPhase}, " + 130 | $"{nameof(TrialPhase)}: {TrialPhase}, " + 131 | $"{nameof(HasTrial)}: {HasTrial}, " + 132 | $"{nameof(HasIntro)}: {HasIntro}, " + 133 | $"{nameof(HasTrialOrIntro)}: {HasTrialOrIntro}"; 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductOfferDetails.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b389bf1726051461b97d14e1220443a1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductPrice.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | /// 7 | /// Information about the Google product's price. 8 | /// 9 | public class ProductPrice 10 | { 11 | /// Total amount of money in micro-units, 12 | /// where 1,000,000 micro-units equal one unit of the currency. 13 | public readonly long PriceAmountMicros; 14 | 15 | /// ISO 4217 currency code for price. 16 | public readonly string PriceCurrencyCode; 17 | 18 | /// Formatted price for the payment, including its currency sign. 19 | public readonly string FormattedPrice; 20 | 21 | /// True, if the price is zero. False otherwise. 22 | public readonly bool IsFree; 23 | 24 | /// Price currency symbol. Null if failed to parse. 25 | [CanBeNull] public readonly string CurrencySymbol; 26 | 27 | public ProductPrice(Dictionary dict) 28 | { 29 | if (dict.TryGetValue("priceAmountMicros", out object value)) PriceAmountMicros = (long)value; 30 | if (dict.TryGetValue("priceCurrencyCode", out value)) PriceCurrencyCode = value as string; 31 | if (dict.TryGetValue("formattedPrice", out value)) FormattedPrice = value as string; 32 | if (dict.TryGetValue("isFree", out value)) IsFree = (bool)value; 33 | if (dict.TryGetValue("currencySymbol", out value)) CurrencySymbol = value as string; 34 | } 35 | 36 | public override string ToString() 37 | { 38 | return $"{nameof(PriceAmountMicros)}: {PriceAmountMicros}, " + 39 | $"{nameof(PriceCurrencyCode)}: {PriceCurrencyCode}, " + 40 | $"{nameof(FormattedPrice)}: {FormattedPrice}, " + 41 | $"{nameof(IsFree)}: {IsFree}, " + 42 | $"{nameof(CurrencySymbol)}: {CurrencySymbol}"; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductPrice.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a1fcbbb07eb2b4740ac8528874738326 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductPricingPhase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace QonversionUnity 4 | { 5 | /// 6 | /// This class represents a pricing phase, describing how a user pays at a point in time. 7 | /// 8 | public class ProductPricingPhase 9 | { 10 | /// Price for the current phase. 11 | public readonly ProductPrice Price; 12 | 13 | /// The billing period for which the given price applies. 14 | public readonly SubscriptionPeriod BillingPeriod; 15 | 16 | /// Number of cycles for which the billing period is applied. 17 | public readonly int BillingCycleCount; 18 | 19 | /// Recurrence mode for the pricing phase. 20 | public readonly PricingPhaseRecurrenceMode RecurrenceMode; 21 | 22 | /// Type of the pricing phase. 23 | public readonly PricingPhaseType Type; 24 | 25 | /// True, if the current phase is a trial period. False otherwise. 26 | public readonly bool IsTrial; 27 | 28 | /// True, if the current phase is an intro period. False otherwise. 29 | /// The intro phase is one of single or recurrent discounted payments. 30 | public readonly bool IsIntro; 31 | 32 | /// True, if the current phase represents the base plan. False otherwise. 33 | public readonly bool IsBasePlan; 34 | 35 | public ProductPricingPhase(Dictionary dict) 36 | { 37 | if (dict.TryGetValue("price", out object value) && value is Dictionary price) 38 | { 39 | Price = new ProductPrice(price); 40 | } 41 | 42 | if (dict.TryGetValue("billingPeriod", out value) && value is Dictionary billingPeriod) 43 | { 44 | BillingPeriod = new SubscriptionPeriod(billingPeriod); 45 | } 46 | 47 | if (dict.TryGetValue("billingCycleCount", out value)) BillingCycleCount = (int)(long)value; 48 | if (dict.TryGetValue("recurrenceMode", out value)) RecurrenceMode = FormatRecurrenceMode(value); 49 | if (dict.TryGetValue("type", out value)) Type = FormatType(value); 50 | if (dict.TryGetValue("isTrial", out value)) IsTrial = (bool)value; 51 | if (dict.TryGetValue("isIntro", out value)) IsIntro = (bool)value; 52 | if (dict.TryGetValue("isBasePlan", out value)) IsBasePlan = (bool)value; 53 | } 54 | 55 | private PricingPhaseType FormatType(object typeValue) 56 | { 57 | string type = typeValue as string; 58 | switch (type) 59 | { 60 | case "Regular": return PricingPhaseType.Regular; 61 | case "FreeTrial": return PricingPhaseType.FreeTrial; 62 | case "DiscountedSinglePayment": return PricingPhaseType.DiscountedSinglePayment; 63 | case "DiscountedRecurringPayment": return PricingPhaseType.DiscountedRecurringPayment; 64 | default: return PricingPhaseType.Unknown; 65 | } 66 | } 67 | 68 | private PricingPhaseRecurrenceMode FormatRecurrenceMode(object recurrenceModeValue) 69 | { 70 | string recurrenceMode = recurrenceModeValue as string; 71 | switch (recurrenceMode) { 72 | case "InfiniteRecurring": return PricingPhaseRecurrenceMode.InfiniteRecurring; 73 | case "FiniteRecurring": return PricingPhaseRecurrenceMode.FiniteRecurring; 74 | case "NonRecurring": return PricingPhaseRecurrenceMode.NonRecurring; 75 | default: return PricingPhaseRecurrenceMode.Unknown; 76 | } 77 | } 78 | 79 | public override string ToString() 80 | { 81 | return $"{nameof(Price)}: {Price}, " + 82 | $"{nameof(BillingPeriod)}: {BillingPeriod}, " + 83 | $"{nameof(BillingCycleCount)}: {BillingCycleCount}, " + 84 | $"{nameof(RecurrenceMode)}: {RecurrenceMode}, " + 85 | $"{nameof(Type)}: {Type}, " + 86 | $"{nameof(IsTrial)}: {IsTrial}, " + 87 | $"{nameof(IsIntro)}: {IsIntro}, " + 88 | $"{nameof(IsBasePlan)}: {IsBasePlan}"; 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductPricingPhase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 129d13ec7f81348fb8a969e8f187c91a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductStoreDetails/ProductStoreDetails.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1aed806485ecb43eab6a4f2681282904 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductType.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum QProductType 4 | { 5 | /// Provides access to content on a recurring basis with a free offer 6 | Trial, 7 | /// Provides access to content on a recurring basis with an introductory offer 8 | /// Currently works for Android only. iOS support will be added soon. 9 | Intro, 10 | /// Provides access to content on a recurring basis 11 | Subscription, 12 | /// Content that users can purchase with a single, non-recurring charge 13 | InApp, 14 | /// Unknown product type 15 | Unknown, 16 | } 17 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ProductType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8243ed1d06a04a3a9affcba77e8e2b98 3 | timeCreated: 1701454390 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PromotionalOffer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace QonversionUnity 4 | { 5 | public class PromotionalOffer 6 | { 7 | public readonly SKProductDiscount ProductDiscount; 8 | public readonly SKPaymentDiscount PaymentDiscount; 9 | 10 | public PromotionalOffer(Dictionary dict) 11 | { 12 | if (dict.TryGetValue("productDiscount", out object value) && value is Dictionary productDiscount) 13 | { 14 | ProductDiscount = new SKProductDiscount(productDiscount); 15 | } 16 | if (dict.TryGetValue("paymentDiscount", out value) && value is Dictionary paymentDiscount) 17 | { 18 | PaymentDiscount = new SKPaymentDiscount(paymentDiscount); 19 | } 20 | } 21 | 22 | public override string ToString() 23 | { 24 | return $"{nameof(ProductDiscount)}: {ProductDiscount}, " + 25 | $"{nameof(PaymentDiscount)}: {PaymentDiscount}"; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PromotionalOffer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f3b6b8019f7640c7840cc65821a1d7a4 3 | timeCreated: 1732029067 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseModel.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace QonversionUnity 4 | { 5 | /// 6 | /// Used to provide all the necessary purchase data to the method. 7 | /// Can be created manually or using the method. 8 | /// 9 | /// If is not specified for Android, then the default offer will be applied. 10 | /// To know how we choose the default offer, see . 11 | /// 12 | /// If you want to remove any intro/trial offer from the purchase on Android (use only a bare base plan), 13 | /// call the method. 14 | /// 15 | public class PurchaseModel 16 | { 17 | public readonly string ProductId; 18 | [CanBeNull] public string OfferId; 19 | 20 | internal bool ApplyOffer = true; 21 | 22 | public PurchaseModel(string productId, [CanBeNull] string offerId = null) 23 | { 24 | ProductId = productId; 25 | OfferId = offerId; 26 | } 27 | 28 | public PurchaseModel RemoveOffer() 29 | { 30 | ApplyOffer = false; 31 | return this; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseModel.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d23e34be58ec4d1aae93cd7de23b3825 3 | timeCreated: 1701455044 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using JetBrains.Annotations; 4 | 5 | namespace QonversionUnity 6 | { 7 | public class PurchaseOptions 8 | { 9 | [CanBeNull] public readonly string OfferId; 10 | 11 | public readonly bool ApplyOffer; 12 | 13 | [CanBeNull] public readonly Product OldProduct; 14 | 15 | [CanBeNull] public readonly PurchaseUpdatePolicy? UpdatePolicy; 16 | 17 | [CanBeNull] public readonly List ContextKeys; 18 | 19 | public readonly int Quantity; 20 | 21 | [CanBeNull] public readonly PromotionalOffer PromotionalOffer; 22 | 23 | public PurchaseOptions( 24 | [CanBeNull] string offerId, 25 | bool applyOffer, 26 | [CanBeNull] Product oldProduct, 27 | [CanBeNull] PurchaseUpdatePolicy? updatePolicy, 28 | [CanBeNull] List contextKeys, 29 | int quantity, 30 | [CanBeNull] PromotionalOffer promotionalOffer) 31 | { 32 | OfferId = offerId; 33 | ApplyOffer = applyOffer; 34 | OldProduct = oldProduct; 35 | UpdatePolicy = updatePolicy; 36 | ContextKeys = contextKeys; 37 | Quantity = quantity; 38 | PromotionalOffer = promotionalOffer; 39 | } 40 | 41 | public override string ToString() { 42 | return $"{nameof(OfferId)}: {OfferId}, " + 43 | $"{nameof(ApplyOffer)}: {ApplyOffer}, " + 44 | $"{nameof(OldProduct)}: {OldProduct}, " + 45 | $"{nameof(UpdatePolicy)}: {UpdatePolicy}, " + 46 | $"{nameof(ContextKeys)}: {ContextKeys}, " + 47 | $"{nameof(Quantity)}: {Quantity}, " + 48 | $"{nameof(PromotionalOffer)}: {PromotionalOffer}"; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseOptions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4ad1a7d219a24e79b8b3d51c4e830b2f 3 | timeCreated: 1725357220 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseOptionsBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class PurchaseOptionsBuilder { 7 | [CanBeNull] private string _offerId; 8 | private bool _applyOffer = true; 9 | [CanBeNull] private Product _oldProduct; 10 | [CanBeNull] private PurchaseUpdatePolicy? _updatePolicy; 11 | [CanBeNull] private List _contextKeys; 12 | private int _quantity = 1; 13 | [CanBeNull] private PromotionalOffer _promotionalOffer; 14 | 15 | /// 16 | /// iOS only. 17 | /// Set quantity of product purchasing. Use for consumable in-app products. 18 | /// 19 | /// Quantity of product purchasing. 20 | /// Builder instance for chain calls. 21 | public PurchaseOptionsBuilder SetQuantity(int quantity) 22 | { 23 | this._quantity = quantity; 24 | return this; 25 | } 26 | 27 | /// 28 | /// Android only. 29 | /// Set offer for the purchase. 30 | /// 31 | /// Concrete offer which you'd like to purchase. 32 | /// Builder instance for chain calls. 33 | public PurchaseOptionsBuilder SetOffer(ProductOfferDetails offer) 34 | { 35 | _offerId = offer.OfferId; 36 | return this; 37 | } 38 | 39 | /// 40 | /// Android only. 41 | /// Set the offer ID to the purchase. 42 | /// 43 | /// Concrete offer ID which you'd like to purchase. 44 | /// Builder instance for chain calls. 45 | public PurchaseOptionsBuilder SetOfferId(string offerId) 46 | { 47 | _offerId = offerId; 48 | return this; 49 | } 50 | 51 | /// 52 | /// Android only. 53 | /// Call this function to remove any intro/trial offer from the purchase (use only a bare base plan). 54 | /// 55 | /// Builder instance for chain calls. 56 | public PurchaseOptionsBuilder RemoveOffer() 57 | { 58 | _applyOffer = false; 59 | return this; 60 | } 61 | 62 | /// 63 | /// Android only. 64 | /// Set Qonversion product from which the upgrade/downgrade will be initialized. 65 | /// 66 | /// Qonversion product from which the upgrade/downgrade will be initialized. 67 | /// Builder instance for chain calls. 68 | public PurchaseOptionsBuilder SetOldProduct(Product oldProduct) 69 | { 70 | _oldProduct = oldProduct; 71 | return this; 72 | } 73 | 74 | 75 | /// 76 | /// Android only. 77 | /// Set the update policy for the purchase. 78 | /// 79 | /// Update policy for the purchase. 80 | /// Builder instance for chain calls. 81 | public PurchaseOptionsBuilder SetUpdatePolicy(PurchaseUpdatePolicy updatePolicy) 82 | { 83 | _updatePolicy = updatePolicy; 84 | return this; 85 | } 86 | 87 | /// 88 | /// Set the context keys associated with a purchase. 89 | /// 90 | /// Context keys for the purchase. 91 | /// Builder instance for chain calls. 92 | public PurchaseOptionsBuilder SetContextKeys(List contextKeys) 93 | { 94 | _contextKeys = contextKeys; 95 | return this; 96 | } 97 | 98 | /// 99 | /// Set the promotional offer details. 100 | /// 101 | /// Promotional offer details. 102 | /// Builder instance for chain calls. 103 | public PurchaseOptionsBuilder SetPromotionalOffer(PromotionalOffer promoOffer) 104 | { 105 | _promotionalOffer = promoOffer; 106 | return this; 107 | } 108 | 109 | /// 110 | /// Generate a instance with all the provided options. 111 | /// 112 | /// The complete instance. 113 | public PurchaseOptions Build() 114 | { 115 | return new PurchaseOptions(_offerId, _applyOffer, _oldProduct, _updatePolicy, _contextKeys, _quantity, _promotionalOffer); 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseOptionsBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8c9a321d73824a668433f26898c31b17 3 | timeCreated: 1725357426 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseUpdateModel.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace QonversionUnity 4 | { 5 | /// 6 | /// Used to provide all the necessary purchase data to the method. 7 | /// Can be created manually or using the method. 8 | /// 9 | /// Requires Qonversion product identifiers - for the purchasing one and 10 | /// for the purchased one. 11 | /// 12 | /// If is not specified for Android, then the default offer will be applied. 13 | /// To know how we choose the default offer, see . 14 | /// 15 | /// If you want to remove any intro/trial offer from the purchase on Android (use only a bare base plan), 16 | /// call the method. 17 | /// 18 | public class PurchaseUpdateModel 19 | { 20 | public readonly string ProductId; 21 | public readonly string OldProductId; 22 | [CanBeNull] public PurchaseUpdatePolicy? UpdatePolicy; 23 | [CanBeNull] public string OfferId; 24 | 25 | internal bool ApplyOffer = true; 26 | 27 | public PurchaseUpdateModel(string productId, string oldProductId, [CanBeNull] PurchaseUpdatePolicy? updatePolicy = null, [CanBeNull] string offerId = null) 28 | { 29 | ProductId = productId; 30 | OldProductId = oldProductId; 31 | UpdatePolicy = updatePolicy; 32 | OfferId = offerId; 33 | } 34 | 35 | public PurchaseUpdateModel RemoveOffer() 36 | { 37 | ApplyOffer = false; 38 | return this; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseUpdateModel.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f3649a3b94f94417a8ba61fa41937e6b 3 | timeCreated: 1701455222 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseUpdatePolicy.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | /// 4 | /// A policy used for purchase updates on Android, which describes 5 | /// how to migrate from purchased plan to a new one. 6 | /// 7 | /// Used in class for purchase updates. 8 | /// 9 | public enum PurchaseUpdatePolicy 10 | { 11 | /// The new plan takes effect immediately, and the user is charged full price of new plan 12 | /// and is given a full billing cycle of subscription, plus remaining prorated time 13 | /// from the old plan. 14 | ChargeFullPrice, 15 | 16 | /// The new plan takes effect immediately, and the billing cycle remains the same. 17 | ChargeProratedPrice, 18 | 19 | /// The new plan takes effect immediately, and the remaining time will be prorated 20 | /// and credited to the user. 21 | WithTimeProration, 22 | 23 | /// The new purchase takes effect immediately, the new plan will take effect 24 | /// when the old item expires. 25 | Deferred, 26 | 27 | /// The new plan takes effect immediately, and the new price will be charged 28 | /// on next recurrence time. 29 | WithoutProration, 30 | 31 | /// Unknown police. 32 | Unknown 33 | } 34 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/PurchaseUpdatePolicy.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 11d8a5507d73422bae604dc45573a52f 3 | timeCreated: 1701455289 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/QonversionError.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class QonversionError 7 | { 8 | public QErrorCode Code; 9 | public string Message; 10 | 11 | public QonversionError(Dictionary dict) 12 | { 13 | if (dict.TryGetValue("code", out object value)) Code = FormatErrorCode(value); 14 | string message = ""; 15 | if (dict.TryGetValue("description", out object description)) 16 | { 17 | message += description; 18 | if (dict.TryGetValue("domain", out object domain)) 19 | { 20 | message += ". Domain: " + domain; 21 | } 22 | if (dict.TryGetValue("additionalMessage", out object additionalMessage)) 23 | { 24 | message += "\nDebugInfo: " + additionalMessage; 25 | } 26 | } 27 | 28 | Message = message; 29 | } 30 | 31 | internal QonversionError(QErrorCode code, string message) 32 | { 33 | Code = code; 34 | Message = message; 35 | } 36 | 37 | public override string ToString() 38 | { 39 | return $"{nameof(Code)}: {Code}, " + 40 | $"{nameof(Message)}: {Message}"; 41 | } 42 | 43 | private QErrorCode FormatErrorCode(object code) 44 | { 45 | return Enum.TryParse(code.ToString(), out QErrorCode parsedSource) 46 | ? parsedSource 47 | : QErrorCode.Unknown; 48 | } 49 | } 50 | 51 | public enum QErrorCode 52 | { 53 | Unknown, // Unknown error 54 | ApiRateLimitExceeded, // API requests rate limit exceeded 55 | AppleStoreError, // Apple Store error received 56 | BackendError, // There was a backend error 57 | BillingUnavailable, // The Billing service is unavailable on the device 58 | ClientInvalid, // Client is not allowed to issue the request, etc 59 | CloudServiceNetworkConnectionFailed, // The device could not connect to the network 60 | CloudServicePermissionDenied, // User is not allowed to access cloud service information 61 | CloudServiceRevoked, // User has revoked permission to use this cloud service 62 | FailedToReceiveData, // Could not receive data 63 | FeatureNotSupported, // The requested feature is not supported 64 | FraudPurchase, // Fraud purchase was detected 65 | IncorrectRequest, // Request failed 66 | InternalError, // Internal backend error 67 | InvalidClientUid, // Client Uid is invalid or not set 68 | InvalidCredentials, // Access token is invalid or not set 69 | InvalidStoreCredentials, // This account does not have access to the requested application 70 | LaunchError, // There was an error while launching Qonversion SDK 71 | NativeModuleError, // Something failed during native iOS or Android modules work or communication between Unity and native 72 | NetworkConnectionFailed, // There was a network issue. Make sure that the Internet connection is available on the device 73 | OfferingsNotFound, // No offerings found 74 | PaymentInvalid, // Purchase identifier was invalid, etc. 75 | PaymentNotAllowed, // This device is not allowed to make the payment 76 | PlayStoreError, // There was an issue with the Play Store service 77 | PrivacyAcknowledgementRequired, // User needs to acknowledge Apple's privacy policy 78 | ProductAlreadyOwned, // Failed to purchase since item is already owned 79 | ProductNotFound, // Failed to purchase since the Qonversion product was not found 80 | ProductNotOwned, // Failed to consume purchase since item is not owned 81 | ProjectConfigError, // The project is not configured or configured incorrectly in the Qonversion Dashboard 82 | PurchaseCanceled, // User pressed back or canceled a dialog for purchase 83 | PurchaseInvalid, // Failure of purchase 84 | PurchasePending, // Purchase is pending 85 | PurchaseUnspecified, // Unspecified state of the purchase 86 | ReceiptValidationError, // Receipt validation error 87 | RemoteConfigurationNotAvailable, // Remote configuration is not available for the current user or for the provided context key 88 | ResponseParsingFailed, // A problem occurred while serializing or deserializing data 89 | StoreProductNotAvailable, // Requested product is not available for purchase or its product id was not found 90 | UnauthorizedRequestData, // App is attempting to use SKPayment's requestData property, but does not have the appropriate entitlement 91 | UnknownClientPlatform, // The current platform is not supported 92 | } 93 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/QonversionError.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b5335b7346c84e0d85ca63af24368c9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/RemoteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using JetBrains.Annotations; 4 | using UnityEngine; 5 | 6 | namespace QonversionUnity 7 | { 8 | public class RemoteConfig 9 | { 10 | public readonly Dictionary Payload; 11 | [CanBeNull] public readonly Experiment Experiment; 12 | public readonly RemoteConfigurationSource Source; 13 | 14 | public RemoteConfig(Dictionary dict) 15 | { 16 | if (dict.TryGetValue("payload", out object value) && value is Dictionary) Payload = value as Dictionary; 17 | if (dict.TryGetValue("experiment", out value) && value is Dictionary experimentInfo) 18 | { 19 | Experiment = new Experiment(experimentInfo); 20 | } 21 | if (dict.TryGetValue("source", out value) && value is Dictionary sourceInfo) 22 | { 23 | Source = new RemoteConfigurationSource(sourceInfo); 24 | } 25 | } 26 | 27 | public override string ToString() 28 | { 29 | return $"{nameof(Payload)}: {Payload}, " + 30 | $"{nameof(Experiment)}: {Experiment}, " + 31 | $"{nameof(Source)}: {Source}"; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/RemoteConfig.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ba2fbd2bcc0e45b5b4cab28b85ad25f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/RemoteConfigList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using JetBrains.Annotations; 4 | 5 | namespace QonversionUnity 6 | { 7 | public class RemoteConfigList 8 | { 9 | public readonly List RemoteConfigs; 10 | 11 | public RemoteConfigList(Dictionary dict) 12 | { 13 | if (dict.TryGetValue("remoteConfigs", out object value) && value is List offerings) 14 | { 15 | RemoteConfigs = Mapper.ConvertObjectsList(offerings); 16 | } 17 | } 18 | 19 | [CanBeNull] 20 | public RemoteConfig RemoteConfigForContextKey(String contextKey) 21 | { 22 | return FindRemoteConfig(contextKey); 23 | } 24 | 25 | [CanBeNull] 26 | public RemoteConfig RemoteConfigForEmptyContextKey() 27 | { 28 | return FindRemoteConfig(null); 29 | } 30 | 31 | [CanBeNull] 32 | private RemoteConfig FindRemoteConfig([CanBeNull] String contextKey) 33 | { 34 | return RemoteConfigs.Find(remoteConfig => remoteConfig.Source.ContextKey == contextKey); 35 | } 36 | 37 | public override string ToString() 38 | { 39 | return $"{nameof(RemoteConfigs)}: {Utils.PrintObjectList(RemoteConfigs)}"; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/RemoteConfigList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c04d46990d4d4e03b14436e3cb92ce0e 3 | timeCreated: 1711619835 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/RemoteConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class RemoteConfigurationSource 7 | { 8 | 9 | public readonly string Id; 10 | public readonly string Name; 11 | public readonly RemoteConfigurationSourceType Type; 12 | public readonly RemoteConfigurationAssignmentType AssignmentType; 13 | [CanBeNull] public readonly string ContextKey; 14 | 15 | 16 | public RemoteConfigurationSource(Dictionary dict) 17 | { 18 | if (dict.TryGetValue("id", out object value)) Id = value as string; 19 | if (dict.TryGetValue("name", out value)) Name = value as string; 20 | if (dict.TryGetValue("assignmentType", out value)) AssignmentType = FormatAssignmentType(value); 21 | if (dict.TryGetValue("type", out value)) Type = FormatSourceType(value); 22 | if (dict.TryGetValue("contextKey", out value)) ContextKey = value as string; 23 | } 24 | 25 | public RemoteConfigurationAssignmentType FormatAssignmentType(object typeValue) 26 | { 27 | string type = typeValue as string; 28 | if (type == "auto") 29 | { 30 | return RemoteConfigurationAssignmentType.Auto; 31 | } 32 | else if (type == "manual") 33 | { 34 | return RemoteConfigurationAssignmentType.Manual; 35 | } 36 | 37 | return RemoteConfigurationAssignmentType.Unknown; 38 | } 39 | 40 | public RemoteConfigurationSourceType FormatSourceType(object typeValue) 41 | { 42 | string type = typeValue as string; 43 | if (type == "experiment_control_group") 44 | { 45 | return RemoteConfigurationSourceType.ExperimentControlGroup; 46 | } 47 | else if (type == "experiment_treatment_group") 48 | { 49 | return RemoteConfigurationSourceType.ExperimentTreatmentGroup; 50 | } 51 | else if (type == "remote_configuration") 52 | { 53 | return RemoteConfigurationSourceType.RemoteConfiguration; 54 | } 55 | 56 | return RemoteConfigurationSourceType.Unknown; 57 | } 58 | 59 | public override string ToString() 60 | { 61 | return $"{nameof(Id)}: {Id}, " + 62 | $"{nameof(Name)}: {Name}, " + 63 | $"{nameof(AssignmentType)}: {AssignmentType}, " + 64 | $"{nameof(Type)}: {Type}, " + 65 | $"{nameof(ContextKey)}: {ContextKey}"; 66 | } 67 | } 68 | 69 | public enum RemoteConfigurationAssignmentType 70 | { 71 | Unknown, 72 | Auto, 73 | Manual 74 | } 75 | 76 | public enum RemoteConfigurationSourceType 77 | { 78 | Unknown, 79 | ExperimentControlGroup, 80 | ExperimentTreatmentGroup, 81 | RemoteConfiguration 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/RemoteConfigurationSource.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 47dd88424cf8b4b63b34e89a3f76b6fb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ScreenPresentationConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using QonversionUnity.MiniJSON; 4 | using UnityEngine; 5 | 6 | namespace QonversionUnity 7 | { 8 | public class ScreenPresentationConfig 9 | { 10 | /// Describes how screens will be displayed. 11 | [Tooltip("For mode details see the enum description.")] 12 | public readonly ScreenPresentationStyle PresentationStyle; 13 | 14 | /// iOS only. For Android consider using . 15 | /// Describes whether should transaction be animated or not. 16 | /// Default value is true. 17 | public readonly bool Animated; 18 | 19 | public ScreenPresentationConfig(ScreenPresentationStyle presentationStyle) 20 | { 21 | PresentationStyle = presentationStyle; 22 | Animated = true; 23 | } 24 | 25 | public ScreenPresentationConfig(ScreenPresentationStyle presentationStyle, bool animated) 26 | { 27 | PresentationStyle = presentationStyle; 28 | Animated = animated; 29 | } 30 | 31 | public string ToJson() 32 | { 33 | Dictionary data = new Dictionary(); 34 | 35 | string presentationStyleName = Enum.GetName(typeof(ScreenPresentationStyle), PresentationStyle); 36 | data["presentationStyle"] = presentationStyleName; 37 | data["animated"] = Animated ? "1" : "0"; 38 | 39 | return data.toJson(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ScreenPresentationConfig.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c6a0a1bedf494be7901137a0ffbcc70b 3 | timeCreated: 1674808729 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ScreenPresentationStyle.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum ScreenPresentationStyle 4 | { 5 | /// on Android - default screen transaction animation will be used. 6 | /// on iOS - not a modal presentation. This style pushes a controller to a current navigation stack. 7 | /// For iOS NavigationController on the top of the stack is required. 8 | Push, 9 | 10 | /// on Android - screen will move from bottom to top. 11 | /// on iOS - UIModalPresentationFullScreen analog. 12 | FullScreen, 13 | 14 | /// iOS only - UIModalPresentationPopover analog 15 | Popover, 16 | 17 | /// Android only - screen will appear/disappear without any animation 18 | /// For iOS consider providing the flag. 19 | NoAnimation, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/ScreenPresentationStyle.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c9772f14cb44431faca69bb2a0841fd6 3 | timeCreated: 1674808596 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkProduct.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 34cf22d7675f2416d9d88b74fa126afb 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkProduct/SKPraymentDiscount.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace QonversionUnity 4 | { 5 | public class SKPaymentDiscount { 6 | public readonly string Identifier; 7 | public readonly string KeyIdentifier; 8 | public readonly string Nonce; 9 | public readonly string Signature; 10 | public readonly long Timestamp; 11 | 12 | public SKPaymentDiscount(Dictionary dict) { 13 | if (dict.TryGetValue("identifier", out object value)) Identifier = value as string; 14 | if (dict.TryGetValue("keyIdentifier", out value)) KeyIdentifier = value as string; 15 | if (dict.TryGetValue("nonce", out value)) Nonce = value as string; 16 | if (dict.TryGetValue("signature", out value)) Signature = value as string; 17 | if (dict.TryGetValue("timestamp", out object timestamp)) Timestamp = (long)timestamp; 18 | } 19 | 20 | public override string ToString() { 21 | return $"{nameof(Identifier)}: {Identifier}, " + 22 | $"{nameof(KeyIdentifier)}: {KeyIdentifier}, " + 23 | $"{nameof(Nonce)}: {Nonce}, " + 24 | $"{nameof(Signature)}: {Signature}, " + 25 | $"{nameof(Timestamp)}: {Timestamp}"; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkProduct/SKPraymentDiscount.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 446d731fe6b84b17a0ae9f3ce196f7e2 3 | timeCreated: 1732029963 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkProduct/SKProduct.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class SKProduct 7 | { 8 | public readonly string ProductIdentifier; 9 | public readonly string LocalizedDescription; 10 | public readonly string LocalizedTitle; 11 | public readonly bool IsFamilyShareable; 12 | public readonly string Price; 13 | [CanBeNull] public readonly SKProductDiscount IntroductoryPrice; 14 | [CanBeNull] public readonly List Discounts; 15 | [CanBeNull] public readonly string SubscriptionGroupIdentifier; 16 | [CanBeNull] public readonly SKProductSubscriptionPeriod SubscriptionPeriod; 17 | public readonly bool IsDownloadable; 18 | [CanBeNull] public readonly List DownloadContentLengths; 19 | [CanBeNull] public readonly string DownloadContentVersion; 20 | [CanBeNull] public readonly string CurrencyCode; 21 | 22 | public SKProduct(Dictionary dict) 23 | { 24 | if (dict.TryGetValue("productIdentifier", out object value)) ProductIdentifier = value as string; 25 | if (dict.TryGetValue("localizedDescription", out value)) LocalizedDescription = value as string; 26 | if (dict.TryGetValue("localizedTitle", out value)) LocalizedTitle = value as string; 27 | 28 | if (dict.TryGetValue("isFamilyShareable", out value)) 29 | { 30 | if (value is bool boolValue) IsFamilyShareable = boolValue; 31 | } 32 | 33 | if (dict.TryGetValue("price", out value)) Price = value as string; 34 | 35 | if (dict.TryGetValue("introductoryPrice", out value) && value is Dictionary introPrice) 36 | { 37 | IntroductoryPrice = new SKProductDiscount(introPrice); 38 | } 39 | 40 | if (dict.TryGetValue("discounts", out value)) 41 | { 42 | if (value is List discounts) Discounts = Mapper.ConvertObjectsList(discounts); 43 | } 44 | 45 | if (dict.TryGetValue("subscriptionGroupIdentifier", out value)) SubscriptionGroupIdentifier = value as string; 46 | 47 | if (dict.TryGetValue("subscriptionPeriod", out value)) 48 | { 49 | if (value is Dictionary subsPeriod) SubscriptionPeriod = new SKProductSubscriptionPeriod(subsPeriod); 50 | } 51 | 52 | if (dict.TryGetValue("isDownloadable", out value)) 53 | { 54 | if (value is bool boolValue) IsDownloadable = boolValue; 55 | } 56 | 57 | if (dict.TryGetValue("downloadContentLengths", out value)) DownloadContentLengths = value as List; 58 | if (dict.TryGetValue("downloadContentVersion", out value)) DownloadContentVersion = value as string; 59 | if (dict.TryGetValue("priceLocale", out object priceLocale)) 60 | { 61 | if (priceLocale is Dictionary priceLocaleDict) 62 | { 63 | if (priceLocaleDict.TryGetValue("currencyCode", out value)) 64 | { 65 | CurrencyCode = value as string; 66 | } 67 | } 68 | } 69 | } 70 | 71 | public override string ToString() 72 | { 73 | return $"{nameof(ProductIdentifier)}: {ProductIdentifier}, " + 74 | $"{nameof(LocalizedDescription)}: {LocalizedDescription}, " + 75 | $"{nameof(LocalizedTitle)}: {LocalizedTitle}, " + 76 | $"{nameof(IsFamilyShareable)}: {IsFamilyShareable}, " + 77 | $"{nameof(Price)}: {Price} , " + 78 | $"{nameof(IntroductoryPrice)}: {IntroductoryPrice}, " + 79 | $"{nameof(Discounts)}: {Utils.PrintObjectList(Discounts)}, " + 80 | $"{nameof(SubscriptionGroupIdentifier)}: {SubscriptionGroupIdentifier}, " + 81 | $"{nameof(SubscriptionPeriod)}: {SubscriptionPeriod}, " + 82 | $"{nameof(IsDownloadable)}: {IsDownloadable} , " + 83 | $"{nameof(DownloadContentLengths)}: {Utils.PrintObjectList(DownloadContentLengths)}, " + 84 | $"{nameof(DownloadContentVersion)}: {DownloadContentVersion}, " + 85 | $"{nameof(CurrencyCode)}: {CurrencyCode}"; 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkProduct/SKProduct.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a47619ab0f35e47b6882af6cbc4c6b05 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkProduct/SKProductDiscount.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using JetBrains.Annotations; 4 | 5 | namespace QonversionUnity 6 | { 7 | public class SKProductDiscount 8 | { 9 | [CanBeNull] public readonly string Identifier; 10 | public readonly SKProductDiscountType Type; 11 | [CanBeNull] public readonly string Price; 12 | [CanBeNull] public readonly string LocaleIdentifier; 13 | public readonly SKProductDiscountPaymentMode PaymentMode; 14 | public readonly int NumberOfPeriods; 15 | [CanBeNull] public readonly SKProductSubscriptionPeriod SubscriptionPeriod; 16 | public readonly string CurrencySymbol; 17 | 18 | public SKProductDiscount(Dictionary dict) 19 | { 20 | if (dict.TryGetValue("identifier", out object value)) Identifier = value as string; 21 | if (dict.TryGetValue("type", out value)) Type = FormatDiscountType(value); 22 | if (dict.TryGetValue("price", out value)) Price = value as string; 23 | if (dict.TryGetValue("paymentMode", out value)) PaymentMode = FormatPaymentMode(value); 24 | if (dict.TryGetValue("numberOfPeriods", out value)) NumberOfPeriods = Convert.ToInt32(value); 25 | 26 | if (dict.TryGetValue("priceLocale", out object priceLocale)) 27 | { 28 | if (priceLocale is Dictionary priceLocaleDict) 29 | { 30 | if (priceLocaleDict.TryGetValue("localeIdentifier", out value)) LocaleIdentifier = value as string; 31 | if (priceLocaleDict.TryGetValue("currencySymbol", out value)) CurrencySymbol = value as string; 32 | } 33 | } 34 | 35 | if (dict.TryGetValue("subscriptionPeriod", out value)) 36 | { 37 | if (value is Dictionary subsPeriod) SubscriptionPeriod = new SKProductSubscriptionPeriod(subsPeriod); 38 | } 39 | } 40 | 41 | public override string ToString() 42 | { 43 | return $"{nameof(Identifier)}: {Identifier}, " + 44 | $"{nameof(Type)}: {Type}, " + 45 | $"{nameof(Price)}: {Price}, " + 46 | $"{nameof(LocaleIdentifier)}: {LocaleIdentifier}, " + 47 | $"{nameof(Price)}: {Price} , " + 48 | $"{nameof(PaymentMode)}: {PaymentMode}, " + 49 | $"{nameof(NumberOfPeriods)}: {NumberOfPeriods}, " + 50 | $"{nameof(SubscriptionPeriod)}: {SubscriptionPeriod}" + 51 | $"{nameof(CurrencySymbol)}: {CurrencySymbol}"; 52 | } 53 | 54 | private SKProductDiscountType FormatDiscountType(object discountType) => 55 | (SKProductDiscountType)Convert.ToInt32(discountType); 56 | 57 | private SKProductDiscountPaymentMode FormatPaymentMode(object paymentMode) => 58 | (SKProductDiscountPaymentMode)Convert.ToInt32(paymentMode); 59 | } 60 | 61 | public enum SKProductDiscountType 62 | { 63 | Introductory, 64 | Subscription 65 | } 66 | 67 | public enum SKProductDiscountPaymentMode 68 | { 69 | PayAsYouGo, 70 | PayUpFront, 71 | FreeTrial 72 | } 73 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkProduct/SKProductDiscount.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 022a118da08d74f60b495168da846a70 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkProduct/SKProductSubscriptionPeriod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class SKProductSubscriptionPeriod 7 | { 8 | public readonly int NumberOfUnits; 9 | public readonly SKPeriodUnit Unit; 10 | 11 | public SKProductSubscriptionPeriod(Dictionary dict) 12 | { 13 | if (dict.TryGetValue("numberOfUnits", out object value)) NumberOfUnits = Convert.ToInt32(value); 14 | if (dict.TryGetValue("unit", out value)) Unit = FormatPeriodUnit(value); 15 | } 16 | 17 | public override string ToString() 18 | { 19 | return $"{nameof(NumberOfUnits)}: {NumberOfUnits}, " + 20 | $"{nameof(Unit)}: {Unit}"; 21 | } 22 | 23 | private SKPeriodUnit FormatPeriodUnit(object periodUnit) => 24 | (SKPeriodUnit)Convert.ToInt32(periodUnit); 25 | } 26 | 27 | public enum SKPeriodUnit 28 | { 29 | Day, 30 | Week, 31 | Month, 32 | Year, 33 | } 34 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkProduct/SKProductSubscriptionPeriod.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8451375a11e03434594db113652a3624 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkuDetails.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace QonversionUnity 5 | { 6 | [Obsolete("Consider using ProductStoreDetails instead.")] 7 | public class SkuDetails 8 | { 9 | /// Textual description of the product. 10 | public readonly string Description; 11 | 12 | /// Trial period in ISO 8601 format. 13 | public readonly string FreeTrialPeriod; 14 | 15 | /// Icon of the product if present. 16 | public readonly string IconUrl; 17 | 18 | /// Introductory price, only applies to [SkuType.subs]. Formatted ("$0.99"). 19 | public readonly string IntroductoryPrice; 20 | 21 | /// Introductory price in micro-units 22 | public readonly long IntroductoryPriceAmountMicros; 23 | 24 | /// The number of billing perios that [introductoryPrice] is valid for ("2"). 25 | public readonly int IntroductoryPriceCycles; 26 | 27 | /// The billing period of [introductoryPrice], in ISO 8601 format. 28 | public readonly string IntroductoryPricePeriod; 29 | 30 | /// String in JSON format that contains SKU details. 31 | public readonly string OriginalJson; 32 | 33 | /// The original price that the user purchased this product for. 34 | public readonly string OriginalPrice; 35 | 36 | /// [originalPrice] in micro-units (990000). 37 | public readonly long OriginalPriceAmountMicros; 38 | 39 | /// Formatted with currency symbol ("$0.99"). 40 | public readonly string Price; 41 | 42 | /// Returns price in micro-units, where 1,000,000 micro-units equal one unit of the currency. 43 | public readonly long PriceAmountMicros; 44 | 45 | /// [price] ISO 4217 currency code. 46 | public readonly string PriceCurrencyCode; 47 | 48 | /// The product ID in Google Play Console. 49 | public readonly string Sku; 50 | 51 | /// Applies to [SkuType.subs], formatted in ISO 8601. 52 | public readonly string SubscriptionPeriod; 53 | 54 | /// The product's title. 55 | public readonly string Title; 56 | 57 | /// Inapp or subs. 58 | public readonly string Type; 59 | 60 | public SkuDetails(Dictionary dict) 61 | { 62 | if (dict.TryGetValue("description", out object value)) Description = value as string; 63 | if (dict.TryGetValue("freeTrialPeriod", out value)) FreeTrialPeriod = value as string; 64 | if (dict.TryGetValue("iconUrl", out value)) IconUrl = value as string; 65 | if (dict.TryGetValue("introductoryPrice", out value)) IntroductoryPrice = value as string; 66 | if (dict.TryGetValue("introductoryPriceAmountMicros", out value)) IntroductoryPriceAmountMicros = (long)value; 67 | if (dict.TryGetValue("introductoryPriceCycles", out value)) IntroductoryPriceCycles = Convert.ToInt32(value); 68 | if (dict.TryGetValue("introductoryPricePeriod", out value)) IntroductoryPricePeriod = value as string; 69 | if (dict.TryGetValue("originalJson", out value)) OriginalJson = value as string; 70 | if (dict.TryGetValue("originalPrice", out value)) OriginalPrice = value as string; 71 | if (dict.TryGetValue("originalPriceAmountMicros", out value)) OriginalPriceAmountMicros = (long)value; 72 | if (dict.TryGetValue("price", out value)) Price = value as string; 73 | if (dict.TryGetValue("priceAmountMicros", out value)) PriceAmountMicros = (long)value; 74 | if (dict.TryGetValue("priceCurrencyCode", out value)) PriceCurrencyCode = value as string; 75 | if (dict.TryGetValue("sku", out value)) Sku = value as string; 76 | if (dict.TryGetValue("subscriptionPeriod", out value)) SubscriptionPeriod = value as string; 77 | if (dict.TryGetValue("title", out value)) Title = value as string; 78 | if (dict.TryGetValue("type", out value)) Type = value as string; 79 | } 80 | 81 | public override string ToString() 82 | { 83 | return $"{nameof(Description)}: {Description}, \n" + 84 | $"{nameof(FreeTrialPeriod)}: {FreeTrialPeriod}, " + 85 | $"{nameof(IconUrl)}: {IconUrl}, " + 86 | $"{nameof(IntroductoryPrice)}: {IntroductoryPrice}, " + 87 | $"{nameof(IntroductoryPriceAmountMicros)}: {IntroductoryPriceAmountMicros}, " + 88 | $"{nameof(IntroductoryPriceCycles)}: {IntroductoryPriceCycles} , " + 89 | $"{nameof(IntroductoryPricePeriod)}: {IntroductoryPricePeriod}, " + 90 | $"{nameof(OriginalJson)}: {OriginalJson}, " + 91 | $"{nameof(OriginalPrice)}: {OriginalPrice}, " + 92 | $"{nameof(OriginalPriceAmountMicros)}: {OriginalPriceAmountMicros}, " + 93 | $"{nameof(Price)}: {Price}, " + 94 | $"{nameof(PriceAmountMicros)}: {PriceAmountMicros}, " + 95 | $"{nameof(PriceCurrencyCode)}: {PriceCurrencyCode}, " + 96 | $"{nameof(Sku)}: {Sku}, " + 97 | $"{nameof(SubscriptionPeriod)}: {SubscriptionPeriod}, " + 98 | $"{nameof(Title)}: {Title}, " + 99 | $"{nameof(Type)}: {Type}"; 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SkuDetails.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 23ce9e7e4cd8f48f8840738ffaef5f55 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SubscriptionPeriod.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace QonversionUnity 4 | { 5 | /// 6 | /// A class describing a subscription period 7 | /// 8 | public class SubscriptionPeriod 9 | { 10 | /// A count of subsequent intervals. 11 | public readonly int UnitCount; 12 | 13 | /// Interval unit. 14 | public readonly SubscriptionPeriodUnit Unit; 15 | 16 | /// ISO 8601 representation of the period, e.g. "P7D", meaning 7 days period. 17 | public readonly string Iso; 18 | 19 | public SubscriptionPeriod(Dictionary dict) 20 | { 21 | if (dict.TryGetValue("iso", out object value)) Iso = value as string; 22 | if (dict.TryGetValue("unitCount", out value)) UnitCount = (int)(long)value; 23 | if (dict.TryGetValue("unit", out value)) Unit = FormatSubscriptionPeriodUnit(value); 24 | } 25 | 26 | public SubscriptionPeriodUnit FormatSubscriptionPeriodUnit(object unitValue) 27 | { 28 | string unit = unitValue as string; 29 | if (unit == "Day") 30 | { 31 | return SubscriptionPeriodUnit.Day; 32 | } 33 | 34 | if (unit == "Week") 35 | { 36 | return SubscriptionPeriodUnit.Week; 37 | } 38 | 39 | if (unit == "Month") 40 | { 41 | return SubscriptionPeriodUnit.Month; 42 | } 43 | 44 | if (unit == "Year") 45 | { 46 | return SubscriptionPeriodUnit.Year; 47 | } 48 | 49 | return SubscriptionPeriodUnit.Unknown; 50 | } 51 | 52 | public override string ToString() 53 | { 54 | return $"{nameof(UnitCount)}: {UnitCount}, " + 55 | $"{nameof(Iso)}: {Iso}, " + 56 | $"{nameof(Unit)}: {Unit}"; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SubscriptionPeriod.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 70b23c73445d4949880a71a288548384 3 | timeCreated: 1701437706 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SubscriptionPeriodUnit.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum SubscriptionPeriodUnit 4 | { 5 | Day, 6 | Week, 7 | Month, 8 | Year, 9 | Unknown, 10 | } 11 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/SubscriptionPeriodUnit.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e3484a14d3e49c7b358851431e2bb66 3 | timeCreated: 1701437751 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/Transaction.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6c2207fece8b44558ad88f2591eb0f89 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/User.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class User 7 | { 8 | public readonly string QonversionId; 9 | [CanBeNull] public readonly string IdentityId; 10 | 11 | public User(string qonversionId, [CanBeNull] string identityId) 12 | { 13 | QonversionId = qonversionId; 14 | IdentityId = identityId; 15 | } 16 | 17 | public User(Dictionary dict) 18 | { 19 | if (dict.TryGetValue("qonversionId", out var qonversionId) && qonversionId != null) 20 | { 21 | QonversionId = qonversionId as string; 22 | } 23 | 24 | if (dict.TryGetValue("identityId", out var identityId) && identityId != null) 25 | { 26 | IdentityId = identityId as string; 27 | } 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return $"{nameof(QonversionId)}: {QonversionId}, " + 33 | $"{nameof(IdentityId)}: {IdentityId}"; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/User.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e90e3bc36aae4e069c0c373e53427b0c 3 | timeCreated: 1668747828 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/UserProperties.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using JetBrains.Annotations; 4 | using UnityEngine; 5 | 6 | namespace QonversionUnity 7 | { 8 | public class UserProperties 9 | { 10 | /// 11 | /// List of all user properties. 12 | /// 13 | public readonly List Properties; 14 | 15 | /// 16 | /// List of user properties, set for the Qonversion defined keys. 17 | /// This is a subset of all list. 18 | /// . 19 | /// 20 | public readonly List DefinedProperties; 21 | 22 | /// 23 | /// List of user properties, set for custom keys. 24 | /// This is a subset of all list. 25 | /// . 26 | /// 27 | public readonly List CustomProperties; 28 | 29 | /// 30 | /// Map of all user properties. 31 | /// This is a flattened version of the list as a key-value map. 32 | /// 33 | public readonly Dictionary FlatPropertiesMap; 34 | 35 | /// 36 | /// Map of user properties, set for the Qonversion defined keys. 37 | /// This is a flattened version of the list as a key-value map. 38 | /// . 39 | /// 40 | public readonly Dictionary FlatDefinedPropertiesMap; 41 | 42 | /// 43 | /// Map of user properties, set for custom keys. 44 | /// This is a flattened version of the list as a key-value map. 45 | /// . 46 | /// 47 | public readonly Dictionary FlatCustomPropertiesMap; 48 | 49 | public UserProperties(Dictionary dict) 50 | { 51 | if (dict.TryGetValue("properties", out var value) && value is List properties) 52 | { 53 | Properties = Mapper.ConvertObjectsList(properties); 54 | } 55 | else 56 | { 57 | Debug.LogError("Failed to parse user properties array, assigning empty list."); 58 | Properties = new List(); 59 | } 60 | DefinedProperties = CalculateDefinedProperties(); 61 | CustomProperties = CalculateCustomProperties(); 62 | FlatPropertiesMap = CalculateFlatPropertiesMap(); 63 | FlatDefinedPropertiesMap = CalculateFlatDefinedPropertiesMap(); 64 | FlatCustomPropertiesMap = CalculateFlatCustomPropertiesMap(); 65 | } 66 | 67 | /// 68 | /// Searches for a property with the given property in all properties list. 69 | /// 70 | [CanBeNull] 71 | public UserProperty GetProperty(string key) 72 | { 73 | return Properties.Find(property => property.Key == key); 74 | } 75 | 76 | /// 77 | /// Searches for a property with the given Qonversion defined property 78 | /// in defined properties list. 79 | /// 80 | [CanBeNull] 81 | public UserProperty GetDefinedProperty(UserPropertyKey key) 82 | { 83 | return DefinedProperties.Find(property => property.DefinedKey == key); 84 | } 85 | 86 | private List CalculateDefinedProperties() 87 | { 88 | return Properties.FindAll( 89 | userProperty => userProperty.DefinedKey != UserPropertyKey.Custom 90 | ); 91 | } 92 | 93 | private List CalculateCustomProperties() 94 | { 95 | return Properties.FindAll( 96 | userProperty => userProperty.DefinedKey == UserPropertyKey.Custom 97 | ); 98 | } 99 | 100 | private Dictionary CalculateFlatPropertiesMap() 101 | { 102 | Dictionary flatPropertiesMap = new Dictionary(); 103 | foreach (var property in Properties) 104 | { 105 | flatPropertiesMap[property.Key] = property.Value; 106 | } 107 | return flatPropertiesMap; 108 | } 109 | 110 | private Dictionary CalculateFlatDefinedPropertiesMap() 111 | { 112 | Dictionary flatDefinedPropertiesMap = new Dictionary(); 113 | foreach (var property in Properties) 114 | { 115 | if (property.DefinedKey != UserPropertyKey.Custom) 116 | { 117 | flatDefinedPropertiesMap[property.DefinedKey] = property.Value; 118 | } 119 | } 120 | return flatDefinedPropertiesMap; 121 | } 122 | 123 | private Dictionary CalculateFlatCustomPropertiesMap() 124 | { 125 | Dictionary flatCustomPropertiesMap = new Dictionary(); 126 | foreach (var property in Properties) 127 | { 128 | if (property.DefinedKey == UserPropertyKey.Custom) 129 | { 130 | flatCustomPropertiesMap[property.Key] = property.Value; 131 | } 132 | } 133 | return flatCustomPropertiesMap; 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/UserProperties.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1e8d7ac2990e44f2972a103d52a7b30d 3 | timeCreated: 1691165498 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/UserProperty.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine.Scripting; 3 | 4 | namespace QonversionUnity 5 | { 6 | public class UserProperty 7 | { 8 | public readonly string Key; 9 | public readonly string Value; 10 | public readonly UserPropertyKey DefinedKey; 11 | 12 | // Informs compiler to save this method from removal via optimization, 13 | // as even if it has no direct calls, it is called via reflection while mapping. 14 | [Preserve] 15 | public UserProperty(Dictionary dict) 16 | { 17 | if (dict.TryGetValue("key", out var key) && key != null) 18 | { 19 | Key = key as string; 20 | DefinedKey = ConvertUserPropertyKey(Key); 21 | } 22 | 23 | if (dict.TryGetValue("value", out var value) && value != null) 24 | { 25 | Value = value as string; 26 | } 27 | } 28 | 29 | public override string ToString() 30 | { 31 | return $"{nameof(Key)}: {Key}, " + 32 | $"{nameof(Value)}: {Value}"; 33 | } 34 | 35 | private UserPropertyKey ConvertUserPropertyKey(string stringKey) 36 | { 37 | switch (stringKey) 38 | { 39 | case "_q_email": 40 | return UserPropertyKey.Email; 41 | case "_q_name": 42 | return UserPropertyKey.Name; 43 | case "_q_kochava_device_id": 44 | return UserPropertyKey.KochavaDeviceId; 45 | case "_q_appsflyer_user_id": 46 | return UserPropertyKey.AppsFlyerUserId; 47 | case "_q_adjust_adid": 48 | return UserPropertyKey.AdjustAdId; 49 | case "_q_custom_user_id": 50 | return UserPropertyKey.CustomUserId; 51 | case "_q_fb_attribution": 52 | return UserPropertyKey.FacebookAttribution; 53 | case "_q_firebase_instance_id": 54 | return UserPropertyKey.FirebaseAppInstanceId; 55 | case "_q_app_set_id": 56 | return UserPropertyKey.AppSetId; 57 | case "_q_advertising_id": 58 | return UserPropertyKey.AdvertisingId; 59 | case "_q_appmetrica_device_id": 60 | return UserPropertyKey.AppMetricaDeviceId; 61 | case "_q_appmetrica_user_profile_id": 62 | return UserPropertyKey.AppMetricaUserProfileId; 63 | case "_q_pushwoosh_hwid": 64 | return UserPropertyKey.PushWooshHwId; 65 | case "_q_pushwoosh_user_id": 66 | return UserPropertyKey.PushWooshUserId; 67 | case "_q_tenjin_aiid": 68 | return UserPropertyKey.TenjinAnalyticsInstallationId; 69 | } 70 | 71 | return UserPropertyKey.Custom; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/UserProperty.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 93d0d943d5504615ab21656f2090226c 3 | timeCreated: 1691165220 -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/UserPropertyKey.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | public enum UserPropertyKey 4 | { 5 | Email, 6 | Name, 7 | KochavaDeviceId, 8 | AppsFlyerUserId, 9 | AdjustAdId, 10 | CustomUserId, 11 | FacebookAttribution, // Android only 12 | FirebaseAppInstanceId, 13 | AppSetId, // Android only 14 | AdvertisingId, // iOS only 15 | AppMetricaDeviceId, 16 | AppMetricaUserProfileId, 17 | PushWooshHwId, 18 | PushWooshUserId, 19 | TenjinAnalyticsInstallationId, 20 | Custom, 21 | } 22 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Dto/UserPropertyKey.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a3f3e84df946549f68ad3cbfa4f727f7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/IAutomations.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | public interface IAutomations 7 | { 8 | /// 9 | /// The Automations delegate is responsible for handling in-app screens and actions when push notification is received. 10 | /// Make sure the method is called before Qonversion.handleNotification. 11 | /// 12 | /// The delegate to handle automations events 13 | public void SetDelegate(AutomationsDelegate automationsDelegate); 14 | 15 | /// 16 | /// Set push token to Qonversion to enable Qonversion push notifications 17 | /// 18 | /// Consider removing this method calls. Qonversion is not working with push notifications anymore. 19 | /// Firebase device token for Android. APNs device token for iOS. 20 | public void SetNotificationsToken(string token); 21 | 22 | /// 23 | /// Call to handle push notifications sent by Qonversion Automations. 24 | /// 25 | /// Consider removing this method calls. Qonversion is not working with push notifications anymore. 26 | /// notification payload data 27 | /// true when a push notification was received from Qonversion. Otherwise, returns false, so you need to handle the notification yourself 28 | /// Firebase RemoteMessage data 29 | /// APNs notification data 30 | public bool HandleNotification(Dictionary notification); 31 | 32 | /// 33 | /// Get parsed custom payload, which you added to the notification in the dashboard 34 | /// 35 | /// Consider removing this method calls. Qonversion is not working with push notifications anymore. 36 | /// notification payload data 37 | /// a map with custom payload from the notification or null if it's not provided 38 | [CanBeNull] 39 | public Dictionary GetNotificationCustomPayload(Dictionary notification); 40 | 41 | /// 42 | /// Show the screen using its ID. 43 | /// 44 | /// identifier of the screen which must be shown 45 | /// callback that will be called when response is received 46 | public void ShowScreen(string screenId, Automations.OnShowScreenResponseReceived callback); 47 | 48 | /// 49 | /// Set the configuration of screen representation. 50 | /// 51 | /// a configuration to apply 52 | /// identifier of screen, to which a config should be applied. 53 | /// If not provided, the config is used for all the screens 54 | public void SetScreenPresentationConfig(ScreenPresentationConfig config, [CanBeNull] string screenId = null); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Runtime/Scripts/IAutomations.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1bf6adea119149b5a8575fd688405c1d 3 | timeCreated: 1670849785 -------------------------------------------------------------------------------- /Runtime/Scripts/IQonversion.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9ded0a1938a14b2788563e72c5f7fbd6 3 | timeCreated: 1670849923 -------------------------------------------------------------------------------- /Runtime/Scripts/Internal.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 00384c60219c4bda98b08e4f7c65bc6f 3 | timeCreated: 1668672384 -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/AutomationsInternal.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using QonversionUnity.MiniJSON; 3 | using UnityEngine; 4 | 5 | namespace QonversionUnity 6 | { 7 | internal class AutomationsInternal : MonoBehaviour, IAutomations 8 | { 9 | private const string GameObjectName = "QonvesrionAutomationsRuntimeGameObject"; 10 | private const string OnShowScreenMethodName = "OnShowScreen"; 11 | 12 | private IAutomationsWrapper _nativeWrapperInstance; 13 | private AutomationsDelegate _automationsDelegate; 14 | 15 | private Automations.OnShowScreenResponseReceived ShowScreenResponseReceivedCallback { get; set; } 16 | 17 | public static AutomationsInternal CreateInstance() 18 | { 19 | GameObject go = new GameObject(GameObjectName); 20 | AutomationsInternal instance = go.AddComponent(); 21 | DontDestroyOnLoad(go); 22 | 23 | return instance; 24 | } 25 | 26 | public void SetDelegate(AutomationsDelegate automationsDelegate) 27 | { 28 | _automationsDelegate = automationsDelegate; 29 | 30 | IAutomationsWrapper instance = GetNativeWrapper(); 31 | instance.SubscribeOnAutomationEvents(); 32 | } 33 | 34 | public void SetNotificationsToken(string token) 35 | { 36 | IAutomationsWrapper instance = GetNativeWrapper(); 37 | instance.SetNotificationsToken(token); 38 | } 39 | 40 | public bool HandleNotification(Dictionary notification) 41 | { 42 | IAutomationsWrapper instance = GetNativeWrapper(); 43 | return instance.HandleNotification(notification.toJson()); 44 | } 45 | 46 | public Dictionary GetNotificationCustomPayload(Dictionary notification) 47 | { 48 | IAutomationsWrapper instance = GetNativeWrapper(); 49 | var payloadJson = instance.GetNotificationCustomPayload(notification.toJson()); 50 | 51 | if (payloadJson == null) 52 | { 53 | return null; 54 | } 55 | 56 | if (!(Json.Deserialize(payloadJson) is Dictionary response)) 57 | { 58 | Debug.LogError("Could not parse custom notification payload."); 59 | return null; 60 | } 61 | 62 | return response; 63 | } 64 | 65 | public void ShowScreen(string screenId, Automations.OnShowScreenResponseReceived callback) 66 | { 67 | ShowScreenResponseReceivedCallback = callback; 68 | 69 | IAutomationsWrapper instance = GetNativeWrapper(); 70 | instance.ShowScreen(screenId, OnShowScreenMethodName); 71 | } 72 | 73 | public void SetScreenPresentationConfig(ScreenPresentationConfig config, string screenId = null) 74 | { 75 | IAutomationsWrapper instance = GetNativeWrapper(); 76 | instance.SetScreenPresentationConfig(config.ToJson(), screenId); 77 | } 78 | 79 | private IAutomationsWrapper GetNativeWrapper() 80 | { 81 | if (_nativeWrapperInstance != null) 82 | { 83 | return _nativeWrapperInstance; 84 | } 85 | 86 | switch (Application.platform) 87 | { 88 | case RuntimePlatform.Android: 89 | _nativeWrapperInstance = new AutomationsWrapperAndroid(); 90 | break; 91 | case RuntimePlatform.IPhonePlayer: 92 | _nativeWrapperInstance = new AutomationsWrapperIOS(); 93 | break; 94 | default: 95 | _nativeWrapperInstance = new AutomationsWrapperNoop(); 96 | break; 97 | } 98 | _nativeWrapperInstance.Initialize(GameObjectName); 99 | 100 | return _nativeWrapperInstance; 101 | } 102 | 103 | // The below methods are called from native when Automations events occur 104 | private void OnAutomationsScreenShown(string jsonString) 105 | { 106 | if (_automationsDelegate == null) 107 | { 108 | return; 109 | } 110 | 111 | string screenId = Mapper.ScreenIdFromJson(jsonString); 112 | 113 | _automationsDelegate.OnAutomationsScreenShown(screenId); 114 | } 115 | 116 | private void OnAutomationsActionStarted(string jsonString) 117 | { 118 | if (_automationsDelegate == null) 119 | { 120 | return; 121 | } 122 | 123 | ActionResult actionResult = Mapper.ActionResultFromJson(jsonString); 124 | _automationsDelegate.OnAutomationsActionStarted(actionResult); 125 | } 126 | 127 | private void OnAutomationsActionFailed(string jsonString) 128 | { 129 | if (_automationsDelegate == null) 130 | { 131 | return; 132 | } 133 | 134 | ActionResult actionResult = Mapper.ActionResultFromJson(jsonString); 135 | _automationsDelegate.OnAutomationsActionFailed(actionResult); 136 | } 137 | 138 | 139 | private void OnAutomationsActionFinished(string jsonString) 140 | { 141 | if (_automationsDelegate == null) 142 | { 143 | return; 144 | } 145 | 146 | ActionResult actionResult = Mapper.ActionResultFromJson(jsonString); 147 | _automationsDelegate.OnAutomationsActionFinished(actionResult); 148 | } 149 | 150 | private void OnAutomationsFinished(string jsonString) 151 | { 152 | if (_automationsDelegate == null) 153 | { 154 | return; 155 | } 156 | 157 | _automationsDelegate.OnAutomationsFinished(); 158 | } 159 | 160 | private void OnShowScreen(string jsonString) 161 | { 162 | var error = Mapper.ErrorFromJson(jsonString); 163 | ShowScreenResponseReceivedCallback(error); 164 | ShowScreenResponseReceivedCallback = null; 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/AutomationsInternal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c4a786ad04fb4a94b86844c34f317f23 3 | timeCreated: 1668753627 -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | internal static class Constants 4 | { 5 | public const int PriceMicrosRatio = 1000000; 6 | } 7 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/Constants.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5ea3fffc4c6514bbdbdce589ee67f561 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/Mapper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c9bbffdaa971c4956be8e45ffcd4b28a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/QonversionInternal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 38c50778583feeb4da0934f2fa914b96 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | internal static class Utils 5 | { 6 | internal static DateTime FormatDate(long time) 7 | { 8 | DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(time); 9 | 10 | return dateTimeOffset.DateTime.ToLocalTime(); 11 | } 12 | 13 | internal static string PrintObjectList(List objectsToPrint) 14 | { 15 | if (objectsToPrint == null) return ""; 16 | 17 | string result = string.Empty; 18 | foreach (T val in objectsToPrint) 19 | { 20 | if (val != null) result += val.ToString(); 21 | } 22 | 23 | return result; 24 | } 25 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/Utils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7e1c5a8d202334384887efe986d70d57 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bc8c98aad7534db3bf2a3733e1e9b9eb 3 | timeCreated: 1668776043 -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/automations.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d39ad171d37c4033a7b7a4c23c0ea18a 3 | timeCreated: 1668776048 -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/automations/AutomationsWrapperNoop.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | internal class AutomationsWrapperNoop : IAutomationsWrapper 4 | { 5 | public void Initialize(string gameObjectName) 6 | { 7 | } 8 | 9 | public void SetNotificationsToken(string token) 10 | { 11 | } 12 | 13 | public bool HandleNotification(string notification) 14 | { 15 | return false; 16 | } 17 | 18 | public string GetNotificationCustomPayload(string notification) 19 | { 20 | return null; 21 | } 22 | 23 | public void SubscribeOnAutomationEvents() 24 | { 25 | } 26 | 27 | public void ShowScreen(string screenId, string callbackName) 28 | { 29 | } 30 | 31 | public void SetScreenPresentationConfig(string configJson, string screenId) 32 | { 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/automations/AutomationsWrapperNoop.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: efc8a0074ad9d48879dfbbec563b3225 3 | timeCreated: 1668776080 -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/automations/IAutomationsWrapper.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace QonversionUnity 4 | { 5 | internal interface IAutomationsWrapper 6 | { 7 | void Initialize(string gameObjectName); 8 | void SetNotificationsToken(string token); 9 | bool HandleNotification(string notification); 10 | [CanBeNull] string GetNotificationCustomPayload(string notification); 11 | void SubscribeOnAutomationEvents(); 12 | void ShowScreen(string screenId, string callbackName); 13 | void SetScreenPresentationConfig(string configJson, [CanBeNull] string screenId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/automations/IAutomationsWrapper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e55580a6da23457280c02026ad96b05d 3 | timeCreated: 1668776004 -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/qonversion.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b14757828b514a959d4e299c27c50782 3 | timeCreated: 1668776059 -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using JetBrains.Annotations; 3 | 4 | namespace QonversionUnity 5 | { 6 | internal interface IQonversionWrapper 7 | { 8 | void Initialize(string gameObjectName); 9 | void InitializeSdk(string projectKey, string launchMode, [CanBeNull] string environment, [CanBeNull] string entitlementsCacheLifetime, [CanBeNull] string proxyUrl, bool kidsMode); 10 | void StoreSdkInfo(string version, string source); 11 | void SyncHistoricalData(); 12 | void SyncStoreKit2Purchases(); 13 | void SetAdvertisingID(); 14 | void SetUserProperty(UserPropertyKey key, string value); 15 | void SetCustomUserProperty(string key, string value); 16 | void UserProperties(string callbackName); 17 | void SyncPurchases(); 18 | void AddAttributionData(string conversionData, string providerName); 19 | void CheckEntitlements(string callbackName); 20 | void GetPromotionalOffer(string productId, string discountId, string callbackName); 21 | void Purchase(string productId, PurchaseOptions purchaseOptions, string callbackName); 22 | void Purchase(PurchaseModel purchaseModel, string callbackName); 23 | void Restore(string callbackName); 24 | void UpdatePurchase(PurchaseUpdateModel purchaseUpdateModel, string callbackName); 25 | void Products(string callbackName); 26 | void Offerings(string callbackName); 27 | void RemoteConfig([CanBeNull] string contextKey, string callbackName); 28 | void RemoteConfigList(string callbackName); 29 | void RemoteConfigList(string contextKeysJson, bool includeEmptyContextKey, string callbackName); 30 | void AttachUserToExperiment(string experimentId, string groupId, string callbackName); 31 | void DetachUserFromExperiment(string experimentId, string callbackName); 32 | void AttachUserToRemoteConfiguration(string remoteConfigurationId, string callbackName); 33 | void DetachUserFromRemoteConfiguration(string remoteConfigurationId, string callbackName); 34 | void IsFallbackFileAccessible(string callbackName); 35 | void CheckTrialIntroEligibility(string productIdsJson, string callbackName); 36 | void SetAppleSearchAdsAttributionEnabled(bool enable); 37 | void Identify(string userID, string callbackName); 38 | void Logout(); 39 | void UserInfo(string callbackName); 40 | void PromoPurchase(string storeProductId, string callbackName); 41 | void PresentCodeRedemptionSheet(); 42 | } 43 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/qonversion/IQonversionWrapper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f8a6901a4a36fb14dbb0c19d2093caf3 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs: -------------------------------------------------------------------------------- 1 | namespace QonversionUnity 2 | { 3 | internal class QonversionWrapperNoop : IQonversionWrapper 4 | { 5 | public void Initialize(string gameObjectName) 6 | { 7 | } 8 | 9 | public void InitializeSdk(string projectKey, string launchMode, string environment, string entitlementsCacheLifetime, 10 | string proxyUrl, bool kidsMode) 11 | { 12 | } 13 | 14 | public void SyncHistoricalData() 15 | { 16 | } 17 | 18 | public void SyncStoreKit2Purchases() 19 | { 20 | } 21 | 22 | public void SetUserProperty(UserPropertyKey key, string value) 23 | { 24 | } 25 | 26 | public void SetCustomUserProperty(string key, string value) 27 | { 28 | } 29 | 30 | public void UserProperties(string callbackName) 31 | { 32 | } 33 | 34 | public void AddAttributionData(string conversionData, string providerName) 35 | { 36 | } 37 | 38 | public void SyncPurchases() 39 | { 40 | } 41 | 42 | public void SetAdvertisingID() 43 | { 44 | } 45 | 46 | public void CheckEntitlements(string callbackName) 47 | { 48 | } 49 | 50 | public void GetPromotionalOffer(string productId, string discountId, string callbackName) 51 | { 52 | } 53 | 54 | public void Purchase(PurchaseModel purchaseModel, string callbackName) 55 | { 56 | } 57 | 58 | public void Purchase(string productId, PurchaseOptions purchaseOptions, string callbackName) 59 | { 60 | } 61 | 62 | public void Restore(string callbackName) 63 | { 64 | } 65 | 66 | public void UpdatePurchase(PurchaseUpdateModel purchaseUpdateModel, string callbackName) 67 | { 68 | } 69 | 70 | public void Products(string callbackName) 71 | { 72 | } 73 | 74 | public void Offerings(string callbackName) 75 | { 76 | } 77 | 78 | public void RemoteConfig(string contextKey, string callbackName) 79 | { 80 | } 81 | 82 | public void RemoteConfigList(string callbackName) 83 | { 84 | } 85 | 86 | public void RemoteConfigList(string contextKeysJson, bool includeEmptyContextKey, string callbackName) 87 | { 88 | } 89 | 90 | public void AttachUserToExperiment(string experimentId, string groupId, string callbackName) 91 | { 92 | } 93 | 94 | public void DetachUserFromExperiment(string experimentId, string callbackName) 95 | { 96 | } 97 | 98 | public void AttachUserToRemoteConfiguration(string remoteConfigurationId, string callbackName) 99 | { 100 | } 101 | 102 | public void DetachUserFromRemoteConfiguration(string remoteConfigurationId, string callbackName) 103 | { 104 | } 105 | 106 | public void IsFallbackFileAccessible(string callbackName) 107 | { 108 | } 109 | 110 | public void StoreSdkInfo(string version, string source) 111 | { 112 | } 113 | 114 | public void CheckTrialIntroEligibility(string productIdsJson, string callbackName) 115 | { 116 | } 117 | 118 | public void SetAppleSearchAdsAttributionEnabled(bool enable) 119 | { 120 | } 121 | 122 | public void Identify(string userID, string callbackName) 123 | { 124 | } 125 | 126 | public void Logout() 127 | { 128 | } 129 | 130 | public void UserInfo(string callbackName) 131 | { 132 | } 133 | 134 | public void PromoPurchase(string storeProductId, string callbackName) 135 | { 136 | } 137 | 138 | public void PresentCodeRedemptionSheet() 139 | { 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /Runtime/Scripts/Internal/wrappers/qonversion/QonversionWrapperNoop.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ba1c72708b384965890bb327159ac57 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Scripts/Qonversion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using JetBrains.Annotations; 4 | 5 | namespace QonversionUnity 6 | { 7 | public static class Qonversion 8 | { 9 | [CanBeNull] private static volatile IQonversion _backingInstance; 10 | private static object _syncRoot = new Object(); 11 | 12 | /// 13 | /// Use this variable to get a current initialized instance of the Qonversion SDK. 14 | /// Please, use the property only after calling . 15 | /// Otherwise, trying to access the variable will cause an exception. 16 | /// 17 | /// Current initialized instance of the Qonversion SDK. 18 | /// throws exception if the instance has not been initialized 19 | public static IQonversion GetSharedInstance() 20 | { 21 | if (_backingInstance == null) 22 | { 23 | throw new Exception( 24 | "Qonversion has not been initialized. You should call " + 25 | "the initialize method before accessing the shared instance of Qonversion." 26 | ); 27 | } 28 | 29 | return _backingInstance; 30 | } 31 | 32 | /// 33 | /// An entry point to use Qonversion SDK. Call to initialize Qonversion SDK with required and extra configs. 34 | /// The function is the best way to set additional configs you need to use Qonversion SDK. 35 | /// You still have an option to set a part of additional configs later via calling separate setters. 36 | /// 37 | /// a config that contains key SDK settings. 38 | /// Call to configure and create a QonversionConfig instance. 39 | /// Initialized instance of the Qonversion SDK. 40 | public static IQonversion Initialize(QonversionConfig config) 41 | { 42 | if (_backingInstance == null) 43 | { 44 | lock (_syncRoot) 45 | { 46 | if (_backingInstance == null) 47 | { 48 | IQonversion instance = QonversionInternal.CreateInstance(); 49 | instance.InitializeInstance(config); 50 | 51 | _backingInstance = instance; 52 | } 53 | } 54 | } 55 | 56 | return _backingInstance; 57 | } 58 | 59 | public delegate void OnPurchaseResultReceived(Dictionary entitlements, QonversionError error, bool isCancelled); 60 | public delegate void OnEntitlementsReceived(Dictionary entitlements, QonversionError error); 61 | public delegate void OnProductsReceived(Dictionary products, QonversionError error); 62 | public delegate void OnOfferingsReceived(Offerings offerings, QonversionError error); 63 | public delegate void OnRemoteConfigReceived(RemoteConfig remoteConfig, QonversionError error); 64 | public delegate void OnRemoteConfigListReceived(RemoteConfigList remoteConfigList, QonversionError error); 65 | public delegate void OnUserPropertiesReceived(UserProperties userProperties, QonversionError error); 66 | public delegate void OnAttachUserResponseReceived(bool success, QonversionError error); 67 | public delegate void OnEligibilitiesReceived(Dictionary eligibilities, QonversionError error); 68 | public delegate void OnUserInfoReceived(User userInfo, QonversionError error); 69 | public delegate void OnFallbackFileAccessibilityResponseReceived(bool success); 70 | public delegate void OnPromotionalOfferReceived(PromotionalOffer promotionalOffer, QonversionError error); 71 | 72 | /// 73 | /// Delegate fires each time a promo purchase from the App Store happens. 74 | /// Be sure you define a delegate for the event . 75 | /// Call StartPromoPurchase in case of your app is ready to start promo purchase. 76 | /// Or cache that delegate and call later when you need. 77 | /// 78 | /// StoreKit product identifier 79 | /// A delegate that will start a promo purchase flow. 80 | /// 81 | /// 82 | public delegate void OnPromoPurchasesReceived(string productId, StartPromoPurchase purchaseDelegate); 83 | 84 | /// 85 | /// Call the function if your app can handle a promo purchase at the current time. 86 | /// Or you can cache the delegate, and call it when the app is ready to make the purchase. 87 | /// 88 | /// Callback that will be called when response is received. Returns entitlements or potentially a QonversionError. 89 | /// 90 | /// 91 | public delegate void StartPromoPurchase(OnEntitlementsReceived callback); 92 | 93 | /// 94 | /// Delegate fires each time a user entitlements change asynchronously, 95 | /// for example, when pending purchases like SCA, Ask to buy, etc., happen. 96 | /// 97 | public delegate void OnUpdatedEntitlementsReceived(Dictionary entitlements); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Runtime/Scripts/Qonversion.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3d153a0da53e4ab38cd2815b94987e82 3 | timeCreated: 1668681655 -------------------------------------------------------------------------------- /Runtime/Scripts/QonversionConfig.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace QonversionUnity 4 | { 5 | public class QonversionConfig 6 | { 7 | public readonly string ProjectKey; 8 | public readonly LaunchMode LaunchMode; 9 | public readonly Environment Environment; 10 | public readonly EntitlementsCacheLifetime EntitlementsCacheLifetime; 11 | [CanBeNull] public readonly string ProxyUrl; 12 | public readonly bool KidsMode; 13 | 14 | public QonversionConfig( 15 | string projectKey, 16 | LaunchMode launchMode, 17 | Environment environment, 18 | EntitlementsCacheLifetime entitlementsCacheLifetime, 19 | [CanBeNull] string proxyUrl, 20 | bool kidsMode 21 | ) 22 | { 23 | ProjectKey = projectKey; 24 | LaunchMode = launchMode; 25 | Environment = environment; 26 | EntitlementsCacheLifetime = entitlementsCacheLifetime; 27 | ProxyUrl = proxyUrl; 28 | KidsMode = kidsMode; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Runtime/Scripts/QonversionConfig.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 081671b389ce42258e66635391aa5c2f 3 | timeCreated: 1668682590 -------------------------------------------------------------------------------- /Runtime/Scripts/QonversionConfigBuilder.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Annotations; 2 | 3 | namespace QonversionUnity 4 | { 5 | public class QonversionConfigBuilder 6 | { 7 | private readonly string _projectKey; 8 | private readonly LaunchMode _launchMode; 9 | private Environment _environment = Environment.Production; 10 | private EntitlementsCacheLifetime _entitlementsCacheLifetime = EntitlementsCacheLifetime.Month; 11 | [CanBeNull] private string _proxyUrl = null; 12 | private bool _kidsMode = false; 13 | 14 | public QonversionConfigBuilder(string projectKey, LaunchMode launchMode) 15 | { 16 | _projectKey = projectKey; 17 | _launchMode = launchMode; 18 | } 19 | 20 | /// 21 | /// Set current application . Used to distinguish sandbox and production users. 22 | /// 23 | /// current environment. 24 | /// builder instance for chain calls. 25 | public QonversionConfigBuilder SetEnvironment(Environment environment) 26 | { 27 | _environment = environment; 28 | return this; 29 | } 30 | 31 | /// 32 | /// Entitlements cache is used when there are problems with the Qonversion API 33 | /// or internet connection. If so, Qonversion will return the last successfully loaded 34 | /// entitlements. The current method allows you to configure how long that cache may be used. 35 | /// The default value is . 36 | /// 37 | /// desired entitlements cache lifetime duration. 38 | /// builder instance for chain calls. 39 | public QonversionConfigBuilder SetEntitlementsCacheLifetime(EntitlementsCacheLifetime lifetime) 40 | { 41 | _entitlementsCacheLifetime = lifetime; 42 | return this; 43 | } 44 | 45 | /// 46 | /// Provide a URL to your proxy server which will redirect all the requests from the app 47 | /// to our API. Please, contact us before using this feature. 48 | /// 49 | /// your proxy server url. 50 | /// builder instance for chain calls. 51 | /// 52 | public QonversionConfigBuilder SetProxyURL(string url) 53 | { 54 | _proxyUrl = url; 55 | return this; 56 | } 57 | 58 | /// 59 | /// Android only. 60 | /// Use this function to enable Qonversion SDK Kids mode. 61 | /// With this mode activated, our SDK does not collect any information that violates Google Children’s Privacy Policy. 62 | /// 63 | /// builder instance for chain calls. 64 | public QonversionConfigBuilder EnableKidsMode() 65 | { 66 | _kidsMode = true; 67 | return this; 68 | } 69 | 70 | /// 71 | /// Generate instance with all the provided configurations. 72 | /// 73 | /// the complete instance. 74 | public QonversionConfig Build() 75 | { 76 | return new QonversionConfig( 77 | _projectKey, 78 | _launchMode, 79 | _environment, 80 | _entitlementsCacheLifetime, 81 | _proxyUrl, 82 | _kidsMode 83 | ); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Runtime/Scripts/QonversionConfigBuilder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e965105671494d86988de6e150a1a2a3 3 | timeCreated: 1668683063 -------------------------------------------------------------------------------- /Runtime/iOS.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 12ddc0ad3eba449488e2184ea69f2006 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/iOS/AutomationsWrapperIOS.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_IOS 2 | using System.Runtime.InteropServices; 3 | #endif 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using JetBrains.Annotations; 8 | using UnityEngine; 9 | 10 | namespace QonversionUnity 11 | { 12 | internal class AutomationsWrapperIOS : IAutomationsWrapper 13 | { 14 | #if UNITY_IOS 15 | [DllImport("__Internal")] 16 | private static extern void _initializeAutomations(string gameObjectName); 17 | 18 | [DllImport("__Internal")] 19 | private static extern void _setNotificationsToken(string token); 20 | 21 | [DllImport("__Internal")] 22 | private static extern bool _handleNotification(string notification); 23 | 24 | [DllImport("__Internal")] 25 | private static extern string _getNotificationCustomPayload(string notification); 26 | 27 | [DllImport("__Internal")] 28 | private static extern void _subscribeOnAutomationEvents(); 29 | 30 | [DllImport("__Internal")] 31 | private static extern void _showScreen(string screenId, string callbackName); 32 | 33 | [DllImport("__Internal")] 34 | private static extern void _setScreenPresentationConfig(string configJson, [CanBeNull] string screenId); 35 | #endif 36 | 37 | public void Initialize(string gameObjectName) 38 | { 39 | #if UNITY_IOS 40 | _initializeAutomations(gameObjectName); 41 | #endif 42 | } 43 | public void SetNotificationsToken(string token) 44 | { 45 | #if UNITY_IOS 46 | _setNotificationsToken(token); 47 | #endif 48 | } 49 | 50 | public bool HandleNotification(string notification) 51 | { 52 | #if UNITY_IOS 53 | return _handleNotification(notification); 54 | #else 55 | return false; 56 | #endif 57 | } 58 | 59 | public string GetNotificationCustomPayload(string notification) 60 | { 61 | #if UNITY_IOS 62 | return _getNotificationCustomPayload(notification); 63 | #else 64 | return null; 65 | #endif 66 | } 67 | 68 | public void SubscribeOnAutomationEvents() 69 | { 70 | #if UNITY_IOS 71 | _subscribeOnAutomationEvents(); 72 | #endif 73 | } 74 | public void ShowScreen(string screenId, string callbackName) 75 | { 76 | #if UNITY_IOS 77 | _showScreen(screenId, callbackName); 78 | #endif 79 | } 80 | 81 | public void SetScreenPresentationConfig(string configJson, string screenId) 82 | { 83 | #if UNITY_IOS 84 | _setScreenPresentationConfig(configJson, screenId); 85 | #endif 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Runtime/iOS/AutomationsWrapperIOS.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 833a9b7bdb0a43228b1153c40421e900 3 | timeCreated: 1668776223 -------------------------------------------------------------------------------- /Runtime/iOS/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1f220c0e7d2a77d4ba1b6302c752a67a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/AutomationsBridge.m: -------------------------------------------------------------------------------- 1 | #import "UtilityBridge.h" 2 | #import "QNUAutomationsDelegate.h" 3 | @import QonversionSandwich; 4 | 5 | char* automationsUnityListenerName = nil; 6 | 7 | static QNUAutomationsDelegate *automationsBridge; 8 | 9 | void _initializeAutomations(const char* unityListener) { 10 | unsigned long len = strlen(unityListener); 11 | automationsUnityListenerName = malloc(len + 1); 12 | strcpy(automationsUnityListenerName, unityListener); 13 | 14 | automationsBridge = [[QNUAutomationsDelegate alloc] initWithListenerName:automationsUnityListenerName]; 15 | } 16 | 17 | void _setNotificationsToken(const char* token) { 18 | NSString *tokenStr = [UtilityBridge convertCStringToNSString:token]; 19 | [automationsBridge setNotificationsToken:tokenStr]; 20 | } 21 | 22 | bool _handleNotification(const char* notification) { 23 | NSDictionary *notificationInfo = [UtilityBridge dictionaryFromJsonString:[UtilityBridge convertCStringToNSString:notification]]; 24 | 25 | BOOL isQonversionNotification = [automationsBridge handleNotification:notificationInfo]; 26 | 27 | return isQonversionNotification; 28 | } 29 | 30 | char* _getNotificationCustomPayload(const char* notification) { 31 | NSDictionary *notificationInfo = [UtilityBridge dictionaryFromJsonString:[UtilityBridge convertCStringToNSString:notification]]; 32 | 33 | NSDictionary *payload = [automationsBridge getNotificationCustomPayload:notificationInfo]; 34 | 35 | if (payload == nil) { 36 | return nil; 37 | } 38 | 39 | const char *data = [UtilityBridge jsonStringFromObject:payload]; 40 | 41 | char* cString = (char*)malloc(strlen(data) + 1); 42 | strcpy(cString, data); 43 | 44 | return cString; 45 | } 46 | 47 | void _showScreen(const char* screenId, const char* unityCallbackName) { 48 | NSString *callbackName = [UtilityBridge convertCStringToNSString:unityCallbackName]; 49 | NSString *screenIdStr = [UtilityBridge convertCStringToNSString:screenId]; 50 | [automationsBridge showScreenWithId:screenIdStr callbackName:callbackName]; 51 | } 52 | 53 | void _subscribeOnAutomationEvents() { 54 | [automationsBridge subscribe]; 55 | } 56 | 57 | void _setScreenPresentationConfig(const char* configData, const char* screenId) { 58 | NSDictionary *config = [UtilityBridge dictionaryFromJsonString:[UtilityBridge convertCStringToNSString:configData]]; 59 | NSString *screenIdStr = [UtilityBridge convertCStringToNSString:screenId]; 60 | [automationsBridge setScreenPresentationConfig:config screenId:screenIdStr]; 61 | } 62 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/AutomationsBridge.m.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3274bd50e96104e20b153fb581760138 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 0 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | - first: 26 | iPhone: iOS 27 | second: 28 | enabled: 1 29 | settings: {} 30 | - first: 31 | tvOS: tvOS 32 | second: 33 | enabled: 1 34 | settings: {} 35 | userData: 36 | assetBundleName: 37 | assetBundleVariant: 38 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/Common.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1c5765ecd60071e49a790d0145515f91 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // QNUAutomationsDelegate.h 3 | // Unity-iPhone 4 | // 5 | // Created by Surik Sarkisyan on 15.03.2022. 6 | // 7 | 8 | #import 9 | @import QonversionSandwich; 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface QNUAutomationsDelegate : NSObject 14 | 15 | - (instancetype)initWithListenerName:(char *)unityListenerName; 16 | - (void)subscribe; 17 | - (void)setNotificationsToken:(NSString *)token; 18 | - (BOOL)handleNotification:(NSDictionary *)notificationInfo; 19 | - (NSDictionary *)getNotificationCustomPayload:(NSDictionary *)payload; 20 | - (void)showScreenWithId:(NSString *)screenId callbackName:(NSString *)callbackName; 21 | - (void)setScreenPresentationConfig:(NSDictionary *)config screenId:(NSString *)screenId; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.h.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 185ee14cf41c34a3ca880e5d40585f29 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 1 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | userData: 26 | assetBundleName: 27 | assetBundleVariant: 28 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // QNUAutomationsDelegate.m 3 | // Unity-iPhone 4 | // 5 | // Created by Surik Sarkisyan on 15.03.2022. 6 | // 7 | 8 | #import "QNUAutomationsDelegate.h" 9 | #import "UtilityBridge.h" 10 | 11 | static NSString *const kEventScreenShown = @"OnAutomationsScreenShown"; 12 | static NSString *const kEventActionStarted = @"OnAutomationsActionStarted"; 13 | static NSString *const kEventActionFailed = @"OnAutomationsActionFailed"; 14 | static NSString *const kEventActionFinished = @"OnAutomationsActionFinished"; 15 | static NSString *const kEventAutomationsFinished = @"OnAutomationsFinished"; 16 | 17 | char* listenerName = nil; 18 | 19 | @interface QNUAutomationsDelegate () 20 | 21 | @property (nonatomic, strong) AutomationsSandwich *automationsSandwich; 22 | @property (nonatomic, copy) NSDictionary *automationEvents; 23 | 24 | @end 25 | 26 | @implementation QNUAutomationsDelegate 27 | 28 | - (instancetype)initWithListenerName:(char *)unityListenerName { 29 | self = [super init]; 30 | 31 | if (self) { 32 | listenerName = unityListenerName; 33 | _automationsSandwich = [AutomationsSandwich new]; 34 | _automationEvents = @{ 35 | @"automations_screen_shown": kEventScreenShown, 36 | @"automations_action_started": kEventActionStarted, 37 | @"automations_action_failed": kEventActionFailed, 38 | @"automations_action_finished": kEventActionFinished, 39 | @"automations_finished": kEventAutomationsFinished 40 | }; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | - (void)subscribe { 47 | [self.automationsSandwich subscribe:self]; 48 | } 49 | 50 | - (void)setNotificationsToken:(NSString *)token { 51 | [self.automationsSandwich setNotificationToken:token]; 52 | } 53 | 54 | - (BOOL)handleNotification:(NSDictionary *)notificationInfo { 55 | return [self.automationsSandwich handleNotification:notificationInfo]; 56 | } 57 | 58 | - (NSDictionary *)getNotificationCustomPayload:(NSDictionary *)payload { 59 | return [self.automationsSandwich getNotificationCustomPayload:payload]; 60 | } 61 | 62 | - (void)automationDidTriggerWithEvent:(NSString * _Nonnull)event payload:(NSDictionary * _Nullable)payload { 63 | NSString *methodName = self.automationEvents[event]; 64 | 65 | [UtilityBridge sendUnityMessage:payload ?: @{} toMethod:methodName unityListener: listenerName]; 66 | } 67 | 68 | - (void)showScreenWithId:(NSString *)screenId callbackName:(NSString *)callbackName { 69 | [self.automationsSandwich showScreen:screenId completion:^(NSDictionary * _Nullable result, SandwichError * _Nullable error) { 70 | [UtilityBridge handleResult:result error:error callbackName:callbackName unityListener:listenerName]; 71 | }]; 72 | } 73 | 74 | - (void)setScreenPresentationConfig:(NSDictionary *)config screenId:(NSString *)screenId { 75 | [self.automationsSandwich setScreenPresentationConfig:config forScreenId:screenId]; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/Common/QNUAutomationsDelegate.m.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3539a63d5587c4502ad192926adb131c 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 0 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | - first: 26 | iPhone: iOS 27 | second: 28 | enabled: 1 29 | settings: {} 30 | - first: 31 | tvOS: tvOS 32 | second: 33 | enabled: 1 34 | settings: {} 35 | userData: 36 | assetBundleName: 37 | assetBundleVariant: 38 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/Common/UtilityBridge.h: -------------------------------------------------------------------------------- 1 | #import 2 | @import QonversionSandwich; 3 | 4 | @interface UtilityBridge : NSObject 5 | 6 | + (NSString*)convertCStringToNSString:(const char *)string; 7 | + (NSDictionary*)dictionaryFromJsonString:(NSString*) jsonString; 8 | + (NSArray*)arrayFromJsonString:(NSString*) jsonString; 9 | + (NSDictionary *)serializeErrorWithCode:(NSString *)code 10 | domain:(NSString *)domain 11 | description:(NSString *)description 12 | additionalMessage:(NSString *)additionalMessage; 13 | + (NSDictionary *)serializeSandwichError:(SandwichError *)error; 14 | + (const char *)jsonStringFromObject:(NSObject *)objectToConvert; 15 | 16 | + (void)sendUnityMessage:(NSObject *)objectToConvert toMethod:(NSString *)methodName 17 | unityListener:(const char *)unityListenerName; 18 | 19 | + (void)handleErrorResponse:(SandwichError *)error toMethod:(NSString *)methodName 20 | unityListener:(const char *)unityListenerName; 21 | + (void)handleLocalError:(NSError *)error 22 | message:(NSString *)message 23 | toMethod:(NSString *)methodName 24 | unityListener:(const char *)unityListenerName; 25 | + (void)handleResult:(NSDictionary *)result 26 | error:(SandwichError *)error 27 | callbackName:(NSString *)callbackName 28 | unityListener:(const char *)unityListenerName; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/Common/UtilityBridge.h.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 48e3194c80281f049b6f5ba07f3b215c 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 1 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | userData: 26 | assetBundleName: 27 | assetBundleVariant: 28 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/Common/UtilityBridge.m: -------------------------------------------------------------------------------- 1 | #import "UtilityBridge.h" 2 | 3 | static NSString *const nativeModuleErrorCode = @"NativeModuleError"; 4 | 5 | @implementation UtilityBridge 6 | 7 | + (NSString*)convertCStringToNSString:(const char *)string { 8 | if (string == NULL) { 9 | return nil; 10 | } 11 | 12 | return [NSString stringWithUTF8String:string]; 13 | } 14 | 15 | + (NSDictionary*)dictionaryFromJsonString:(NSString*) jsonString { 16 | if (!jsonString) { 17 | return @{}; 18 | } 19 | 20 | NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; 21 | NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; 22 | 23 | return dictionary; 24 | } 25 | 26 | + (NSArray*)arrayFromJsonString:(NSString*) jsonString { 27 | if (!jsonString) { 28 | return @[]; 29 | } 30 | 31 | NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; 32 | NSArray *array = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:nil]; 33 | 34 | return array; 35 | } 36 | 37 | + (NSDictionary *)serializeErrorWithCode:(NSString *)code 38 | domain:(NSString *)domain 39 | description:(NSString *)description 40 | additionalMessage:(NSString *)additionalMessage { 41 | NSMutableDictionary *errorDict = [NSMutableDictionary new]; 42 | errorDict[@"code"] = code; 43 | errorDict[@"domain"] = domain; 44 | errorDict[@"description"] = description; 45 | errorDict[@"additionalMessage"] = additionalMessage; 46 | 47 | NSMutableDictionary *result = [NSMutableDictionary new]; 48 | result[@"error"] = errorDict; 49 | 50 | return [result copy]; 51 | } 52 | 53 | + (NSDictionary *)serializeSandwichError:(SandwichError *)error { 54 | NSDictionary *errorDict = [UtilityBridge serializeErrorWithCode:error.code 55 | domain:error.domain 56 | description:error.details 57 | additionalMessage:error.additionalMessage]; 58 | 59 | return [errorDict copy]; 60 | } 61 | 62 | + (void)handleErrorResponse:(SandwichError *)error toMethod:(NSString *)methodName 63 | unityListener:(const char *)unityListenerName { 64 | NSDictionary *errorDict = [UtilityBridge serializeSandwichError:error]; 65 | [UtilityBridge sendUnityMessage:errorDict toMethod:methodName unityListener:unityListenerName]; 66 | } 67 | 68 | + (void)handleLocalError:(NSError *)error 69 | message:(NSString *)message 70 | toMethod:(NSString *)methodName 71 | unityListener:(const char *)unityListenerName { 72 | NSDictionary *errorDict = [UtilityBridge serializeErrorWithCode:nativeModuleErrorCode 73 | domain:error.domain 74 | description:message 75 | additionalMessage:error.localizedDescription]; 76 | [UtilityBridge sendUnityMessage:errorDict toMethod:methodName unityListener:unityListenerName]; 77 | } 78 | 79 | + (const char *)jsonStringFromObject:(NSObject *)objectToConvert { 80 | if (objectToConvert == nil) { 81 | return nil; 82 | } 83 | 84 | NSError *error = nil; 85 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:objectToConvert options:0 error:&error]; 86 | 87 | if (error) { 88 | NSLog(@"An error occurred while serializing data: %@", error.localizedDescription); 89 | return nil; 90 | } 91 | 92 | if (jsonData) { 93 | NSString *json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 94 | return json.UTF8String; 95 | } 96 | return nil; 97 | } 98 | 99 | + (void)sendUnityMessage:(NSObject *)objectToConvert 100 | toMethod:(NSString *)methodName 101 | unityListener:(const char *)unityListenerName { 102 | const char *data = [UtilityBridge jsonStringFromObject:objectToConvert]; 103 | 104 | if (data) { 105 | UnitySendMessage(unityListenerName, methodName.UTF8String, data); 106 | } 107 | return; 108 | } 109 | 110 | + (void)handleResult:(NSDictionary *)result 111 | error:(SandwichError *)error 112 | callbackName:(NSString *)callbackName 113 | unityListener:(const char *)unityListenerName { 114 | if (error) { 115 | [UtilityBridge handleErrorResponse:error toMethod:callbackName unityListener:unityListenerName]; 116 | } else { 117 | [UtilityBridge sendUnityMessage:result toMethod:callbackName unityListener:unityListenerName]; 118 | } 119 | } 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/Common/UtilityBridge.m.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 666fb1fa0c7e977428a9aee8f0797497 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 0 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | - first: 26 | iPhone: iOS 27 | second: 28 | enabled: 1 29 | settings: {} 30 | - first: 31 | tvOS: tvOS 32 | second: 33 | enabled: 1 34 | settings: {} 35 | userData: 36 | assetBundleName: 37 | assetBundleVariant: 38 | -------------------------------------------------------------------------------- /Runtime/iOS/Plugins/QonversionBridge.m.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd940853716574fd8a7a72a9a6d34390 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 0 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 0 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | - first: 26 | iPhone: iOS 27 | second: 28 | enabled: 1 29 | settings: {} 30 | - first: 31 | tvOS: tvOS 32 | second: 33 | enabled: 1 34 | settings: {} 35 | userData: 36 | assetBundleName: 37 | assetBundleVariant: 38 | -------------------------------------------------------------------------------- /Runtime/iOS/QonversionWrapperIOS.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c9b40e5937b479a4e8d83a389ea7e051 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /fastlane.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 089159a4944c04210aeeacfd063d3601 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /fastlane/Appfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qonversion/unity-sdk/fab0c8c34d3428624f14b77926eefbaf4e50dcfc/fastlane/Appfile -------------------------------------------------------------------------------- /fastlane/Appfile.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df504593313e54776a427d43dca4e661 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | def update_package_json(new_version) 2 | path = "../package.json" 3 | regex = /"version": ".*",/ 4 | result_value = "\"version\": \"#{new_version}\"," 5 | 6 | update_file(path, regex, result_value) 7 | end 8 | 9 | def update_constant(new_version) 10 | path = "../Runtime/Scripts/Internal/QonversionInternal.cs" 11 | regex = /private const string SdkVersion = ".*";/ 12 | result_value = "private const string SdkVersion = \"#{new_version}\";" 13 | 14 | update_file(path, regex, result_value) 15 | end 16 | 17 | def upgrade_sandwich_android(new_version) 18 | path = "../Editor/QonversionDependencies.xml" 19 | common_part = "/ 21 | result_value = "#{common_part}#{new_version}\" \/>" 22 | 23 | update_file(path, regex, result_value) 24 | end 25 | 26 | def upgrade_sandwich_ios(new_version) 27 | path = "../Editor/QonversionDependencies.xml" 28 | common_part = "/ 30 | result_value = "#{common_part}#{new_version}\" \/>" 31 | 32 | update_file(path, regex, result_value) 33 | end 34 | 35 | def update_file(path, regex, result_value) 36 | file = File.read(path) 37 | new_content = file.gsub(regex, result_value) 38 | File.open(path, 'w') { |line| line.puts new_content } 39 | end 40 | 41 | def get_tag 42 | tag = last_git_tag() 43 | puts tag 44 | result_tag = tag.scan(%r{\d{1,2}.\d{1,2}.\d{1,3}}).first 45 | return result_tag 46 | end 47 | 48 | def calculate_minor_version(tag) 49 | major, minor, patch = parse_versions(tag) 50 | new_minor_version = minor.to_i.next.to_s 51 | new_version = major + "." + new_minor_version + "." + "0" 52 | return new_version 53 | end 54 | 55 | def calculate_patch_version(tag) 56 | major, minor, patch = parse_versions(tag) 57 | new_patch_version = patch.to_i.next.to_s 58 | new_version = major + "." + minor + "." + new_patch_version 59 | 60 | return new_version 61 | end 62 | 63 | def push_tag(tag) 64 | system("git checkout develop") 65 | system("git pull origin develop") 66 | add_git_tag(tag: tag) 67 | push_git_tags(tag: tag) 68 | end 69 | 70 | def parse_versions(tag) 71 | split_version_array = tag.split(".", 3) 72 | 73 | if split_version_array.length == 3 74 | major = split_version_array[0] 75 | minor = split_version_array[1] 76 | patch = split_version_array[2] 77 | 78 | return major, minor, patch 79 | end 80 | end 81 | 82 | lane :patch do 83 | tag = get_tag 84 | new_version = calculate_patch_version(tag) 85 | new_tag = "prerelease/" + new_version 86 | push_tag(new_tag) 87 | end 88 | 89 | lane :minor do 90 | tag = get_tag 91 | new_version = calculate_minor_version(tag) 92 | new_tag = "prerelease/" + new_version 93 | push_tag(new_tag) 94 | end 95 | 96 | lane :bump do |options| 97 | new_version = options[:version] 98 | 99 | update_package_json(new_version) 100 | update_constant(new_version) 101 | end 102 | 103 | lane :upgrade_sandwich do |options| 104 | new_version = options[:version] 105 | 106 | upgrade_sandwich_android(new_version) 107 | upgrade_sandwich_ios(new_version) 108 | end 109 | 110 | lane :provide_next_patch_version do 111 | tag = get_tag 112 | new_version = calculate_patch_version(tag) 113 | sh("echo version=#{new_version} >> \"$GITHUB_ENV\"") 114 | end 115 | -------------------------------------------------------------------------------- /fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ---- 3 | 4 | # Installation 5 | 6 | Make sure you have the latest version of the Xcode command line tools installed: 7 | 8 | ```sh 9 | xcode-select --install 10 | ``` 11 | 12 | For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) 13 | 14 | # Available Actions 15 | 16 | ### patch 17 | 18 | ```sh 19 | [bundle exec] fastlane patch 20 | ``` 21 | 22 | 23 | 24 | ### minor 25 | 26 | ```sh 27 | [bundle exec] fastlane minor 28 | ``` 29 | 30 | 31 | 32 | ### bump 33 | 34 | ```sh 35 | [bundle exec] fastlane bump 36 | ``` 37 | 38 | 39 | 40 | ### upgrade_sandwich 41 | 42 | ```sh 43 | [bundle exec] fastlane upgrade_sandwich 44 | ``` 45 | 46 | 47 | 48 | ### provide_next_patch_version 49 | 50 | ```sh 51 | [bundle exec] fastlane provide_next_patch_version 52 | ``` 53 | 54 | 55 | 56 | ---- 57 | 58 | This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. 59 | 60 | More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). 61 | 62 | The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 63 | -------------------------------------------------------------------------------- /fastlane/README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0f7d66a11e8894098917aa1f4ef1507a 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /fastlane/fastfile.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0490d362f09d34421838ef526cb8839d 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /fastlane/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /fastlane/report.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ce3590874b3444ee79db9c2164fd95be 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /img.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 48c2b6eb637629f45a1e09fdfab22448 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /img/UnityQonversionLauncher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qonversion/unity-sdk/fab0c8c34d3428624f14b77926eefbaf4e50dcfc/img/UnityQonversionLauncher.png -------------------------------------------------------------------------------- /img/UnityQonversionLauncher.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 721fa4cd076d647b7a88c24f5c0e1aec 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | vTOnly: 0 27 | ignoreMasterTextureLimit: 0 28 | grayScaleToAlpha: 0 29 | generateCubemap: 6 30 | cubemapConvolution: 0 31 | seamlessCubemap: 0 32 | textureFormat: 1 33 | maxTextureSize: 2048 34 | textureSettings: 35 | serializedVersion: 2 36 | filterMode: 1 37 | aniso: 1 38 | mipBias: 0 39 | wrapU: 1 40 | wrapV: 1 41 | wrapW: 1 42 | nPOTScale: 0 43 | lightmap: 0 44 | compressionQuality: 50 45 | spriteMode: 1 46 | spriteExtrude: 1 47 | spriteMeshType: 1 48 | alignment: 0 49 | spritePivot: {x: 0.5, y: 0.5} 50 | spritePixelsToUnits: 100 51 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 52 | spriteGenerateFallbackPhysicsShape: 1 53 | alphaUsage: 1 54 | alphaIsTransparency: 1 55 | spriteTessellationDetail: -1 56 | textureType: 8 57 | textureShape: 1 58 | singleChannelComponent: 0 59 | flipbookRows: 1 60 | flipbookColumns: 1 61 | maxTextureSizeSet: 0 62 | compressionQualitySet: 0 63 | textureFormatSet: 0 64 | ignorePngGamma: 0 65 | applyGammaDecoding: 0 66 | platformSettings: 67 | - serializedVersion: 3 68 | buildTarget: DefaultTexturePlatform 69 | maxTextureSize: 2048 70 | resizeAlgorithm: 0 71 | textureFormat: -1 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 0 77 | androidETC2FallbackOverride: 0 78 | forceMaximumCompressionQuality_BC6H_BC7: 0 79 | spriteSheet: 80 | serializedVersion: 2 81 | sprites: [] 82 | outline: [] 83 | physicsShape: [] 84 | bones: [] 85 | spriteID: 5e97eb03825dee720800000000000000 86 | internalID: 0 87 | vertices: [] 88 | indices: 89 | edges: [] 90 | weights: [] 91 | secondaryTextures: [] 92 | nameFileIdTable: {} 93 | spritePackingTag: 94 | pSDRemoveMatte: 0 95 | pSDShowRemoveMatteOption: 0 96 | userData: 97 | assetBundleName: 98 | assetBundleVariant: 99 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.qonversion.unity", 3 | "displayName": "Qonversion", 4 | "version": "8.2.0", 5 | "unity": "2018.3", 6 | "description": "Empower your mobile app marketing and product decisions with precise subscription data.", 7 | "author": { 8 | "name": "qonversion.io", 9 | "url": "https://github.com/qonversion/unity-sdk" 10 | }, 11 | "keywords": [ 12 | "unity", 13 | "qonversion", 14 | "ios", 15 | "android", 16 | "apple", 17 | "subscription", 18 | "analytics", 19 | "iap", 20 | "purchase" 21 | ], 22 | "category": "Unity", 23 | "files": [ 24 | "/README.md", 25 | "/README.md.meta", 26 | "/package.json", 27 | "/package.json.meta", 28 | "/Runtime", 29 | "/Runtime.meta", 30 | "/Editor", 31 | "/Editor.meta" 32 | ], 33 | "dependencies": {} 34 | } 35 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e77a923a5f798344db5fb608a5876fed 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------