libgdx / gdx-pay

A libGDX cross-platform API for InApp purchasing.
Apache License 2.0
225 stars 83 forks source link

Upgrade to Google Billing 5 #247

Closed mathkend closed 1 year ago

mathkend commented 1 year ago

Update to Google Billing 5 Removed SKU Concept Purchases now can return multiple products. Only handling one (This can be enabled at Play Store - In App Product - Setting) ** The workflow about Subscriptions is unchanged and untested.

The changes are tested in a similar way but not the actual code. Only changed to update the project since i do not use it anymore, but there are a lot of requests at the Discord.

Feel free to question or improve the Pull Request.

kharindev commented 1 year ago

how to add this to my project? Thank you.

mathkend commented 1 year ago

how to add this to my project? Thank you.

Maybe you should wait for this to have a proper review, necessary changes and to be merged.

mathkend commented 1 year ago

Thanks, I made some comments. We upgraded Gradle as well, can you resolve conflicts caused by this when you are at it?

@MrStahlfelge This changes in gradle requires Java 11, are you sure about it? (gdx-pay-android-amazon)

MrStahlfelge commented 1 year ago

how to add this to my project? Thank you.

Maybe you should wait for this to have a proper review, necessary changes and to be merged.

Everyone testing as soon as possible is good. Can be done by building locally, instructions are on the README files.

MrStahlfelge commented 1 year ago

Thanks, I made some comments. We upgraded Gradle as well, can you resolve conflicts caused by this when you are at it?

@MrStahlfelge This changes in gradle requires Java 11, are you sure about it? (gdx-pay-android-amazon)

Building Android needs Java 11 nowadays, so it is good to go.

keesvandieren commented 1 year ago

I have worked a while to support subscriptions, created patch based on your branch; basic support is there, but free trial period not yet. I have to find out how to simulate this, as on my device free trial period was already used. All help there is welcome.

Add_subscriptions,_but_without_free_trial_info.patch.zip

bitdream commented 1 year ago

Is upgrading Gradle really necessary? Java 11 is not compatiple with Java 8! This is a big update.

mathkend commented 1 year ago

The INAPP purchase is unavailable in older devices. Query products list already generate problems like: Response Code: FEATURE_NOT_SUPPORTED, Debug Message: Client does not support ProductDetails.

Not sure how to fix it yet. Play Store acuses old versions, but there is no new version to update.

shpowley commented 1 year ago

I have worked a while to support subscriptions, created patch based on your branch; basic support is there, but free trial period not yet. I have to find out how to simulate this, as on my device free trial period was already used. All help there is welcome.

Add_subscriptions,_but_without_free_trial_info.patch.zip

I tested with your patch code. Thank you.

Individual CONSUMABLE and ENTITLEMENT purchases worked fine.

Initially, SUBSCRIPTION with multiple offers failed with my particular setup. Maybe because my initial offer was not "backwards compatible" (see attached screenshot). As per the recommendation in https://developer.android.com/google/play/billing/migrate-gpblv5#launching-offer, I only modified getBillingFlowParams() for ProductType and this fixed the error. My initial offer was a 1-month, pre-paid subscription and could be purchased multiple times.

    protected BillingFlowParams.Builder getBillingFlowParams(ProductDetails productDetails) {
        List<BillingFlowParams.ProductDetailsParams> productDetailsParamsList;

        if (productDetails.getProductType().equals(ProductType.INAPP)) {
            productDetailsParamsList =
              Collections.singletonList(
                BillingFlowParams.ProductDetailsParams.newBuilder()
                  .setProductDetails(productDetails)
                  .build()
              );
        }
        else {
            String offerToken = productDetails
              .getSubscriptionOfferDetails()
              .get(0) // HOW TO SPECIFY AN ALTERNATE OFFER USING gdx-pay?
              .getOfferToken();

            productDetailsParamsList =
              Collections.singletonList(
                BillingFlowParams.ProductDetailsParams.newBuilder()
                  .setProductDetails(productDetails)
                  .setOfferToken(offerToken)
                  .build()
              );
        }

        return BillingFlowParams.newBuilder().setProductDetailsParamsList(productDetailsParamsList);
    }

As mentioned in previous comments, only the SUBSCRIPTION's first offer can be purchased. I didn't know how to test free-trial scenario.

Screenshot of my play console subscription hierarchy:

Screenshot 2022-09-13 062925
MrStahlfelge commented 1 year ago

Great, thanks for testing! @keesvandieren can you push your changes, I think we can merge the branch then to publish a snapshot for more people to test.

keesvandieren commented 1 year ago

Add_support_for_subscriptions_with_free_trial.patch.zip

Attached the patch for support of subscriptions with free trial.

I cannot test free trial as it is already used with my account and it is a once per account setting. But the code is simple, the complex logic is re-used from previous implementation so no risk there.

Can @mathkend please apply this patch to your pull request branch? After that we can go for release I feel

