21

How do you get token of PurchaseDetails object in Android? Based on the docs, https://developer.android.com/google/play/billing/integrate#java, to launch a purchase flow we need to do something like below:

// An activity reference from which the billing flow will be launched.
Activity activity = ...;

ImmutableList productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // to get an offer token, call ProductDetails.getSubscriptionOfferDetails()
            // for a list of offers that are available to the user
            .setOfferToken(selectedOfferToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

Note that it shows to get the offer token:

to get an offer token, call ProductDetails.getSubscriptionOfferDetails()

This assumes we are using a subscription, however in my case I'm using an in app purchase which is a one-off purchase. If it is a subscription I believe I could try and use the getOfferToken() method as show here: https://developer.android.com/reference/com/android/billingclient/api/ProductDetails.SubscriptionOfferDetails#getOfferToken()

However, with a one time purchase the object does not contain any methods to deal with tokens, https://developer.android.com/reference/com/android/billingclient/api/ProductDetails.OneTimePurchaseOfferDetails.

So my question is what do we pass into the selectedOfferToken for a one time purchase product?

Mark
  • 3,138
  • 5
  • 19
  • 36

4 Answers4

23

For anyone who has been struggling with this, I hope this helps, took days of my time...it seems we don't need to call the .setOfferToken(selectedOfferToken) method.

ImmutableList productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // to get an offer token, call ProductDetails.getSubscriptionOfferDetails()
            // for a list of offers that are available to the user
            .build()
    );
Mark
  • 3,138
  • 5
  • 19
  • 36
  • Thanks Man. Documentation says to get token we can call ProductDetails.getSubscriptionOfferDetails() but it throws null value. and I tried to ommi this mf token and it works. – Arel Guatno Aug 29 '22 at 10:43
  • 2
    Yes, I can purchase successfully without setOfferToken. It seems setOfferToken only for Subscription use – Hsiao-Ting Feb 03 '23 at 06:25
  • 3
    need to check the type of productDetails, if it's Subscription then need to set offer token otherwise you will get `java.lang.NullPointerException: offerToken is required for constructing ProductDetailsParams.` for InApp type do nothing – user924 Feb 05 '23 at 17:30
5

Found a solution with OfferToken:

.setOfferToken(productDetails.getSubscriptionOfferDetails().get(0).getOfferToken())

Simple workaround. :)

MoD
  • 564
  • 4
  • 14
  • Explanation: The offer details array (productDetails.subscriptionOfferDetails) always contains base plan details (if any base plan exists), so even if your subscription contains only a base plan without offers it will still have offerToken for purchase. chance use it without any tension ;) – Chandra Sekhar Bala Jul 22 '23 at 16:04
0

If you use a product with subscription not specifying getOfferToken results in a crash. At the moment is am using MoD s workaround, but i still get "Error - The item you requested is not available for purchase". I do not know if this is due to getOfferToken. In the description of product+base plane + offer Google said that a "base plane" has multiple "offers", but i never defined any offer. So this also could be the reason. In the debugger one can see values in the offer string, so Google seems to provide some default offer , but , yes need to further test. In any case - if you use subscriptions you need to set an offer String. I also tried what happens when sending a wrong offer string - something like "cheesymeasy". Google then returns "Error Something went wrong on our end. Please try again". So most likely the string returned by getOfferToken is indeed valid.

MatthiasL
  • 81
  • 6
0

for Kotlin

ProductDetailsParams.newBuilder()
                            .setProductDetails(productDetails)
                            .setOfferToken(it.offerToken)
                            .build()
Yuliia Ashomok
  • 8,336
  • 2
  • 60
  • 69