feat:新增BillingService2(优化API设计)
This commit is contained in:
@@ -5,9 +5,11 @@ import android.content.Context
|
|||||||
import com.alibaba.android.arouter.facade.annotation.Route
|
import com.alibaba.android.arouter.facade.annotation.Route
|
||||||
import com.example.module_base.config.RouterPath
|
import com.example.module_base.config.RouterPath
|
||||||
import com.example.module_base.support.billing.IBillingService
|
import com.example.module_base.support.billing.IBillingService
|
||||||
|
import com.example.module_base.support.billing.IBillingService2
|
||||||
import com.example.module_base.support.google.IGoogleService
|
import com.example.module_base.support.google.IGoogleService
|
||||||
import com.example.module_base.support.login.ILoginService
|
import com.example.module_base.support.login.ILoginService
|
||||||
import com.example.module_google.billing.BillingService
|
import com.example.module_google.billing.BillingService
|
||||||
|
import com.example.module_google.billing.BillingService2
|
||||||
import com.example.module_google.login.GoogleLoginService
|
import com.example.module_google.login.GoogleLoginService
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,6 +29,13 @@ class GoogleServiceImpl : IGoogleService {
|
|||||||
return BillingService(activity, listener)
|
return BillingService(activity, listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun newBillingService2(
|
||||||
|
activity: Activity,
|
||||||
|
listener: IBillingService2.Listener
|
||||||
|
): IBillingService2 {
|
||||||
|
return BillingService2(activity, listener)
|
||||||
|
}
|
||||||
|
|
||||||
override fun init(context: Context?) {
|
override fun init(context: Context?) {
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -18,9 +18,9 @@ import com.android.billingclient.api.QueryPurchasesParams
|
|||||||
import com.example.module_base.support.billing.IBillingService
|
import com.example.module_base.support.billing.IBillingService
|
||||||
import com.example.module_base.support.billing.IProductDetails
|
import com.example.module_base.support.billing.IProductDetails
|
||||||
import com.example.module_base.support.billing.IPurchase
|
import com.example.module_base.support.billing.IPurchase
|
||||||
import java.io.IOException
|
|
||||||
import com.example.module_google.BuildConfig
|
import com.example.module_google.BuildConfig
|
||||||
|
|
||||||
|
@Deprecated("后续使用BillingService2代替")
|
||||||
class BillingService(/*活动*/
|
class BillingService(/*活动*/
|
||||||
private val activity: Activity, /*监听*/
|
private val activity: Activity, /*监听*/
|
||||||
private val listener: IBillingService.Listener
|
private val listener: IBillingService.Listener
|
||||||
@@ -43,6 +43,8 @@ class BillingService(/*活动*/
|
|||||||
/*商品列表*/
|
/*商品列表*/
|
||||||
private val purchaseList: MutableList<IPurchase> = ArrayList()
|
private val purchaseList: MutableList<IPurchase> = ArrayList()
|
||||||
|
|
||||||
|
private var logEnabled = true
|
||||||
|
|
||||||
init {
|
init {
|
||||||
billingClient =
|
billingClient =
|
||||||
BillingClient.newBuilder(activity).enablePendingPurchases().setListener(this).build()
|
BillingClient.newBuilder(activity).enablePendingPurchases().setListener(this).build()
|
||||||
@@ -52,18 +54,20 @@ class BillingService(/*活动*/
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setLogEnabled(enabled: Boolean) {
|
||||||
|
logEnabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
override fun isServiceConnected(): Boolean {
|
override fun isServiceConnected(): Boolean {
|
||||||
return isServiceConnected
|
return isServiceConnected
|
||||||
}
|
}
|
||||||
|
|
||||||
/*开始连接Play*/
|
/*开始连接Play*/
|
||||||
private fun startServiceConnection(executeOnSuccess: Runnable?) {
|
private fun startServiceConnection(executeOnSuccess: Runnable?) {
|
||||||
|
log("startServiceConnection")
|
||||||
billingClient?.startConnection(object : BillingClientStateListener {
|
billingClient?.startConnection(object : BillingClientStateListener {
|
||||||
override fun onBillingSetupFinished(billingResult: BillingResult) {
|
override fun onBillingSetupFinished(billingResult: BillingResult) {
|
||||||
Log.d(
|
log("startServiceConnection onBillingSetupFinished code:${billingResult.responseCode}")
|
||||||
TAG,
|
|
||||||
"Setup finished. Response code: " + billingResult.debugMessage + " code = " + billingResult.responseCode
|
|
||||||
)
|
|
||||||
if (billingResult.responseCode == BillingResponseCode.OK) {
|
if (billingResult.responseCode == BillingResponseCode.OK) {
|
||||||
isServiceConnected = true
|
isServiceConnected = true
|
||||||
executeOnSuccess?.run()
|
executeOnSuccess?.run()
|
||||||
@@ -73,6 +77,7 @@ class BillingService(/*活动*/
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onBillingServiceDisconnected() {
|
override fun onBillingServiceDisconnected() {
|
||||||
|
log("startServiceConnection onBillingServiceDisconnected")
|
||||||
isServiceConnected = false
|
isServiceConnected = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -80,12 +85,15 @@ class BillingService(/*活动*/
|
|||||||
|
|
||||||
/*请求商品库存*/
|
/*请求商品库存*/
|
||||||
override fun onQueryPurchases() {
|
override fun onQueryPurchases() {
|
||||||
|
log("onQueryPurchases()")
|
||||||
val queryToExecute = Runnable {
|
val queryToExecute = Runnable {
|
||||||
|
log("onQueryPurchases() run")
|
||||||
billingClient?.queryPurchasesAsync(
|
billingClient?.queryPurchasesAsync(
|
||||||
QueryPurchasesParams.newBuilder()
|
QueryPurchasesParams.newBuilder()
|
||||||
.setProductType(BillingClient.ProductType.INAPP)
|
.setProductType(BillingClient.ProductType.INAPP)
|
||||||
.build()
|
.build()
|
||||||
) { billingResult: BillingResult, purchases: List<Purchase>? ->
|
) { billingResult: BillingResult, purchases: List<Purchase>? ->
|
||||||
|
log("onQueryPurchases() result code:${billingResult.responseCode} purchases:${purchases?.size}")
|
||||||
onPurchasesUpdated(
|
onPurchasesUpdated(
|
||||||
billingResult,
|
billingResult,
|
||||||
purchases
|
purchases
|
||||||
@@ -97,7 +105,7 @@ class BillingService(/*活动*/
|
|||||||
|
|
||||||
/*更新商品*/
|
/*更新商品*/
|
||||||
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
|
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
|
||||||
Log.i(TAG, "billingResult.getResponseCode()==" + billingResult.responseCode)
|
log("onPurchasesUpdated() code:${billingResult.responseCode} purchases:${purchases?.size}")
|
||||||
purchaseList.clear()
|
purchaseList.clear()
|
||||||
if (billingResult.responseCode == BillingResponseCode.OK) {
|
if (billingResult.responseCode == BillingResponseCode.OK) {
|
||||||
if (purchases != null) {
|
if (purchases != null) {
|
||||||
@@ -107,9 +115,6 @@ class BillingService(/*活动*/
|
|||||||
}
|
}
|
||||||
listener.onPurchasesUpdated(purchaseList)
|
listener.onPurchasesUpdated(purchaseList)
|
||||||
} else {
|
} else {
|
||||||
if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
listener.onFailedHandle(billingResult.responseCode)
|
listener.onFailedHandle(billingResult.responseCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,8 +132,8 @@ class BillingService(/*活动*/
|
|||||||
private fun verifyValidSignature(signedData: String, signature: String): Boolean {
|
private fun verifyValidSignature(signedData: String, signature: String): Boolean {
|
||||||
return try {
|
return try {
|
||||||
Security.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, signedData, signature)
|
Security.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, signedData, signature)
|
||||||
} catch (e: IOException) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Got an exception trying to validate a purchase: $e")
|
log("verifyValidSignature() e:${e.message}")
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,6 +152,7 @@ class BillingService(/*活动*/
|
|||||||
productIdList: List<String>,
|
productIdList: List<String>,
|
||||||
listener: IBillingService.ProductDetailsResponseListener
|
listener: IBillingService.ProductDetailsResponseListener
|
||||||
) {
|
) {
|
||||||
|
log("querySkuDetailsAsync() productIdList:${productIdList.size}")
|
||||||
val queryRequest = Runnable {
|
val queryRequest = Runnable {
|
||||||
val products = ArrayList<QueryProductDetailsParams.Product>()
|
val products = ArrayList<QueryProductDetailsParams.Product>()
|
||||||
for (productId in productIdList) {
|
for (productId in productIdList) {
|
||||||
@@ -160,16 +166,22 @@ class BillingService(/*活动*/
|
|||||||
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder()
|
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder()
|
||||||
.setProductList(products)
|
.setProductList(products)
|
||||||
.build()
|
.build()
|
||||||
|
log("querySkuDetailsAsync() run")
|
||||||
billingClient?.queryProductDetailsAsync(
|
billingClient?.queryProductDetailsAsync(
|
||||||
queryProductDetailsParams,
|
queryProductDetailsParams
|
||||||
ProductDetailsResponseListenerAdapter(listener)
|
) { p0, p1 ->
|
||||||
)
|
log("querySkuDetailsAsync() result code:${p0.responseCode} size:${p1.size}")
|
||||||
|
listener.onProductDetailsResponse(BillingResultImpl(p0), p1.map {
|
||||||
|
ProductDetailsImpl(it)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
executeServiceRequest(queryRequest)
|
executeServiceRequest(queryRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*启动购买,订购流程*/
|
/*启动购买,订购流程*/
|
||||||
override fun initiatePurchaseFlow(productDetails: IProductDetails, recordId: String) {
|
override fun initiatePurchaseFlow(productDetails: IProductDetails, recordId: String) {
|
||||||
|
log("initiatePurchaseFlow() productId:${productDetails.getProductId()}")
|
||||||
val details = productDetails.getData() as? ProductDetails ?: return
|
val details = productDetails.getData() as? ProductDetails ?: return
|
||||||
val purchaseFlowRequest = Runnable {
|
val purchaseFlowRequest = Runnable {
|
||||||
val p = ProductDetailsParams.newBuilder()
|
val p = ProductDetailsParams.newBuilder()
|
||||||
@@ -187,19 +199,20 @@ class BillingService(/*活动*/
|
|||||||
.setObfuscatedProfileId(jsonObject.toJSONString())
|
.setObfuscatedProfileId(jsonObject.toJSONString())
|
||||||
.setProductDetailsParamsList(java.util.List.of(p))
|
.setProductDetailsParamsList(java.util.List.of(p))
|
||||||
.build()
|
.build()
|
||||||
|
log("initiatePurchaseFlow() run")
|
||||||
val billingResult = billingClient?.launchBillingFlow(activity, purchaseParams)
|
val billingResult = billingClient?.launchBillingFlow(activity, purchaseParams)
|
||||||
Log.i(
|
log("initiatePurchaseFlow() result code:${billingResult?.responseCode}")
|
||||||
TAG,
|
|
||||||
" initiatePurchaseFlow billingResult=" + billingResult?.responseCode + " " + billingResult?.debugMessage
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
executeServiceRequest(purchaseFlowRequest)
|
executeServiceRequest(purchaseFlowRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun consumeAsync(purchaseToken: String) {
|
override fun consumeAsync(purchaseToken: String) {
|
||||||
|
log("consumeAsync()")
|
||||||
val consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken).build()
|
val consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken).build()
|
||||||
executeServiceRequest {
|
executeServiceRequest {
|
||||||
|
log("consumeAsync() run")
|
||||||
billingClient?.consumeAsync(consumeParams) { billingResult: BillingResult, s: String? ->
|
billingClient?.consumeAsync(consumeParams) { billingResult: BillingResult, s: String? ->
|
||||||
|
log("consumeAsync() result code:${billingResult.responseCode}")
|
||||||
listener.onConsumeFinished(
|
listener.onConsumeFinished(
|
||||||
purchaseToken,
|
purchaseToken,
|
||||||
billingResult.responseCode
|
billingResult.responseCode
|
||||||
@@ -212,10 +225,16 @@ class BillingService(/*活动*/
|
|||||||
* 销毁结算客户端并断开连接
|
* 销毁结算客户端并断开连接
|
||||||
*/
|
*/
|
||||||
override fun destroy() {
|
override fun destroy() {
|
||||||
Log.d(TAG, "Destroying the manager.")
|
log("destroy()")
|
||||||
if (billingClient != null && billingClient?.isReady == true) {
|
if (billingClient != null && billingClient?.isReady == true) {
|
||||||
billingClient?.endConnection()
|
billingClient?.endConnection()
|
||||||
billingClient = null
|
billingClient = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun log(message: String) {
|
||||||
|
if (logEnabled) {
|
||||||
|
Log.d(TAG, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,240 @@
|
|||||||
|
package com.example.module_google.billing
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.util.Log
|
||||||
|
import com.alibaba.fastjson.JSONObject
|
||||||
|
import com.android.billingclient.api.BillingClient
|
||||||
|
import com.android.billingclient.api.BillingClient.BillingResponseCode
|
||||||
|
import com.android.billingclient.api.BillingClientStateListener
|
||||||
|
import com.android.billingclient.api.BillingFlowParams
|
||||||
|
import com.android.billingclient.api.BillingFlowParams.ProductDetailsParams
|
||||||
|
import com.android.billingclient.api.BillingResult
|
||||||
|
import com.android.billingclient.api.ConsumeParams
|
||||||
|
import com.android.billingclient.api.ProductDetails
|
||||||
|
import com.android.billingclient.api.Purchase
|
||||||
|
import com.android.billingclient.api.PurchasesUpdatedListener
|
||||||
|
import com.android.billingclient.api.QueryProductDetailsParams
|
||||||
|
import com.android.billingclient.api.QueryPurchasesParams
|
||||||
|
import com.example.module_base.support.billing.IBillingService2
|
||||||
|
import com.example.module_base.support.billing.IProductDetails
|
||||||
|
import com.example.module_base.support.billing.OnBillingClientStateListener
|
||||||
|
import com.example.module_base.support.billing.OnConsumeResponseListener
|
||||||
|
import com.example.module_base.support.billing.OnProductDetailsResponseListener
|
||||||
|
import com.example.module_base.support.billing.OnPurchasesResponseListener
|
||||||
|
import com.example.module_google.BuildConfig
|
||||||
|
|
||||||
|
class BillingService2(/*活动*/
|
||||||
|
private val activity: Activity, /*监听*/
|
||||||
|
private val listener: IBillingService2.Listener
|
||||||
|
) : IBillingService2, PurchasesUpdatedListener {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "BillingService2"
|
||||||
|
|
||||||
|
/*购买key*/
|
||||||
|
private const val BASE_64_ENCODED_PUBLIC_KEY = BuildConfig.GOOGLE_BILLING_PUBLIC_KEY
|
||||||
|
}
|
||||||
|
|
||||||
|
/*客户端*/
|
||||||
|
private var billingClient: BillingClient?
|
||||||
|
|
||||||
|
/*是否连接成功*/
|
||||||
|
private var isServiceConnected = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
private var logEnabled = true
|
||||||
|
|
||||||
|
init {
|
||||||
|
billingClient =
|
||||||
|
BillingClient.newBuilder(activity).enablePendingPurchases().setListener(this).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setLogEnabled(enabled: Boolean) {
|
||||||
|
this.logEnabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun startConnection(listener: OnBillingClientStateListener) {
|
||||||
|
log("startConnection()")
|
||||||
|
startServiceConnection {
|
||||||
|
log("startConnection() result code:${it.responseCode}")
|
||||||
|
listener.onBillingSetupFinished(BillingResultImpl(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isServiceConnected(): Boolean {
|
||||||
|
return isServiceConnected
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun queryPurchases(listener: OnPurchasesResponseListener) {
|
||||||
|
log("queryPurchases()")
|
||||||
|
val queryToExecute = Runnable {
|
||||||
|
log("queryPurchases() run")
|
||||||
|
billingClient?.queryPurchasesAsync(
|
||||||
|
QueryPurchasesParams.newBuilder()
|
||||||
|
.setProductType(BillingClient.ProductType.INAPP)
|
||||||
|
.build()
|
||||||
|
) { p0, p1 ->
|
||||||
|
log("queryPurchases() result code:${p0.responseCode} p1:${p1.size}")
|
||||||
|
listener.onQueryPurchasesResponse(
|
||||||
|
BillingResultImpl(p0),
|
||||||
|
verifyValidSignature(p1.map {
|
||||||
|
PurchaseImpl(it)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executeServiceRequest(queryToExecute)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun querySkuDetailsAsync(
|
||||||
|
productIdList: List<String>,
|
||||||
|
listener: OnProductDetailsResponseListener
|
||||||
|
) {
|
||||||
|
log("querySkuDetailsAsync() productIdList:${productIdList.size}")
|
||||||
|
val queryRequest = Runnable {
|
||||||
|
val products = ArrayList<QueryProductDetailsParams.Product>()
|
||||||
|
for (productId in productIdList) {
|
||||||
|
products.add(
|
||||||
|
QueryProductDetailsParams.Product.newBuilder()
|
||||||
|
.setProductId(productId)
|
||||||
|
.setProductType(BillingClient.ProductType.INAPP)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder()
|
||||||
|
.setProductList(products)
|
||||||
|
.build()
|
||||||
|
log("querySkuDetailsAsync() run")
|
||||||
|
billingClient?.queryProductDetailsAsync(
|
||||||
|
queryProductDetailsParams
|
||||||
|
) { p0, p1 ->
|
||||||
|
log("querySkuDetailsAsync() result code:${p0.responseCode} size:${p1.size}")
|
||||||
|
listener.onProductDetailsResponse(BillingResultImpl(p0), p1.map {
|
||||||
|
ProductDetailsImpl(it)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executeServiceRequest(queryRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun consumeAsync(
|
||||||
|
purchaseToken: String,
|
||||||
|
listener: OnConsumeResponseListener
|
||||||
|
) {
|
||||||
|
log("consumeAsync()")
|
||||||
|
val consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchaseToken).build()
|
||||||
|
executeServiceRequest {
|
||||||
|
log("consumeAsync() run")
|
||||||
|
billingClient?.consumeAsync(consumeParams) { billingResult: BillingResult, s: String ->
|
||||||
|
log("consumeAsync() result code:${billingResult.responseCode} s:${s}")
|
||||||
|
listener.onConsumeResponse(
|
||||||
|
BillingResultImpl(billingResult), s
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun launchBillingFlow(productDetails: IProductDetails, recordId: String) {
|
||||||
|
log("launchBillingFlow() productId:${productDetails.getProductId()}")
|
||||||
|
val details = productDetails.getData() as? ProductDetails ?: return
|
||||||
|
val purchaseFlowRequest = Runnable {
|
||||||
|
val p = ProductDetailsParams.newBuilder()
|
||||||
|
.setProductDetails(details)
|
||||||
|
.build()
|
||||||
|
val jsonObject = JSONObject()
|
||||||
|
val oneTimePurchaseOfferDetails = details.oneTimePurchaseOfferDetails
|
||||||
|
if (oneTimePurchaseOfferDetails != null) {
|
||||||
|
jsonObject["p"] = oneTimePurchaseOfferDetails.formattedPrice
|
||||||
|
jsonObject["a"] = oneTimePurchaseOfferDetails.priceAmountMicros / 10000
|
||||||
|
jsonObject["c"] = oneTimePurchaseOfferDetails.priceCurrencyCode
|
||||||
|
}
|
||||||
|
val purchaseParams = BillingFlowParams.newBuilder()
|
||||||
|
.setObfuscatedAccountId(recordId)
|
||||||
|
.setObfuscatedProfileId(jsonObject.toJSONString())
|
||||||
|
.setProductDetailsParamsList(java.util.List.of(p))
|
||||||
|
.build()
|
||||||
|
val billingResult = billingClient?.launchBillingFlow(activity, purchaseParams)
|
||||||
|
log("launchBillingFlow() result code:${billingResult?.responseCode}")
|
||||||
|
}
|
||||||
|
executeServiceRequest(purchaseFlowRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*开始连接Play*/
|
||||||
|
private fun startServiceConnection(callback: (BillingResult) -> Unit) {
|
||||||
|
log("startServiceConnection()")
|
||||||
|
billingClient?.startConnection(object : BillingClientStateListener {
|
||||||
|
override fun onBillingSetupFinished(billingResult: BillingResult) {
|
||||||
|
log("startServiceConnection() onBillingSetupFinished code:${billingResult.responseCode}")
|
||||||
|
if (billingResult.responseCode == BillingResponseCode.OK) {
|
||||||
|
isServiceConnected = true
|
||||||
|
} else {
|
||||||
|
isServiceConnected = true
|
||||||
|
}
|
||||||
|
callback.invoke(billingResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBillingServiceDisconnected() {
|
||||||
|
log("startServiceConnection() onBillingServiceDisconnected")
|
||||||
|
isServiceConnected = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/*更新商品*/
|
||||||
|
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
|
||||||
|
log("onPurchasesUpdated code:${billingResult.responseCode} size:${purchases?.size}")
|
||||||
|
listener.onPurchasesUpdated(
|
||||||
|
BillingResultImpl(billingResult),
|
||||||
|
verifyValidSignature(purchases?.map {
|
||||||
|
PurchaseImpl(it)
|
||||||
|
} ?: emptyList())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun verifyValidSignature(purchases: List<PurchaseImpl>): List<PurchaseImpl> {
|
||||||
|
return purchases.filter {
|
||||||
|
//验证签名数据
|
||||||
|
verifyValidSignature(it.data.originalJson, it.data.signature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*验证签名*/
|
||||||
|
private fun verifyValidSignature(signedData: String, signature: String): Boolean {
|
||||||
|
return try {
|
||||||
|
Security.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, signedData, signature)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
log("verifyValidSignature e:${e.message}")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*执行服务请求*/
|
||||||
|
private fun executeServiceRequest(runnable: Runnable) {
|
||||||
|
if (isServiceConnected) {
|
||||||
|
runnable.run()
|
||||||
|
} else {
|
||||||
|
startServiceConnection {
|
||||||
|
if (it.responseCode == BillingResponseCode.OK) {
|
||||||
|
runnable.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁结算客户端并断开连接
|
||||||
|
*/
|
||||||
|
override fun destroy() {
|
||||||
|
log("destroy()")
|
||||||
|
if (billingClient != null && billingClient?.isReady == true) {
|
||||||
|
billingClient?.endConnection()
|
||||||
|
billingClient = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun log(message: String) {
|
||||||
|
if (logEnabled) {
|
||||||
|
Log.d(TAG, message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,19 +0,0 @@
|
|||||||
package com.example.module_google.billing
|
|
||||||
|
|
||||||
import com.android.billingclient.api.BillingResult
|
|
||||||
import com.android.billingclient.api.ProductDetails
|
|
||||||
import com.android.billingclient.api.ProductDetailsResponseListener
|
|
||||||
import com.example.module_base.support.billing.IBillingService
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Max on 2023/11/22 20:23
|
|
||||||
* Desc:
|
|
||||||
**/
|
|
||||||
class ProductDetailsResponseListenerAdapter(private val listener: IBillingService.ProductDetailsResponseListener) :
|
|
||||||
ProductDetailsResponseListener {
|
|
||||||
override fun onProductDetailsResponse(p0: BillingResult, p1: MutableList<ProductDetails>) {
|
|
||||||
listener.onProductDetailsResponse(BillingResultImpl(p0), p1.map {
|
|
||||||
ProductDetailsImpl(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user