generallibrary/src/main/java/com/dayu/general/activity/CardReadActivity.kt
@@ -122,6 +122,11 @@ handleUserCard(cardNumber, cardType, nfcAdapter) } "00" -> { // 地区卡:显示卡片类型信息 handleUserCard(cardNumber, cardType, nfcAdapter) } else -> { // 管理类卡:显示卡片类型信息 handleManagementCard(cardNumber, cardType) @@ -138,6 +143,7 @@ * 处理用户卡 */ private fun handleUserCard(cardNumber: String, cardType: String, nfcAdapter: NfcReadHelper) { if (cardType != "00") { // 解析用户卡数据 val userCard = nfcAdapter.getUserCardData() if (userCard == null) { @@ -145,7 +151,7 @@ } return } binding.tvCardNumber.text = cardNumber // 输出用户卡内所有信息到日志 android.util.Log.d("CardReadActivity", "=== 用户卡信息 ===") android.util.Log.d("CardReadActivity", "卡号: $cardNumber") @@ -162,9 +168,14 @@ android.util.Log.d("CardReadActivity", "电量单价: ${userCard.electricPrice}") android.util.Log.d("CardReadActivity", "充值时间: ${userCard.rechargeDate}") android.util.Log.d("CardReadActivity", "==================") getCardInfo(cardNumber, cardType, userCard) } else { getCardInfo(cardNumber, cardType, null) } // 根据卡号获取卡片详细信息 getCardInfo(cardNumber, cardType, userCard) } /** @@ -222,7 +233,7 @@ /** * 获取卡片详细信息(用户卡专用) */ private fun getCardInfo(cardNumber: String, cardType: String, userCard: UserCard) { private fun getCardInfo(cardNumber: String, cardType: String, userCard: UserCard?) { val map = mutableMapOf<String, Any>() map["cardAddr"] = cardNumber ApiManager.getInstance().requestGetLoading( @@ -257,7 +268,7 @@ cardInfo: CardInfoResult?, cardNumber: String, cardType: String, userCard: UserCard userCard: UserCard? ) { // 隐藏读卡提示,显示信息区域 binding.cardReadLL.visibility = android.view.View.GONE @@ -266,34 +277,49 @@ val cardTypeName = getCardTypeName(cardType) // 显示卡内数据 binding.tvCardType.text = cardTypeName // 显示用户卡特有字段 binding.llCardBalance.visibility = android.view.View.VISIBLE binding.llUserNumber.visibility = android.view.View.VISIBLE binding.llCardStatus.visibility = android.view.View.VISIBLE userCard.let { card -> // 余额转换为元(原始数据可能是分) binding.tvCardBalance.text = MornyUtil.changeF2Y(card.balance.toInt()) + "元" // 使用完整的用户编号 binding.tvUserNumber.text = cardInfo?.cardNum binding.tvCardNumber.text = cardNumber // 处理卡内数据 - 优先使用userCard,如果为空则从cardInfo获取 if (userCard != null) { // 从卡内数据获取信息 binding.tvCardBalance.text = MornyUtil.changeF2Y(userCard.balance.toInt()) + "元" // 充值时间作为最后使用时间 if (card.rechargeDate != null) { val rechargeDate = userCard.rechargeDate if (rechargeDate != null) { binding.llLastUseTime.visibility = android.view.View.VISIBLE val dateFormat = java.text.SimpleDateFormat("yyyy-MM-dd HH:mm", java.util.Locale.getDefault()) binding.tvLastUseTime.text = dateFormat.format(card.rechargeDate!!.time) binding.tvLastUseTime.text = dateFormat.format(rechargeDate.time) } else { binding.llLastUseTime.visibility = android.view.View.GONE } } else { // userCard为空时,从cardInfo获取数据 cardInfo?.let { info -> // 从接口返回的数据中获取余额,转换为正确的类型 val balance = info.balance ?: 0.0 binding.tvCardBalance.text = MornyUtil.changeF2Y((balance * 100).toInt()) + "元" // 如果cardInfo中有最后使用时间相关字段,可以在这里设置 // 暂时隐藏最后使用时间 binding.llLastUseTime.visibility = android.view.View.GONE } ?: run { // 如果cardInfo也为空,显示默认值 binding.tvCardBalance.text = "0.00元" binding.llLastUseTime.visibility = android.view.View.GONE } } // 显示服务器数据 cardInfo?.let { info -> // 使用完整的用户编号 binding.tvUserNumber.text = info.cardNum ?: cardNumber binding.tvUserName.text = info.userName ?: "未知" binding.tvPhone.text = info.phone ?: "未绑定" binding.tvIdCard.text = info.userCode ?: "未录入" // 使用userCode作为身份证号的替代 @@ -308,6 +334,14 @@ } binding.tvCardStatus.text = statusText binding.tvCardStatus.setTextColor(statusColor) } ?: run { // 如果cardInfo为空,显示默认值 binding.tvUserNumber.text = cardNumber binding.tvUserName.text = "未知" binding.tvPhone.text = "未绑定" binding.tvIdCard.text = "未录入" binding.tvCardStatus.text = "未知状态" binding.tvCardStatus.setTextColor(android.graphics.Color.parseColor("#9E9E9E")) } } generallibrary/src/main/java/com/dayu/general/activity/CardWriteSuccessActivity.kt
@@ -1,6 +1,7 @@ package com.dayu.general.activity import android.os.Bundle import com.dayu.baselibrary.utils.MornyUtil import com.dayu.general.bean.card.UserCard import com.dayu.general.databinding.ActivityCardWriteSuccessBinding import com.dayu.general.tool.CardOperationType @@ -105,7 +106,7 @@ binding.titleBar.setCenterText("写卡成功") binding.successTitle.text = "写卡成功" binding.successMessage.text = "卡内余额已更新为 ${userCard?.balance}元" "卡内余额已更新为"+MornyUtil.changeF2Y(userCard?.balance?:0.toInt()) +"元" } else -> { generallibrary/src/main/java/com/dayu/general/activity/NewCard2Activity.kt
@@ -172,17 +172,48 @@ ApiManager.getInstance().requestGetLoading( this, "terminal/paymentmethod/get", Array<PaymentMethod>::class.java, Any::class.java, null, object : SubscriberListener<BaseResponse<Array<PaymentMethod>>>() { override fun onNext(response: BaseResponse<Array<PaymentMethod>>) { object : SubscriberListener<BaseResponse<Any>>() { override fun onNext(response: BaseResponse<Any>) { if (response.success) { // 获取支付方式列表,现在content直接是PaymentMethod数组 val paymentMethods = response.content?.toList() ?: listOf() try { // 安全地处理返回的content,服务器返回的是ArrayList<LinkedHashMap> val paymentMethods = mutableListOf<PaymentMethod>() val content = response.content if (content is List<*>) { content.forEach { item -> if (item is Map<*, *>) { val id = item["id"]?.toString() ?: "" val name = item["name"]?.toString() ?: "" if (id.isNotEmpty() && name.isNotEmpty()) { paymentMethods.add(PaymentMethod(id, name)) } } } } if (paymentMethods.isNotEmpty()) { paymentMethodList = paymentMethods // 更新支付方式显示 updatePaymentMethodRadioGroup() } else { Toast.makeText( this@NewCard2Activity, "获取支付方式失败:返回数据为空", Toast.LENGTH_SHORT ).show() } } catch (e: Exception) { android.util.Log.e("NewCard2Activity", "解析支付方式数据失败", e) android.util.Log.e("NewCard2Activity", "原始数据类型: ${response.content?.javaClass?.name}") android.util.Log.e("NewCard2Activity", "原始数据内容: ${response.content}") Toast.makeText( this@NewCard2Activity, "解析支付方式数据失败: ${e.message}", Toast.LENGTH_SHORT ).show() } } else { Toast.makeText( @@ -195,6 +226,7 @@ override fun onError(e: Throwable?) { super.onError(e) android.util.Log.e("NewCard2Activity", "网络请求失败", e) Toast.makeText( this@NewCard2Activity, "获取支付方式失败: ${e?.message ?: "网络异常"}", generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt
@@ -254,8 +254,9 @@ // 返还操作显示信息 var textData = StringBuilder() textData.append("返还\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") textData.append("返还金额:" + returnAmount + "元") textData.append("返还金额:" + returnAmount + "元\n") textData.append("返还后卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") binding?.cardData?.text = textData.toString() } @@ -263,8 +264,9 @@ // 补扣操作显示信息 var textData = StringBuilder() textData.append("补扣\n") textData.append("卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") textData.append("补扣金额:" + deductAmount + "元") textData.append("补扣金额:" + deductAmount + "元\n") textData.append("补扣后卡内余额:" + MornyUtil.changeF2Y(userCard.balance) + "元\n") binding?.cardData?.text = textData.toString() } @@ -514,7 +516,7 @@ CardOperationType.RegionCardMake -> { // 区域表号卡写卡逻辑(功能卡,无需写入用户数据) var areaCard = AreaCard() areaCard.areaNumber = regionNumber.toInt() areaCard.areaNumber = regionNumber areaCard.projectCode = projectNumber.toInt() nfcWreatHelper.writeDataAsync( areaCard.getZeroBytes(), generallibrary/src/main/java/com/dayu/general/activity/RechargeDetailActivity.kt
@@ -23,6 +23,7 @@ import com.dayu.general.bean.net.RechargeRequest import com.dayu.general.bean.net.RechargeResult import com.dayu.general.bean.card.UserCard import com.dayu.general.bean.net.PaymentMethodListResponse import com.dayu.general.databinding.ActivityRechargeDetailBinding import com.dayu.general.net.ApiManager import com.dayu.general.net.BaseResponse @@ -149,23 +150,60 @@ } /** * 获取支付方式列表 * 获取支付方式列表 - 使用Object类型安全处理JSON数组 */ private fun getPaymentMethods() { ApiManager.getInstance().requestGetLoading( this, "terminal/paymentmethod/get", Array<PaymentMethod>::class.java, Any::class.java, null, object : SubscriberListener<BaseResponse<Array<PaymentMethod>>>() { override fun onNext(response: BaseResponse<Array<PaymentMethod>>) { object : SubscriberListener<BaseResponse<Any>>() { override fun onNext(response: BaseResponse<Any>) { if (response.success) { // 获取支付方式列表,现在content直接是PaymentMethod数组 val paymentMethods = response.content?.toList() ?: listOf() try { // 安全地处理返回的content,服务器返回的是ArrayList<LinkedHashMap> val paymentMethods = mutableListOf<PaymentMethod>() val content = response.content if (content is List<*>) { content.forEach { item -> if (item is Map<*, *>) { val id = item["id"]?.toString() ?: "" val name = item["name"]?.toString() ?: "" if (id.isNotEmpty() && name.isNotEmpty()) { paymentMethods.add(PaymentMethod(id, name)) } } } } if (paymentMethods.isNotEmpty()) { paymentMethodList = paymentMethods // 更新支付方式显示 updatePaymentMethodRadioGroup() // 调试日志 android.util.Log.d("RechargeDetail", "成功获取${paymentMethods.size}个支付方式:") paymentMethods.forEach { method -> android.util.Log.d("RechargeDetail", "- ID: ${method.id}, Name: ${method.name}") } } else { Toast.makeText( this@RechargeDetailActivity, "获取支付方式失败:返回数据为空", Toast.LENGTH_SHORT ).show() } } catch (e: Exception) { android.util.Log.e("RechargeDetail", "解析支付方式数据失败", e) android.util.Log.e("RechargeDetail", "原始数据类型: ${response.content?.javaClass?.name}") android.util.Log.e("RechargeDetail", "原始数据内容: $response.content") Toast.makeText( this@RechargeDetailActivity, "解析支付方式数据失败: ${e.message}", Toast.LENGTH_SHORT ).show() } } else { Toast.makeText( @@ -178,6 +216,7 @@ override fun onError(e: Throwable?) { super.onError(e) android.util.Log.e("RechargeDetail", "网络请求失败", e) Toast.makeText( this@RechargeDetailActivity, "获取支付方式失败: ${e?.message ?: "网络异常"}", @@ -341,30 +380,42 @@ return } // 调用充值接口 callRechargeApi(rechargeAmount, bonusAmount) // 调用充值接口,传递当前余额 callRechargeApi(currentBalance, rechargeAmount, bonusAmount) } /** * 调用充值接口 */ private fun callRechargeApi(rechargeAmount: Double, bonusAmount: Double) { private fun callRechargeApi(currentBalance: Double, rechargeAmount: Double, bonusAmount: Double) { val cardNum = cardInfo?.cardNum ?: cardAddress ?: "" if (cardNum.isEmpty()) { ToastUtil.show("卡号信息缺失") return } // 验证支付方式是否已选择,如果为空则重新获取支付方式 if (paymentId.isEmpty()) { ToastUtil.show("支付方式未加载,正在重新获取...") // 重新获取支付方式,成功后自动重试充值 getPaymentMethodsAndRetryRecharge(currentBalance, rechargeAmount, bonusAmount) return } // 获取水价(如果为空会自动触发MainActivity获取) val currentWaterPrice = BaseApplication.requestWaterPrice() // 构建充值请求参数 // 打印调试信息 android.util.Log.d("RechargeDetail", "充值参数 - paymentMethod: $paymentMethod, paymentId: $paymentId") android.util.Log.d("RechargeDetail", "字段含义 - money(当前余额): ${String.format("%.2f", currentBalance)}元, amount(充值金额): ${String.format("%.2f", rechargeAmount)}元, gift(赠送金额): ${String.format("%.2f", bonusAmount)}元") // 构建充值请求参数 - 修正字段含义 val rechargeRequest = RechargeRequest( rechargeType = 2, cardNum = cardNum, money = String.format("%.0f", rechargeAmount), amount = String.format("%.0f", bonusAmount), gift = String.format("%.0f", bonusAmount), money = String.format("%.2f", currentBalance), // money为当前卡余额 amount = String.format("%.2f", rechargeAmount), // amount为充值金额 gift = String.format("%.2f", bonusAmount), // gift为赠送金额 paymentId = paymentId, price = String.format("%.2f", currentWaterPrice), // 使用统一获取的水价 remarks = "充值", @@ -412,6 +463,64 @@ } /** * 重新获取支付方式并重试充值 */ private fun getPaymentMethodsAndRetryRecharge(currentBalance: Double, rechargeAmount: Double, bonusAmount: Double) { ApiManager.getInstance().requestGetLoading( this, "terminal/paymentmethod/get", Any::class.java, null, object : SubscriberListener<BaseResponse<Any>>() { override fun onNext(response: BaseResponse<Any>) { if (response.success) { try { // 安全地处理返回的content,服务器返回的是ArrayList<LinkedHashMap> val paymentMethods = mutableListOf<PaymentMethod>() val content = response.content if (content is List<*>) { content.forEach { item -> if (item is Map<*, *>) { val id = item["id"]?.toString() ?: "" val name = item["name"]?.toString() ?: "" if (id.isNotEmpty() && name.isNotEmpty()) { paymentMethods.add(PaymentMethod(id, name)) } } } } if (paymentMethods.isNotEmpty()) { paymentMethodList = paymentMethods // 更新支付方式显示 updatePaymentMethodRadioGroup() // 支付方式加载成功后,自动重试充值 ToastUtil.show("支付方式加载成功,正在重试充值...") callRechargeApi(currentBalance, rechargeAmount, bonusAmount) } else { ToastUtil.show("获取支付方式失败:返回数据为空") } } catch (e: Exception) { android.util.Log.e("RechargeDetail", "解析支付方式数据失败", e) android.util.Log.e("RechargeDetail", "原始数据类型: ${response.content?.javaClass?.name}") android.util.Log.e("RechargeDetail", "原始数据内容: ${response.content}") ToastUtil.show("解析支付方式数据失败: ${e.message}") } } else { ToastUtil.show("获取支付方式失败: ${response.msg}") } } override fun onError(e: Throwable?) { super.onError(e) ToastUtil.show("获取支付方式失败: ${e?.message ?: "网络异常"}") } } ) } /** * 启动写卡界面 */ private fun startWriteCardActivity( generallibrary/src/main/java/com/dayu/general/bean/card/AreaCard.kt
@@ -14,7 +14,7 @@ const val CARD_TYPE = CardCommon.REGION_CARD // 卡类型固定为0xB0 } var areaNumber: Int = 0 // 国家行政区域号(12位BCD,精确到村) var areaNumber: String = "" // 国家行政区域号(12位BCD,精确到村) var projectCode: Int = 0 // 项目编码(HEX 1-255) /** @@ -38,17 +38,18 @@ // 解析国家行政区域号(0-5位) val areaCodeBytes = zero.copyOfRange(0, 6) areaCard.areaNumber = BcdUtil.bcdToStr(areaCodeBytes).toInt() areaCard.areaNumber = BcdUtil.bcdToStr(areaCodeBytes) // 解析项目编码(6位) areaCard.projectCode = HexUtil.get16To10LowHightByBytes(byteArrayOf(zero[6])) areaCard.projectCode = HexUtil.get16to10(HexUtil.byteToHex(zero[6])) // 验证卡类型和识别码 if (HexUtil.byteToHex(zero[8]) != CARD_TYPE || zero[9] != IDENTIFY_CODE_A0 || zero[10] != IDENTIFY_CODE_B1 || zero[11] != IDENTIFY_CODE_C2 || zero[12] != IDENTIFY_CODE_89) { zero[12] != IDENTIFY_CODE_89 ) { return null } @@ -67,11 +68,11 @@ val data = ByteArray(16) try { // 设置国家行政区域号(BCD格式,6字节,0-5位) val areaCodeBytes = BcdUtil.strToBcd(String.format("%012d", areaNumber)) val areaCodeBytes = BcdUtil.strToBcd(areaNumber) System.arraycopy(areaCodeBytes, 0, data, 0, 6) // 设置项目编码(6位) data[6] = projectCode.toByte() data[6] = HexUtil.hexToByte(HexUtil.get10to16(projectCode)) // 设置备用位(7位) data[7] = 0x00 generallibrary/src/main/java/com/dayu/general/bean/net/NewCardInfo.kt
@@ -6,7 +6,7 @@ val name: String ) // 支付方式接口返回数据类 // 支付方式接口返回数据类(旧版本,保留兼容性) data class PaymentMethodResponse( val itemTotal: Any?, val obj: List<PaymentMethod>, @@ -15,6 +15,20 @@ val pageTotal: Any? ) // 支付方式列表包装类,用于处理直接返回PaymentMethod数组的接口 // 这个类实际上只是一个简单的包装器,让Gson能够正确解析JSON数组 class PaymentMethodListResponse : ArrayList<PaymentMethod>() { companion object { // 静态方法,从List<PaymentMethod>创建实例 fun from(list: List<PaymentMethod>): PaymentMethodListResponse { val response = PaymentMethodListResponse() response.addAll(list) return response } } } // 用户信息数据类 data class ClientInfo( val clientId: String, generallibrary/src/main/java/com/dayu/general/net/ApiManager.kt
@@ -159,13 +159,33 @@ } is List<*> -> { try { // 直接处理List类型的content,不需要重新解析 when { // 如果目标类型是List的子类(如PaymentMethodListResponse),直接转换 List::class.java.isAssignableFrom(tClass) -> { @Suppress("UNCHECKED_CAST") response.content = MyJsonParser.getListByJson( MyJsonParser.getJsonbyList(content), tClass ) as T response.content = content as T } // 如果content是Map列表,尝试转换为目标对象列表 content.isNotEmpty() && content[0] is Map<*, *> -> { val jsonData = MyJsonParser.getJsonbyList(content) @Suppress("UNCHECKED_CAST") response.content = MyJsonParser.getListByJson(jsonData, tClass) as T } else -> { @Suppress("UNCHECKED_CAST") response.content = content as T } } } catch (e: Exception) { Log.e(TAG, "Error parsing list content", e) // 如果解析失败,尝试直接转换 try { @Suppress("UNCHECKED_CAST") response.content = content as T } catch (e2: Exception) { Log.e(TAG, "Failed to cast content directly", e2) } } } is Int, is String, is Boolean -> {