mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-03 01:39:22 +02:00
Update google play billing library
This commit is contained in:
parent
620af536ce
commit
aa06c8aaed
5 changed files with 80 additions and 51 deletions
|
@ -200,8 +200,7 @@ dependencies {
|
|||
implementation 'com.squareup.okhttp3:okhttp-tls:4.9.3'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
|
||||
|
||||
googleApiImplementation "com.android.billingclient:billing:4.1.0"
|
||||
googleApiImplementation "com.android.billingclient:billing-ktx:4.1.0"
|
||||
googleApiImplementation "com.android.billingclient:billing-ktx:5.0.0"
|
||||
|
||||
implementation('io.socket:socket.io-client:2.0.0') {
|
||||
exclude group: 'org.json', module: 'json'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* TimeLimit Copyright <C> 2019 - 2021 Jonas Lochmann
|
||||
* TimeLimit Copyright <C> 2019 - 2022 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -123,12 +123,16 @@ class ActivityPurchaseModel(application: Application): AndroidViewModel(applicat
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun querySkus(skuIds: List<String>): List<SkuDetails> = initAndUseClient { client ->
|
||||
val (billingResult, data) = client.querySkuDetails(
|
||||
SkuDetailsParams.newBuilder()
|
||||
.setSkusList(skuIds)
|
||||
.setType(BillingClient.SkuType.INAPP)
|
||||
suspend fun queryProducts(productIds: List<String>): List<ProductDetails> = initAndUseClient { client ->
|
||||
val (billingResult, data) = client.queryProductDetails(
|
||||
QueryProductDetailsParams.newBuilder()
|
||||
.setProductList(productIds.map { skuId ->
|
||||
QueryProductDetailsParams.Product.newBuilder()
|
||||
.setProductId(skuId)
|
||||
.setProductType(BillingClient.ProductType.INAPP)
|
||||
.build()
|
||||
})
|
||||
.build()
|
||||
)
|
||||
|
||||
billingResult.assertSuccess()
|
||||
|
@ -137,7 +141,11 @@ class ActivityPurchaseModel(application: Application): AndroidViewModel(applicat
|
|||
}
|
||||
|
||||
suspend fun queryPurchases() = initAndUseClient { client ->
|
||||
val response = client.queryPurchasesAsync(BillingClient.SkuType.INAPP)
|
||||
val response = client.queryPurchasesAsync(
|
||||
QueryPurchasesParams.newBuilder()
|
||||
.setProductType(BillingClient.ProductType.INAPP)
|
||||
.build()
|
||||
)
|
||||
|
||||
response.billingResult.assertSuccess()
|
||||
|
||||
|
@ -153,7 +161,11 @@ class ActivityPurchaseModel(application: Application): AndroidViewModel(applicat
|
|||
|
||||
try {
|
||||
initAndUseClient { client ->
|
||||
val result = client.queryPurchasesAsync(BillingClient.SkuType.INAPP)
|
||||
val result = client.queryPurchasesAsync(
|
||||
QueryPurchasesParams.newBuilder()
|
||||
.setProductType(BillingClient.ProductType.INAPP)
|
||||
.build()
|
||||
)
|
||||
|
||||
result.billingResult.assertSuccess()
|
||||
|
||||
|
@ -223,7 +235,7 @@ class ActivityPurchaseModel(application: Application): AndroidViewModel(applicat
|
|||
Log.d(LOG_TAG, "handlePurchase($purchase)")
|
||||
}
|
||||
|
||||
val sku = purchase.skus.single()
|
||||
val sku = purchase.products.single()
|
||||
|
||||
if (PurchaseIds.SAL_SKUS.contains(sku)) {
|
||||
// just acknowledge
|
||||
|
@ -262,14 +274,14 @@ class ActivityPurchaseModel(application: Application): AndroidViewModel(applicat
|
|||
}
|
||||
}
|
||||
|
||||
fun startPurchase(sku: String, checkAtBackend: Boolean, activity: Activity) {
|
||||
fun startPurchase(productId: String, checkAtBackend: Boolean, activity: Activity) {
|
||||
runAsync {
|
||||
try {
|
||||
val skuDetails = querySkus(listOf(sku)).single()
|
||||
val productDetails = queryProducts(listOf(productId)).single()
|
||||
|
||||
if (skuDetails.sku != sku) throw IllegalStateException()
|
||||
if (productDetails.productId != productId) throw IllegalStateException()
|
||||
|
||||
startPurchase(skuDetails, checkAtBackend, activity)
|
||||
startPurchase(productDetails, checkAtBackend, activity)
|
||||
} catch (ex: Exception) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(LOG_TAG, "could not start purchase", ex)
|
||||
|
@ -280,7 +292,7 @@ class ActivityPurchaseModel(application: Application): AndroidViewModel(applicat
|
|||
}
|
||||
}
|
||||
|
||||
fun startPurchase(skuDetails: SkuDetails, checkAtBackend: Boolean, activity: Activity) {
|
||||
private fun startPurchase(productDetails: ProductDetails, checkAtBackend: Boolean, activity: Activity) {
|
||||
runAsync {
|
||||
initAndUseClient { client ->
|
||||
try {
|
||||
|
@ -299,10 +311,14 @@ class ActivityPurchaseModel(application: Application): AndroidViewModel(applicat
|
|||
}
|
||||
|
||||
client.launchBillingFlow(
|
||||
activity,
|
||||
BillingFlowParams.newBuilder()
|
||||
.setSkuDetails(skuDetails)
|
||||
activity,
|
||||
BillingFlowParams.newBuilder()
|
||||
.setProductDetailsParamsList(listOf(
|
||||
BillingFlowParams.ProductDetailsParams.newBuilder()
|
||||
.setProductDetails(productDetails)
|
||||
.build()
|
||||
))
|
||||
.build()
|
||||
).assertSuccess()
|
||||
} catch (ex: Exception) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
|
|
|
@ -62,11 +62,11 @@ class PurchaseModel(application: Application): AndroidViewModel(application) {
|
|||
if (canDoPurchase.publicKey?.contentEquals(Base64.decode(BuildConfig.googlePlayKey, 0)) == false) {
|
||||
statusInternal.value = PurchaseFragmentServerHasDifferentPublicKey
|
||||
} else {
|
||||
val skus = activityPurchaseModel.querySkus(PurchaseIds.BUY_SKUS)
|
||||
val skus = activityPurchaseModel.queryProducts(PurchaseIds.BUY_SKUS)
|
||||
|
||||
statusInternal.value = PurchaseFragmentReady(
|
||||
monthPrice = skus.find { it.sku == PurchaseIds.SKU_MONTH }?.price.toString(),
|
||||
yearPrice = skus.find { it.sku == PurchaseIds.SKU_YEAR }?.price.toString()
|
||||
monthPrice = skus.find { it.productId == PurchaseIds.SKU_MONTH }?.oneTimePurchaseOfferDetails?.formattedPrice.toString(),
|
||||
yearPrice = skus.find { it.productId == PurchaseIds.SKU_YEAR }?.oneTimePurchaseOfferDetails?.formattedPrice.toString()
|
||||
)
|
||||
}
|
||||
} else if (canDoPurchase == CanDoPurchaseStatus.NotDueToOldPurchase) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* TimeLimit Copyright <C> 2019 - 2021 Jonas Lochmann
|
||||
* TimeLimit Copyright <C> 2019 - 2022 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -37,18 +37,18 @@ class StayAwesomeModel(application: Application): AndroidViewModel(application)
|
|||
}
|
||||
|
||||
try {
|
||||
val skus = activityPurchaseModel.querySkus(PurchaseIds.SAL_SKUS)
|
||||
val skus = activityPurchaseModel.queryProducts(PurchaseIds.SAL_SKUS)
|
||||
val purchases = activityPurchaseModel.queryPurchases()
|
||||
|
||||
statusInternal.value = ReadyStayAwesomeStatus(
|
||||
PurchaseIds.SAL_SKUS.map { skuId ->
|
||||
val sku = skus.find { it.sku == skuId }
|
||||
val sku = skus.find { it.productId == skuId }
|
||||
|
||||
StayAwesomeItem(
|
||||
id = skuId,
|
||||
title = sku?.description ?: skuId,
|
||||
price = sku?.price ?: "???",
|
||||
bought = purchases.find { purchase -> purchase.skus.find { sku -> sku == skuId } != null } != null
|
||||
price = sku?.oneTimePurchaseOfferDetails?.formattedPrice.toString(),
|
||||
bought = purchases.find { purchase -> purchase.products.find { sku -> sku == skuId } != null } != null
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* TimeLimit Copyright <C> 2019 - 2021 Jonas Lochmann
|
||||
* TimeLimit Copyright <C> 2019 - 2022 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -28,20 +28,18 @@ object BillingClient {
|
|||
|
||||
fun endConnection() {}
|
||||
|
||||
fun querySkuDetails(param: SkuDetailsParams) = QuerySkuDetailsResult.instance
|
||||
fun queryProductDetails(param: QueryProductDetailsParams) = QueryProductDetailsResult.instance
|
||||
fun launchBillingFlow(activity: Activity, params: BillingFlowParams) = BillingResult
|
||||
fun acknowledgePurchase(params: AcknowledgePurchaseParams) = BillingResult
|
||||
fun consumePurchase(params: ConsumeParams) = BillingResult
|
||||
suspend fun queryPurchasesAsync(type: String) = QueryPurchasesResult
|
||||
suspend fun queryPurchasesAsync(request: QueryPurchasesParams) = QueryPurchasesResult
|
||||
|
||||
object BillingResponseCode {
|
||||
const val OK = 0
|
||||
const val ERR = 1
|
||||
}
|
||||
|
||||
object SkuType {
|
||||
const val INAPP = ""
|
||||
}
|
||||
enum class ProductType { INAPP }
|
||||
|
||||
object Builder {
|
||||
fun enablePendingPurchases() = this
|
||||
|
@ -55,26 +53,20 @@ object BillingResult {
|
|||
const val debugMessage = "only mock linked"
|
||||
}
|
||||
|
||||
object SkuDetails {
|
||||
const val sku = ""
|
||||
const val price = ""
|
||||
object ProductDetails {
|
||||
const val productId = ""
|
||||
const val description = ""
|
||||
}
|
||||
val oneTimePurchaseOfferDetails: OfferDetails? = OfferDetails
|
||||
|
||||
object SkuDetailsParams {
|
||||
fun newBuilder() = Builder
|
||||
|
||||
object Builder {
|
||||
fun setSkusList(list: List<String>) = this
|
||||
fun setType(type: String) = this
|
||||
fun build() = SkuDetailsParams
|
||||
object OfferDetails {
|
||||
const val formattedPrice = ""
|
||||
}
|
||||
}
|
||||
|
||||
object Purchase {
|
||||
const val purchaseState = PurchaseState.PURCHASED
|
||||
const val isAcknowledged = true
|
||||
val skus = listOf("")
|
||||
val products = emptyList<String>()
|
||||
const val purchaseToken = ""
|
||||
const val originalJson = ""
|
||||
const val signature = ""
|
||||
|
@ -103,11 +95,14 @@ object ConsumeParams {
|
|||
}
|
||||
|
||||
object BillingFlowParams {
|
||||
fun newBuilder() = Builder
|
||||
fun newBuilder() = this
|
||||
fun setProductDetailsParamsList(details: List<ProductDetailsParams>) = this
|
||||
fun build() = this
|
||||
|
||||
object Builder {
|
||||
fun setSkuDetails(details: SkuDetails) = this
|
||||
fun build() = BillingFlowParams
|
||||
object ProductDetailsParams {
|
||||
fun newBuilder() = this
|
||||
fun setProductDetails(details: ProductDetails) = this
|
||||
fun build() = this
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,9 +111,9 @@ object QueryPurchasesResult {
|
|||
val purchasesList: List<Purchase> = emptyList()
|
||||
}
|
||||
|
||||
data class QuerySkuDetailsResult(val billingResult: BillingResult, val details: List<SkuDetails>?) {
|
||||
data class QueryProductDetailsResult(val billingResult: BillingResult, val details: List<ProductDetails>?) {
|
||||
companion object {
|
||||
val instance = QuerySkuDetailsResult(BillingResult, emptyList())
|
||||
val instance = QueryProductDetailsResult(BillingResult, emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,4 +124,23 @@ interface BillingClientStateListener {
|
|||
|
||||
interface PurchasesUpdatedListener {
|
||||
fun onPurchasesUpdated(p0: BillingResult, p1: MutableList<Purchase>?)
|
||||
}
|
||||
|
||||
object QueryProductDetailsParams {
|
||||
fun newBuilder() = this
|
||||
fun setProductList(list: List<Product>) = this
|
||||
fun build() = this
|
||||
|
||||
object Product {
|
||||
fun newBuilder() = this
|
||||
fun setProductId(id: String) = this
|
||||
fun setProductType(type: BillingClient.ProductType) = this
|
||||
fun build() = this
|
||||
}
|
||||
}
|
||||
|
||||
object QueryPurchasesParams {
|
||||
fun newBuilder() = this
|
||||
fun setProductType(type: BillingClient.ProductType) = this
|
||||
fun build() = this
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue