TransactionPoster: don't finish transactions for non-subscriptions if they're not processed#2841
Conversation
There was a problem hiding this comment.
@tonycosentini this is ready. Just gotta change to use the real store transaction ID not the RC ID.
Also I wonder if we should restrict this by sandbox and store too /cc @aboedo
There was a problem hiding this comment.
Does non subscription here mean both a consumable and a non-consumable? 🤔
Can the answer to this be added as a comment to this function?
There was a problem hiding this comment.
@NachoSoto is your comment here still true? Or is this ready to go? I think the khepri PR has been merged, not sure whether it's been deployed
There was a problem hiding this comment.
Also...
We might wanna do it for non-renewing subscriptions as well, since they have the same characteristics as consumables in that they disappear from the receipt forever.
And lastly, non-consumables don't actually need this, do they get the same treatment?
There was a problem hiding this comment.
TODO: we discovered that they're included, so test those too:
- Integration test
- Sandbox test.
There was a problem hiding this comment.
I updated the PR, logs, and code to make this more clear. I was mixing consumables with non-subscriptions everywhere.
We might wanna do it for non-renewing subscriptions as well, since they have the same characteristics as consumables in that they disappear from the receipt forever.
And lastly, non-consumables don't actually need this, do they get the same treatment?
See TransactionPoster.shouldFinish(transaction:for:customerInfo:). That new logic is based on StoreProduct.productCategory (subscription / non-subscriptions).
We can't use ProductType because we can't determine that for SK1 products (see SK1StoreProduct.productType).
There was a problem hiding this comment.
Just a note that we could in theory distinguish between non-renewing and auto-renewing subs by mixing in the subs vs non subs distinction + expiration date != nil, but it's a non-trivial change that feels a bit more risky, and it isn't worth the effort.
|
Waiting on @tonycosentini to change transaction identifiers for StoreKit tests so we can verify this in integration tests. |
1def557 to
1e0ad6e
Compare
70ee846 to
b6c08ab
Compare
|
This should be ready. |
b6c08ab to
00215b7
Compare
Codecov Report
@@ Coverage Diff @@
## main #2841 +/- ##
==========================================
+ Coverage 86.74% 86.79% +0.04%
==========================================
Files 219 220 +1
Lines 15650 15701 +51
==========================================
+ Hits 13576 13627 +51
Misses 2074 2074
|
00215b7 to
556d11e
Compare
joshdholtz
left a comment
There was a problem hiding this comment.
This makes sense to me! I think I really have questions about if and how consumables and non-consumables are being treated here 🤷♂️ The title of the PR mentions consumables but the code refers to non-subscriptions.
There was a problem hiding this comment.
Does non subscription here mean both a consumable and a non-consumable? 🤔
Can the answer to this be added as a comment to this function?
There was a problem hiding this comment.
My head is still getting stuck here if nonSubscription means consumable or non-consumable and if they should be treated the same 🤷♂️
There was a problem hiding this comment.
yeah... I think ideal behavior is:
- auto-renewing subscriptions and non-consumables: business as usual
- consumables and non-renewing subscriptions: finish only if part of response
Current is:
- auto-renewing subscriptions and non-renewing subscriptions: business as usual
- consumables and non-consumables: finish only if part of the response
There was a problem hiding this comment.
But we should make sure the backend behaves in the same way
There was a problem hiding this comment.
Answer to this (will test to make sure), non_subscriptions include:
- Consumables
- Non-consumables
- Non-renewing subscriptions
There was a problem hiding this comment.
Updating on this comment for folks who haven't been following as closely - I believe we do now have integration tests with non-consumables and non-subscriptions, and have used them to confirm that the backend indeed sends them as the same thing, and they're safe to treat the same way.
There was a problem hiding this comment.
Should we add this to the PR description as well?
There was a problem hiding this comment.
I extracted this to #3009 so we can make that a feature and keep this as a fix.
tonidero
left a comment
There was a problem hiding this comment.
I'm a bit worried about the storeTransactionIdentifier vs transactionIdentifier nomenclature and their differences between subscriptions and non-subscriptions... Other than that, I think this is good
556d11e to
008002b
Compare
b744267 to
d867701
Compare
@joshdholtz I updated the log, PR description, and code to make that more clear. |
This will be used for #2841, but it can be useful for users as well.
d867701 to
49ed141
Compare
|
This is ready now. |
…if they're not processed
49ed141 to
3940482
Compare
This test was added in #2841, but iOS 12 can't detect offline `CustomerInfo`s because those aren't available, so this test isn't relevant there. Fixes https://app.circleci.com/pipelines/github/RevenueCat/purchases-ios/14193/workflows/a3836667-878c-4bdd-939a-e809e9f0ac5a/jobs/107291/tests
**This is an automatic release.** ### Bugfixes * `PurchasesOrchestrator`: fixed callback not invoked regression during downgrades (#3028) via NachoSoto (@NachoSoto) * `TransactionPoster`: don't finish transactions for non-subscriptions if they're not processed (#2841) via NachoSoto (@NachoSoto) ### Performance Improvements * `StoreKit 2`: only listen to `StoreKit.Transaction.updates` when SK2 is enabled (#3032) via NachoSoto (@NachoSoto) * `CustomerInfoManager`: post transactions in parallel to POST receipts only once (#2954) via NachoSoto (@NachoSoto) ### Other Changes * `PostedTransactionCache`: remove implementation (#3030) via NachoSoto (@NachoSoto) * `Integration Tests`: improved `testCanPurchaseMultipleSubscriptions` (#3025) via NachoSoto (@NachoSoto) * `GitHub`: improved `ISSUE_TEMPLATE` (#3022) via NachoSoto (@NachoSoto) * `TransactionPoster`: added transaction ID and Date to log (#3026) via NachoSoto (@NachoSoto) * `TransactionPoster`: fix iOS 12 test (#3018) via NachoSoto (@NachoSoto) * `SystemInfo`: added `ClockType` (#3014) via NachoSoto (@NachoSoto) * `Integration Tests`: begin tests with `UIApplication.willEnterForegroundNotification` to simulate a real app (#3015) via NachoSoto (@NachoSoto) * `Integration Tests`: add tests to verify `CustomerInfo`+`Offerings` request de-dupping (#3013) via NachoSoto (@NachoSoto) * `SwiftLint`: disable `unneeded_synthesized_initializer` (#3010) via NachoSoto (@NachoSoto) * Added `internal` `NonSubscriptionTransaction.storeTransactionIdentifier` (#3009) via NachoSoto (@NachoSoto) * `Integration Tests`: added tests for non-renewing and non-consumable packages (#3008) via NachoSoto (@NachoSoto) * Expanded `EnsureNonEmptyArrayDecodable` to `EnsureNonEmptyCollectionDecodable` (#3002) via NachoSoto (@NachoSoto)
…if they're not processed (#2841)
**This is an automatic release.** ### Bugfixes * `PurchasesOrchestrator`: fixed callback not invoked regression during downgrades (#3028) via NachoSoto (@NachoSoto) * `TransactionPoster`: don't finish transactions for non-subscriptions if they're not processed (#2841) via NachoSoto (@NachoSoto) ### Performance Improvements * `StoreKit 2`: only listen to `StoreKit.Transaction.updates` when SK2 is enabled (#3032) via NachoSoto (@NachoSoto) * `CustomerInfoManager`: post transactions in parallel to POST receipts only once (#2954) via NachoSoto (@NachoSoto) ### Other Changes * `PostedTransactionCache`: remove implementation (#3030) via NachoSoto (@NachoSoto) * `Integration Tests`: improved `testCanPurchaseMultipleSubscriptions` (#3025) via NachoSoto (@NachoSoto) * `GitHub`: improved `ISSUE_TEMPLATE` (#3022) via NachoSoto (@NachoSoto) * `TransactionPoster`: added transaction ID and Date to log (#3026) via NachoSoto (@NachoSoto) * `TransactionPoster`: fix iOS 12 test (#3018) via NachoSoto (@NachoSoto) * `SystemInfo`: added `ClockType` (#3014) via NachoSoto (@NachoSoto) * `Integration Tests`: begin tests with `UIApplication.willEnterForegroundNotification` to simulate a real app (#3015) via NachoSoto (@NachoSoto) * `Integration Tests`: add tests to verify `CustomerInfo`+`Offerings` request de-dupping (#3013) via NachoSoto (@NachoSoto) * `SwiftLint`: disable `unneeded_synthesized_initializer` (#3010) via NachoSoto (@NachoSoto) * Added `internal` `NonSubscriptionTransaction.storeTransactionIdentifier` (#3009) via NachoSoto (@NachoSoto) * `Integration Tests`: added tests for non-renewing and non-consumable packages (#3008) via NachoSoto (@NachoSoto) * Expanded `EnsureNonEmptyArrayDecodable` to `EnsureNonEmptyCollectionDecodable` (#3002) via NachoSoto (@NachoSoto)
This ensures that if the server returns a 200, but didn't actually process the transaction, we don't lose it forever.
When this happens, a warning will be logged:
Dependencies:
Integration Tests: added tests for non-renewing and non-consumable packages #3008internalNonSubscriptionTransaction.storeTransactionIdentifier#3009