Amazon Offering Parsing#824
Conversation
…ng for amazon vs play
# Conflicts: # common/src/test/java/com/revenuecat/purchases/common/OfferingsTest.kt # purchases/src/main/kotlin/com/revenuecat/purchases/Purchases.kt
swehner
left a comment
There was a problem hiding this comment.
Looks good - I like the approach. Small comment re: the interface
| "offering", | ||
| Store.PLAY_STORE |
There was a problem hiding this comment.
All these changes are completely unrelated, right?
There was a problem hiding this comment.
oh yeah, the test changes are left from a different approach. was waiting to update them to this one until i get sign off
| val productIdentifier = packageJson.getString("platform_product_identifier") | ||
|
|
||
| val planIdentifier = packageJson.optString("platform_product_plan_identifier").takeIf { it.isNotEmpty() } | ||
| val product = findMatchingProduct(productsById, productIdentifier, planIdentifier) |
There was a problem hiding this comment.
I think this interface is a bit strange - one difference between Amazon and Google is that Amazon just needs platform_product_identifier and that Google also needs the platform_product_plan_identifier. I would move this difference into the findMatchingProduct method.
Otherwise for any new piece of information we'll have to change the API again.
Maybe we can do findMatchingProduct(productsById, packageJson)?
There was a problem hiding this comment.
fair point... i was just trying to reuse as much code as possible but it's less future-proof.
There was a problem hiding this comment.
Yeah, since we are trying to avoid having store-specific logic here, that makes sense.
# Conflicts: # common/src/main/java/com/revenuecat/purchases/common/OfferingFactories.kt # feature/amazon/src/main/java/com/revenuecat/purchases/amazon/storeProductConversions.kt
tonidero
left a comment
There was a problem hiding this comment.
Sorry for the delay! The approach makes sense to me 👍
|
|
||
| abstract class OfferingParser { | ||
|
|
||
| abstract fun findMatchingProduct( |
There was a problem hiding this comment.
This could be protected I think?
| } | ||
| } | ||
|
|
||
| fun String.toPackageType(): PackageType = |
There was a problem hiding this comment.
And this could be private I think?
| val productIdentifier = packageJson.getString("platform_product_identifier") | ||
|
|
||
| val planIdentifier = packageJson.optString("platform_product_plan_identifier").takeIf { it.isNotEmpty() } | ||
| val product = findMatchingProduct(productsById, productIdentifier, planIdentifier) |
There was a problem hiding this comment.
Yeah, since we are trying to avoid having store-specific logic here, that makes sense.
|
@tonidero thanks for the review :) |
# Conflicts: # feature/amazon/src/main/java/com/revenuecat/purchases/amazon/storeProductConversions.kt
vegaro
left a comment
There was a problem hiding this comment.
Approach also makes sense to me. Sorry for the delay
| ?.firstOrNull() | ||
| } | ||
| return storeProducts?.firstOrNull { storeProduct -> | ||
| storeProduct.subscriptionOptions?.firstOrNull { it.isBasePlan }?.id == planIdentifier |
There was a problem hiding this comment.
The SubscriptionOptions has a basePlan property now you can now use 👇
| storeProduct.subscriptionOptions?.firstOrNull { it.isBasePlan }?.id == planIdentifier | |
| storeProduct.subscriptionOptions?.basePlan?.id == planIdentifier |
There was a problem hiding this comment.
ah yes, i hope i didn't miss anything else when merging... it seems like that was the only change to OfferingFactories since this PR...
There was a problem hiding this comment.
Yup yup, I think this is the only part of the improvements that can be used here 😇 Pretty small improvement but 🤷♂️
ee3c8d1 to
9acd764
Compare
| import org.junit.runner.RunWith | ||
| import org.robolectric.annotation.Config | ||
|
|
||
| //@RunWith(AndroidJUnit4::class) |
There was a problem hiding this comment.
i started writing these but felt like it would kinda be wasted time without AmazonStoreProduct work done..
b49189d to
cbc11a0
Compare
joshdholtz
left a comment
There was a problem hiding this comment.
This looks good to me! Just one question about some commented out tests and I think you have a commented about writing more tests but... LGTM 💪
| // private fun mockOfferingsParser() { | ||
| // with(mockOfferingParser) { | ||
| // every { | ||
| // retrieveCustomerInfo(any(), any(), false, any()) | ||
| // } answers { | ||
| // val callback = arg<ReceiveCustomerInfoCallback?>(3) | ||
| // if (errorGettingCustomerInfo == null) { | ||
| // callback?.onReceived(mockInfo) | ||
| // } else { | ||
| // callback?.onError(errorGettingCustomerInfo) | ||
| // } | ||
| // } | ||
| // every { | ||
| // cacheCustomerInfo(any()) | ||
| // } just runs | ||
| // every { | ||
| // sendUpdatedCustomerInfoToDelegateIfChanged(any()) | ||
| // } just runs | ||
| // every { | ||
| // updatedCustomerInfoListener = any() | ||
| // } just runs | ||
| // every { | ||
| // updatedCustomerInfoListener | ||
| // } returns null | ||
| // } | ||
| // } | ||
|
|
There was a problem hiding this comment.
Do these need to be uncommented or rewritten yet?
There was a problem hiding this comment.
was gonna wait until amazonstoreproduct is done!
b9450a1 to
fe5f4a7
Compare
Amazon only has a single productId (the
termSku) returned in offerings, while google has both the subId and the basePlanID. So now the way we parse offerings must split between the stores.This PR introduces an
OfferingParserandOfferingParserFactory, instantiating the correct parser from the factory upon initialization. I'd love to get some feedback on this approach before writing tests, as I think those will be a lot of work...My thoughts on other potential implementations and why i chose this one:
this is the easiest, but it breaks our general "don't have store-specific stuff in purchases" rule. see this commit as an example
this feels a bit like over-architecting to me... but i could see more complex offering parsing in the future -- for instance, if we implement sorted
SubscriptionOptions. This is the route I took in this PR.I went this route here, but it doesn't feel totally right since offering parsing doesn't communicate with the billing libraries and isn't really a "billing" thing.