3 Commits

Author SHA1 Message Date
max
ed1fbf2304 修改material版本号为1.6.1(aab转apks失败) 2024-03-05 14:23:37 +08:00
max
3257c96a7b fix:恢复误删除的引用 2024-03-04 15:39:45 +08:00
max
10d3d5a477 #Molistar:移除google登录相关代码 2024-03-04 15:17:28 +08:00
6 changed files with 38 additions and 341 deletions

View File

@@ -4,15 +4,11 @@ android {
def gak = project.hasProperty("GOOGLE_BILLING_PUBLIC_KEY") ? GOOGLE_BILLING_PUBLIC_KEY :
"Define GOOGLE_BILLING_PUBLIC_KEY in gradle.properties. Or './gradlew -PGOOGLE_BILLING_PUBLIC_KEY=gak_value ... taskName'"
def gsci = project.hasProperty("GOOGLE_SERVER_CLIENT_ID") ? GOOGLE_SERVER_CLIENT_ID :
"Define GOOGLE_SERVER_CLIENT_ID in gradle.properties. Or 'gradle -PGOOGLE_SERVER_CLIENT_ID=gak_value ... taskName'"
println("GOOGLE_BILLING_PUBLIC_KEY:" + gak)
println("GOOGLE_SERVER_CLIENT_ID:" + gsci)
defaultConfig {
buildConfigField "String", "GOOGLE_BILLING_PUBLIC_KEY", "\"$gak\""
buildConfigField "String", "GOOGLE_SERVER_CLIENT_ID", "\"$gsci\""
}
}
@@ -23,9 +19,6 @@ kapt {
}
dependencies {
// google登录
implementation 'com.google.android.gms:play-services-auth:21.0.0'
// googleplay内购
implementation 'com.google.android.gms:play-services-wallet:19.2.1'
implementation 'com.android.billingclient:billing:6.0.1'

View File

@@ -5,11 +5,9 @@ import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.example.module_base.config.RouterPath
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.login.ILoginService
import com.example.module_google.billing.BillingService
import com.example.module_google.billing.BillingService2
import com.example.module_google.login.GoogleLoginService
/**
@@ -29,13 +27,6 @@ class GoogleServiceImpl : IGoogleService {
return BillingService(activity, listener)
}
override fun newBillingService2(
activity: Activity,
listener: IBillingService2.Listener
): IBillingService2 {
return BillingService2(activity, listener)
}
override fun init(context: Context?) {
}
}

View File

@@ -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.IProductDetails
import com.example.module_base.support.billing.IPurchase
import java.io.IOException
import com.example.module_google.BuildConfig
@Deprecated("后续使用BillingService2代替")
class BillingService(/*活动*/
private val activity: Activity, /*监听*/
private val listener: IBillingService.Listener
@@ -43,8 +43,6 @@ class BillingService(/*活动*/
/*商品列表*/
private val purchaseList: MutableList<IPurchase> = ArrayList()
private var logEnabled = true
init {
billingClient =
BillingClient.newBuilder(activity).enablePendingPurchases().setListener(this).build()
@@ -54,20 +52,18 @@ class BillingService(/*活动*/
}
}
override fun setLogEnabled(enabled: Boolean) {
logEnabled = enabled
}
override fun isServiceConnected(): Boolean {
return isServiceConnected
}
/*开始连接Play*/
private fun startServiceConnection(executeOnSuccess: Runnable?) {
log("startServiceConnection")
billingClient?.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
log("startServiceConnection onBillingSetupFinished code:${billingResult.responseCode}")
Log.d(
TAG,
"Setup finished. Response code: " + billingResult.debugMessage + " code = " + billingResult.responseCode
)
if (billingResult.responseCode == BillingResponseCode.OK) {
isServiceConnected = true
executeOnSuccess?.run()
@@ -77,7 +73,6 @@ class BillingService(/*活动*/
}
override fun onBillingServiceDisconnected() {
log("startServiceConnection onBillingServiceDisconnected")
isServiceConnected = false
}
})
@@ -85,15 +80,12 @@ class BillingService(/*活动*/
/*请求商品库存*/
override fun onQueryPurchases() {
log("onQueryPurchases()")
val queryToExecute = Runnable {
log("onQueryPurchases() run")
billingClient?.queryPurchasesAsync(
QueryPurchasesParams.newBuilder()
.setProductType(BillingClient.ProductType.INAPP)
.build()
) { billingResult: BillingResult, purchases: List<Purchase>? ->
log("onQueryPurchases() result code:${billingResult.responseCode} purchases:${purchases?.size}")
onPurchasesUpdated(
billingResult,
purchases
@@ -105,7 +97,7 @@ class BillingService(/*活动*/
/*更新商品*/
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
log("onPurchasesUpdated() code:${billingResult.responseCode} purchases:${purchases?.size}")
Log.i(TAG, "billingResult.getResponseCode()==" + billingResult.responseCode)
purchaseList.clear()
if (billingResult.responseCode == BillingResponseCode.OK) {
if (purchases != null) {
@@ -115,6 +107,9 @@ class BillingService(/*活动*/
}
listener.onPurchasesUpdated(purchaseList)
} else {
if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
} else {
}
listener.onFailedHandle(billingResult.responseCode)
}
}
@@ -132,8 +127,8 @@ class BillingService(/*活动*/
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}")
} catch (e: IOException) {
Log.e(TAG, "Got an exception trying to validate a purchase: $e")
false
}
}
@@ -152,7 +147,6 @@ class BillingService(/*活动*/
productIdList: List<String>,
listener: IBillingService.ProductDetailsResponseListener
) {
log("querySkuDetailsAsync() productIdList:${productIdList.size}")
val queryRequest = Runnable {
val products = ArrayList<QueryProductDetailsParams.Product>()
for (productId in productIdList) {
@@ -166,22 +160,16 @@ class BillingService(/*活动*/
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)
})
}
queryProductDetailsParams,
ProductDetailsResponseListenerAdapter(listener)
)
}
executeServiceRequest(queryRequest)
}
/*启动购买,订购流程*/
override fun initiatePurchaseFlow(productDetails: IProductDetails, recordId: String) {
log("initiatePurchaseFlow() productId:${productDetails.getProductId()}")
val details = productDetails.getData() as? ProductDetails ?: return
val purchaseFlowRequest = Runnable {
val p = ProductDetailsParams.newBuilder()
@@ -199,20 +187,19 @@ class BillingService(/*活动*/
.setObfuscatedProfileId(jsonObject.toJSONString())
.setProductDetailsParamsList(java.util.List.of(p))
.build()
log("initiatePurchaseFlow() run")
val billingResult = billingClient?.launchBillingFlow(activity, purchaseParams)
log("initiatePurchaseFlow() result code:${billingResult?.responseCode}")
Log.i(
TAG,
" initiatePurchaseFlow billingResult=" + billingResult?.responseCode + " " + billingResult?.debugMessage
)
}
executeServiceRequest(purchaseFlowRequest)
}
override fun consumeAsync(purchaseToken: String) {
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}")
listener.onConsumeFinished(
purchaseToken,
billingResult.responseCode
@@ -225,16 +212,10 @@ class BillingService(/*活动*/
* 销毁结算客户端并断开连接
*/
override fun destroy() {
log("destroy()")
Log.d(TAG, "Destroying the manager.")
if (billingClient != null && billingClient?.isReady == true) {
billingClient?.endConnection()
billingClient = null
}
}
private fun log(message: String) {
if (logEnabled) {
Log.d(TAG, message)
}
}
}

View File

@@ -1,240 +0,0 @@
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)
}
}
}

