StoreKit 1: changed result of cancelled purchases to be consistent with StoreKit 2#1910
Merged
Conversation
8573da0 to
db62724
Compare
…with StoreKit 2 Fixes [CSDK-464]. Follow up to #1869. SK1 and SK2 had inconsistent behavior during cancelled purchases. - SK1 / completion-block: no `CustomerInfo` + cancelled + `ErrorCode.purchaseCancelledError` - **SK1 / `async`: thrown `ErrorCode.purchaseCancelledError`**⚠️ - SK2 / completion-block: `CustomerInfo` + cancelled + `ErrorCode.purchaseCancelledError` - SK2 / `async`: `CustomerInfo` + cancelled (not error) The output is now consistent across the board: - SK1 / completion-block: `CustomerInfo` + cancelled + `ErrorCode.purchaseCancelledError` - SK1 / `async`: `CustomerInfo` + cancelled (not error) - SK2 / completion-block: `CustomerInfo` + cancelled + `ErrorCode.purchaseCancelledError` - SK2 / `async`: `CustomerInfo` + cancelled (not error) This is of course a somewhat backwards incompatible change, but this output is now what makes the most sense based on the types. *This would only break existing code if users are relying on the existence of `CustomerInfo` alone without checking `error` or `userCancelled`. - Completion-block API: There's 2 ways of detecting cancellation, both valid and reasonable. Either checking that `cancelled` is `true`, or comparing `error` with `ErrorCode.purchaseCancelledError` - `async` API: A cancelled purchase no longer throws. This didn't make sense in SK1, because it meant that `userCancelled` was always `false` in the case that the purchase method returned.
db62724 to
8fcf133
Compare
StoreKit 1: changed result of cancelled purchases to be consistent with StoreKit 2StoreKit 1: changed result of cancelled purchases to be consistent with StoreKit 2
tonidero
approved these changes
Sep 22, 2022
tonidero
left a comment
Contributor
There was a problem hiding this comment.
I can see how this changes the behavior and users could potentially be relying in the old behavior... While I wouldn't consider it a breaking change, we should mention this prominently in the Changelog on the next release.
| ) | ||
| result = try await self.purchases.purchase(product: product) | ||
| } catch { | ||
| receivedError = error as NSError |
Contributor
There was a problem hiding this comment.
Could we replace this with a fail?
Contributor
Author
There was a problem hiding this comment.
No because it's inside of a Task so it's happening asynchronously.
There's a comment above explaining why it has to be this way:
// Need to do this async so the code below can invoke the
updatedTransactiondelegate method.
Co-authored-by: Toni Rico <antonio.rico.diez@revenuecat.com>
Contributor
Author
💯 |
NachoSoto
added a commit
that referenced
this pull request
Sep 27, 2022
**This is an automatic release.** ### New Features * 🚨 `StoreKit 2` is now enabled by default 🚨 (#1922) via NachoSoto (@NachoSoto) * Extracted `PurchasesType` and `PurchasesSwiftType` (#1912) via NachoSoto (@NachoSoto) ### Bugfixes * `StoreKit 1`: changed result of cancelled purchases to be consistent with `StoreKit 2` (#1910) via NachoSoto (@NachoSoto) * `PaymentQueueWrapper`: handle promotional purchase requests from App Store when SK1 is disabled (#1901) via NachoSoto (@NachoSoto) ### Other Changes * Fixed iOS 12 tests (#1936) via NachoSoto (@NachoSoto) * `CacheableNetworkOperation`: fixed race condition in new test (#1932) via NachoSoto (@NachoSoto) * `BasePurchasesTests`: changed default back to SK1 (#1935) via NachoSoto (@NachoSoto) * `Logger`: refactored default `LogLevel` definition (#1934) via NachoSoto (@NachoSoto) * `AppleReceipt`: refactored declarations into nested types (#1933) via NachoSoto (@NachoSoto) * `Integration Tests`: relaunch tests when retrying failures (#1925) via NachoSoto (@NachoSoto) * `CircleCI`: downgraded release jobs to Xcode 13.x (#1927) via NachoSoto (@NachoSoto) * `ErrorUtils`: added test to verify that `PublicError`s can be `catch`'d as `ErrorCode` (#1924) via NachoSoto (@NachoSoto) * `StoreKitIntegrationTests`: print `AppleReceipt` data whenever `verifyEntitlementWentThrough` fails (#1929) via NachoSoto (@NachoSoto) * `OperationQueue`: log debug message when requests are found in cache and skipped (#1926) via NachoSoto (@NachoSoto) * `GetCustomerInfoAPI`: avoid making a request if there's any `PostReceiptDataOperation` in progress (#1911) via NachoSoto (@NachoSoto) * `PurchaseTester`: allow HTTP requests and enable setting `ProxyURL` (#1917) via NachoSoto (@NachoSoto)
3 tasks
NachoSoto
added a commit
that referenced
this pull request
Apr 26, 2023
…PurchasesOrchestrator` for cancelled purchases Fixes SDK-3088 Supersedes #2447 Note that it's currently impossible to test this for SK2, so we only have SK1 tests (we have a Radar for that). The next step will be to deprecate the current API to remove the `userCancelled` property and make this the new behavior. See also #1910 for an explanation of the different return values of the purchase APIs.
NachoSoto
added a commit
that referenced
this pull request
Apr 26, 2023
…cancelled purchases (#2449) Fixes SDK-3088 Supersedes #2447 Thanks to @tonidero for doing most of this. Note that it's currently impossible to test this for SK2, so we only have SK1 tests (we have a Radar for that). The next step will be to deprecate the current API to remove the `userCancelled` property and make this the new behavior. See also #1910 for an explanation of the different return values of the purchase APIs.
NachoSoto
added a commit
that referenced
this pull request
Apr 26, 2023
…d` as `unavailable` Follow up to #2449. This is step 2 of 3 towards getting rid of `userCancelled` in purchase results. After #2449, `ENABLE_CUSTOM_ENTITLEMENT_COMPUTATION` builds no longer send `userCancelled` `true` for cancellations, and instead throw `ErrorCode.purchaseCancelledError`. To avoid users detecting cancellations looking at this property, it's not deprecated. To achieve that, I converted the `tuple` into a `struct`. This also required moving the affected `purchase` methods from `PurchasesType` to `PurchasesSwiftType`, but that's an implementation detail. The public API remains _mostly_ unchanged, with the only caveat that it's no longer possible to destructure the result tuple, so: ```swift let (transaction, customerInfo, cancelled) = Purchases.shared.purchase(...) ``` Needs to become: ```swift let result = Purchases.shared.purchase(...) ``` I updated the API tester to reflect that, as well as checking the properties of `PurchaseResultData`. As it's documented in #1910, completion block APIs already did send both `userCancelled` and the `error`, so we don't need to change those. This paves the future for a full deprecation, where we mark it `deprecated` for normal builds as well, and change the behavior regardless of the `DangerousSettings`.
NachoSoto
added a commit
that referenced
this pull request
Apr 26, 2023
…cancelled purchases (#2449) Fixes SDK-3088 Supersedes #2447 Thanks to @tonidero for doing most of this. Note that it's currently impossible to test this for SK2, so we only have SK1 tests (we have a Radar for that). The next step will be to deprecate the current API to remove the `userCancelled` property and make this the new behavior. See also #1910 for an explanation of the different return values of the purchase APIs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes CSDK-464. Follow up to #1869.
SK1 and SK2 had inconsistent behavior during cancelled purchases.
Before this PR:
CustomerInfo+ cancelled +ErrorCode.purchaseCancelledErrorasync: thrownErrorCode.purchaseCancelledErrorCustomerInfo+ cancelled +ErrorCode.purchaseCancelledErrorasync:CustomerInfo+ cancelled (not error)After this PR:
The output is now consistent across the board:
CustomerInfo+ cancelled +ErrorCode.purchaseCancelledErrorasync:CustomerInfo+ cancelled (not error)CustomerInfo+ cancelled +ErrorCode.purchaseCancelledErrorasync:CustomerInfo+ cancelled (not error)Notes
This is of course a somewhat backwards incompatible change, but this output is now what makes the most sense based on the types. This would only break existing code if users are relying on the existence of
CustomerInfoalone without checkingerrororuserCancelled.There's 2 ways of detecting cancellation, both valid and reasonable. Either checking that
cancelledistrue, or comparingerrorwithErrorCode.purchaseCancelledErrorasyncAPI:A cancelled purchase no longer throws. This didn't make sense in SK1, because it meant that
userCancelledwas alwaysfalsein the case that the purchase method returned. This also matchesStoreKit's behavior inProduct.purchase()