[Experimental] Web purchase redemption#1889
Conversation
…emory until configuration
… allow processing after setting the listener
306ba28 to
c158a87
Compare
There was a problem hiding this comment.
Not a fan of the developer having to handle the deep links like this... I think there is a big chance of the developer passing us the same link multiple times (which could still happen with the approach in #1880 but less likely IMO).
There was a problem hiding this comment.
Can we keep track of what is already redeemed? E.g. by storing those tokens/urls on disk or something.
There was a problem hiding this comment.
Yes we could... Though I guess there is also a chance it's a valid use case to redeem, as in, maybe the redemption failed the first time due to a connection error or something and they need to try again. I guess we could only "cache" it if there is a successful redemption in this case, but if we for example add deep links to display the paywall in the future, there would be valid use cases of showing the paywall multiple times.
Not to say it's not ok! This approach does provide much more flexibility to the developer, but also more responsibility :P
There was a problem hiding this comment.
Yea indeed, I meant to cache successful redemptions. If only to alleviate our own backend. Paywall or other non web purchase deeplinks would indeed be excluded from this.
| @OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class) | ||
| class MainActivity : AppCompatActivity() { | ||
|
|
||
| internal var rcDeepLink: Purchases.DeepLink? = null |
There was a problem hiding this comment.
If multiple links are used continuously before redeeming each, the developer is in charge of handling each on their own... For this PoC, I'm just caching the last one used, but again, it's more logic the developer will need to handle.
There was a problem hiding this comment.
I see your point, but wouldn't they need to manage the WebPurchaseRedeemer objects in the other approach?
I'm also trying to think how much of an edge case this is. Is it realistic that a user is buying multiple things, clicking on the links for each (e.g. before being logged in in the app), and then starts a login flow and expects that all purchases are then redeemed? Let me know if you have a different scenario in mind, just trying to think this through haha.
There was a problem hiding this comment.
Yeah it's certainly an edge case... And yeah it might be ok to just leave it to the developer. We can always try to provide some code samples if devs start asking for them.
| } | ||
|
|
||
| @OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class) | ||
| override fun onResume() { |
There was a problem hiding this comment.
Could have done this on the Activity, but preferred to do it in the fragment to show how it would be to handle at the UI part of the app (whether it's using compose or fragments)
|
|
||
| @ExperimentalPreviewRevenueCatPurchasesAPI | ||
| sealed class DeepLink { | ||
| class WebRedemptionLink internal constructor(internal val redemptionToken: String) : DeepLink() |
There was a problem hiding this comment.
Made everything internal. Devs shouldn't need to build an instance of this on their own, nor access the token directly.
There was a problem hiding this comment.
Good call! What's the reason this is nested in Purchases? (Don't really have an opinion, just curious haha.)
There was a problem hiding this comment.
Mostly seemed DeepLink was too generic as a top-level class 😅 So I wanted to namespace it inside the SDK.
There was a problem hiding this comment.
Haha alright makes sense! (Devs can always use import aliasing of course.)
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1889 +/- ##
==========================================
- Coverage 82.25% 82.16% -0.09%
==========================================
Files 227 231 +4
Lines 7968 8048 +80
Branches 1121 1132 +11
==========================================
+ Hits 6554 6613 +59
- Misses 967 986 +19
- Partials 447 449 +2 ☔ View full report in Codecov by Sentry. |
JayShortway
left a comment
There was a problem hiding this comment.
I do like it! Had some naming suggestions mostly. I also think it speaks to its simplicity that it's about half the additional lines vs the other approach (342 vs 767).
I think the main decision boils down to how much we want to cater to the edge case you mentioned, and how big of an edge case that is. Let me know if you have a different take!
|
|
||
| @ExperimentalPreviewRevenueCatPurchasesAPI | ||
| sealed class DeepLink { | ||
| class WebRedemptionLink internal constructor(internal val redemptionToken: String) : DeepLink() |
There was a problem hiding this comment.
Good call! What's the reason this is nested in Purchases? (Don't really have an opinion, just curious haha.)
| @OptIn(ExperimentalPreviewRevenueCatPurchasesAPI::class) | ||
| class MainActivity : AppCompatActivity() { | ||
|
|
||
| internal var rcDeepLink: Purchases.DeepLink? = null |
There was a problem hiding this comment.
I see your point, but wouldn't they need to manage the WebPurchaseRedeemer objects in the other approach?
I'm also trying to think how much of an edge case this is. Is it realistic that a user is buying multiple things, clicking on the links for each (e.g. before being logged in in the app), and then starts a login flow and expects that all purchases are then redeemed? Let me know if you have a different scenario in mind, just trying to think this through haha.
There was a problem hiding this comment.
Can we keep track of what is already redeemed? E.g. by storing those tokens/urls on disk or something.
JayShortway
left a comment
There was a problem hiding this comment.
Amazing! Great job on this! Also good to see it's extensively tested. Had some minor comments / suggestions, but no blockers. Feel free to ignore at your discretion.
| import android.content.Intent | ||
|
|
||
| @ExperimentalPreviewRevenueCatPurchasesAPI | ||
| @JvmSynthetic |
**This is an automatic release.** ## RevenueCat SDK ### ✨ New Features * [Experimental] Web purchase redemption (#1889) via Toni Rico (@tonidero) ### 🐞 Bugfixes * Keeps the org.json package. (#1891) via JayShortway (@JayShortway) ### 📦 Dependency Updates * Bump rexml from 3.3.8 to 3.3.9 (#1892) via dependabot[bot] (@dependabot[bot]) * Bump danger from 9.5.0 to 9.5.1 (#1885) via dependabot[bot] (@dependabot[bot]) * Bump fastlane from 2.224.0 to 2.225.0 (#1884) via dependabot[bot] (@dependabot[bot]) ## RevenueCatUI SDK ### 🐞 Bugfixes * Fix application of modifiers in `Markdown` component (#1893) via Toni Rico (@tonidero) ### 🔄 Other Changes * [CI] Allow publishing snapshot releases manually from branches (#1888) via Toni Rico (@tonidero) * Detekt auto-fixes (#1886) via Toni Rico (@tonidero) Co-authored-by: revenuecat-ops <ops@revenuecat.com>
### Description This adds some new result types to a web purchase redemption: - InvalidToken - AlreadyRedeemed - Expired. This one includes additional information like the obfuscated email where a new token was/will be sent and whether that email was sent. This falls behind the experimental APIs introduced in #1889 Additionally, this renames `parseAsDeepLink` to `parseAsWebPurchaseRedemption` and removes the `DeepLink` type. This is a breaking change, but should be ok since the API is marked as experimental and not usable still by any customers.
Description
This adds experimental support to redeeming anonymous web purchases performed through RCBilling. The main API changes here are:
Purchases.parseAsDeepLinkthat parses the intent and returns a deep link if it needs to be handledPurchases.sharedInstance.redeemWebPurchasethat uses a parsed deep link to perform the redemption.DeepLinksealed class with the types of deep linksRedeemWebPurchaseListenerto listen to the result of the redemption.RedeemWebPurchaseListener.Resultsealed class with the result of the redemption.All these are currently experimental APIs