How do I distinguish between for consumeable products and for products that aren't consumed? - in-app-billing

I used 'com.android.billingclient: billing: 2.0.3'.
How do I distinguish between for consumable products and for products that aren't consumed?
Consumables are approved for purchase with consumeAsync() and non-consumable products are approved for purchase with acknowledgePurchase().
It seems like consumable products and non-consumable products are classified through whether consumeAsync() is called or not.
1. Are there other methods of classification?
(https://developer.android.com/google/play/billing/billing_library_overview#acknowledge/)
2. acknowledgePurchase () is directed to apis for non-consumable products. Shouldn't it be used for consumable products?
I can add a developer paylaod this way:
For consumable products, consumeAsync() takes a ConsumeParams object that includes a developer payload field, as shown in the following example:
BillingClient client = ...
ConsumeResponseListener listener = ...
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(/* token */)
.setDeveloperPayload(/* payload */)
.build();
client.consumeAsync(consumeParams, listener);
For products that aren't consumed, acknowledgePurchase() takes an AcknowledgePurchaseParams object that includes a developer payload field, as shown in the following example:
BillingClient client = ...
AcknowledgePurchaseResponseListener listener = ...
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(/* token */)
.setDeveloperPayload(/* payload */)
.build();
client.acknowledgePurchase(acknowledgePurchaseParams, listener);
(https://developer.android.com/google/play/billing/billing_library_overview#attach_a_developer_payload)
3. Do you plan to add management type for consumable and non-consumable products in the future?
4. Could the call be restricted for mistyped functions?

Google Play doesn't have the knowledge of consumable SKUs vs non-consumable SKUs. Only developers have this knowledge.
If you would like users to repeated purchase one SKU (like coins, gems), then you can call consumeAsync() to remove it from user's library. Google Play won't allow users to repurchase a SKU if it is already in his library. Therefore, you have to consume it (remove it from his library).
For some other SKU, such as subscription or ads free, premium content unlock, limited item, if you want users only buy once then don't consume it. Instead, use acknowledgePurchase API. Google Play introduced this as a contract to make sure that you have granted the products to users.
Therefore, I would say keep a catalog of consumable, non-consumable SKUs on your side. And based on the type, call the correct Google's API.

For what I understand so far,
non-consumable product call acknowledgePurchase() is to set the purchase record to acknowledged in Google side, so when u trying to trigger queryPurchase(), it will show the product is purchased with acknowledged (parse the json data to view the data)
consumable product call consumeAsync() is to remove the data in Google side. So when trigger queryPurchase() should be no record for that.
Why consumable product can purchase again?
Because the record ady removed from the record. When trigger purchase again will not return error code 7 (BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED)
both consumeAsync() and acknowledgePurchase() also will set the payment to done. If didn't trigger anyone of them, then it will auto refund after 3 days. Both of the action also work as acknowledge the payment.
So for your question
1. Are there other methods of classification?
Those acknowledged one should be non-consumable product, since consumable product record should be removed after success record to our side. Or if want to classify, maybe can set developer payload for the acknowledgement(can't changed after set)
2. acknowledgePurchase () is directed to apis for non-consumable products. Shouldn't it be used for consumable products?
no, use it separately based on your requirement
The answer maybe incorrect. Just some sharing about it.
welcome to answer my question also related to this, acknowledgement perform at server side
Server side can do something similar to mobile side comsumeAsync() in Google Billing Library?

Related

StoreKit2 to validate purchase of paid-app

I have a paid-up-front app in the Mac App Store, and I want to verify that the user purchased the app legitimately by verifying the receipt. The StoreKit2 framework (introduced with iOS15/macOS12) claims to have an easy way to do this, but I can't get it to work. From the documentation I've seen, I believe the Transaction.currentEntitlements call will only return transactions for IAP and subscriptions. There is another method Transaction.all which says it "returns all transaction history", but it's not clear if it should include transactions for paid apps. I've tried running the app (with Xcode debugger attached) I get no results.
Here's how I'm calling it:
for await result in Transaction.all {
guard case .verified(let transaction) = result else { continue }
print("verified product = \(transaction.productID)")
}
But I get nothing printed in the console when I run this.
This is what the documentation says about Transaction.all:
This sequence returns the user’s transaction history current to the
moment you access the sequence. The sequence emits a finite number of
transactions. If the App Store processes new transactions for the user
while you’re accessing this sequence, the new transactions appear in
the transaction listener, updates. The transaction history doesn’t
include finished consumable products or finished non-renewing
subscriptions, repurchased non-consumable products or subscriptions,
or restored purchases.
Even after reading this, I'm not 100% sure if paid apps transactions should show up in the transaction history or not.
Can anyone clarify this? If it should show paid apps in the history, what's the best way to test this out during development (before it's actually in the App Store)?

How to implement auto renew subscription in app billing google play

I'm researching method to implement auto renew subscription in app billing with google play. I read https://developer.android.com/google/play/billing/billing_subscriptions.html and see
Billing continues indefinitely at the interval and price specified for the subscription. At each subscription renewal, Google Play charges the user account automatically, then notifies the user of the charges afterward by email. For monthly and annual subscriptions, billing cycles will always match subscription cycles, based on the purchase date. (Seasonal subscriptions are charged annually, on the first day of the season.)
When the subscription payment is approved, Google Play provides a purchase token back to the purchasing app through the In-app Billing API. Your apps can store the token locally or pass it to your backend servers, which can then use it to validate or cancel the subscription remotely using the Google Play Developer API.
So have any method to my server know when user's subscription was renewed? Instead of google play send new bill subscription to android app after that android app send this new bill to my server just for validate.
Can google play send a notify to my server when user's subscription renewed such as notify the user by email ? I want to google play send me a notify that user's subscription was renewed automatically so that my backend will update expire their subscription in app increase. Don't need android app have to check bill each time user open store to check have new bill from goole play charge automation or not. Do it implement?
My workfollow
Google charge a new cycle subscription and notify to my server { body such as bundId, bill, product_id or subscription package name, expire date...), also sent mail to user about their subscription automation renewed.
My server determine change subscription of the user and validate in app purchase by google play api and change expire package subscription in your app if validate is valid.
Store newest bill in my db
Is that possible?
[Update] Recommend from goolge play api doc
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.
How to implement recommend from google api, any doc or tutorials ?
I have currently exactly the same problem. The concept of Google is not well-conceived. There is a possibility to notify your backend server about financial transactions (see here), but I would not recommend this. You rely your business transactions on a lot of Google services and your server uptime. If anything goes wrong or is down or something, you will not be informed and your backend business logic does not work anymore.
This recommendation of Google you mentioned sucks as well. What happens if there is an auto-renawal (which delivers a new purchaseToken to your app) and the user never opens your app. Then the new subscription data will never be transferred to your server. And if you never got a new token, how can you check, if the user is still a subscriber, since this limited Google Play Developer API stupidly needs a purchaseToken as parameter (see here) that you never get as long as the user does not open your app at least once after an auto-renewal (to submit it to your server).
I think about implementing this in this way:
1.) I continuously check the purchase records by cron job. A purchase record is a database entry which contains all data from the initial subscription (orderId, purchaseToken, and so on, all that is needed for the security validation process on the server). Every purchase record is connected to a user's account (some UserID) in my backend system. As long as the autoRenewing attribute of the purchaseRecord is not false, the subscription is valid. Even if the expiryTimeMillis is exceeded, this one user could still have a valid subscription, because of the use case I described above: Subscription will be auto-renewed by Google, but the user never opens the app, so no transfer token is sent to your server and you are still not informed about the subscription update.
2.) If the use cancels his subscription any when, the autoRenewing would be false at any time. That means that the subscription will indeed end at the expiryTimeMillis.
3.) When the user opens your app and transfers the new purchaseToken to your backend, you will get a new purchase record which is again connected to the user account with his User ID. The user will probably have 2 purchase records now. The old one and the new one. If so, you could delete the old one, and the same process repeats with the new purchase record at step 1.
I didn't have implemented the concept so far, so I don't know if this really works like this. Maybe this could work in a different manner, but maybe it's a step into the right direction.
I don't think, relying upon daily basis cronjob is a feasible way to go about this problem, It is messy and you have to also consider the case when your application is handling too many requests, you have a limit of transactions that made using android developer's api. The better way to implement it would be to use google's recommendation. Which stats:
...
Note: Due to quota restrictions, it is not recommended to check state by polling the Google Play Developer API at regular intervals instead of leveraging Real-time developer notifications.
...
Here, You can follow the following url
How to get expiry date for Subscription with client side in Android? and to implement the auto-renewal subscription.

