123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- package cn.yyxx.eyuangame.core.impl.iab
- import android.app.Activity
- import android.text.TextUtils
- import cn.yyxx.eyuangame.base.entity.SdkChargeInfo
- import cn.yyxx.eyuangame.base.utils.Logger
- import cn.yyxx.eyuangame.core.entity.ResultInfo
- import cn.yyxx.eyuangame.core.impl.SdkBridgeImpl
- import cn.yyxx.eyuangame.core.internal.IImplCallback
- import cn.yyxx.eyuangame.core.internal.IRequestCallback
- import cn.yyxx.eyuangame.core.network.SdkRequest
- import cn.yyxx.eyuangame.core.utils.MMKVUtils
- import cn.yyxx.support.ResUtils
- import cn.yyxx.support.hawkeye.ToastUtils
- import com.android.billingclient.api.*
- import org.json.JSONException
- import org.json.JSONObject
- /**
- * @author #Suyghur.
- * Created on 2021/06/28
- */
- class ChargeImpl : InAppBilling() {
- //初始化IAB收银台客户端
- //连接谷歌商店
- private lateinit var implCallback: IImplCallback
- private lateinit var chargeInfo: SdkChargeInfo
- fun charge(activity: Activity, chargeInfo: SdkChargeInfo, callback: IImplCallback) {
- if (!checkGoogleApiAvailability(activity)) {
- ToastUtils.toastInfo(activity, "Your phone or Google account does not support In-app Billing")
- callback.onResult(-1, "谷歌iab支付服务不可用")
- return
- }
- this.implCallback = callback
- this.chargeInfo = chargeInfo
- showDialog(activity)
- // checkLocalNotifyFailedOrder(activity)
- getOrderId(activity)
- }
- override fun chargePurchasesUpdated(activity: Activity, purchase: Purchase) {
- Logger.d("chargePurchasesUpdated")
- notifyOrder2Backend(activity, chargeInfo.orderId, purchase, false)
- }
- override fun preRewardPurchasesUpdated(activity: Activity, purchase: Purchase) {
- }
- override fun queryRewardInfo(activity: Activity) {
- }
- /**
- * 查询未消耗订单
- */
- override fun queryChargeInfo(activity: Activity) {
- billingClient?.apply {
- val list = queryPurchases(BillingClient.SkuType.INAPP).purchasesList
- if (list.isNullOrEmpty()) {
- //正常发起支付流程
- querySkuDetails(activity)
- } else {
- Logger.e("存在未消耗订单,发起补单流程,size : ${list.size}")
- run breaking@{
- if (list.size > 0) {
- list.forEach { purchase ->
- if (purchase.sku == SdkBridgeImpl.initBean.rewardId) {
- Logger.e("存在阻塞的预注册奖励,停止支付流程")
- if (list.size == 1) {
- dismissDialog()
- disConnection()
- ToastUtils.toastInfo(activity, "In-app Billing has some error , please restart app and try again")
- implCallback.onResult(-1, "存在阻塞的预注册奖励,停止支付流程")
- }
- //跳出支付流程
- return@breaking
- } else {
- consumeCacheOrder(activity, purchase)
- }
- }
- } else {
- //发起正常支付流程
- querySkuDetails(activity)
- }
- }
- }
- // queryPurchasesAsync(BillingClient.SkuType.INAPP, object : PurchasesResponseListener {
- // override fun onQueryPurchasesResponse(billingResult: BillingResult, list: MutableList<Purchase>) {
- // logBillingResult("onQueryPurchasesResponse", billingResult)
- // if (list.isNullOrEmpty()) {
- // //正常发起支付流程
- // Logger.d("正常发起支付流程")
- // querySkuDetails(activity)
- // } else {
- // Logger.e("存在未消耗订单,发起补单流程,size : ${list.size}")
- // run breaking@{
- // list.forEach { purchase ->
- // purchase.skus.forEach {
- // if (it.equals(SdkBridgeImpl.initBean.rewardId)) {
- // Logger.e("存在阻塞的预注册奖励,停止支付流程")
- // if (list.size == 1) {
- // dismissDialog()
- // disConnection()
- // ToastUtils.toastInfo(activity, "In-app Billing has some error , please restart app and try again")
- // implCallback.onResult(-1, "存在阻塞的预注册奖励,停止支付流程")
- // }
- // //跳出支付流程
- // return@breaking
- // } else {
- // consumeCacheOrder(activity, purchase)
- // }
- // }
- // }
- // }
- // }
- // }
- // })
- }
- }
- override fun purchasesUpdatedFailed() {
- }
- override fun connectGooglePlayFailed() {
- }
- /**
- * 检查本地通知发货失败订单
- */
- private fun checkLocalNotifyFailedOrder(activity: Activity) {
- }
- /**
- * 获取订单号
- */
- private fun getOrderId(activity: Activity) {
- SdkRequest.instance.createOrder(activity, chargeInfo, object : IRequestCallback {
- override fun onResponse(resultInfo: ResultInfo) {
- if (resultInfo.code == 1 && !TextUtils.isEmpty(resultInfo.data)) {
- try {
- val jsonObject = JSONObject(resultInfo.data)
- chargeInfo.orderId = jsonObject.getString("order_id")
- Logger.d("order_id ---> ${chargeInfo.orderId}")
- //获取订单号成功,初始化IAB收银台客户端
- Logger.d("获取订单号成功,初始化IAB收银台客户端")
- initializeBillingClient(activity)
- connectGooglePlay(activity, false)
- } catch (e: JSONException) {
- e.printStackTrace()
- dismissDialog()
- val msg = if (TextUtils.isEmpty(resultInfo.msg)) {
- ResUtils.getResString(activity, "yyxx_charge_tv_error")
- } else {
- resultInfo.msg
- }
- ToastUtils.toastInfo(activity, msg)
- implCallback.onResult(-1, "获取订单异常")
- }
- } else {
- dismissDialog()
- val msg = if (TextUtils.isEmpty(resultInfo.msg)) {
- ResUtils.getResString(activity, "yyxx_charge_tv_error")
- } else {
- resultInfo.msg
- }
- ToastUtils.toastInfo(activity, msg)
- implCallback.onResult(-1, "获取订单异常")
- }
- }
- })
- }
- /**
- * 查询商品信息
- */
- private fun querySkuDetails(activity: Activity) {
- val skus = mutableListOf<String>()
- skus.add(chargeInfo.productId)
- val params = SkuDetailsParams.newBuilder().setType(BillingClient.SkuType.INAPP).setSkusList(skus).build()
- billingClient?.querySkuDetailsAsync(params) { billingResult, list ->
- logBillingResult("onSkuDetailsResponse", billingResult)
- dismissDialog()
- if (list.isNullOrEmpty()) {
- //查询商品信息失败
- Logger.e("查询商品信息失败")
- ToastUtils.toastInfo(activity, ResUtils.getResString(activity, "yyxx_charge_tv_error"))
- implCallback.onResult(-1, "查询商品信息失败")
- disConnection()
- } else {
- if (list.size == 1) {
- val skuDetails = list[0]
- Logger.d("product id : ${skuDetails.sku}")
- launchBillingFlow(activity, skuDetails)
- } else {
- ToastUtils.toastInfo(activity, ResUtils.getResString(activity, "yyxx_charge_tv_error"))
- implCallback.onResult(-1, "查询商品信息异常")
- disConnection()
- }
- }
- }
- }
- /**
- * 启动收银台
- *
- */
- private fun launchBillingFlow(activity: Activity, skuDetails: SkuDetails) {
- billingClient?.apply {
- if (isReady) {
- val flowParams = BillingFlowParams.newBuilder().setObfuscatedAccountId(chargeInfo.orderId).setSkuDetails(skuDetails).build()
- val billingResult = launchBillingFlow(activity, flowParams)
- logBillingResult("launchBillingFlow", billingResult)
- if (billingResult.responseCode != BillingClient.BillingResponseCode.OK) {
- dismissDialog()
- disConnection()
- ToastUtils.toastInfo(activity, ResUtils.getResString(activity, "yyxx_charge_tv_error"))
- implCallback.onResult(-1, "启动谷歌收银台失败")
- }
- } else {
- dismissDialog()
- disConnection()
- ToastUtils.toastInfo(activity, ResUtils.getResString(activity, "yyxx_charge_tv_error"))
- implCallback.onResult(-1, "启动谷歌收银台失败")
- }
- }
- }
- /**
- * 通知服务端发货
- */
- private fun notifyOrder2Backend(activity: Activity, orderId: String, purchase: Purchase, isCache: Boolean = false) {
- SdkRequest.instance.notifyOrder(activity, orderId, purchase.originalJson, object : IRequestCallback {
- override fun onResponse(resultInfo: ResultInfo) {
- if (resultInfo.code == 1) {
- //消耗订单
- consumeAsync(activity, purchase, isCache)
- } else {
- //失败则缓存订单
- saveOrderInfo(purchase.orderId, orderId)
- dismissDialog()
- disConnection()
- val msg = if (TextUtils.isEmpty(resultInfo.msg)) {
- ResUtils.getResString(activity, "yyxx_charge_tv_error")
- } else {
- resultInfo.msg
- }
- ToastUtils.toastInfo(activity, msg)
- implCallback.onResult(-1, "发货失败")
- }
- }
- })
- }
- /**
- * 消耗缓存订单
- */
- private fun consumeCacheOrder(activity: Activity, purchase: Purchase) {
- //消耗完了再发起支付
- Logger.d("消耗缓存订单 : $purchase")
- var orderId = ""
- purchase.accountIdentifiers?.apply {
- orderId = if (!TextUtils.isEmpty(obfuscatedAccountId)) {
- obfuscatedAccountId!!
- } else {
- //TODO getLocalOrderId
- getOrderInfo(purchase.orderId)
- }
- }
- notifyOrder2Backend(activity, orderId, purchase, true)
- // consumeAsync(activity, purchase.purchaseToken, true)
- }
- /**
- * 消耗订单
- */
- private fun consumeAsync(activity: Activity, purchase: Purchase, isCache: Boolean = false) {
- val consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchase.purchaseToken).build()
- billingClient?.apply {
- if (isReady) {
- consumeAsync(consumeParams) { billingResult, token ->
- logBillingResult("onConsumeResponse", billingResult)
- dismissDialog()
- if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
- // saveOrder2Local()
- if (isCache) {
- querySkuDetails(activity)
- } else {
- implCallback.onResult(0, "支付成功")
- disConnection()
- }
- removeOrderInfo(purchase.orderId)
- } else {
- implCallback.onResult(-1, "消耗订单异常")
- disConnection()
- ToastUtils.toastInfo(activity, ResUtils.getResString(activity, "yyxx_charge_tv_error"))
- }
- }
- } else {
- dismissDialog()
- disConnection()
- implCallback.onResult(-1, "消耗订单异常")
- ToastUtils.toastInfo(activity, ResUtils.getResString(activity, "yyxx_charge_tv_error"))
- }
- }
- }
- private fun saveOrderInfo(googleOrderId: String, orderId: String) {
- try {
- MMKVUtils.instance.orderKV.encode(googleOrderId, orderId)
- } catch (e: JSONException) {
- e.printStackTrace()
- }
- }
- private fun getOrderInfo(googleOrderId: String): String {
- val info = MMKVUtils.instance.orderKV.decodeString(googleOrderId)
- Logger.d("getOrderInfo : $info")
- return if (TextUtils.isEmpty(info)) {
- ""
- } else {
- info!!
- }
- }
- private fun removeOrderInfo(googleOrderId: String) {
- MMKVUtils.instance.orderKV.removeValueForKey(googleOrderId)
- }
- companion object {
- val instance: ChargeImpl by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
- ChargeImpl()
- }
- }
- }
|