Solved

Setting up a Consumable in-app Purchase Architecture

  • 1 September 2021
  • 4 replies
  • 1129 views

Badge +1

I am new to RevenueCat and I am looking for advice on how to architect my consumable in-app purchases with ReveneCat. With the current app I am developing for macOS, I use the AWS Polly service and each usage of Polly costs money (pay as you go). I am using consumable in-app purchases to control my cost structures from users so that I will always make a profit no matter the overall customer usage. One requirement is fiscal security where the user can't spoof/hack the consumable resources on device, so I need to store their current resource count in the cloud. I read the following in the ReveneCat help pages.

Non-Subscription Purchases:

It's important to note that at the moment, logic for keeping track of consumable redemptions must be handled outside of RevenueCat. We recommend your server is set up to receive Webhook events for NON_RENEWING_PURCHASE to appropriately provide consumable content for your users.

For example: RevenueCat can track a consumable coin purchase and include it in the purchaserInfo, but cannot track if you've granted a user the appropriate number of coins for that purchase.

If I understand this correctly, it means I need an external server to process and store the current consumable count for each user. I also need to be able to process refunds (webhooks?) in order to properly reduce the user's current resource count and prevent fraudulent abuse of the in-app purchase. So what are the pitfalls I should look out for when setting this system up?

As a side note, I am leaning towards using AWS Lightsail for about $20 a month (including the database) for my backend server. It's cheap and scalable. Are there alternative suggestions for a server backend?

icon

Best answer by cody 8 September 2021, 22:58

View original

4 replies

Userlevel 6
Badge +8

Hey @Brendan Murphy! đź‘‹

If I understand this correctly, it means I need an external server to process and store the current consumable count for each user. I also need to be able to process refunds (webhooks?) in order to properly reduce the user's current resource count and prevent fraudulent abuse of the in-app purchase. So what are the pitfalls I should look out for when setting this system up?


This is correct- you’ll need to have your own server to be the source of truth for your consumable count that responds to webhook events from RevenueCat. Webhooks are sent for NON_RENEWING_PURCHASE as well as REFUND, so that should be enough in itself to keep track of the consumables (from the financial/purchase side of things).

You’ll also then need to manage the “redemptions” on your end with some kind of custom transaction system, but this is generally out of the scope of RevenueCat.

As a side note, I am leaning towards using AWS Lightsail for about $20 a month (including the database) for my backend server. It's cheap and scalable. Are there alternative suggestions for a server backend?


I’m not sure I can personally speak to this one- there are a ton of options out there, but AWS definitely is a good one for the reasons you have here and would probably be a great choice. You could use something like Heroku or a droplet on DigitalOcean, but it will definitely come down to personal preference.

I'd go for the following (planning to implement it):
I would have the complete purchase trigger some kind of UI refresh to display the new total of credits. 

The main issue is is that there is no easy way of knowing when a webhook completes, you'd have to implement some kind of polling logic, or just make assumptions and live with the fact that it would work 95% of the times.

Badge

I'd go for the following (planning to implement it):
I would have the complete purchase trigger some kind of UI refresh to display the new total of credits. 

The main issue is is that there is no easy way of knowing when a webhook completes, you'd have to implement some kind of polling logic, or just make assumptions and live with the fact that it would work 95% of the times.

Thank you for the reply and your thoughts on this!
If this is actually the case and no better solution is possible, I personally don’t see a benefit in using a webhook for my case as currently the only possible way of not being in sync with the purchase is that the app crashes right in between the purchase flow completing and the cloud function being triggered.

Badge

Hey @Brendan Murphy! 👋

If I understand this correctly, it means I need an external server to process and store the current consumable count for each user. I also need to be able to process refunds (webhooks?) in order to properly reduce the user's current resource count and prevent fraudulent abuse of the in-app purchase. So what are the pitfalls I should look out for when setting this system up?


This is correct- you’ll need to have your own server to be the source of truth for your consumable count that responds to webhook events from RevenueCat. Webhooks are sent for NON_RENEWING_PURCHASE as well as REFUND, so that should be enough in itself to keep track of the consumables (from the financial/purchase side of things).


Hey @cody I am currently implementing consumables in our production app and have a quick question which is appending to this one since it’s related and maybe not worth its own thread but let me know if I should open a new one instead:

The only thing I still don’t get about using webhooks is how it would work from a UX perspective.
My current implementation will trigger a cloud function once a user-initiated purchaseStoreProduct() functions successfully returns. That cloud function will update the database with the obtained consumable and returns the updated consumables to the UI once it was successful, presenting the item.

If I would now use a webhook, that would mean that I would not call anything after a user-initiated purchaseStoreProduct() functions successfully returns but instead revenuecat would call that earlier mentioned cloud function right? - but then how would the user get the updated consumables as the user did not trigger the cloud function and therefore does not get the actual state?
We could have a real-time listener to the database but then we couldn’t show a loading state for the time everything processes because we’re not actually waiting for the return of the cloud function. What is the best-practice here?

I didn’t find much helpful information for that case so any insights are highly appreciated!​​​​​​​

Reply