How to share In-App purchase data between two iOS apps?

I want to share In-App purchased product identifiers from one app(say "App1") to another app(say "App2"). Both run on iOS 7 devices. And more importantly since "App2" was released long time back, both the apps have different Team IDs. When the user clicks on a "Restore purchase from App1" button I want "App2" to unlock certain features based on the purchases the user has made in "App1". What is the best way to achieve this?
I dont want to use UIDocumentInteractionController or UIActivityViewController because that would require unnecessary user interaction.
Key chain items or iCloud key-value storage cannot be shared because both the apps have different Team IDs.
Can't use an exclusive server through which the two apps can communicate.
You cannot do this by using the IAP API. You could store the information on your server and unlock it for a user, however, this is against the App Store Review Guidelines:
Apps utilizing a system other than the In-App Purchase API (IAP) to purchase content, functionality, or services in an App will be rejected.
And technically you would not be using the API if you checked against your own server and provided the content through that.
Now this looks possible for subscriptions with App Bundles: https://developer.apple.com/documentation/storekit/in-app_purchase/offering_a_subscription_across_multiple_apps
You can offer customers auto-renewable subscription services that are accessible through multiple apps across one or more operating systems.
In order to offer this functionality, your server must grant access to the subscription content across all apps, despite the user having purchased the subscription within a specific app. You can use a unified account management database along with server-side receipt validation to validate a user's purchase and ensure in-app transactions are handled. By entitling subscription access from your server, you can provide users the ability to access your subscription across multiple apps.
It's Possible using Authentication API
step 1: When purchased product successfully to store status inside API
step 2: Then call API every time of didFinishLaunching to check purchase status and use multiple APP
Another benefit is make payment without any payment gateway...

