* feat: have testing apps take RevenueCat API key and Proxy URL from local.xcconfig file
* fix wording mistakes in `Local.xcconfig.SAMPLE`
* chore: include `ConfigItem.swift` file in `verify_no_included_apikeys` check
* fix more mistakes in comments
* Introduce PurchaseParams to allow passing extra configuration info when making a purchase
* simplify naming
* fallback to old method when flag is not enabled
* Add $(inherited) to the test targets so they pick up compiler flags from Local.xcconfig
* Include product/package inside PurchaseParams
* fix tests
* add compiler flag check
* update purchase tester
* fix docs
* add tests
* Update Sources/Networking/Operations/PostReceiptDataOperation.swift
Co-authored-by: Toni Rico <toni.rico.diez@revenuecat.com>
---------
Co-authored-by: Toni Rico <toni.rico.diez@revenuecat.com>
### Description
This adds a new API `setKochavaDeviceId` that allows to set the kochava
device ID required for the Kochava integration.
Keeping on hold until backend support is added
### Motivation
Adding new method to manually sync attributes and fetch fresh offerings
### Description
- New `Purchases.shared.syncAttributesAndOfferingsIfNeeded()` method
- Syncs subscriber attributes and then fetches fresh offerings from
network
- This is designed to be a blocking call since developer will want fresh
offerings after syncing subscriber attributes
- The method is rate limited to 5 calls per minute (new `RateLimiter`
class()
---------
Co-authored-by: Josh Holtz <me@joshholtz.com>
### Motivation
New function to get `Offering` by a placement identifier
### Description
New `currentOffering(forPlacement: String): Offering?` method on
`Offerings`
- Added demo button for this in purchase tester app
```swift
// Example usage
if let offering = offerings.currentOffering(forPlacement: "onboarding") {
showPaywall(offering)
}
```
#### Logic flow
- If a placement identifier explicitly exists within the
`placements.offeringIdsByPlacement` dictionary, the method attempts to
fetch the corresponding `Offering` without resorting to a fallback
- Example: when there is a `nil` / null value for a placement, we don't
want to use the fallback
- If the placement identifier does not exist, the method then attempts
to fetch a fallback offering defined by `placements.fallbackOfferingId`
#### New placements object in offerings response
```js
{
// other offerings stuff
"placements": {
"fallback_offering_id": "offering_a", // can be null
"offering_ids_by_placement": {
"onboarding_start": null,
"onboarding_end": "offering_b",
}
}
}
```
---------
Co-authored-by: Guido Torres <guido@revenuecat.com>
Co-authored-by: Josh Holtz <me@joshholtz.com>
Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
Checking for the presence of `Xcode/DerivedData` in the receipt path was
failing for TestFlight builds or if the .app bundle generated by Xcode
was moved from the folder.
Additionally, checking for `MASReceipt/receipt` seems less robust than
simply using compiler directives.
Instead, for macOS apps, we check the environment embedded in the receipt and alternatively check the signature of the app bundle.
---------
Co-authored-by: NachoSoto <NachoSoto@users.noreply.github.com>
Apple changed `xrOS` to `visionOS` on the latest beta. Looks like this
was already supported in prior `Xcode 15.1` betas, so this doesn't break
compatibility with them.
See #2211.
If `restorePurchases` fails for any reason, we still want to try to load
the local receipt. We're only interested in refreshing the receipt to
load it.
This will help test observer mode, mimicking how an app might use
`RevenueCat` with observer mode.
When that setting is enabled, 2 new buttons will appear:

The implementation isn't the most maintainable, but we don't really need
it to be. I favored simplicity instead of over-complicating the
implementation. It's not meant to be a canonical example of the correct
way to purchase with StoreKit, just a quick way of testing this
behavior.
I added this in order to debug #2132.
### Changes:
- Extracted `Core` framework to be used by both apps
- Added new `watchOS` target
- Changed `fastlane match` to also create profiles for this new target
- Added a simple view in the watch app that displays a text if an
entitlement is active, or a `restore` purchases button otherwise
This is just a starting point, we can add more to it in the future.
#### Note:
_Unfortunately I haven't been able to test this because of an Apple bug
(`FB11873951`):_

* Initial commit of new SwiftUI Purchase Tester
* Mover to Test/TestingApps/PurchaseTesterSwiftUI and updated deprecated attribution stuff
* Undoing things here because whoops
* Updates from PR