yijianlianUI/app/src/main/java/com/yingmao/clash/act/MemberRechargeActivity.kt

581 lines
25 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.yingmao.clash.act
import android.annotation.SuppressLint
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import com.alipay.sdk.app.PayTask
import com.cncat.vpn.common.log.Log
import com.orhanobut.logger.Logger
import com.stripe.android.PaymentConfiguration
import com.stripe.android.Stripe
import com.stripe.android.confirmAlipayPayment
import com.stripe.android.model.ConfirmPaymentIntentParams
import com.stripe.android.model.StripeIntent
import com.tencent.mmkv.MMKV
import com.yingmao.clash.BuildConfig
import com.yingmao.clash.R
import com.yingmao.clash.act.NewMainActivity.Companion.profileBinder
import com.yingmao.clash.app.MainApplication
import com.yingmao.clash.base.BaseActivity
import com.yingmao.clash.conf.BZYConstants
import com.yingmao.clash.entity.CheckLoginRsp
import com.yingmao.clash.entity.PayUploadParamData
import com.yingmao.clash.entity.RechargeModelEntity
import com.yingmao.clash.fragment.NewAccFragment
import com.yingmao.clash.fragment.NewAccFragment.Companion.clashRunning
import com.yingmao.clash.fragment.recharge.RechargeViewModel
import com.yingmao.clash.fragment.recharge.adapter.RechargeModelAdapter
import com.yingmao.clash.fragment.recharge.adapter.VIPRechargeAdapter
import com.yingmao.clash.net.http.HttpReqType
import com.yingmao.clash.net.http.HttpStatus
import com.yingmao.clash.net.http.entity.Grade
import com.yingmao.clash.net.http.entity.PayRsp
import com.yingmao.clash.net.http.entity.RechargeInfo
import com.yingmao.clash.net.http.entity.RechargeInfoRsp
import com.yingmao.clash.net.http.entity.Trade
import com.yingmao.clash.util.CommonUtils
import com.yingmao.clash.util.PayUtils
import com.yingmao.clash.util.ThreadUtils
import com.yingmao.clash.view.RxToast
import com.yingmao.clash.view.dialog.DialogDoMainChoose
import com.yingmao.clash.view.dialog.PayConfirmDialog
import com.yingmao.clash.view.dialog.RxDialogShapeLoading
import com.yingmao.clash.view.dialog.SplashDialog
import com.yingmao.clash.vm.MainAtyVM
import com.yingmao.clash.webview.BZYWebViewKeFu
import com.yingmao.clash.webview.CustomerServiceWebView
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.util.Locale
class MemberRechargeActivity : BaseActivity() {
private lateinit var aiBack: AppCompatImageView
private lateinit var viewModel: RechargeViewModel
private lateinit var swipeLayout: SwipeRefreshLayout
private lateinit var rvRechargeList:RecyclerView
private lateinit var tvPay:TextView
private lateinit var tvRechargeRecord:TextView
private lateinit var clCustom: ConstraintLayout
private var selectedGrade: Grade? = null
private lateinit var rxDialogShapeLoading: RxDialogShapeLoading
private var outTradeNo = ""
private var selectedGradeID :Int=0
//stripePay 支付
private var paymentIntentClientSecret: String = ""
private lateinit var mainAtyVM: MainAtyVM
private val stripe: Stripe by lazy {
Stripe(
this@MemberRechargeActivity,
PaymentConfiguration.getInstance(this@MemberRechargeActivity).publishableKey
)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.member_recharge_layout)
initView()
initData()
}
private fun initData() {
mainAtyVM = ViewModelProvider(this)[MainAtyVM::class.java]
viewModel = ViewModelProvider(this)[RechargeViewModel::class.java]
observe(this, viewModel)
//获取充值列表
val username = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME,"")!!
val phToken = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN,"")!!
val userId = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_USER_ID)!!
viewModel.getPhRechargeInfo(username, phToken, userId)
}
private fun initView() {
aiBack=findViewById(R.id.aiBack)
swipeLayout=findViewById(R.id.swipeLayout)
rvRechargeList=findViewById(R.id.rvRechargeList)
tvPay=findViewById(R.id.tvPay)
tvRechargeRecord=findViewById(R.id.tvRechargeRecord)
clCustom=findViewById(R.id.clCustom)
swipeLayout.setColorSchemeColors(Color.rgb(47, 223, 189))
swipeLayout.setOnRefreshListener {
selectedGrade = null
val username = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME,"")!!
val phToken = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN,"")!!
//获取充值列表
val userId = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_USER_ID)!!
viewModel.getPhRechargeInfo(username, phToken, userId)
}
aiBack.setOnClickListener {
val intent=Intent()
this.setResult(1000,intent)
finish() // 关闭当前 Activity
}
tvRechargeRecord.setOnClickListener {
startActivity(Intent(this@MemberRechargeActivity, ExpensesRecordActivity::class.java))
}
tvPay.setOnClickListener {
if (selectedGrade == null) {
RxToast.info(resources.getString(R.string.selectRechargeAmount))
return@setOnClickListener
}
viewModel.pay("1", selectedGrade!!, "pointCard")
}
clCustom.setOnClickListener {
startActivity(Intent(this@MemberRechargeActivity, CustomerServiceWebView::class.java))
}
}
private fun checkExpire(): Boolean {
val validPeriod = MMKV.defaultMMKV().decodeLong(BZYConstants.MMKV_KEY_VPN_VALID_PERIOD)
if (validPeriod > 0) {
val nowTime = System.currentTimeMillis()
Log.d("validPeriod==>$validPeriod, nowTime==>$nowTime")
if (validPeriod >= nowTime) {
return false
}
}
return true
}
override fun httpLoading(httpStatus: HttpStatus.Loading) {
when (httpStatus.reqType) {
HttpReqType.GET_RECHARGE_INFO -> {
Logger.d("获取充值续费信息")
swipeLayout.isRefreshing = true
}
HttpReqType.PAY -> {
Logger.d("支付获取订单号")
showLoadingDialog(resources.getString(R.string.GeneratingOrder))
}
else->{
}
}
}
override fun httpSuccess(httpStatus: HttpStatus.Success) {
when (httpStatus.reqType) {
HttpReqType.GET_RECHARGE_INFO -> {
Logger.d("获取充值续费信息请求成功")
swipeLayout.isRefreshing = false
(httpStatus.rsp as RechargeInfoRsp).let {
when (it.code) {
"1088" -> {
RxToast.info(resources.getString(R.string.LoginOut))
cleanUserInfo()
}
"1000" -> {
it.data?.let { rechargeInfo ->
initAdapter(rechargeInfo)
}
}
else -> {
RxToast.error(if (it.message.isNullOrBlank())resources.getString(R.string.FailedRechargeList)+ "${it.code}" else "${it.code}:${it.message}")
}
}
}
}
HttpReqType.PAY -> {
hideLoadingDialog()
Logger.d("生成订单请求成功")
(httpStatus.rsp as PayRsp).let { rsp ->
if (rsp.code != "1000") {
RxToast.error(if (rsp.message.isNullOrBlank()) resources.getString(R.string.OrderGenerationFailed)+"${rsp.code}" else "${rsp.code}:${rsp.message}")
} else {
let {
outTradeNo = rsp.data?.outTradeNo!!
val newUrl = rsp.data.payUrl.toString()
orderPayment(rsp.data)
Logger.e("支付url${newUrl}")
}
}
}
}
HttpReqType.unionPay -> {
(httpStatus.rsp as PayRsp).let { rsp ->
if (rsp.code != "1000") {
RxToast.error(if (rsp.message.isNullOrBlank()) resources.getString(R.string.OrderGenerationFailed)+"${rsp.code}" else "${rsp.code}:${rsp.message}")
} else {
if (rsp.data != null) {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(rsp.data.payUrl)))
}
}
}
}
HttpReqType.StripeType ->{
(httpStatus.rsp as PayUploadParamData).let {
if(it.data!=null){
paymentIntentClientSecret= it.data.clientSecret.toString()
startCheckout()
}else{
hideLoading()
RxToast.info(getString(R.string.NoPaymentReceipt))
}
}
}
HttpReqType.StripeWeChat ->{
(httpStatus.rsp as PayUploadParamData).let {
if(it.data!=null){
paymentIntentClientSecret= it.data.clientSecret.toString()
val serviceUrl = MMKV.defaultMMKV().decodeString(
BZYConstants.MMKV_KEY_CURRENT_HOST,
BuildConfig.service_url
)!!
val payUrl=serviceUrl+"/78zccgy0nsgknh9n4/iiii.html?s=${it.data.clientSecret.toString()}"
val uri = Uri.parse(payUrl)
val intent = Intent(Intent.ACTION_VIEW)
intent.setData(uri)
startActivity(intent)
}else{
hideLoading()
RxToast.info(getString(R.string.NoPaymentReceipt))
}
}
}
else->{
}
}
}
override fun httpFailure(httpStatus: HttpStatus.Failure) {
when (httpStatus.reqType) {
HttpReqType.GET_RECHARGE_INFO -> {
if (super.switchServer2()) {
val username =
MMKV.defaultMMKV()
.decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")!!
val phToken =
MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN, "")!!
val userId = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_USER_ID)!!
viewModel.getPhRechargeInfo(username, phToken, userId)
}
Logger.d("获取充值续费信息异常${httpStatus.msg}")
swipeLayout.isRefreshing = false
RxToast.error(resources.getString(R.string.DataError))
}
HttpReqType.PAY -> {
Logger.d("获取支付订单号异常${httpStatus.msg}")
RxToast.error(resources.getString(R.string.DataPayNumber))
}
HttpReqType.unionPay -> {
Logger.d("OrderGenerationFailed${httpStatus.msg}")
RxToast.error(resources.getString(R.string.OrderGenerationFailed))
}
HttpReqType.StripeType -> {
hideLoading()
RxToast.error(resources.getString(R.string.NoPaymentReceipt))
}
else->{
}
}
}
var dialogDoMainChoose: DialogDoMainChoose? = null
private fun showDomainList() {
try {
SplashHelper(viewModel).getHostWithFallback { success ->
MainScope().launch {
if (success) {
if (dialogDoMainChoose == null) {
dialogDoMainChoose = DialogDoMainChoose(this@MemberRechargeActivity)
}
if (dialogDoMainChoose?.isShowing == false) {
dialogDoMainChoose?.setOnTryButtonListener(object :
DialogDoMainChoose.OnTryButtonListener {
override fun tryButton() {
val username = MMKV.defaultMMKV()
.decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")!!
val phToken = MMKV.defaultMMKV()
.decodeString(BZYConstants.MMKV_KEY_PH_TOKEN, "")!!
// viewModel.getPointCardSurplus(username, phToken)
val userId = MMKV.defaultMMKV()
.decodeString(BZYConstants.MMKV_KEY_USER_ID)!!
viewModel.getPhRechargeInfo(username, phToken, userId)
dialogDoMainChoose?.dismiss()
}
override fun cancel() {
com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN cancel")
dialogDoMainChoose?.dismiss()
}
})
dialogDoMainChoose?.setOnListItemListener(object :
DialogDoMainChoose.OnListItemListener {
override fun listItemClick() {
MainApplication.restartApp(this@MemberRechargeActivity, object :
MainApplication.OnRestartButtonListener {
override fun enterButton() {
}
override fun cancelButton() {
val username = MMKV.defaultMMKV()
.decodeString(
BZYConstants.MMKV_KEY_REMEMBER_USERNAME,
""
)!!
val phToken = MMKV.defaultMMKV()
.decodeString(BZYConstants.MMKV_KEY_PH_TOKEN, "")!!
val userId = MMKV.defaultMMKV()
.decodeString(BZYConstants.MMKV_KEY_USER_ID)!!
viewModel.getPhRechargeInfo(username, phToken, userId)
dialogDoMainChoose?.dismiss()
}
})
}
})
dialogDoMainChoose?.show()
}
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun showLoadingDialog(content: String) {
apply {
if (!::rxDialogShapeLoading.isInitialized) {
rxDialogShapeLoading = RxDialogShapeLoading(this)
}
rxDialogShapeLoading.setLoadingText(content)
rxDialogShapeLoading.setCancelable(false)
if (!rxDialogShapeLoading.isShowing) {
rxDialogShapeLoading.show()
}
}
}
private fun hideLoadingDialog() {
if (::rxDialogShapeLoading.isInitialized && rxDialogShapeLoading.isShowing) {
rxDialogShapeLoading.cancel()
}
}
private fun initAdapter(recharge: RechargeInfo) {
val rechargeListAdapter = VIPRechargeAdapter()
rvRechargeList.layoutManager =GridLayoutManager(CommonUtils.getApp(), 2, GridLayoutManager.VERTICAL, false)
rechargeListAdapter.setCloudServiceList(recharge,this@MemberRechargeActivity)
rvRechargeList.adapter=rechargeListAdapter
rechargeListAdapter.setListener(object :VIPRechargeAdapter.VIPRechargeItemClickListener{
@SuppressLint("SetTextI18n")
override fun onItemClick(noteItem: Grade?) {
selectedGrade=noteItem
val amount = selectedGrade!!.amount?.toFloat()
if (amount != null) {
if(selectedGrade!!.id!=null){
selectedGradeID = selectedGrade!!.id!!
}
val decimalFormat = DecimalFormat("#0.00")
tvPay.text =resources.getString(R.string.ActivateVIP)+"(¥${decimalFormat.format(amount)}"
}
}
})
}
@OptIn(DelicateCoroutinesApi::class)
private fun startCheckout() {
GlobalScope.launch {
runCatching {
stripe.confirmAlipayPayment(
ConfirmPaymentIntentParams.createAlipay(paymentIntentClientSecret),
{ data -> PayTask(this@MemberRechargeActivity).payV2(data, true) }
)
}.fold(
onSuccess = { result ->
hideLoading()
val paymentIntent = result.intent
when (paymentIntent.status) {
StripeIntent.Status.Succeeded -> {
Log.i("startCheckout支付成功")
ThreadUtils.runOnUiThread {
RxToast.info(getString(R.string.PaymentCompleted))
}
}
StripeIntent.Status.RequiresAction -> {
Log.i("startCheckoutRequiresAction")
ThreadUtils.runOnUiThread {
RxToast.info(getString(R.string.PaymentCancellation))
}
}
else -> {
Log.i("startCheckout status::${paymentIntent.status}")
}
}
},
onFailure = {
Log.i("startCheckout支付失败${it.message}")
hideLoading()
ThreadUtils.runOnUiThread {
RxToast.info(getString(R.string.NoPaymentReceipt))
}
}
)
}
}
private fun orderPayment(data: Trade) {
Log.i("PayGradeIDTEST:${selectedGradeID}")
val payList = mutableListOf<RechargeModelEntity>()
if (data.payType != null) {
let {
MaterialDialog(it).show {
this.cancelable(true)
cornerRadius(res = R.dimen.dp_10)
customView(
R.layout.backup_payment_dialog,
scrollable = false,
noVerticalPadding = true,
horizontalPadding = false
)
val rvPay = findViewById<RecyclerView>(R.id.rvPay)
for (index in data.payType!!) {
if (index.payModel != null && index.payChannel != null && index.payType != null) {
val rme = RechargeModelEntity(
index.payModel!!,
index.payChannel!!,
index.payParam!!,
index.payType!!,
index.payOrder!!
)
payList.add(rme)
}
}
// payList.sortBy { item -> item.payModel }
//7是快捷支付排第一
payList.sortBy { if (it.payModel == 7) 0 else 1 }
val groupBy = payList.groupBy { item -> item.payModel }
val rcmAdapter = RechargeModelAdapter()
rvPay.layoutManager = LinearLayoutManager(this@MemberRechargeActivity)
rcmAdapter.setCloudServiceList(groupBy, this@MemberRechargeActivity)
rvPay.adapter = rcmAdapter
rcmAdapter.setListener(object :
RechargeModelAdapter.RechargeModelClickListener {
override fun onItemClick(
rcEntity: RechargeModelEntity?,
) {
if (rcEntity?.payModel == 7 && rcEntity.payType == 1) {
if (selectedGradeID != 0) {
if (!PayUtils.isAlipayInstalled(this@MemberRechargeActivity)) {
RxToast.error(resources.getString(R.string.AlipayNotInstalled))
return
}
dismiss()
showLoading(
resources.getString(R.string.PaymentIn),
this@MemberRechargeActivity
)
Log.i("PayGradeID:${selectedGradeID}")
viewModel.getPayClientSecret(selectedGradeID)
} else {
dismiss()
RxToast.info(getString(R.string.NoPaymentReceipt))
}
} else if (rcEntity?.payModel == 7 && rcEntity.payType == 2) {
if (selectedGradeID != 0) {
viewModel.getWeChatPayClientSecret(selectedGradeID)
dismiss()
} else {
dismiss()
RxToast.info(getString(R.string.NoPaymentReceipt))
}
} else {
val payModel = rcEntity?.payModel ?: 0
val payType = rcEntity?.payType ?: 0
val payParam = rcEntity?.payParam ?: ""
viewModel.orderPayment(data, payModel, payType, payParam)
}
}
})
getCustomView().findViewById<AppCompatImageView>(R.id.ivBack)
.setOnClickListener {
dismiss()
}
}
}
}
}
override fun onBackPressed() {
val intent=Intent()
this.setResult(1000,intent)
finish() // 关闭当前 Activity
super.onBackPressed()
}
override fun onDestroy() {
super.onDestroy()
if(dialogDoMainChoose!=null){
if(dialogDoMainChoose!!.isShowing){
dialogDoMainChoose!!.dismiss()
dialogDoMainChoose=null
}
}
}
private fun cleanUserInfo() {
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_PH_TOKEN)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_TOKEN)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_CURRENT_NODE)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_SELECTED_NAME_KEY)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_VPN_UserCommand)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.PROFILE_SUB_URL)
Log.d("cleanUserInfo clashRunning==>$clashRunning")
if (clashRunning) {
NewAccFragment().stopClash()
}
mainAtyVM.stopHeartBeat()
cleanProfile()
val intent=Intent(CommonUtils.getApp(), LoginActivity::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
finish()
}
private fun cleanProfile() {
Log.d("cleanProfile start")
GlobalScope.launch(Dispatchers.IO) {
profileBinder?.let { pm ->
pm.queryAll().forEach { profile ->
Log.d("cleanProfile go delete name==>${profile.name}, uuid==>${profile.uuid}")
pm.delete(profile.uuid)
}
} ?: let {
Log.d("profileBinder is null")
}
}
}
}