shpowley commented 1 year ago

I tested the latest patch and the free trial appears to work.

I did encounter a couple issues.

1) As mentioned previously, hard-coding the subscription offer index(?) for index 0 causes problems. For instance, Play console doesn't allow deleting an offer - only de-activating the offer. An active offer at a higher index is inaccessible. Only solution is to just create a new subscription with the correct offer details..

2) Code only handles INFINITE_RECURRING subscriptions. Something like a pre-paid monthly subscription doesn't get added to informationMap (ex. only paying for only a month of video streaming). Just removing the phase.getRecurrenceMode() check fixed this.

OLD:

private static boolean isPaidForSubscriptionPhase(ProductDetails.PricingPhase phase) {
    return phase.getRecurrenceMode() == ProductDetails.RecurrenceMode.INFINITE_RECURRING && phase.getPriceAmountMicros() > 0;
}

NEW:

private static boolean isPaidForSubscriptionPhase(ProductDetails.PricingPhase phase) {
    return phase.getPriceAmountMicros() > 0;
}

UNRELATED: Unclear how to apply .patch to PR. $ git am <patch_file> failed and manually applied changes.

keesvandieren commented 1 year ago

@shpowley thanks for your feedback!

Regarding this:

As mentioned previously, hard-coding the subscription offer index(?) for index 0 causes problems. For instance, Play console doesn't allow deleting an offer - only de-activating the offer. An active offer at a higher index is inaccessible. Only solution is to just create a new subscription with the correct offer details..

Do you have a suggestion of how to choose another? Maybe instead of get(0) we should always get the last one? Now I am using this method:

    private static ProductDetails.SubscriptionOfferDetails getActiveSubscriptionOfferDetails(List<ProductDetails.SubscriptionOfferDetails> subscriptionOfferDetails) {
        return subscriptionOfferDetails.get(subscriptionOfferDetails.size() - 1);
    }

Applied this method change:

    private static boolean isPaidForSubscriptionPhase(ProductDetails.PricingPhase phase) {
        return phase.getPriceAmountMicros() > 0;
    }

UNRELATED: Unclear how to apply .patch to PR. $ git am failed and manually applied changes.

I use IDEA to Create the Patch via the Menu Git > Patch. Maybe apply from there is easier to use?

New version available here: Add_support_for_subscriptions_with_free_trial.patch.zip

Tested it with my subscription, worked for me. Waiting for your feedback.

shpowley commented 1 year ago

@keesvandieren Applied and tested latest patch directly against PR using Android Studio + GIT plugin (thanks).

Worked as expected for the different purchase scenarios mentioned in previous posts, but unable to test the free-trial again. Creating a new test app with duplicate code + Play console setup would trigger a free-trial, but that seems a bit overkill.

Regarding the subscription offer index. Play console allows you to activate/de-activate any offer in the list - so assuming that the first or last index is the intended/active one doesn't seem ideal. An overloaded purchase() method on the PurchaseManager interface would be preferred I think.

In addition to the existing:

public void purchase(String identifier) {..}

Also add:

public void purchase(String identifier, int subscriptionOfferIndex) {..}

Unfortunately, PurchaseManager is also implemented elsewhere and this issue is Google-specific. I tried placing the overloaded purchase() directly on PurchaseManagerGoogleBilling, but that didn't work. Is altering PurchaseManager not viable?

HuaweiPurchaseManager PurchaseManagerAndroidAmazon PurchaseManageriOSApple

MrStahlfelge commented 1 year ago

The offer index should be set in a Google-specific configuration.

keesvandieren commented 1 year ago

@shpowley will only enabled offerIndices be returned? I checked for enabledness booleans in the APIs, but couldn't find any pointers there.

Can we release a first version where we cannot yet set the index, and do that in subsequent release?

shpowley commented 1 year ago

@keesvandieren In debug, the entire offer list is always returned, every base plan + child offer(s), regardless of active status. Multiple active base plans and child offers can exist on a subscription. I didn't see a way determine an offer's active status. Deleting subscription data in Play console isn't supported.

I don't actually use subscriptions. The current level of support seems more than fine - with the caveat that each subscription ideally has only one offer.

keesvandieren commented 1 year ago

We have the implementation now which alway selects the first.

Add_support_for_subscriptions_with_free_trial.patch.zip

Ok with this PR?

I think I cannot push to mathkend:master? Can @mathkend apply this patch, update the PR? Or approve the patch and I will create a new PR with all the changes in it.

kharindev commented 1 year ago

Do you think it will be possible to update Google Billing by November?

keesvandieren commented 1 year ago

@kharindev yes, if I get no feedback on my latest comment I will be creating a new PR with all fixes soon and release it.

shpowley commented 1 year ago

@keesvandieren Intermittently checking the status of this. Integrating your patch version in my android apps now - only using entitlement purchase. Discord #android discussion might get more feedback. I posted a link there.

keesvandieren commented 1 year ago

Completed with PR #249