package com.gamedog.vididin.manager import android.app.Activity import android.os.Handler import android.os.Looper import com.ama.core.architecture.util.AndroidUtil import com.ama.core.architecture.util.DeviceUtil import com.ama.core.architecture.util.MD5Util import com.ama.core.architecture.util.SpUtil import com.ama.core.architecture.util.eventbus.NotifyMan import com.gamedog.vididin.VidiConst import com.gamedog.vididin.VidiConst.ZEROBUY_SECRET import com.gamedog.vididin.VididinEvents import com.gamedog.vididin.beans.ZeroBuyItem import com.gamedog.vididin.beans.ZeroBuyWithdrawResp import com.gamedog.vididin.core.login.login.AccountManager import com.gamedog.vididin.features.withdraw.dialogs.WithdrawBindBankDialog import com.gamedog.vididin.features.withdraw.dialogs.WithdrawInfoConfirmDialog import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_FAIL import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_ONGOING import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_SUCCESS import com.gamedog.vididin.manager.WithdrawManager.Companion.TRANSACTION_STATE_UNSTART import com.gamedog.vididin.netbase.NetworkUtil import com.gamedog.vididin.netbase.Result import com.gamedog.vididin.request.RequestUtil import com.vididin.real.money.game.R import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import okhttp3.internal.http2.Http2Reader import java.util.concurrent.locks.ReentrantLock import kotlin.Int class ZeroManager private constructor() { companion object { @Volatile private var instance: ZeroManager? = null fun instance(): ZeroManager { return instance ?: synchronized(this) { instance ?: ZeroManager().also { instance = it } } } } private val mBgScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private val mRecordList: MutableList by lazy { SpUtil.instance().getList(SpUtil.KEY_ZEROBUY_WIN_ITEMS).toMutableList() } private val mRecordLocker = ReentrantLock() private val mLooperHandler = Handler(Looper.getMainLooper()) private val mLoopRunnable = object : Runnable { override fun run() { loopCheckTransactionState() } } init { loopCheckTransactionState() mLooperHandler.postDelayed(mLoopRunnable, 20 * 1000) } private fun saveWinWithdrawInfos() { SpUtil.instance().putList(SpUtil.KEY_ZEROBUY_WIN_ITEMS, mRecordList) notifyChangeUpdate() } private fun notifyChangeUpdate() { NotifyMan.instance().sendEvent(VididinEvents.EVENT_ZERO_WITHDRAW_LIST_CHANGED, null) } /** * only add new one, if already exist - then do nothing */ fun addWinWithdrawItem(zeroItem: ZeroBuyItem) { val userId = AccountManager.getAccount().userId zeroItem.winners?.let { if (it.contains(userId) && zeroItem.completed) { var alreadyExist = false try { mRecordLocker.lock() mRecordList.forEach { if (it.purchase_id == zeroItem.id) { alreadyExist = true return@forEach } } if (!alreadyExist) { mRecordList.add(WinZeroWithdrawInfoItem(zeroItem.id, zeroItem.title, zeroItem.price)) saveWinWithdrawInfos() } } finally { mRecordLocker.unlock() } } } } fun getZeroWithdrawItem(zeroItem: ZeroBuyItem): WinZeroWithdrawInfoItem { try { mRecordLocker.lock() return mRecordList.filter { zeroItem.id == it.purchase_id }[0] } finally { mRecordLocker.unlock() } } fun couldStartWithdraw(zeroItem: ZeroBuyItem): Boolean { val userId = AccountManager.getAccount().userId zeroItem.winners?.let { if (it.contains(userId) && zeroItem.completed) { try { mRecordLocker.lock() mRecordList.forEach { if (it.purchase_id == zeroItem.id) { return it.withdrawState == TRANSACTION_STATE_UNSTART || it.withdrawState == TRANSACTION_STATE_FAIL } } addWinWithdrawItem(zeroItem) return true } finally { mRecordLocker.unlock() } } } return false } private fun requestZeroWithdrawReward(zeroWithdrawItem: WinZeroWithdrawInfoItem) { mBgScope.launch { // header val operationVal = VidiConst.ZERO_WITHDRAW_OPERATION val curTimeSec = System.currentTimeMillis()/1000 val signStr = RequestUtil.getZeroBuyRequestSign(curTimeSec, operationVal) val requestHeaders = mapOf("Operation" to operationVal.toString(), "Timestamp" to curTimeSec.toString(), "Sign" to signStr) // body param val requestParams: MutableMap = mutableMapOf("AppId" to AndroidUtil.getPackageId(), "DeviceId" to DeviceUtil.generateDeviceId()) val userId = AccountManager.getAccount().userId if (userId > 0) { requestParams.put("UserId", userId.toString()) } val joinZeroBuyItemIds = SpUtil.instance().getList(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS) requestParams.put("ActivityId", zeroWithdrawItem.purchase_id.toString()) // withdraw 相关参数: val bankCPFAccount = AccountManager.getAccount().bankInfo?.bankAccount!! val accountType = "CPF" requestParams.put("Account", bankCPFAccount) requestParams.put("AccountType", accountType) requestParams.put("Country", Country.BR.name) requestParams.put("DocumentType", accountType) requestParams.put("DocumentId", bankCPFAccount) requestParams.put("BankCode", AccountManager.getAccount().bankInfo?.bankAccount!!) val signOriginStr = "${zeroWithdrawItem.purchase_id}-${userId}-${bankCPFAccount}-${accountType}-${bankCPFAccount}-${accountType}-${ZEROBUY_SECRET}" requestParams.put("Sign", MD5Util.md5(signOriginStr)!!) val result = NetworkUtil.post("${VidiConst.URL_ZERO_BUY}/any", requestHeaders, requestParams, joinZeroBuyItemIds) when (result) { is Result.Success -> { val respObj = AndroidUtil.json2Object(result.data.string()) respObj?.let { if (it.code == 0 && it.content.isNotEmpty()) { zeroWithdrawItem.orderId = respObj.content zeroWithdrawItem.withdrawState = TRANSACTION_STATE_ONGOING saveWinWithdrawInfos() loopCheckTransactionState() AndroidUtil.showToast(R.string.zero_withdraw_ongoing) return@launch } else { zeroWithdrawItem.withdrawState = TRANSACTION_STATE_FAIL zeroWithdrawItem.failReason = respObj.code saveWinWithdrawInfos() AndroidUtil.showToast(R.string.zero_withdraw_failed) } } } is Result.Error -> { AndroidUtil.showToast(R.string.net_error) } is Result.Loading -> { } } } } private fun requestZeroWithdrawResult(zeroWithdrawItem: WinZeroWithdrawInfoItem) { mBgScope.launch { // header val operationVal = VidiConst.ZERO_WITHDRAW_RESULT_CHECK val curTimeSec = System.currentTimeMillis()/1000 val signStr = RequestUtil.getZeroBuyRequestSign(curTimeSec, operationVal) val requestHeaders = mapOf("Operation" to operationVal.toString(), "Timestamp" to curTimeSec.toString(), "Sign" to signStr) // body param val requestParams: MutableMap = mutableMapOf("AppId" to AndroidUtil.getPackageId()) val userId = AccountManager.getAccount().userId if (userId > 0) { requestParams.put("UserId", userId.toString()) } val joinZeroBuyItemIds = SpUtil.instance().getList(SpUtil.KEY_ZEROBUY_JOINED_ACTIVITY_IDS) requestParams.put("ActivityId", zeroWithdrawItem.purchase_id.toString()) // withdraw check result 相关参数: requestParams.put("device_id", zeroWithdrawItem.orderId) requestParams.put("order_id", zeroWithdrawItem.orderId) /*val signOriginStr = "${zeroWithdrawItem.purchase_id}-${userId}-${bankCPFAccount}-${accountType}-${bankCPFAccount}-${accountType}-${ZEROBUY_SECRET}" requestParams.put("Sign", MD5Util.md5(signOriginStr)!!)*/ val result = NetworkUtil.post("${VidiConst.URL_ZERO_BUY}/any", requestHeaders, requestParams, joinZeroBuyItemIds) when (result) { is Result.Success -> { val respObj = AndroidUtil.json2Object(result.data.string()) respObj?.let { if (it.code == 0 && it.content.isNotEmpty()) { zeroWithdrawItem.orderId = respObj.content zeroWithdrawItem.withdrawState = TRANSACTION_STATE_ONGOING saveWinWithdrawInfos() AndroidUtil.showToast(R.string.zero_withdraw_ongoing) return@launch } else { zeroWithdrawItem.withdrawState = TRANSACTION_STATE_FAIL zeroWithdrawItem.failReason = respObj.code saveWinWithdrawInfos() AndroidUtil.showToast(R.string.zero_withdraw_failed) } } } is Result.Error -> { AndroidUtil.showToast(R.string.net_error) } is Result.Loading -> { } } } } fun startWithdrawProcess(activity: Activity, item: ZeroBuyItem) { val zeroWithdrawInfoItem = getZeroWithdrawItem(item) if (couldStartWithdraw(item)) { val onConfirmed: (cashNum: Float)->Unit = { requestZeroWithdrawReward(zeroWithdrawInfoItem) } if (AccountManager.isBankAccountExist()) { WithdrawInfoConfirmDialog(activity, onConfirmed).setWithDrawCashNumStr(zeroWithdrawInfoItem.winCashNumStr!!).show() } else { WithdrawBindBankDialog(activity = activity, onConfirmed).setWithDrawCashNumStr(zeroWithdrawInfoItem.winCashNumStr!!).show() } } else { when (zeroWithdrawInfoItem.withdrawState) { TRANSACTION_STATE_ONGOING -> { AndroidUtil.showToast(R.string.claim_reward_onging) } TRANSACTION_STATE_SUCCESS -> { AndroidUtil.showToast(R.string.has_claimed_reward) } } } } private fun loopCheckTransactionState() { var unCheckCount = 0 try { mRecordLocker.lock() mRecordList.forEach { record -> if (record.withdrawState == TRANSACTION_STATE_ONGOING) { unCheckCount++ } } } finally { mRecordLocker.unlock() } if (unCheckCount > 0) { try { mRecordLocker.lock() mRecordList.forEachIndexed { index, record -> if (record.withdrawState == TRANSACTION_STATE_ONGOING) { requestZeroWithdrawResult(record) } } } finally { mRecordLocker.unlock() } } mLooperHandler.postDelayed(mLoopRunnable, 20 * 1000) } } data class WinZeroWithdrawInfoItem( val purchase_id: Int = 0, val purchase_title: String? = "", val winCashNumStr: String? = "", var operateMs: Long = System.currentTimeMillis(), var withdrawState: Int = TRANSACTION_STATE_UNSTART, var failReason: Int = 0, var hasShowResultDialog: Boolean = false, var orderId: String = "", ) enum class Country(val code: Int) { ANY(0), // 任意国家 BR(1), // 巴西 TR(2), // 土耳其 PK(3) // 巴基斯坦 } enum class Currency(val code: Int) { ANY(0), // 任意国家货币 BRL(1), // 巴西雷亚尔 TRY(2), // 土耳其里拉 PKR(3) // 巴基斯坦卢比 } enum class Language(val code: Int) { ANY(0), // 任意国家语言 PT(1), // 葡萄牙语(巴西,葡萄牙) TR(2), // 土耳其语(土耳其) UR(3) // 乌尔都语(巴基斯坦) }