We have a special business/premium model, and we need help migrating our model to a flutter app which uses IAP.
Currently, our system works as follows:
Users can purchase "packages" through Stripe. Each package contains one or more "digital accesses" and we send a package redemption ID via email. On our site, users can redeem the package (once they receive the email), and we credit the digital accesses to their account.
Digital access has the following properties:
moduleName - The user gets access to this module
durationInDay - From the redemption, this will be the duration.
I think the following would be the best way to extend our business model with IAP:
We consider every successful subscription-related transaction as a package purchase, but this time the user does not need to redeem the package. Instead, we directly credit the package to their account. We set the appUserId to our user's unique identifier (UUID) for every user.
There should be a Revenue Cat endpoint where we can query all previous transactions of a subscriber (every transaction should have a unique ID), and we can sync the payments. When we get the transactions, we find those that have not been synced in our database. Then, we credit the package to the last seen appUserId and store it in a <transactionId, appUserId> format in the database. Let's call this mechanism "sync-with-rc" on our end.
We also need another endpoint, "restore-purchase," on our end. This endpoint queries all previous transactions of a user from Revenue Cat and finds active subscriptions.
After that we revoke access based on <transactionId,appUserId> pair, and set the new app user id for transaction.
Purchase:
1. call purchaseProduct of SDK
2. call syncPurchases of SDK (send the new receipt to RC)
3. then call sync-with-rc endpoint
Restore purchase:
1. call restorePurchase of SDK (this will sync receipt and transfer the subscription in RC if needed)
2. call restore-purchase endpoint
Renewal:
We can receive this event via webhooks and credit the package to the last seen appUserId. If our server is not available (therefore, the package is not credited), the user can restore their purchase using the described method.
Unfortunately we cannot do that, because the /subscribers endpoint does not return the user’s transactions.
This is the way what we found to solve this problem:
Use webhooks.
Purchase:
1. call purchaseProduct of SDK
2. RC call our endpoint (webhook), and we credit the package directly to the user.
Restore:
1. call restorePurchase of SDK (this will generate a webhook event if a transfer happened)
2. We revoke accesses (with transferred_from), and credit package to user ids. (transferred_to). Btw I don’t really understand, on what transferred_from and transferred_to values depend?
Renewal:
1. RC call our endpoint, and simply credit the package to user
Everything seemed to be fine until our server not receive the RC webhook. (for any reason, network, maintenance)
When a user makes a purchase and our server is not available, the user is unable to restore their purchase because in this "webhook way", the restore only works if the platform user has a subscription under another app user ID. (This will generate a transfer event) but in this case, we are simply out of sync.
As you can see I’m trying my best, but I don’t know how to deal with this problem correctly.
I would gladly accept any help or guidance.