1.增加信用卡支付信息展示
This commit is contained in:
@@ -28,9 +28,9 @@ android {
|
||||
applicationId "com.abbidot.tracker"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 35
|
||||
versionCode 2211
|
||||
versionName "2.2.11"
|
||||
// versionName "2.2.11-Beta1"
|
||||
versionCode 2212
|
||||
// versionName "2.2.12"
|
||||
versionName "2.2.12-Beta1"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class CreditCardAdapter(
|
||||
}
|
||||
primary.visibility = if (item.isPrimary) View.VISIBLE else View.GONE
|
||||
holder.getTextView(R.id.tv_credit_card_number_item).apply {
|
||||
val formatCardNumber = Util.formatCardNumber(item.cardNumber)
|
||||
val formatCardNumber = maskString(Util.formatCardNumber(item.cardNumber))
|
||||
val cardLogoImageId = Util.getCreditCardType(item.cardNumber)
|
||||
text = formatCardNumber
|
||||
if (cardLogoImageId == 0) setCompoundDrawablesWithIntrinsicBounds(
|
||||
@@ -50,4 +50,24 @@ class CreditCardAdapter(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun maskString(input: String): String {
|
||||
if (input.isBlank()) return input
|
||||
// 先去除原有所有空格,统一重新4位分隔
|
||||
val noSpace = input.replace(" ", "")
|
||||
// 每4位分组加空格
|
||||
val splitStr = buildString {
|
||||
for (i in noSpace.indices step 4) {
|
||||
val end = minOf(i + 4, noSpace.length)
|
||||
append(noSpace.substring(i, end))
|
||||
if (end != noSpace.length) append(" ")
|
||||
}
|
||||
}
|
||||
// 再对分隔后的字符串脱敏(仅最后4位明文,其余非空格变*)
|
||||
if (splitStr.length <= 4) return splitStr
|
||||
val hidePart = splitStr.dropLast(4)
|
||||
val showPart = splitStr.takeLast(4)
|
||||
val maskHide = hidePart.map { if (it == ' ') ' ' else '*' }.joinToString("")
|
||||
return maskHide + showPart
|
||||
}
|
||||
}
|
||||
@@ -56,8 +56,11 @@ interface INetworkService {
|
||||
|
||||
//亚马逊服务器(国外ip)
|
||||
const val BASE_URL_ABROAD = "https://aws.abbidot.com/abbidot/"
|
||||
// const val BASE_URL_ABROAD = "http://192.168.0.220:8080/abbidot/"
|
||||
// const val BASE_URL_ABROAD = "$IP_SERVER:8443/abbidotServer/"
|
||||
|
||||
//测试服务器
|
||||
const val BASE_URL_TEST = "https://aws.abbidot.com:8443/abbidot/"
|
||||
// const val BASE_URL_TEST = "http://aws.abbidot.com:8089/abbidot/"
|
||||
// const val BASE_URL_ABROAD = "http://192.168.0.220:8080/abbidot/"
|
||||
|
||||
//亚马逊服务器(国内ip)
|
||||
// const val BASE_URL_CN = "$IP_SERVER:8443/abbidotServer/"
|
||||
@@ -1133,6 +1136,16 @@ interface INetworkService {
|
||||
@Field("iccid") iccid: String
|
||||
): BaseResponse<String>
|
||||
|
||||
/**
|
||||
* 保存支付信息
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST("pay$STRIPE_VERSION_NUMBER/savePaymentMethodInfo")
|
||||
suspend fun savePaymentMethodInfo(
|
||||
@Field("userId") orderId: String,
|
||||
@Field("paymentMethodID") paymentMethodID: String
|
||||
): BaseResponse<String>
|
||||
|
||||
/**
|
||||
* Stripe支付 Rsa算法解密测试
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.abbidot.tracker.retrofit2
|
||||
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.network.base.BaseNetworkApi
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.tracker.bean.FencesBean
|
||||
import com.abbidot.tracker.bean.PayResultBean
|
||||
import com.abbidot.tracker.bean.SetMealBean
|
||||
@@ -1008,9 +1006,8 @@ object NetworkApi : BaseNetworkApi<INetworkService>(INetworkService.BASE_URL) {
|
||||
* Stripe支付创建消费用户
|
||||
*/
|
||||
suspend fun createCustomer(
|
||||
param: String, userId: String, userName: String, email: String
|
||||
param: String, userId: String, userName: String, email: String, paymentMethodID: String
|
||||
) = getResult {
|
||||
val paymentMethodID = MMKVUtil.getString(MMKVKey.PaymentMethodID)
|
||||
service.createCustomer(param, userId, userName, email, paymentMethodID)
|
||||
}
|
||||
|
||||
@@ -1062,6 +1059,13 @@ object NetworkApi : BaseNetworkApi<INetworkService>(INetworkService.BASE_URL) {
|
||||
service.cancelStripeSubscription(orderId, subscriptionId, iccid)
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存支付信息
|
||||
*/
|
||||
suspend fun savePaymentMethodInfo(userId: String, paymentMethodID: String) = getResult {
|
||||
service.savePaymentMethodInfo(userId, paymentMethodID)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stripe支付 Rsa算法解密测试
|
||||
*/
|
||||
|
||||
@@ -81,11 +81,12 @@ class SplashActivity : QMUIActivity() {
|
||||
Utils.SECRET_KEY = Util.getMetadata(applicationContext, KeyNames.HTTP_REQUEST_KEY)
|
||||
INetworkService.apply {
|
||||
//国内外服务器切换域名
|
||||
BASE_URL = if (AppUtils.isChina()) {
|
||||
BASE_URL = if (AppUtils.isDebug()) BASE_URL_TEST
|
||||
else if (AppUtils.isChina())
|
||||
BASE_URL_CN
|
||||
} else {
|
||||
else
|
||||
BASE_URL_ABROAD
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SRBleUtil.instance.init(application)
|
||||
|
||||
@@ -267,7 +267,8 @@ class PetProfileActivity :
|
||||
private fun setPetData() {
|
||||
mViewBinding.apply {
|
||||
mPetBean?.let {
|
||||
ViewUtil.instance.setPetTypeHead(mContext,
|
||||
ViewUtil.instance.setPetTypeHead(
|
||||
mContext,
|
||||
ilPetProfileHeadLayout.ilPetProfileHead.appHeadImage, it.imgurl, it.petType
|
||||
)
|
||||
|
||||
@@ -332,7 +333,8 @@ class PetProfileActivity :
|
||||
val dataBean = typeList[pos]
|
||||
mPetBean?.apply {
|
||||
petType = dataBean.menuType
|
||||
if (TextUtils.isEmpty(mSelectPetHeadPath) && TextUtils.isEmpty(imgurl)) ViewUtil.instance.setPetTypeHead(mContext,
|
||||
if (TextUtils.isEmpty(mSelectPetHeadPath) && TextUtils.isEmpty(imgurl)) ViewUtil.instance.setPetTypeHead(
|
||||
mContext,
|
||||
mViewBinding.ilPetProfileHeadLayout.ilPetProfileHead.appHeadImage,
|
||||
imgurl,
|
||||
petType
|
||||
|
||||
@@ -6,20 +6,30 @@ import android.text.InputType
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.view.View.OnFocusChangeListener
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.widget.AppCompatEditText
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.abbidot.baselibrary.constant.ResultCode
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.base.BaseActivity
|
||||
import com.abbidot.tracker.base.BaseDialog
|
||||
import com.abbidot.tracker.bean.CreditCardBean
|
||||
import com.abbidot.tracker.constant.ConstantInt
|
||||
import com.abbidot.tracker.constant.ConstantString
|
||||
import com.abbidot.tracker.constant.GetResultCallback
|
||||
import com.abbidot.tracker.database.MyDatabase
|
||||
import com.abbidot.tracker.databinding.ActivityAddCreditCardPaymentBinding
|
||||
import com.abbidot.tracker.util.ThirdPartyUtil
|
||||
import com.abbidot.tracker.util.Util
|
||||
import com.abbidot.tracker.util.ViewUtil
|
||||
import com.abbidot.tracker.vm.SubscriptionPayViewModel
|
||||
import com.stripe.android.ApiResultCallback
|
||||
import com.stripe.android.Stripe
|
||||
import com.stripe.android.model.PaymentMethod
|
||||
import com.stripe.android.model.PaymentMethodCreateParams
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -28,6 +38,8 @@ class AddCreditCardPaymentActivity :
|
||||
BaseActivity<ActivityAddCreditCardPaymentBinding>(ActivityAddCreditCardPaymentBinding::inflate),
|
||||
OnFocusChangeListener {
|
||||
|
||||
private val mSubscriptionPayViewModel: SubscriptionPayViewModel by viewModels()
|
||||
|
||||
private var mCreditCard: CreditCardBean? = null
|
||||
private var mOldCard: CreditCardBean? = null
|
||||
private var isEdit = false
|
||||
@@ -47,7 +59,7 @@ class AddCreditCardPaymentActivity :
|
||||
if (isEdit) {
|
||||
mOldCard = mCreditCard
|
||||
setTopBarTitle(R.string.txt_edit_pay_method)
|
||||
mRightImageButton = addRightImageButton(R.drawable.icon_delete_svg)
|
||||
// mRightImageButton = addRightImageButton(R.drawable.icon_delete_svg)
|
||||
} else {
|
||||
setTopBarTitle(R.string.txt_add_payment)
|
||||
}
|
||||
@@ -116,6 +128,21 @@ class AddCreditCardPaymentActivity :
|
||||
}
|
||||
}
|
||||
|
||||
override fun liveDataObserve() {
|
||||
mSubscriptionPayViewModel.mSavePaymentMethodIDLiveData.observe(this) {
|
||||
dealRequestResult(it, object : GetResultCallback {
|
||||
override fun onResult(any: Any) {
|
||||
setResult(ResultCode.ResultCode_1, null)
|
||||
showToast(R.string.txt_save_successful, isFinish = true)
|
||||
}
|
||||
|
||||
override fun onRequestError(exceptionCode: String?) {
|
||||
setButtonEnabled(mViewBinding.btnSaveNewCreditCard, ConstantInt.Type1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑时显示还原内容
|
||||
*/
|
||||
@@ -215,7 +242,6 @@ class AddCreditCardPaymentActivity :
|
||||
}
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
||||
val list = MyDatabase.creditCardDao().findAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||
var existCard: CreditCardBean? = null
|
||||
list?.apply {
|
||||
@@ -318,6 +344,90 @@ class AddCreditCardPaymentActivity :
|
||||
}
|
||||
}
|
||||
|
||||
private fun confirmSaveCardV2() {
|
||||
mViewBinding.apply {
|
||||
val cardNumber = ilAddCardNumber.etInputView2Content.text.toString().replace(" ", "")
|
||||
val cardName = ilAddCardNameOnCard.etInputView2Content.text.toString()
|
||||
val creditCardValidity = etAddCardMmDdContent.text.toString()
|
||||
val cvv = etAddCardCvcContent.text.toString()
|
||||
|
||||
if (TextUtils.isEmpty(cardNumber) || TextUtils.isEmpty(cardName) || TextUtils.isEmpty(
|
||||
creditCardValidity
|
||||
) || TextUtils.isEmpty(cvv)
|
||||
) {
|
||||
showToast(R.string.txt_not_null)
|
||||
return
|
||||
}
|
||||
|
||||
if (!creditCardValidity.contains("/")) {
|
||||
showToast(R.string.txt_card_validity_format)
|
||||
return
|
||||
} else {
|
||||
val dates = creditCardValidity.split("/")
|
||||
try {
|
||||
if (dates[0].toInt() > 12) {
|
||||
showToast(R.string.txt_card_validity_format)
|
||||
return
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
showToast(R.string.txt_card_validity_format)
|
||||
return
|
||||
}
|
||||
}
|
||||
if (Util.getCreditCardType(cardNumber) == 0 || cardNumber.length < 9) {
|
||||
showToast(R.string.txt_card_number_format)
|
||||
return
|
||||
}
|
||||
|
||||
setButtonEnabled(btnSaveNewCreditCard, ConstantInt.Type0)
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
mCreditCard?.let {
|
||||
MyDatabase.creditCardDao().deleteAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||
it.cardNumber = cardNumber
|
||||
it.cardName = cardName
|
||||
it.expirationDate = creditCardValidity
|
||||
it.cvv = cvv
|
||||
val insertResult = MyDatabase.creditCardDao().insert(it)
|
||||
if (insertResult > 0) {
|
||||
if (isEdit) {
|
||||
val dates = creditCardValidity.split("/")
|
||||
// 用 PaymentMethodCreateParams 封装银行卡,不再直接new Card
|
||||
val cardParams =
|
||||
PaymentMethodCreateParams.Card.Builder().setNumber(cardNumber)
|
||||
.setExpiryMonth(dates[0].toInt())
|
||||
.setExpiryYear(dates[1].toInt()).setCvc(cvv).build()
|
||||
val paymentMethodParams = PaymentMethodCreateParams.create(cardParams)
|
||||
val stripeKey = ThirdPartyUtil.instance.getStripeKey(mContext)
|
||||
LogUtil.e("支付stripeKey=$stripeKey")
|
||||
Stripe(mContext, stripeKey).createPaymentMethod(
|
||||
paymentMethodParams,
|
||||
callback = object : ApiResultCallback<PaymentMethod> {
|
||||
override fun onError(e: Exception) {
|
||||
showToast(R.string.txt_missing_param)
|
||||
setButtonEnabled(btnSaveNewCreditCard, ConstantInt.Type1)
|
||||
LogUtil.e("PaymentMethodCreateParams,${e.message}")
|
||||
}
|
||||
|
||||
override fun onSuccess(result: PaymentMethod) {
|
||||
LogUtil.e(result.toString())
|
||||
val paymentMethodID = "${result.id}"
|
||||
mSubscriptionPayViewModel.savePaymentMethodInfo(
|
||||
paymentMethodID
|
||||
)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
runOnUiThread {
|
||||
setResult(ResultCode.ResultCode_1, null)
|
||||
showToast(R.string.txt_save_successful, isFinish = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteCard() {
|
||||
ViewUtil.instance.showDialog(
|
||||
mContext, R.string.txt_sure_delete_card, object : BaseDialog.OnDialogOkListener {
|
||||
@@ -338,7 +448,7 @@ class AddCreditCardPaymentActivity :
|
||||
override fun onClick(v: View?) {
|
||||
mViewBinding.apply {
|
||||
when (v!!) {
|
||||
btnSaveNewCreditCard -> confirmSaveCard()
|
||||
btnSaveNewCreditCard -> confirmSaveCardV2()
|
||||
llAddCardMmDdLayout -> setClickEditViewVisible(etAddCardMmDdContent)
|
||||
llAddCardCvcLayout -> setClickEditViewVisible(etAddCardCvcContent)
|
||||
ilAddCardNameOnCard.root -> setClickEditViewVisible(ilAddCardNameOnCard.etInputView2Content)
|
||||
|
||||
@@ -46,26 +46,6 @@ class PaymentMethodActivity :
|
||||
setTopBarTitle(R.string.txt_payment_method)
|
||||
setLeftBackImage(R.drawable.icon_white_back_svg)
|
||||
|
||||
// 用 PaymentMethodCreateParams 封装银行卡,不再直接new Card
|
||||
// val cardParams = PaymentMethodCreateParams.Card.Builder()
|
||||
// .setNumber("4242424242424242")
|
||||
// .setExpiryMonth(12)
|
||||
// .setExpiryYear(2028)
|
||||
// .setCvc("123")
|
||||
// .build()
|
||||
// val paymentMethodParams = PaymentMethodCreateParams.create(cardParams)
|
||||
// val stripeKey = ThirdPartyUtil.instance.getStripeKey(mContext)
|
||||
// Stripe(mContext, stripeKey).createPaymentMethod(
|
||||
// paymentMethodParams, callback = object : ApiResultCallback<PaymentMethod> {
|
||||
// override fun onError(e: Exception) {
|
||||
// LogUtil.e("ApiResultCallback,${e.message}")
|
||||
// }
|
||||
//
|
||||
// override fun onSuccess(result: PaymentMethod) {
|
||||
// LogUtil.e(result.toString())
|
||||
// }
|
||||
// })
|
||||
|
||||
intent.extras?.apply {
|
||||
mOrderBean = Util.getParcelableAdaptive(
|
||||
intent, ConstantString.LkSetMeal, SubscriptionsOrderBean::class.java
|
||||
@@ -103,7 +83,7 @@ class PaymentMethodActivity :
|
||||
getUserPaymentMethodID()
|
||||
}
|
||||
|
||||
fun getUserPaymentMethodID(){
|
||||
fun getUserPaymentMethodID() {
|
||||
mSubscriptionPayViewModel.getUserPaymentMethodID()
|
||||
}
|
||||
|
||||
@@ -117,6 +97,7 @@ class PaymentMethodActivity :
|
||||
override fun onResult(any: Any) {
|
||||
it.getOrNull()?.let { p ->
|
||||
mPaymentIDBean = p
|
||||
(mFragments[0] as CreditCardPaymentFragment).getCardData(p.stripeMethodInfo)
|
||||
if (mFragments.size > 1) {
|
||||
(mFragments[1] as PaypalPaymentFragment).showPaypalInfo()
|
||||
}
|
||||
|
||||
@@ -786,7 +786,7 @@ class MapV3Fragment : BaseFragment<FragmentMapV3Binding>(FragmentMapV3Binding::i
|
||||
MMKVUtil.putBoolean(MMKVKey.isGpsToGCJ02, !isOutOfChina)
|
||||
}
|
||||
|
||||
showNoSetWifiDialog(this)
|
||||
// showNoSetWifiDialog(this)
|
||||
|
||||
mHomeMapCommon.refreshPetCurrentLocation(latitude, longitude, isMoveCamera)
|
||||
isMoveCamera = false
|
||||
|
||||
@@ -2,16 +2,15 @@ package com.abbidot.tracker.ui.fragment.subscribe
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.abbidot.baselibrary.constant.MMKVKey
|
||||
import com.abbidot.baselibrary.constant.ResultCode
|
||||
import com.abbidot.baselibrary.list.BaseRecyclerAdapter
|
||||
import com.abbidot.baselibrary.util.AppUtils
|
||||
import com.abbidot.baselibrary.util.LogUtil
|
||||
import com.abbidot.baselibrary.util.MMKVUtil
|
||||
import com.abbidot.tracker.R
|
||||
import com.abbidot.tracker.adapter.CreditCardAdapter
|
||||
import com.abbidot.tracker.base.BaseFragment
|
||||
@@ -90,20 +89,46 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
||||
|
||||
setOnClickListenerViews(btnCreditCardPaymentAdd, btnMakePaymentCreditCard)
|
||||
}
|
||||
getCardData()
|
||||
// getCardData()
|
||||
}
|
||||
|
||||
private fun getCardData() {
|
||||
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||
val list = MyDatabase.creditCardDao().findAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||
list?.let {
|
||||
mActivity?.runOnUiThread {
|
||||
val sortedByList = list.sortedByDescending { l -> l.isPrimary }.toMutableList()
|
||||
setCheckAndPrimaryState(sortedByList)
|
||||
mCreditCardAdapter.setData(sortedByList, true)
|
||||
fun getCardData(stripeMethodInfo: CreditCardBean) {
|
||||
if (TextUtils.isEmpty(stripeMethodInfo.lastFourNumber)) {
|
||||
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||
val list = MyDatabase.creditCardDao().findAll(MyDatabase.CREDIT_CARD_TABLE)
|
||||
list?.let {
|
||||
mActivity?.runOnUiThread {
|
||||
val sortedByList =
|
||||
list.sortedByDescending { l -> l.isPrimary }.toMutableList()
|
||||
setCheckAndPrimaryState(sortedByList)
|
||||
mCreditCardAdapter.setData(sortedByList, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stripeMethodInfo.apply {
|
||||
expirationDate = "$expMonth/$expYear"
|
||||
cardNumber = lastFourNumber
|
||||
cardName = "****"
|
||||
cvv = "****"
|
||||
}
|
||||
mViewBinding.apply {
|
||||
tvCreditCardPaymentChoose.visibility = View.VISIBLE
|
||||
btnCreditCardPaymentAdd.visibility = View.INVISIBLE
|
||||
//卡管理 不需要点击效果
|
||||
if (null == getHostActivity(PaymentMethodActivity::class.java)?.mOrderBean) {
|
||||
btnMakePaymentCreditCard.visibility = View.GONE
|
||||
} else {
|
||||
stripeMethodInfo.checked = true
|
||||
btnMakePaymentCreditCard.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
mutableListOf<CreditCardBean>().apply {
|
||||
add(stripeMethodInfo)
|
||||
mCreditCardAdapter.setData(this, true)
|
||||
}
|
||||
}
|
||||
ViewUtil.instance.viewShow(mViewBinding.rvCreditCardPaymentList)
|
||||
}
|
||||
|
||||
fun goEditCard(cardBean: CreditCardBean) {
|
||||
@@ -181,7 +206,7 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
||||
}
|
||||
mViewBinding.apply {
|
||||
tvCreditCardPaymentChoose.visibility = View.VISIBLE
|
||||
btnCreditCardPaymentAdd.visibility = View.VISIBLE
|
||||
btnCreditCardPaymentAdd.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +237,8 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
||||
// }
|
||||
// }
|
||||
if (it.resultCode == ResultCode.ResultCode_1) {
|
||||
getCardData()
|
||||
// getCardData()
|
||||
getHostActivity(PaymentMethodActivity::class.java)?.getUserPaymentMethodID()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,38 +254,43 @@ class CreditCardPaymentFragment : BaseFragment<FragmentCreditCardPaymentBinding>
|
||||
// }
|
||||
|
||||
private fun startCreditCardPayment() {
|
||||
val list = mCreditCardAdapter.getData()
|
||||
for (card in list) {
|
||||
if (card.checked) {
|
||||
showNoCancelableLoading(true)
|
||||
getHostActivity(PaymentMethodActivity::class.java)?.let {
|
||||
val list = mCreditCardAdapter.getData()
|
||||
for (card in list) {
|
||||
if (card.checked) {
|
||||
showNoCancelableLoading(true)
|
||||
if (null == it.mPaymentIDBean || TextUtils.isEmpty(it.mPaymentIDBean?.stripeMethodInfo?.lastFourNumber)) {
|
||||
val dates = card.expirationDate.split("/")
|
||||
// 用 PaymentMethodCreateParams 封装银行卡,不再直接new Card
|
||||
val cardParams =
|
||||
PaymentMethodCreateParams.Card.Builder().setNumber(card.cardNumber)
|
||||
.setExpiryMonth(dates[0].toInt()).setExpiryYear(dates[1].toInt())
|
||||
.setCvc(card.cvv).build()
|
||||
val paymentMethodParams = PaymentMethodCreateParams.create(cardParams)
|
||||
val stripeKey = ThirdPartyUtil.instance.getStripeKey(mContext!!)
|
||||
LogUtil.e("支付stripeKey=$stripeKey")
|
||||
Stripe(mContext!!, stripeKey).createPaymentMethod(
|
||||
paymentMethodParams,
|
||||
callback = object : ApiResultCallback<PaymentMethod> {
|
||||
override fun onError(e: Exception) {
|
||||
showToast(R.string.txt_missing_param)
|
||||
showNoCancelableLoading(false)
|
||||
LogUtil.e("ApiResultCallback,${e.message}")
|
||||
}
|
||||
|
||||
val dates = card.expirationDate.split("/")
|
||||
// 用 PaymentMethodCreateParams 封装银行卡,不再直接new Card
|
||||
val cardParams = PaymentMethodCreateParams.Card.Builder()
|
||||
.setNumber(card.cardNumber)
|
||||
.setExpiryMonth(dates[0].toInt())
|
||||
.setExpiryYear(dates[1].toInt())
|
||||
.setCvc(card.cvv)
|
||||
.build()
|
||||
val paymentMethodParams = PaymentMethodCreateParams.create(cardParams)
|
||||
val stripeKey = ThirdPartyUtil.instance.getStripeKey(mContext!!)
|
||||
Stripe(mContext!!, stripeKey).createPaymentMethod(
|
||||
paymentMethodParams, callback = object : ApiResultCallback<PaymentMethod> {
|
||||
override fun onError(e: Exception) {
|
||||
showToast(R.string.txt_missing_param)
|
||||
showNoCancelableLoading(false)
|
||||
LogUtil.e("ApiResultCallback,${e.message}")
|
||||
}
|
||||
|
||||
override fun onSuccess(result: PaymentMethod) {
|
||||
LogUtil.e(result.toString())
|
||||
val paymentMethodID = "${result.id}"
|
||||
MMKVUtil.putString(MMKVKey.PaymentMethodID, paymentMethodID)
|
||||
mSubscriptionPayViewModel.createCustomer(card)
|
||||
}
|
||||
})
|
||||
break
|
||||
override fun onSuccess(result: PaymentMethod) {
|
||||
LogUtil.e(result.toString())
|
||||
val paymentMethodID = "${result.id}"
|
||||
mSubscriptionPayViewModel.createCustomer(card, paymentMethodID)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
mSubscriptionPayViewModel.createCustomer(card, "")
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,14 +39,17 @@ class PaypalPaymentFragment :
|
||||
tvPaypalPaymentGoTip.visibility = View.GONE
|
||||
btnSureRedirectPaypal.visibility = View.GONE
|
||||
ivSureRedirectPaypalBg.visibility = View.GONE
|
||||
showPaypalInfo()
|
||||
} else {
|
||||
tvNoPaypalPaymentEmail.visibility = View.GONE
|
||||
}
|
||||
showPaypalInfo()
|
||||
}
|
||||
}
|
||||
|
||||
fun showPaypalInfo() {
|
||||
if (null == getHostActivity(PaymentMethodActivity::class.java)?.mOrderBean) {
|
||||
return
|
||||
}
|
||||
getHostActivity(PaymentMethodActivity::class.java)?.let {
|
||||
it.mPaymentIDBean?.let { pId ->
|
||||
mViewBinding.tvPaypalPaymentEmail.text = pId.paypalMethodInfo.email
|
||||
|
||||
@@ -28,17 +28,21 @@ class SocketUtilManageV2 {
|
||||
|
||||
@Synchronized
|
||||
fun initEasySocket(context: Context, mac: String, data: ByteArray) {
|
||||
val data1 = SRBleCmdUtil.instance.byteToInt(data[1])
|
||||
val data2 = SRBleCmdUtil.instance.byteToInt(data[2])
|
||||
val data3 = SRBleCmdUtil.instance.byteToInt(data[3])
|
||||
val data4 = SRBleCmdUtil.instance.byteToInt(data[4])
|
||||
val ip = "$data1.$data2.$data3.$data4"
|
||||
val port = SRBleCmdUtil.instance.byte2ArrayToInt(data.sliceArray(5..6))
|
||||
val socketAddress = "$ip:$port"
|
||||
LogUtil.e(socketAddress)
|
||||
mMac = mac
|
||||
mNeedSendMessage = data.sliceArray(8..data.size - 2)
|
||||
initEasySocket(context, ip, port)
|
||||
try {
|
||||
val data1 = SRBleCmdUtil.instance.byteToInt(data[1])
|
||||
val data2 = SRBleCmdUtil.instance.byteToInt(data[2])
|
||||
val data3 = SRBleCmdUtil.instance.byteToInt(data[3])
|
||||
val data4 = SRBleCmdUtil.instance.byteToInt(data[4])
|
||||
val ip = "$data1.$data2.$data3.$data4"
|
||||
val port = SRBleCmdUtil.instance.byte2ArrayToInt(data.sliceArray(5..6))
|
||||
val socketAddress = "$ip:$port"
|
||||
LogUtil.e(socketAddress)
|
||||
mMac = mac
|
||||
mNeedSendMessage = data.sliceArray(8..data.size - 2)
|
||||
initEasySocket(context, ip, port)
|
||||
} catch (e: Exception) {
|
||||
LogUtil.e("initEasySocket 异常:${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -873,17 +873,38 @@ class Util {
|
||||
|
||||
|
||||
/**
|
||||
* 限制limitLetterLength个字母或limitLetterLength/2个中文,限制空格输入
|
||||
* 截断到最大limitLetterLength单位
|
||||
* @param limitLetterLength 限制字母的个数
|
||||
* 字符串截断 + 空格规则:
|
||||
* 1. 首位不能是空格
|
||||
* 2. 首位之后,只允许连续 1 个空格
|
||||
* 3. 按[字符计算长度]截断,不超过限制长度
|
||||
* @param limitLetterLength 最大字符单位长度
|
||||
* @return 处理后的字符串
|
||||
*/
|
||||
fun String.limitLetterChinese(limitLetterLength: Int): String {
|
||||
val sb = StringBuilder()
|
||||
// 标记:上一个字符是否是空格
|
||||
var lastIsSpace = false
|
||||
|
||||
for (c in this) {
|
||||
if (c == ' ') break
|
||||
// 规则1:首位直接拦截空格
|
||||
if (sb.isEmpty() && c == ' ') {
|
||||
continue
|
||||
}
|
||||
|
||||
// 规则2:已存在一个连续空格,再遇到空格直接跳过(只保留单个空格)
|
||||
if (c == ' ' && lastIsSpace) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 拼接后判断是否超出长度限制,超出则终止
|
||||
val temp = sb.toString() + c
|
||||
if (temp.calcLengthUnit() > limitLetterLength) break
|
||||
if (temp.calcLengthUnit() > limitLetterLength) {
|
||||
break
|
||||
}
|
||||
|
||||
// 追加字符,并更新空格标记
|
||||
sb.append(c)
|
||||
lastIsSpace = (c == ' ')
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
@@ -28,11 +28,12 @@ class SubscriptionPayViewModel : ViewModel() {
|
||||
val mCreateStripeOrderLiveData = MutableLiveData<Result<PayResultBean>>()
|
||||
val mCreatePaypalOrderLiveData = MutableLiveData<Result<PayResultBean>>()
|
||||
val mPaymentMethodIDLiveData = MutableLiveData<Result<PaymentIDBean>>()
|
||||
val mSavePaymentMethodIDLiveData = MutableLiveData<Result<String>>()
|
||||
|
||||
/**
|
||||
* Stripe支付创建消费用户
|
||||
*/
|
||||
fun createCustomer(card: CreditCardBean) {
|
||||
fun createCustomer(card: CreditCardBean,paymentMethodID: String) {
|
||||
// activity.showLoading(true)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val userId = MMKVUtil.getString(MMKVKey.UserId)
|
||||
@@ -52,7 +53,7 @@ class SubscriptionPayViewModel : ViewModel() {
|
||||
|
||||
val rsaKey = RSA.encrypt(cardJso, b)
|
||||
LogUtil.e(cardJso)
|
||||
val result = NetworkApi.createCustomer(rsaKey, userId, userName, email)
|
||||
val result = NetworkApi.createCustomer(rsaKey, userId, userName, email,paymentMethodID)
|
||||
mSubscriptionCustomerLiveData.postValue(result)
|
||||
}
|
||||
}
|
||||
@@ -80,4 +81,12 @@ class SubscriptionPayViewModel : ViewModel() {
|
||||
mPaymentMethodIDLiveData.value = result
|
||||
}
|
||||
}
|
||||
|
||||
fun savePaymentMethodInfo(paymentMethodID: String) {
|
||||
viewModelScope.launch {
|
||||
val userId = MMKVUtil.getString(MMKVKey.UserId)
|
||||
val result = NetworkApi.savePaymentMethodInfo(userId, paymentMethodID)
|
||||
mSavePaymentMethodIDLiveData.value = result
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@
|
||||
android:id="@+id/rv_credit_card_payment_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:layout_above="@id/btn_make_payment_credit_card"
|
||||
android:layout_below="@id/btn_credit_card_payment_add"
|
||||
android:layout_marginTop="@dimen/dp_12" />
|
||||
|
||||
Reference in New Issue
Block a user