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

565 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.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
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.R
import com.yingmao.clash.base.BaseActivity
import com.yingmao.clash.conf.BZYConstants
import com.yingmao.clash.entity.PayUploadParamData
import com.yingmao.clash.fragment.recharge.RechargeViewModel
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.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.RxDialogShapeLoading
import kotlinx.coroutines.DelicateCoroutinesApi
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 userIdentity: TextView
private lateinit var userIdentityNumber: TextView
private lateinit var expirationTime: TextView
private lateinit var userIdentityNumberCopy: TextView
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 var selectedGrade: Grade? = null
private lateinit var rxDialogShapeLoading: RxDialogShapeLoading
private var outTradeNo = ""
private var selectedGradeID :Int=0
//stripePay 支付
private var paymentIntentClientSecret: String = ""
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() {
setExpireDate()
if(checkExpire()){
userIdentity.text=resources.getString(R.string.TemporaryUser)
}else{
userIdentity.text=resources.getString(R.string.VIPMember)
}
userIdentityNumber.text = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME)
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)
userIdentity=findViewById(R.id.userIdentity)
userIdentityNumber=findViewById(R.id.userIdentityNumber)
expirationTime=findViewById(R.id.expirationTime)
userIdentityNumberCopy=findViewById(R.id.userIdentityNumberCopy)
swipeLayout=findViewById(R.id.swipeLayout)
rvRechargeList=findViewById(R.id.rvRechargeList)
tvPay=findViewById(R.id.tvPay)
tvRechargeRecord=findViewById(R.id.tvRechargeRecord)
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 {
finish() // 关闭当前 Activity
}
userIdentityNumberCopy.setOnClickListener {
val userName = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME)
val clipboardManager =getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText("text", userName)
clipboardManager.setPrimaryClip(clipData)
RxToast.info(resources.getString(R.string.CopyToClipboard))
}
userIdentityNumber.setOnClickListener {
val userName = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME)
val clipboardManager =getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText("text", userName)
clipboardManager.setPrimaryClip(clipData)
RxToast.info(resources.getString(R.string.CopyToClipboard))
}
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")
}
}
@SuppressLint("SimpleDateFormat")
fun setExpireDate() {
val isExpire = checkExpire()
var endTimeInfo = "--"
if (isExpire) {
endTimeInfo = resources.getString(R.string.AccountExpired)
} else {
val validPeriod = MMKV.defaultMMKV().decodeLong(BZYConstants.MMKV_KEY_VPN_VALID_PERIOD)
val decodeString = MMKV.defaultMMKV().decodeString(BZYConstants.languageInfo, "")
if (decodeString.isNullOrEmpty()) {
//获取当前系统语言
val config = resources.configuration
val language = config.locale.language
if (language.equals("en")) {
val dateFormat = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val localEN = Locale.ENGLISH
SimpleDateFormat("MM/dd/yyyy HH:mm", localEN)
} else {
val localEN = Locale.ENGLISH
SimpleDateFormat("MM/dd/yyyy HH:mm", localEN)
}
endTimeInfo = dateFormat.format(validPeriod)
} else {
val dateFormat = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
SimpleDateFormat("yyyy年MM月dd日 HH:mm")
} else {
SimpleDateFormat("yyyy年MM月dd日 HH:mm")
}
endTimeInfo = dateFormat.format(validPeriod)
}
} else {
if (decodeString == "English") {
val dateFormat = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val locale = Locale.ENGLISH
SimpleDateFormat("MM/dd/yyyy HH:mm", locale)
} else {
val locale = Locale.ENGLISH
SimpleDateFormat("MM/dd/yyyy HH:mm", locale)
}
endTimeInfo = dateFormat.format(validPeriod)
} else {
val dateFormat = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
SimpleDateFormat("yyyy年MM月dd日 HH:mm")
} else {
SimpleDateFormat("yyyy年MM月dd日 HH:mm")
}
endTimeInfo = dateFormat.format(validPeriod)
}
}
}
expirationTime.text = endTimeInfo
}
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 { it ->
if (it.code != "1000") {
RxToast.error(if (it.message.isNullOrBlank())resources.getString(R.string.FailedRechargeList)+ "${it.code}" else "${it.code}:${it.message}")
} else {
it.data?.let { it1 ->
it1.grade?.let {
if (it.size > 0) {
initAdapter(it)
}
}
}
}
}
}
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))
}
}
}
else->{
}
}
}
override fun httpFailure(httpStatus: HttpStatus.Failure) {
when (httpStatus.reqType) {
HttpReqType.GET_RECHARGE_INFO -> {
showDomainList()
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)
}
override fun cancel() {
com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN cancel")
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: MutableList<Grade>) {
Log.i("dataInfo::${recharge.size}")
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}")
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
)
for (index in data.payType!!){
if(index.payModel==10){
findViewById<LinearLayout>(R.id.llAggregatePayment).visibility= View.VISIBLE
val JUhePay=findViewById<TextView>(R.id.JUhePay)
JUhePay.visibility= View.VISIBLE
JUhePay.text = index.payChannel
if(index.payType==1){
val ivAlipay =findViewById<AppCompatImageView>(R.id.ivAlipay)
ivAlipay.visibility= View.VISIBLE
ivAlipay.setOnClickListener {
val payModel = index.payModel
val payType =index.payType
val payParam = index.payParam
if (payModel != null && payType != null && payParam != null) {
viewModel.orderPayment(data, payModel, payType, payParam)
} else {
viewModel.orderPayment(data, 10, 1, "ip@影喵充值")
}
}
}else if(index.payType==2){
val ivWechatPay= findViewById<AppCompatImageView>(R.id.ivWechatPay)
ivWechatPay.visibility= View.VISIBLE
ivWechatPay.setOnClickListener {
val payModel = index.payModel
val payType =index.payType
val payParam =index.payParam
if (payModel != null && payType != null && payParam != null) {
viewModel.orderPayment(data, payModel, payType, payParam)
} else {
viewModel.orderPayment(data, 10, 2, "ip@影喵充值")
}
}
}
}else if(index.payModel==11){
findViewById<LinearLayout>(R.id.llQuickPayment).visibility= View.VISIBLE
val KJPay=findViewById<TextView>(R.id.KJPay)
KJPay.visibility= View.VISIBLE
KJPay.text = index.payChannel
if(index.payType==1){
val ivQuickPayment=findViewById<AppCompatImageView>(R.id.ivQuickPayment)
ivQuickPayment.visibility= View.VISIBLE
ivQuickPayment.setOnClickListener {
val payModel =index.payModel
val payType =index.payType
val payParam =index.payParam
if (payModel != null && payType != null && payParam != null) {
viewModel.orderPayment(data, payModel, payType, payParam)
} else {
viewModel.orderPayment(data, 11, 1, "ip@影喵充值")
}
}
}else if(index.payType==2){
val ivQPWechatPay=findViewById<AppCompatImageView>(R.id.ivQPWechatPay)
ivQPWechatPay.visibility= View.VISIBLE
ivQPWechatPay.setOnClickListener {
val payModel =index.payModel
val payType =index.payType
val payParam =index.payParam
if (payModel != null && payType != null && payParam != null) {
viewModel.orderPayment(data, payModel, payType, payParam)
} else {
viewModel.orderPayment(data, 11, 1, "ip@影喵充值")
}
}
}
}else if(index.payModel==7){
findViewById<LinearLayout>(R.id.llStripe).visibility= View.VISIBLE
findViewById<LinearLayout>(R.id.llStripePay).visibility= View.VISIBLE
findViewById<TextView>(R.id.tvStripePay).visibility= View.VISIBLE
findViewById<AppCompatImageView>(R.id.ivStripeAlipay).visibility= View.VISIBLE
findViewById<AppCompatImageView>(R.id.ivStripeAlipay).setOnClickListener {
if(selectedGradeID!=0){
if(!PayUtils.isAlipayInstalled(this@MemberRechargeActivity)){
RxToast.error(resources.getString(R.string.AlipayNotInstalled))
return@setOnClickListener
}
dismiss()
showLoading(resources.getString(R.string.PaymentIn),this@MemberRechargeActivity)
Log.i("PayGradeID:${selectedGradeID}")
viewModel.getPayClientSecret(selectedGradeID)
}else{
RxToast.info(getString(R.string.NoPaymentReceipt))
}
}
}
}
getCustomView().findViewById<AppCompatImageView>(R.id.ivBack).setOnClickListener {
dismiss()
}
}
}
}
}
}