How to design optimal Google Play Billing flow? - android

I started to implement Google Play Billing flow (Subscriptions only) for simple use cases but surprisingly there are quite limited articles showing how to do it in an optimal way. ClassyTaxi example (https://github.com/android/play-billing-samples/tree/3f34105c34e2ed2e88055ccf2b04088e8a5fd3a2/ClassyTaxiJava) is in my opinion over-complicated and mix some functions (e.g. acknowledging by Android app instead on back-end server).
Simple case:
App is built around Firebase services (Auth, Firestore, Cloud Functions, etc.)
Subscriptions are linked to the App user
Only one subscription type (Premium access), billed monthly or yearly
My billing flow for new purchases:
Android app starts BillingClient based on the subscription billing frequency chosen by the user
After successful payment processing, BillingClient sends a notification via RTDN/PubSub
Cloud Function processes that notification gets all Purchase data (Purchases.subscriptionsv2:get), verify it, stores in Firestore ("PurchasesCollection") with userId, and acknowledges
(Optional) Send FCM notification to all user devices about SubsctiptionState change
Android app listens "PurchasesCollection" to react to any Purchase change
With this approach, the Android app is just listening to Firestore changes and not making any Purchase processing activities as all of them are done on the server side.
In case of any Purchase changes (cancellations, pausing, expiring, etc.) Cloud Function will receive notification via RTDN and updates existing purchase, so the Android app will always get the most recent Subscription status and data.
Are there any drawbacks or security issues I didn't take into account?
In case the Android app just needs to confirm if a user is entitled to receive Premium access would it be sufficient to make a simple check expiryTime = Future (for at least one purchase from the list of all users' purchases)?
What is the most optimal and secure flow for this simple case?

Related

Get iOS/Android subscription status for all subscribed users?

I'm (re) building an app for iOS and Android that has an existing subscription model (monthly and annual) through IAP.
There's already an existing app which has users subscribed, for the rebuild i'm reusing the current product/subscription IDs in Google Play Console/App Store Connect.
I'm using Cognito for login and when a (new) user subscribes I have a webhook setup that listens for events from the respective store and stores the subscription status as a claim against the user. This also works for when a user cancels/modifies their subscription, i'll get an event to the webhook and update the backend accordingly.
My problem however, is this
I need to migrate any existing users with existing subscriptions across to my new app, to for this to be a success I need:
A list of users that have an active subscription using the existing subscription/product IDs
Once I have this I can create users in Cognito and ensure their subscription status is correct, is there an endpoint/approach for each platform that allows me to get a list of users with an active subscription? Alternatively is there any event I can hook into from the subscriptions/purchases webhook that would allow me to do this?
The key is I need to make sure that any existing users that login have their subscription on the new app and for this to happen I need to know their current subscription status so I can store it against them in Cognito.
Any help is greatly appreicated

google play in-app purchase notification for pub/sub topic

I'm trying to implement the backend of payment processor with google play in-app billing.
Google play billing api is tottally built for serveless scenario and is being a hell of a work to make it work for a normal world situation where apps have backends that need to validate and process payment logic.
i'm following this tutorial: https://developer.android.com/google/play/billing/getting-ready#configure-rtdn
but only after implementing the whole logic i read the small line
Real-time developer notifications (RTDN) is a mechanism to receive
notifications from Google whenever there is a change in a user's
entitlement within your app. RTDN leverages the use of Google Cloud
Pub/Sub, which allows you to receive data that is either pushed to a
URL that you set or is polled using a client library. These
notifications allow you to react immediately to subscription state
changes, avoiding the need to poll the Google Play Developer API. Note
that inefficient use of the Google Play Developer API can lead to API
quota restrictions.
so my logic integration is well done, the test message in play console works but google play billing is not sending the real notifications because my app deals with in-app products and not with subscriptions
then i read this tutorial https://developer.android.com/google/play/billing/rtdn-reference and it says
Note: A OneTimePurchaseNotification is sent only for some types of
one-time purchases. For more information, see Integrate.
but the link that was: https://developer.android.com/google/play/integrate goes to 404
does anyone know how to make google play console send notification for payment status on in-app purchases?
also how to get notifications for refunded purchases
OneTimeProductNotification was introduced in 2019-05-07 and its main purpose of handling cash purchases
https://developer.android.google.cn/google/play/billing/release-notes#release-2_0
As release notes says:
"This notification type is sent only for purchases associated with delayed forms of payment, such as cash"
+1 for your question becuase this is a weird scenario with lack of docs from google.
When I tested the notification from google play console by clicking "Send test notification" it works, but when I'm trying do so from my android app using testing client billing IT DOES NOT WORK!
but this screenshot says that
...for updates to your in-app products and subs...
In order to get refund purchases, you can try Voided Purchases API
The Google Play Voided Purchases API provides a list of orders that are associated with purchases that a user has voided. You can use information from this list to implement a revocation system that prevents the user from accessing products from those orders.
This API applies to one-time in-app orders and App Subscriptions.
A purchase can be voided in the following ways:
The user requests a refund for their order.
The user cancels their order.
An order is charged back.
Developer cancels or refunds order. Note: only revoked orders will be shown in the Voided Purchases API. If developer refunds without setting the revoke option, orders will not show up in the API.
Google cancels or refunds order.
Just copy and paste the below line of code to the permissions input box and then add this to the members.
google-play-developer-notifications#system.gserviceaccount.com
Next give permission to pub/sub publisher and you are good to go.
The mistake you would have done is you would have added a service account already present in your google cloud account which is not correct.
Above solution works perfectly fine for me!

How to realize a google play billing subscription in an open source app?

I'm researching for developing an open source app that will get a sync feature in future.
This will be realized with Firebase Firestore. This feature should only be available to users subscribing to an abonnement via Google Play Billing.
Now, if I upload my google-services.json to my open source repo, anyone can compile the app and remove the check, whether there's an active subscription or not.
But if I don't upload my google-services.json, CircleCI can't build my project, since the file is missing.
Does anyone have experience in this matter, or some tips?
Thanks!
you should have a server for this. firebase or custom, doesn't matter, but the purchase, subscription, and renewal business rules should not be in your app providing the services based on the subscription status.
If all of the logic is in your app, without server, then you're bound to have issues with this. There's no way around that.
You should also assume that somebody will break your subscription logic (to provide free access) and the apk will be listed forever on something like apkmirror for anyone to get it.
Here's a suggested proper flow.
Server:
users need to have a login
have a list of products a user can subscribe to, with SKUs
that exist in the google play store, under your app's products
App:
app calls your server to get a list of products available for this user. you really care about getting the SKUs for this.
make request to google's billing client to get pricing for the list of SKUs
when customer purchases something using google's billing sdk, you'll get a purchase receipt object
send your purchase receipt to your server
Server:
the server will validate the purchase receipt with Google, where the server itself makes an API call to google to verify the authenticity of the receipt
if the receipt succeeds, the server returns a success code
App:
if the response from sending the receipt succeeds, then you make a new request to the billing SDK, this time to fulfill the purchase (close the transaction)
when fulfillment succeeds, call your server to notify that fulfillment is completed. send the lenght of the subscription (monthly, yearly...)
Server:
grant access to the subscription content the user just purchased
when the renewal time is up (which came from the fulfillment call), your server wakes up and calls google to renew the subscription
if renewal succeeds, user continues to have access to the subscription content
Yes, this is A LOT more work, but it is also dramatically more resilient and future proof than having a true/false flag in your app.
With that being said, if your subscriptions are $1 a year, and you expect to have no more than 10 users...then do the quick and easy way.

For subscription in Android, how to handle if client's credit card expires?

I am currently working on an application that incorporates google in-app subscriptions. It seems like google would handle most of billing and transactions, but the questions are:
1. if user's credit card is expired while the app is trying to renew a subscription, do I need to handle this case on the device or my backend server?
2. if no, would google sent notification to the user?
3. if yes, how do I check the state of user's credit card????(hopefully i don't need to)
As per the documentation:
If a recurring payment fails (for example, because the customer’s credit card has become invalid), the subscription does not renew. The
getPurchases() method does not return failed or expired subscriptions.
Recommendation: Include business logic in your app to notify your
backend servers of subscription purchases, tokens, and any billing
errors that may occur. Your backend servers can use the server-side
API to query and update your records and follow up with customers
directly, if needed.
1.Looks like it should be your server's responsibility to check with Google on daily basis or so and disable the content if subscription is not active. If payment fails due to what ever reason, Google doesn't renew the subscription automatically again, so it's as good as saying that subscription is canceled.
2.Google does notify to user.

Recurring subscriptions on Android

I've implemented a recurring subscription for Android In App Billing, but I'm wondering how the apps knows that the subscription is renewed. In testing, at least, the subscription is ended after 1 day. Will it be continued when the app is published on the store?
On iOS the testing subscription is renewed a couple of times. Enough to let you test when the subscription is renewed, but what is the best way to do this on Android?
Can I use the purchaseToken to let my server query Google Play API or do ever renewed subscription get a new purchaseToken?
In android IAP, The purchase token expires when the user manually cancels the subscription or disables the auto-renew. Otherwise, you will get a valid purchase token every time. In test mode, the tester's subscription automatically gets expired after 5 minutes but in production, it will work fine. So don't get worried about the production behavior. If you are running the app as a tester, you will get the below payment modes on the payment flow start.
You will have 2 options to test your implementation
Test Card(Always Approves)
Test Card(Always Declines)
By testing both of the cards, you can be sure about the implementation. Your app should be capable of handling both responses from IAP. If both flows goes well, You shouldn't be worried about it. You are ready to roll-out it on production. Here is the Official Docs, may help you to understand the entire flow.
If you designed custom flow to manage IAP, You can verify the IAP Token from backend using the Google Play Developer API and allow the user to consume the feature accordingly. For the custom flow, You can send custom JWT token from backend according to IAP Token expiry and set custom JWT Token exp claim. By using this method you can check the custom token is expired or not in the client-side, If it's happened so, You can fetch the new IAP token and send it to your backend. Your backend should validate that IAP token and issue new JWT token to user and cycle goes on. Let me know if you want the custom flow, I'll post it here.
You simply periodically query the Google Play server to check the items that the user own, if it is a subscription, it will reply that he/she owns it while it is active and therefore has not expired.
Do not forget to verify the signature of the received data, and much better using a server side verification
Android - protecting in app purchases with server side verification

Categories

Resources