TheDragoner
TheDragoner

Reputation: 375

How to identify the subscription duration (monthly or yearly) from a purchase in Google Play Billing Library?

I am using the Google Play Billing Library in my Kotlin app to allow users to purchase subscriptions. I have a single product with two subscription offers: one for a monthly duration and the other for a yearly duration.

After a user purchases a subscription, I can retrieve their purchase details using the BillingClient.queryPurchasesAsync() method, but it doesn't display the duration.

I want to determine whether the user selected the monthly or yearly subscription offer after the purchase has been made.

What I’ve Tried:

I queried the available ProductDetails using BillingClient.queryProductDetailsAsync() to retrieve the subscription offers (SubscriptionOfferDetails).

I attempted to compare the offerToken from the Purchase object with the offerToken in SubscriptionOfferDetails, but they are not the same.

How can I correctly determine the subscription duration (monthly or yearly) for a completed purchase when using the Google Play Billing Library? Is there a proper way to map the purchase details to the specific offer details?

Any guidance or examples would be greatly appreciated!

fun startBillingConnection() {
    billingClient.startConnection(object : BillingClientStateListener {
        override fun onBillingSetupFinished(billingResult: BillingResult) {
            if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                Log.d(TAG, "Billing response OK")
                queryPurchases()
                queryProductDetails()
                _billingState.update { it.copy(isClientConnected = true) }
            } else {
                Log.e(TAG, billingResult.debugMessage)
                handleBillingError(billingResult, ErrorContext.CONNECTION)
                _billingState.update { it.copy(isClientConnected = false) }
            }
        }

        override fun onBillingServiceDisconnected() {
            Log.i(TAG, "Billing connection disconnected")
            _billingState.update { it.copy(isClientConnected = false) }
        }
    })
}

private fun querySubscriptionProducts() {
    val params = QueryProductDetailsParams.newBuilder()
    val productList = SUBS_PRODUCTS.map { productId ->
        QueryProductDetailsParams.Product.newBuilder()
            .setProductId(productId)
            .setProductType(BillingClient.ProductType.SUBS)
            .build()
    }

    params.setProductList(productList).let { productDetailsParams ->
        billingClient.queryProductDetailsAsync(productDetailsParams.build(), this)
    }
}

override fun onProductDetailsResponse(
    billingResult: BillingResult,
    productDetailsList: MutableList<ProductDetails>
) {
    when (billingResult.responseCode) {
        BillingClient.BillingResponseCode.OK -> {
            if (productDetailsList.isEmpty()) {
                Log.e(TAG, "onProductDetailsResponse: Found null or empty ProductDetails.")
            } else {
                val newProducts = productDetailsList.associateBy { it.productId }
                _billingState.update {
                    it.copy(products = it.products + newProducts)
                }
            }
        }

        else -> {
            handleBillingError(billingResult, ErrorContext.PRODUCT_DETAILS)
        }
    }
}

Upvotes: 0

Views: 47

Answers (1)

S-Sh
S-Sh

Reputation: 3913

The duration of the sub is Product's property, not Purchase's. After you retrieve info about products with BillingClient.queryProductDetailsAsync(), you can get subscription info:

productDetails[0].getSubscriptionOfferDetails()[0].getPricingPhases().getBillingPeriod()

Notes:

  1. use appropriate indices, according to offer plans speicified (in the Console) for each subscription
  2. Billing period is formatted string, see example here

Upvotes: 0

Related Questions