j3k0 / cordova-plugin-purchase

In-App Purchase for Cordova on iOS, Android and Windows
https://purchase.cordova.fovea.cc
1.3k stars 537 forks source link

Android - Some devices unable to get product info, unable to place orders. #1613

Open EEETA opened 3 days ago

EEETA commented 3 days ago

Hi, @j3k0

I'm migrating my plugin from v11.x to v13.11.1 due to Google Play requirements (upgrading Play Billing from v4 to v7). I modified my old code based on the migration doc after upgrading the plugin library.

Observed behavior

For iPhone, product info can be obtained normally. However, for Android devices, some are able to get the info while others cannot.

Project environment:

> node: v20.14.0
> angular: "1.7.9",
> cordova-ios: "^5.1.1",
> cordova-android: "^12.0.1",
> cordova-plugin-purchase: "^13.11.1",

Devices info and issues:

In China, phones cannot use Google services without rooting. But rooting may also remove some features and not be as full-featured as the original system.

image

image

I confirmed using same apk and product IDs. I don't understand why on the same phone(Redmi k50), the old version using the plugin v11 could get product and support placing orders, while the migrated new version can't get product info. If it's about product registration failure, then why the other two Android phones can get products normally?

Code

Pasted Graphic 4 image image image

This issue has puzzled me for days. Please offer your help and answer my questions.Thanks.

john290n commented 2 days ago

Hi @EEETA, Im facing the same issue on android since Im using the cordova-plugin-purchase v13.11.1 only on android because for iOS it works well. The error that Im getting when I try to register products is “Product with this id not found” and it is very weird. The products are undefined everytime. I did all needed steps:

  1. By creating products, subscriptions on the Google Play console
  2. My android app is deployed on production, I pushed a new release to closed and internal testing
  3. I logged in with the license user on my android physical device

I use React Js and capacitor.

john290n commented 2 days ago

I did research for many days, but I didn’t find anything to fix it. 😕 Please let me know if you have fixed it

EEETA commented 1 day ago

@john290n You can try the following steps one by one (best to prepare multiple Android devices):

  1. Make sure you have correctly uploaded the products to the store and successfully configured the products (the configuration may not take effect in real-time, best to configure in advance), and check their activation status.
  2. If you need to use sandbox simulated payment, the test users also need to be configured in advance for 24 hours, and it may take effect the next day. Log in to the Android test device you prepared.
  3. Make sure you have filled in any information required by Google Play (such as country/region, app details, payment information, etc.) and sent it for review.
  4. Check the versionCode of the testing package installed locally, which needs to be consistent with the version on the Google Play track.
  5. Before actually getting your custom product information, you can try connecting to the Platform.TEST in the plugin first and try to get the TEST product from the store.
    
    CdvPurchase.store.register([{
        type: CdvPurchase.ProductType.CONSUMABLE,
        id: 'test-consumable',
        platform: CdvPurchase.Platform.TEST,
    }]);

