Skip to main content
Solved

Three consumable products in my own layout ...

  • July 16, 2024
  • 5 replies
  • 138 views

Forum|alt.badge.img+2

Good afternoon,
Guys, please help me, I need an example code in Kotlin.
I have the simplest option: no authorization, no subscriptions, no Compose.
Only three products (Consumables), my own layout with three buttons (for each product).

How can I get the price of a product and setOnClickListener so that the process of purchasing this product begins?

 val tv_Crystals_100: TextView = findViewById(R.id.tv_Crystals_100)
 val tv_Crystals_200: TextView = findViewById(R.id.tv_Crystals_200)
 val tv_Crystals_500: TextView = findViewById(R.id.tv_Crystals_500)

 tv_Crystals_100.text = "__price_"
 tv_Crystals_100.setOnClickListener { ... }

 tv_Crystals_200.text = "__price_"
 tv_Crystals_200.setOnClickListener { ... }

 tv_Crystals_500.text = "__price_"
 tv_Crystals_500.setOnClickListener { ... }

Thanks a lot in advance
Denis

Best answer by sharif

Hi @Denis-44aa44,

We have an ongoing support ticket about this but I will also answer your question here.

To get the price of a product:

private fun fetchProductDetails() {
Purchases.sharedInstance.getProducts(productIds, object : ReceiveProductsCallback {
override fun onReceived(products: List<StoreProduct>) {
products.forEach { product ->
when (product.identifier) {
"your tvCrystals100 product" -> tvCrystals100.text = product.price
"your tvCrystals200 product" -> tvCrystals200.text = product.price
"your tvCrystals500 product" -> tvCrystals500.text = product.price
}
}
}

override fun onError(error: PurchasesError) {
// Handle error
Log.e("RevenueCat", "Error fetching products: ${error.message}")
}
})
}

To purchase products using setOnClickListener:

val tv_Crystals_100: TextView = findViewById(R.id.tv_btn_Buy_01)
val tv_Crystals_200: TextView = findViewById(R.id.tv_btn_Buy_02)
val tv_Crystals_500: TextView = findViewById(R.id.tv_btn_Buy_03)

tv_Crystals_100.text = "___"
tv_Crystals_100.setOnClickListener { purchaseProduct(<put your product ID here>) }

tv_Crystals_200.text = "___"
tv_Crystals_200.setOnClickListener { purchaseProduct(<put your product ID here>) }

tv_Crystals_500.text = "___"
tv_Crystals_500.setOnClickListener { purchaseProduct(<put your product ID here>) }


private fun purchaseProduct(productId: String) {
Purchases.sharedInstance.purchaseProduct(this, productId, object : PurchaseCompletedCallback {
override fun onCompleted(purchase: Purchase, customerInfo: CustomerInfo) {
// Handle successful purchase
}

override fun onError(error: PurchasesError, userCancelled: Boolean) {
// Handle purchase error
if (userCancelled) {
// The user cancelled the purchase
} else {
// The purchase experienced an error, handle it
}
}
})
}

 

This post has been closed for comments

5 replies

sharif
RevenueCat Staff
Forum|alt.badge.img+9
  • RevenueCat Staff
  • Answer
  • July 18, 2024

Hi @Denis-44aa44,

We have an ongoing support ticket about this but I will also answer your question here.

To get the price of a product:

private fun fetchProductDetails() {
Purchases.sharedInstance.getProducts(productIds, object : ReceiveProductsCallback {
override fun onReceived(products: List<StoreProduct>) {
products.forEach { product ->
when (product.identifier) {
"your tvCrystals100 product" -> tvCrystals100.text = product.price
"your tvCrystals200 product" -> tvCrystals200.text = product.price
"your tvCrystals500 product" -> tvCrystals500.text = product.price
}
}
}

override fun onError(error: PurchasesError) {
// Handle error
Log.e("RevenueCat", "Error fetching products: ${error.message}")
}
})
}

To purchase products using setOnClickListener:

val tv_Crystals_100: TextView = findViewById(R.id.tv_btn_Buy_01)
val tv_Crystals_200: TextView = findViewById(R.id.tv_btn_Buy_02)
val tv_Crystals_500: TextView = findViewById(R.id.tv_btn_Buy_03)

tv_Crystals_100.text = "___"
tv_Crystals_100.setOnClickListener { purchaseProduct(<put your product ID here>) }

