* Sk2: fetch products, make purchases (#800) * added product struct * added Product protocol and separated wrappers for sk1 and sk2 * added price and localizedPriceString to Product * added bridging code and first call to generic productsWithIdentifiers * a lot of cleanup, added a couple more properties for products * added subscription group id and cleaned up a bit * Updated productsManager so it forwards the products calls to fetchers for sk1 and sk2 * updated a few tests and API availability checks * updated a few methods to use productwrapper instead of skproduct * updated tests in many places and apis * fixed rebase issues * fixed a few todos * fixed a few issues caught by swiftlint * fixed rebase issues and some visibility issues * updated a few places to use SK2 * added horrifyingly hacky implementation for purchasing with sk2 * small cleanup, re-added method for getting SKProducts directly * cleanup * added caching to sk2 products fetcher * removed trailing whitespace * slight cleanup * added more clarifying comments * another cleanup * added missing availability marks for macOS * fixed availability marks for ProductsFetcher in ProductsManager * yet another fix for macOS availability checks * and more fixes for macOS version since 13.0 doesn't exist * fixed issues in api tester * fixed pod lib lint on non-arch64 architectures * bundle update fastlane * added test for dictionary += operator * removed unnecessary method for fetching product wrappers * cleanup file names * updated references in StoreKitTests * fixed targets for test file * fixed rebase issues * added StoreKit 2 transaction listener in the hopes of getting purchases working, unfortunately doesn't seem to work well * fix bad refactor * refactored, move purchasing logic to the orchestrator, added processing of results of SK 2 purchases to the orchestrator and the sk2 listener * added arch checks in a few places to fix builds in armv7 * added another todo * updated test for ProductsManager in StoreKit Test * renamed `Product.swift` -> `ProductWrapper.swift` * increased timeout for test * added checks to ensure test compatibility with lower iOS versions * ProductWrapper -> ProductDetails * import Purchases -> import RevenueCat * withProductDetailss -> withProductDetails * productDetailss -> productDetails * productsFromOptimalStore -> productsFromOptimalStoreKitVersion * linting * `Task.init {` -> `Task {` * added comment explaining explicit cancel * more improvements from PR comments * `} catch let error {` -> `} catch {` * readability improvements * move init to the top for consistency * extracted logging string into PurchasesString * extracted another string * added todo comment * improvements from PR comments, removed redundant method * removed unused method, more renames and improvements from PR comments * updates xcode version for CI * split files into StoreKit 1 and StoreKit 2 groups * fix indentation * fixed rebase issues * Fix PurchaseTester project (#847) * CheckTrialOrIntroPriceEligibility StoreKit2 support (#807) * Sk2: fetch products, make purchases (#800) * added product struct * added Product protocol and separated wrappers for sk1 and sk2 * added price and localizedPriceString to Product * added bridging code and first call to generic productsWithIdentifiers * a lot of cleanup, added a couple more properties for products * added subscription group id and cleaned up a bit * Updated productsManager so it forwards the products calls to fetchers for sk1 and sk2 * updated a few tests and API availability checks * updated a few methods to use productwrapper instead of skproduct * updated tests in many places and apis * fixed rebase issues * fixed a few todos * fixed a few issues caught by swiftlint * fixed rebase issues and some visibility issues * updated a few places to use SK2 * added horrifyingly hacky implementation for purchasing with sk2 * small cleanup, re-added method for getting SKProducts directly * cleanup * added caching to sk2 products fetcher * removed trailing whitespace * slight cleanup * added more clarifying comments * another cleanup * added missing availability marks for macOS * fixed availability marks for ProductsFetcher in ProductsManager * yet another fix for macOS availability checks * and more fixes for macOS version since 13.0 doesn't exist * fixed issues in api tester * fixed pod lib lint on non-arch64 architectures * bundle update fastlane * added test for dictionary += operator * removed unnecessary method for fetching product wrappers * cleanup file names * updated references in StoreKitTests * fixed targets for test file * fixed rebase issues * added StoreKit 2 transaction listener in the hopes of getting purchases working, unfortunately doesn't seem to work well * fix bad refactor * refactored, move purchasing logic to the orchestrator, added processing of results of SK 2 purchases to the orchestrator and the sk2 listener * added arch checks in a few places to fix builds in armv7 * added another todo * updated test for ProductsManager in StoreKit Test * renamed `Product.swift` -> `ProductWrapper.swift` * increased timeout for test * added checks to ensure test compatibility with lower iOS versions * ProductWrapper -> ProductDetails * import Purchases -> import RevenueCat * withProductDetailss -> withProductDetails * productDetailss -> productDetails * productsFromOptimalStore -> productsFromOptimalStoreKitVersion * linting * `Task.init {` -> `Task {` * added comment explaining explicit cancel * more improvements from PR comments * `} catch let error {` -> `} catch {` * readability improvements * move init to the top for consistency * extracted logging string into PurchasesString * extracted another string * added todo comment * improvements from PR comments, removed redundant method * removed unused method, more renames and improvements from PR comments * updates xcode version for CI * split files into StoreKit 1 and StoreKit 2 groups * fix indentation * adds check intro trial sk2 support * fixes and renames * removes debugging variables * fixes and use of ProductsManager * fix sk2Product isEligibleForIntroOffer * remove swiftlint warning * adds header and links to issues * fix strings * early return * indentation fix * removes maccatalyst * fixes compilation and renames to checkEligibility * changes on ProductsManager adding a specific sk2 function * makes changes in TrialOrIntroPriceEligibilityChecker * rename function to sk2ProductDetails * some renaming * duplicated ProductsFetcherSK1Tests.swift * add XCTUnwrap * revert Co-authored-by: aboedo <andresboedo@gmail.com> * fixed offeringsManagerTests (#856) * Separate storekit test and backend tests (#845) * Sk2: fetch products, make purchases (#800) * added product struct * added Product protocol and separated wrappers for sk1 and sk2 * added price and localizedPriceString to Product * added bridging code and first call to generic productsWithIdentifiers * a lot of cleanup, added a couple more properties for products * added subscription group id and cleaned up a bit * Updated productsManager so it forwards the products calls to fetchers for sk1 and sk2 * updated a few tests and API availability checks * updated a few methods to use productwrapper instead of skproduct * updated tests in many places and apis * fixed rebase issues * fixed a few todos * fixed a few issues caught by swiftlint * fixed rebase issues and some visibility issues * updated a few places to use SK2 * added horrifyingly hacky implementation for purchasing with sk2 * small cleanup, re-added method for getting SKProducts directly * cleanup * added caching to sk2 products fetcher * removed trailing whitespace * slight cleanup * added more clarifying comments * another cleanup * added missing availability marks for macOS * fixed availability marks for ProductsFetcher in ProductsManager * yet another fix for macOS availability checks * and more fixes for macOS version since 13.0 doesn't exist * fixed issues in api tester * fixed pod lib lint on non-arch64 architectures * bundle update fastlane * added test for dictionary += operator * removed unnecessary method for fetching product wrappers * cleanup file names * updated references in StoreKitTests * fixed targets for test file * fixed rebase issues * added StoreKit 2 transaction listener in the hopes of getting purchases working, unfortunately doesn't seem to work well * fix bad refactor * refactored, move purchasing logic to the orchestrator, added processing of results of SK 2 purchases to the orchestrator and the sk2 listener * added arch checks in a few places to fix builds in armv7 * added another todo * updated test for ProductsManager in StoreKit Test * renamed `Product.swift` -> `ProductWrapper.swift` * increased timeout for test * added checks to ensure test compatibility with lower iOS versions * ProductWrapper -> ProductDetails * import Purchases -> import RevenueCat * withProductDetailss -> withProductDetails * productDetailss -> productDetails * productsFromOptimalStore -> productsFromOptimalStoreKitVersion * linting * `Task.init {` -> `Task {` * added comment explaining explicit cancel * more improvements from PR comments * `} catch let error {` -> `} catch {` * readability improvements * move init to the top for consistency * extracted logging string into PurchasesString * extracted another string * added todo comment * improvements from PR comments, removed redundant method * removed unused method, more renames and improvements from PR comments * updates xcode version for CI * split files into StoreKit 1 and StoreKit 2 groups * fix indentation * updated all references from StoreKitTests -> BackendIntegrationTests * updated references in a few more places * updated name of target back to StoreKitTests so the cert doesn't get updated 🙄 * fixed issues in tests * updated arch checks for arm devices from if arm64 to if !arm, so that the code will run successfully in intel macs * upgraded deployment target to 12.0 to fix issues when compiling StoreKit 2. Removed arch checks. * added separate `UnitTestsHostApp` since the `StoreKitTest` app has higher minimum deployment target than the unit tests target * added separate scheme for unit tests to address the need of StoreKitTest * fixed scheme name for Scanfile * small fixes * added skipping of test depending on OS version availability * added pre-warming of iOS device since tests aren't starting up correctly in CI * added pre-warming of iphone 6 and tv * fixed devices setup since iPhone 6 is no longer available in CircleCI * renamed StoreKitTestApp + StoreKitTests -> BackendIntegrationTests + HostApp * more fixes to naming * updated Nimble version, more fixes to paths * removed host app for regular unit tests, fixed setup * even more naming fixes, updated the scan schemes so we don't try to test appleTV for the StoreKitUnitTests * enabled backend_integration_tests for all commits * added missing dependency to RevenueCat framework from StoreKitUnitTests target * fixed dependencies between targets, which would compile more targets than necessary and would have issues where the main framework would get built for the wrong platform * update fastlane * fixed lane name * fixed deployment target for backend integration tests * updated scan device OS for backend integration tests to 15.0 * fixed integration tests running wrong fastlane lane, added pre-warming devices for regular unit tests, added command line tools installation step * removed command line tools installation step * updated device name since iPhone SE isn't available on circleCI * updated iPhone SE -> iPhone 8 in a couple more places * removed pre-warming of devices, since it has been removed from Xcode 13 * removed 14.5 device from tests for now * removed signing from backend integration tests * fixed rebase issues * Sk2: ProductDetails cleanup and improvements (#832) * moved logic to wrap products into productsFetcher, added basic test to compare sk1Wrapper and sk2Wrapper * added more checks to cover all existing properties for productWrappers * added test to check that sk1 wrapper works correctly * added test for SK2 product wrapper * renamed internal method `purchase(product:` -> `purchase(sk1Product:` * moved StoreKit2TransactionListener into corresponding group in project * added base file for PurchaseOrchestratorTests, improved a couple of version checks for tests * updated imports to `RevenueCat` * re-added @available in a couple of tests * update naming: ProductWrapper -> ProductDetails * fix rebasing issue * added type aliases for legacy and new skproduct, updated references to them in many places * renamed mockSKProduct -> mockLegacySKProduct * more cleanup * updated naming in a few more places * and more naming updates * final batch of naming updates * updated naming from new and legacy sk products to sk1 and sk2 products * fixed naming issues with variable names that started in uppercase * more fixes to variable names * even more naming fixes * final batch of naming updates, rebase fixes * several fixes from rebase * removed another arch check * fixes from PR comments * fixed missing mocks for MockProductsManager * more "productDetailss" var renames * removed scan_scheme env variable since we're setting it manually * added extra test configuration for UnitTests scheme, set test ordering to random * small ci configuration updates * added more generous timeout for one test case * added pre-warming of simulators * added device pre-warming at the fastlane level * added test plan * added manual sleep of 5 mins to see if that fixes the testing issues * re-added manual opening of simulators, otherwise the wait makes no sense * made the wait for simulator bit only happen in ci * improvement from PR comments * fixed one reason for app crash in iOS < 15, since SceneDelegate was missing * added check for subscriptionGroupIdentifier * updated to use XCTSkip instead of early return in a couple of tests * Tests for CheckTrialOrIntroductoryPriceEligibility StoreKit2 using StoreKitTests (#863) * Storekit 2: fix tests for iOS 14.5 (#890) * updated storage of underlyingSK2Product to use Any to prevent crashes in 14.5 devices * added comment and small cleanup * re-added iOS 14.5 devices to fastlane scan * fixed rebase issues * merge storekit_2_disable_mac_builds * Sk2 purchase tests (#873) * added tests skeleton, cleaned up handling of purchase sk2 package * code clean up, added mocks to sk unit tests target, clean up tests code * added mockStoreKit2Listener, fixed purchasesOrchestator test * implemented missing test cases * casted SK2Product to any for storing to prevent linking issues * fixed more issues with linking + moved PurchasesOrchestratorTests to storekit tests * linting * fixed duplicate files in build phase * fixed more issues with linking on older OS * fixed rebase issues * fix one test in SwiftAPITester * updated xcode version for swift api tester * updated api testers to use an existing bundle id to prevent code signing issues * remove development team + undo bundle id updates * added fastlane match readonly step * re-add dev team * re-add dev team to release builds for objc api tester ios * updated certs to use fastlane match * specified missing params for match * fixed copy/paste issue * `MockStoreKit2Listener` -> `MockStoreKit2TransactionListener` * added clearing of user defaults before every test run * added crude handling of the user cancelled case for SK2 purchases. * fixed indentation * updated test name to reflect what it's actually testing * reset the value of `failTransactionsEnabled` before every test * moved to using `resetToDefaultState` * Removes `RequiresXcode13` (#895) * improve pre-warming and fix flaky tests (#897) * replaced manual pre-warming with orb * removed appleTV from prewarming list * removed duplicate source file * added test timeouts * added artificial wait before running storekit tests * made the artificial wait run only once * removed unnecessary param * moved the `Self.hasWaited = true` line above, removed unnecessary parenthesis * doubled the wait time just in case, made it a static let. * doubled initial wait time again * removed another instance of `wait_for_simulator:true` * Temporarily disable sk2 purchases (#898) * added a feature flag to disable SK2 temporarily * fixed tests * Show Manage Subscriptions public API (#896) * fix rebase issue * fixed rebase issues * Re-enable macOS builds (#923) * updated xcode version to 13.1.0 * re-enabled macOS builds, re-added API tester for macOS * Merge main into storekit_2 (#930) * Begin Refund Request (#924) * Fix/explicit errors on tasks (#940) * replaced `Task.init` with `_ = Task<Void, Never>`, so that if the contents of the task throw, the compiler forces us to handle the exception * added link with explanation to the swift style guide * Fix: storekit 2 tests on older OS versions (#951) * removed duplicate line for devices * fixed tests for older os versions by not storing SK2 types directly in the tests target. * fixed copy/pasta * merged main into sk2 (#952) * improvements from PR comments * more improvements from PR comments * even more improvements from PR comments * more improvements from PR comments * updated to use the new lock * removed outdated comment * added missing cases to switch * refactor to pass in the systemInfo to productsManager, and to reuse existing instances for intro eligiblity * made useStoreKit2IfAvailable an instance variable instead of static * added test cases for fetching from optimal sk with different sk version preferences * fixed instance of the wrong method being called from overriden `setUpWithError` * oops, fixed missing `try` * added more detail to fatalError message when sk version can't be determined * split tests for `TrialOrIntroPriceEligibilityChecker` into SK1 and SK2 * fix merge conflicts Co-authored-by: Cesar de la Vega <cesarvegaro@gmail.com> Co-authored-by: beylmk <maddie@revenuecat.com>
Magic Weather SwiftUI - RevenueCat Sample
Magic Weather is a sample app demonstrating the proper methods for using RevenueCat's Purchases SDK. This sample uses only native platform components - no third-party SDKs other than the Purchases SDK.
Sign up for a free RevenueCat account here.
Requirements
This sample uses:
- SwiftUI
- Xcode 12.2
- iOS 14
- Swift 5
See minimum platform version requirements for RevenueCat's Purchases SDK here.
Features
| Feature | Sample Project Location |
|---|---|
| 🕹 Configuring the Purchases SDK | Lifecycle/MagicWeatherApp.swift |
| 💰 Building a basic paywall | Views/PaywallView.swift |
| 🔐 Checking subscription status | Views/WeatherView.swift |
| 🤑 Restoring transactions | Views/UserView.swift |
| 👥 Identifying the user | ViewModels/UserViewModel.swift |
| 🚪 Logging out the user | ViewModels/UserViewModel.swift |
Setup & Run
Prerequisites
- Be sure to have an Apple Developer Account.
- You must join the Apple Developer Program to create In-App Purchases.
- You must sign the Paid Applications Agreement and complete your bank/tax information to test In-App Purchases.
- Be sure to set up a Sandbox Tester Account for testing purposes.
- Add your App-Specific Shared Secret to RevenueCat. If you don't have a RevenueCat account yet, sign up for free here.
- Be sure to set up at least one subscription on the App Store and link it to RevenueCat:
- Add the product (e.g.
rc_3999_1y) to RevenueCat's dashboard. It should match the product ID on the App Store. - Attach the product to an entitlement, e.g.
premium. - Attach the product to a package (e.g.
Annual) inside an offering (e.g.saleordefault).
- Add the product (e.g.
- If you're testing on a simulator instead of a physical device, be sure to set up your StoreKit configuration files.
- Get your API key from your RevenueCat project.
Steps to Run
-
Open the file
Magic Weather SwiftUI.xcodeprojin Xcode. -
On the General tab of the project editor, match the bundle ID to your bundle ID in App Store Connect and RevenueCat.
-
On the Signing & Capabilities tab of the project editor, select the correct development team from the Team dropdown.
-
In the
Constants.swiftfile:- Replace the value for
apiKeywith the API key from your RevenueCat project. - Replace the value for
entitlementIDwith the entitlement ID of your product in RevenueCat's dashboard. - Comment out the error directives.
- Replace the value for
-
Build the app and run it on your device.
Example Flow: Purchasing a Subscription
- On the home page, select Change the Weather.
- On the prompted payment sheet, select the product listed.
- On the next modal, select Subscribe.
- On the next modal, sign in with your Sandbox Apple ID.
- On the next modal, select Ok.
- Return to the home page and select Change the Weather to see the weather change!
Purchase Flow Demo
Support
For more technical resources, check out our documentation.
Looking for RevenueCat Support? Visit our community.