const product = CdvPurchase.store.get('test-consumable, CdvPurchase.Platform.TEST); alert(JSON.stringify(product))

 
***Following the first 5 steps, it should prove that the registration logic of your code is correct (getting Platform.TEST and PlatformAPPLE_APPSTORE normally).***

You can try the final step,
  1. getting the product from Platform.GOOGLE_PLAY.

6.1 Make sure the plugin is loaded normally after the Android app starts.

6.2 Print out CdvPurchase, CdvPurchase.store and your ProductId before store.register (make sure the log content exists and the id is consistent with the configuration on Google Play).

6.3 Execute CdvPurchase.store.initialize([..., CdvPurchase.Platform.GOOGLE_PLAY]) at the end of initialization.

6.4 You can manually store.update() to refresh the current product prices and status before executing store.get().

6.5 Make sure the id and platform parameters in store.get(id, platform) are correct.

6.6 If no problems, you should at least be able to get the product information by this point. (If still unable to retrieve, try Step 6 again with a different Android device.)



As for my Redmi k50 being unable to retrieve products, I currently suspect it may be due to an update to Google services or require further iteration of the plugin. I still have not found a solution and am waiting for answers.
john290n commented 1 day ago

Many thanks @EEETA, I will try to do all steps above!

john290n commented 1 day ago

@EEETA I tried your steps but it is not working.

These are the logs that Im getting on Android Studio:

I/Capacitor/Console: File: http://localhost/static/js/8.00a9bea1.chunk.js - Line 1 - Msg: Create CdvPurchase... I/Capacitor/Console: File: http://localhost/static/js/45.62950d65.chunk.js - Line 1 - Msg: LENGTH OF PRODUCTS I/Capacitor/Console: File: http://localhost/static/js/45.62950d65.chunk.js - Line 1 - Msg: Product Loaded: undefined I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase] INFO: initialize(["android-playstore","paid subscription"]) v13.11.1 I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.Adapters] INFO: Adding platforms: [{"platform":"android-playstore"},{"platform":"paid subscription"}] I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.Adapters] INFO: I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.Adapters] INFO: I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.Adapters] INFO: GooglePlay initializing... I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay] INFO: Initialize I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay.Bridge] INFO: setup ok I/Capacitor/Console: File: http://localhost/static/js/45.62950d65.chunk.js - Line 1 - Msg: LENGTH OF PRODUCTS V/Capacitor/Plugin: To native (Cordova plugin): callbackId: InAppBillingPlugin78179932, service: InAppBillingPlugin, action: setListener, actionArgs: [] V/Capacitor/Plugin: To native (Cordova plugin): callbackId: InAppBillingPlugin78179933, service: InAppBillingPlugin, action: init, actionArgs: [] D/CdvPurchase: sendToListener() -> ready D/CdvPurchase: data -> {} D/CdvPurchase: init() I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay.Bridge] INFO: listener: {"type":"ready","data":{}} D/CdvPurchase: startServiceConnection() I/Capacitor/Console: File: http://localhost/static/js/45.62950d65.chunk.js - Line 1 - Msg: LENGTH OF PRODUCTS D/CdvPurchase: startServiceConnection() -> Success D/CdvPurchase: init() -> Success I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay] DEBUG: Ready I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.Adapters] INFO: GooglePlay initialized. I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.Adapters] INFO: GooglePlay products: [{"type":"paid subscription","id":"1_month_premium","platform":"android-playstore"}] I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay] DEBUG: Load: [{"type":"paid subscription","id":"1_month_premium","platform":"android-playstore"}] I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay] DEBUG: getAvailableProducts: [] | ["1_month_premium"] I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay.Bridge] INFO: getAvailableProducts() V/Capacitor/Plugin: To native (Cordova plugin): callbackId: InAppBillingPlugin78179934, service: InAppBillingPlugin, action: getAvailableProducts, actionArgs: [[],["1_month_premium"]] D/CdvPurchase: getAvailableProducts() D/CdvPurchase: queryAllProductDetails() D/CdvPurchase: queryAllProductDetails() -> Query SUBS. D/CdvPurchase: queryProductDetailsAsync() D/CdvPurchase: executeServiceRequest() -> OK D/CdvPurchase: queryProductDetailsAsync() -> Success W/CdvPurchase: queryAllProductDetails() -> Query returned nothing. D/CdvPurchase: queryAllProductDetails() -> Calling listener. D/CdvPurchase: getAvailableProducts() -> Success I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay] DEBUG: Loaded: [] I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay] DEBUG: getPurchases I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay.Bridge] INFO: getPurchases() V/Capacitor/Plugin: To native (Cordova plugin): callbackId: InAppBillingPlugin78179935, service: InAppBillingPlugin, action: getPurchases, actionArgs: ["null"] D/CdvPurchase: getPurchases() D/CdvPurchase: queryPurchases() D/CdvPurchase: executeServiceRequest() -> OK I/CdvPurchase: queryPurchases(SUBS) -> Elapsed time: 29ms I/CdvPurchase: queryPurchases(INAPP) -> Elapsed time: 37ms D/CdvPurchase: sendToListener() -> setPurchases D/CdvPurchase: data -> {"purchases":[]} I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay.Bridge] INFO: listener: {"type":"setPurchases","data":{"purchases":[]}} I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay] DEBUG: onSetPurchases: [] I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay] DEBUG: onPurchaseUpdated: I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.AdapterListener] DEBUG: receiptsReady: android-playstore (1/0) I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.GooglePlay] DEBUG: getPurchases success I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.Adapters] INFO: GooglePlay products loaded: [{"isError":true,"code":6777012,"message":"Product with id 1_month_premium not found.","platform":"android-playstore","productId":"1_month_premium"}] I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.Adapters] INFO: GooglePlay receipts loaded: [] I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.AdapterListener] DEBUG: setSupportedPlatforms: android-playstore (1 have their receipts ready) I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.AdapterListener] DEBUG: triggering receiptsReady() I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase] DEBUG: Calling callback: type=receiptsReady() name=receiptsMonitor_setup reason=adapterListener_setSupportedPlatforms I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.ReceiptsMonitor] DEBUG: receiptsReady... I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.ReceiptsMonitor] DEBUG: check(0/0) I/Capacitor/Console: File: http://localhost/ - Line 3209 - Msg: [CdvPurchase.ReceiptsMonitor] INFO: receiptsVerified()

The subscription seems to be active in Google Play Console

Screenshot 2024-10-19 at 10 54 17

And here is my code in React Js:

Screenshot 2024-10-19 at 11 37 24
john290n commented 1 day ago

Im testing it locally with Android physical device, by connecting it with Wifi on Android studio

EEETA commented 1 day ago

@john290n I saw from your logs that the product cannot be loaded with the message "Line 1 - Msg: Product Loaded: undefined". Did you run the tests from step 5? You can first connect to Platform.TEST to see, if step 5 can retrieve the TEST product. Then you can try using other physical Android devices. Currently I don't have any other suggestions, I still think there may be compatibility issues between the phone itself, the plugin and Google Play.

john290n commented 1 day ago

@EEETA I tried with TEST on web browser by running the React Js on web and Im getting these results:

Screenshot 2024-10-19 at 11 45 17
EEETA commented 1 day ago

@john290n In Platform.TEST, the id and platform need to correspond one-to-one, otherwise it will show prompts such as product unavailable if set incorrectly. Among them, CdvPurchase.ProductType.CONSUMABLE type corresponds to the "test-consumable" id. If you want to test other types, you should click the link to the fifth step I provided to find the type you need. image image

Don't forget to modify the id in store.get() as well after modifying the id in store.register().

john290n commented 1 day ago

@EEETA Yes, you're right, it worked on the web. However, how can I be sure that in-app purchases with subscriptions will work in production? When I tried using the product IDs I set up in the Google Play Console with the platform set to GOOGLE_PLAY, it wasn’t working.

Screenshot 2024-10-19 at 11 59 05
EEETA commented 1 day ago

@john290n Yes, after validation, we know that the registration logic of your code itself is normal, and your product type is also supported. For situations where Google Play cannot be retrieved, when I tried switching to other Android devices, it was able to on other Android devices, other possibilities may only need to wait for the plugin author to adjust.

john290n commented 1 day ago

@EEETA So it means that my code is okay? Now if I want to try it out in Android physical device with Android studio locally I can just change the Platform.GOOGLE_PLAY, and the id of product?

john290n commented 1 day ago

@EEETA Could you please provide me with a screenshot or an explanation of the steps you took to set up the Products/Subscriptions on your Google Play Console?

EEETA commented 1 day ago

@john290n Currently it seems that your code is correct, the bigger reason is the problem between the phone itself, the plugin and Google Play, because you can correctly retrieve information from Platform.TEST and Platform.APPLE_APPSTORE, only GooglePlay is not working. However, you can still try one more approach - try each type one by one, when I tried before it was unrelated to type, if you have other Android devices, it is recommended to switch to other test devices for testing.

image My product type is different from yours, I have set it as CONSUMABLE.

john290n commented 1 day ago

@EEETA Aha, so you created the product in the In-app products section and not under the Subscription tab. How do I use the license testing user when testing locally? Currently, I'm just logged in with this user on my Samsung Galaxy account.

EEETA commented 1 day ago

@john290n Yes, I am in the sandbox environment, which can help me do store payments in the local test environment, but extra configuration is required, and the specific configuration steps are also more complicated. You can try looking up relevant documents for guidance. image

john290n commented 1 day ago

@EEETA, have you checked the logs? Are your logs similar to mine when the product with this ID is not found? I just want to make sure we’re experiencing the same issue.

EEETA commented 1 day ago

@john290n It's the same issue(unable to retrieve GooglePlay product information on Android), and the logs are similar as well, but I am using web chrome debugging, the only difference is that our product IDs and types are different.

john290n commented 1 day ago

@EEETA, do you have any idea if this issue is going to persist? Are you considering switching to a different library?

EEETA commented 1 day ago

@john290n I'm not sure when this issue will be resolved. I'm trying to communicate with the plugin author but haven't received a response yet. I will continue waiting.

john290n commented 1 day ago

@EEETA how can we verify that the products in the Google Play Console are OK and valid to use?

EEETA commented 1 day ago

@john290n It should be that after store.register, if you can get the product information and the status is normal, then it indicates it's available. But in the documentation for plugin v13, I didn't see any relevant description for the register part, I feel the documentation description is somewhat lacking. I confirmed this by setting the correct and incorrect ids. If the id is different from GooglePlay, it will be unable to get the product or prompt other errors. As for whether to verify the product is available, I can only initiate store.order(), there may be other methods provided by the plugin but I'm not very clear, this is also what I'm currently trying to figure out.

john290n commented 1 day ago

@EEETA Yes, but I just set up the merchant account in the Monetize tab, and I created the in-app products. I’m not sure if there are any other steps needed. My app is in production, and all other steps are complete.

Screenshot 2024-10-19 at 13 03 19
john290n commented 23 hours ago

@EEETA, I just noticed that my payment profile on the Google Play Console is not set up yet. Could this be the issue with the undefined products?

EEETA commented 5 hours ago

@john290n Sorry, I'm not certain if you definitely need to fill in this information. But based on my search results and viewing previous issues, I found that many people said it's necessary to fill in the GooglePlay & AppStore information (including the original author) properly. So it's best if you configure it as well.

john290n commented 2 hours ago

@EEETA thank you, please let me know if you find something to fix the issue!