Switching from a paid app to a free app with auto-renewing subscription

I have an app which costs $5. I'd like to change this so that the app is free and that users must purchase an auto-renewing subscription to use it. I know how to implement the auto-renewing subscription, but the problem is dealing with users who have already bought the app for $5; I'd like to continue letting these users use my app without a subscription.
The rub is that for privacy reasons I can't store any identifying information on my server which link an account for my app to a specific person (not even UIDID). What I can do is maintain a separate database table which links UIDIDs to subscription purchase receipts which will allow me to know if a user has a subscription.
So my question is, how can I identify users who got my app when it cost $5? I know there's a way to restore in-app purchase receipts, but is there a way to to retrieve a receipt for the initial purchase of the $5 app which I could store on my server?
The poor man's solution is just to mark all current UIDIDs (i.e. the UIDIDs of people who have paid $5) in my server as paid, but then they would have to buy a subscription if they ever wanted to use my app from a different device.
The previously selected answer is outdated. The new answer is that it is possible today with the new receipts that were standardized this year (2013).
The receipt now has two additional fields: original_application_version and original_purchase_date which can be used to detect when a user purchased and therefore be used to guide logic around what users should get what features.
You can see more about 10 minutes in here: http://devstreaming.apple.com/videos/wwdc/2013/308xex4x6ybggtlw4ztv0sg5btp/308/308-SD.mov?dl=1
or if that link dies here: https://developer.apple.com/wwdc/videos/ and search for Using Receipts to Protect Your Digital Sales.
Chaning your business model like this is not very well supported by the App Store.
Your "poor mans" solution is probably one of the best of a poor set of options.
Another one would be to switch to a new app entirely (just a different bundle ID in practice). Anyone using your old app would have paid, regardless of which device they use. Anyone using the "new" app would need a subscription. Obviously you'd lose any reviews and possibly external links that you currently have.

In app auto-renewable subscriptions