View File

@@ -0,0 +1,19 @@
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)
})
}
}

View File

@@ -3,66 +3,19 @@ package com.example.module_google.login
import android.app.Activity
import android.content.Intent
import com.example.module_base.support.login.ILoginService
import com.example.module_base.support.login.LoginSDKException
import com.example.module_base.support.login.PlatformInfo
import com.example.module_google.BuildConfig
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException
import kotlin.random.Random
/**
* Created by Max on 2023/11/22 15:59
* Desc:Google登录
**/
class GoogleLoginService : ILoginService {
private val requestCode = Random.nextInt(10000, 20000)
private var listener: ILoginService.Listener? = null
private var googleSignInOptions: GoogleSignInOptions =
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestProfile()
.requestIdToken(BuildConfig.GOOGLE_SERVER_CLIENT_ID)
.build()
private var googleSignInClient: GoogleSignInClient? = null
override fun login(activity: Activity, listener: ILoginService.Listener) {
this.listener = listener
if (this.googleSignInClient == null) {
this.googleSignInClient =
GoogleSignIn.getClient(activity.applicationContext, googleSignInOptions)
}
activity.startActivityForResult(
googleSignInClient!!.signInIntent,
requestCode
)
}
override fun logout() {
googleSignInClient?.signOut()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == this.requestCode) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
val account = task.getResult(ApiException::class.java)
val info = PlatformInfo(
id = account!!.id!!,
name = account.displayName,
gender = null,
avatar = account.photoUrl?.toString()
)
listener?.onSuccess(info)
} catch (e: ApiException) {
listener?.onFailure(LoginSDKException(e.statusCode, e))
} catch (e: Exception) {
listener?.onFailure(LoginSDKException(-100))
}
}
}
}