tv_Crystals_200.text = "___"
tv_Crystals_200.setOnClickListener { purchaseProduct(<put your product ID here>) }

tv_Crystals_500.text = "___"
tv_Crystals_500.setOnClickListener { purchaseProduct(<put your product ID here>) }


private fun purchaseProduct(productId: String) {
Purchases.sharedInstance.purchaseProduct(this, productId, object : PurchaseCompletedCallback {
override fun onCompleted(purchase: Purchase, customerInfo: CustomerInfo) {
// Handle successful purchase
}

override fun onError(error: PurchasesError, userCancelled: Boolean) {
// Handle purchase error
if (userCancelled) {
// The user cancelled the purchase
} else {
// The purchase experienced an error, handle it
}
}
})
}

 


Forum|alt.badge.img+2
  • Author
  • New Member
  • July 20, 2024

Thank you very much for your help. But I still can't do it.

Android Studio states that purchaseProduct is already deprecated.

productId an error occurs that (Type mismatch, Required:
StoreProduct, Found: String)

Please help me


Forum|alt.badge.img+2
  • Author
  • New Member
  • July 21, 2024

Thank you very much for your help.
It seems like I figured it out, but I had to replace something in your code.

Denis


sharif
RevenueCat Staff
Forum|alt.badge.img+9
  • RevenueCat Staff
  • July 24, 2024

Hi @Denis-44aa44,

Thanks for confirming you got it working! If you are able, please share what changes you had to make so that I can fix my original answer. If you are not able then no problem, I’m glad it’s working now.


Forum|alt.badge.img+2
  • Author
  • New Member
  • July 24, 2024

Yes, of course, here is an example of code that works for me.
Let me remind you that I have the simplest option.
Three buttons, three products (Consumables), and my own layout.

1  Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.xxxxxxxxxxxxx)

Purchases.logLevel = LogLevel.DEBUG
Purchases.configure(PurchasesConfiguration.Builder(this, "goog_xxxxxxxxxxxxxxxxxxxxx").appUserID(null).build())

fetchProductDetails()
}

2  Kotlin

    private fun fetchProductDetails() {

val tv_btn_Buy_01: TextView = findViewById(R.id.tv_btn_Buy_01)
val tv_btn_Buy_02: TextView = findViewById(R.id.tv_btn_Buy_02)
val tv_btn_Buy_03: TextView = findViewById(R.id.tv_btn_Buy_03)


Purchases.sharedInstance.getProducts( productIds, object : GetStoreProductsCallback {

override fun onReceived(products: List<StoreProduct>) {
products.forEach { product ->
when (product.id) {

"crystals_100" -> { tv_btn_Buy_01.text = product.price.formatted; tv_btn_Buy_01.setOnClickListener { purchaseProduct( product.copyWithOfferingId(product.id) ) } }
"crystals_200" -> { tv_btn_Buy_02.text = product.price.formatted; tv_btn_Buy_02.setOnClickListener { purchaseProduct( product.copyWithOfferingId(product.id) ) } }
"crystals_500" -> { tv_btn_Buy_03.text = product.price.formatted; tv_btn_Buy_03.setOnClickListener { purchaseProduct( product.copyWithOfferingId(product.id) ) } }

}
}
}

override fun onError(error: PurchasesError) {

buildError(error.message)

with(error) {
when (code) {
PurchasesErrorCode.PurchaseNotAllowedError -> { .... }
.... -> { .... }
else -> { .... }
}

}
}


})
}

3  Kotlin

        private fun purchaseProduct(productId: StoreProduct) {   

Purchases.sharedInstance.purchaseWith(
PurchaseParams.Builder(this, productId).build(),
onError = { error, userCancelled ->
buildError(error.message)
},
onSuccess = { storeTransaction, customerInfo ->

when (productId.id) {
"crystals_100" -> {addPurchasedCrystals(100)}
"crystals_200" -> {addPurchasedCrystals(200)}
"crystals_500" -> {addPurchasedCrystals(500)}
}

}
)
}

 

If I have a mistake or something that can be improved, please write.

Now I'm sorting out errors when making a purchase.
And I don’t quite understand what and how errors need to be handled.
For example this: PurchasesErrorCode.OperationAlreadyInProgressError.

This parameter Purchases.logLevel = LogLevel.DEBUG is needed for debugging. What should this parameter be for shopping to work as usual?


Sincerely,
Denis