Sorry for the millionth question about iTunes subscriptions, but I still have a few doubts.
Basically I'm implementing auto-renewable subscriptions in my app and I want to make sure I got it right. Here's a list of steps to take that I came up with:
whenever an user buys a subscription, send the receipt to the server to validate it
if the receipt is valid, save it on the database
on application load, ask the server if a receipt for this UDID exists (this is to figure out if the user has a valid subscription)
if so, check if a new item has been added on the store in a date range from the subscription start date to the expire date
if any, notify the user about those items in some way and mark them as freely downloadable
Are these steps correct? And if so, why does the Apple doc say:
In most cases, your iOS client application should not need to change. In fact, your client application is now made simpler, as you can use the same code to recover auto-renewable subscriptions as you do to recover nonconsumable products. This is described in “Restoring Transactions.”Your application receives a separate transaction for each period of time where the subscription was renewed; your application should verify each receipt separately.
To me it looks like this needs some code to handle all the various cases I mentioned, instead. Or I'm totally wrong about it. Am I?
Plus, how do I know about the subscription expiration date? I can't find a way to get this information anywhere. Am I supposed to save this on my own database?
Update:
I've figured out a few things since I posted this question. Feel free to correct me if I'm wrong.
First of all I guess I'm supposed to store the length of the subscription somewhere on my own database, because as stated on Apple's docs, you cannot retrieve it in any way through Apple's web services. In fact, each subscription length has a different product identifier, so you should have a way to convert a product identifier to a subscription length.
Also, Sylvian has posted details about his implementation of auto-renewable subscriptions, so at least I know my thinking wasn't too much flawed.
Now the only problem is this: how do I know that an user has a valid subscription? I could store this information on my server, yeah, but how do I associate an user with a completed transaction? Should I save the device's UDID?
Here is how we implemented In App Purchases and specifically the new auto-renewable products at my company.
The application transmits the transaction receipt to our webservice, we return OK to the application if we handled it correctly and Apple could verify it. In that case we updated the user account (i.e. the database) to say "yes he has paid and his subscription is valid till the receipt expiration date".
After the OK for this webservice, the application reloads the account info through another webservice, and see there is a valid subscription. That was it... Until auto-renewable products appeared.
We now had to implement some CRON jobs which runs every day: every day we make a list of passes which are supposed to expire, and we ask Apple if the original receipt is still valid: the magic thing is that in their answer, there is a field latest-receipt which embeds the latest receipt. If it is not the same as the one we have, we understand that the subscription has been renewed automatically, we store the latest receipt for the next cron check, and we update the user account to extend the expiration date.
Hope it helps.
I think I found a solution. It doesn't require an additional username/password and it seems to be working.
Note: If you think this is inappropriate, please explain why in the comments. Thanks.
Basically, whenever an user buys a subscription, I validate the receipt against my server and store the receipt data in the user defaults. Then, when the app is opened, or whenever I need to check if the subscription is still valid, I retrieve the previously saved receipt data from the user defaults and validate it against the server.
My webservice just returns whether the subscription is still valid or has expired, plus some other related information such as the subscription length. To do this, it just queries the iTunes server as usual, and checks if the status response is nonzero. 21006 means that the subscription has expired.
If your app has some user management i.e. you use username/password to use the app, then you have to maintain a server to record the purchase/validity of the currently logged in user. This is applicable for normal subscription and non-consumable purchase. But... if you use the new auto-renewable subscription, then it's NOT possible to maintain multiple user in that app, because : this kind of purchase can not be done multiple times within the subscription period using the same Apple ID from the same application and I found it really annoying and finding a better solution for this case i.e where I have multiple child account in the app but I want to use the same Apple-Id to purchase a auto-renewable subscription for each account. And I think I have to use the old subscription model. Any new thoughts ?
as far as I have understand it the apple server will contact you (or the customer with his iPhone) and tell "look here I have a valid purchase for you". Inside your App you read this message and unlock the regarding content for use. The next step is to tell the apple server that you have responded to the receipt and the apple server will not show the message again.
So with a renewable subscription you get for each period a new message. Correct me if I'm wrong, please.