baselibrary/src/main/java/com/dayu/baselibrary/tools/nfc/NativeNfcWriteHelper.java
@@ -25,7 +25,6 @@ private static NativeNfcWriteHelper helper; public void setIntent(Intent intent) { this.tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); } @@ -43,7 +42,6 @@ helper.setIntent(intent); return helper; } /** * 写卡 @@ -109,6 +107,85 @@ return false; } /** * 写卡(带回调) * * @param userCard 用户卡内容 * @param sector 扇区 * @param callBack 回调接口 */ public boolean writeUserData(BaseUserCardCard userCard, int sector, NFCCallBack callBack) { if (userCard != null) { int a = sector; try { MifareClassic mfc = MifareClassic.get(tag); if (null != mfc) { try { // 连接NFC mfc.connect(); // 验证扇区密码 boolean isOpen = false; for (int i = 0; i < listKeyA.size(); i++) { if (mfc.authenticateSectorWithKeyA(a, listKeyA.get(i))) { isOpen = true; if (listKeyA.get(i).equals(defauleKey)) { // 当前为默认白卡密码时写卡时修改密码 changePasword(a, mfc); } break; } } if (isOpen) { for (int b = 0; b < 3; b++) { byte[] data; if (b == 0) { data = userCard.getZeroBytes(); } else if (b == 1) { data = userCard.getOneBytes(); } else { data = userCard.getTwoBytes(); } int bIndex = mfc.sectorToBlock(a); // 写卡 mfc.writeBlock(bIndex + b, data); } if (callBack != null) { callBack.isSusses(true, "用户数据写入成功"); } return true; } if (callBack != null) { callBack.isSusses(false, "扇区" + a + "密码验证失败"); } return false; } catch (Exception e) { e.printStackTrace(); if (callBack != null) { callBack.isSusses(false, "扇区" + a + "写卡异常: " + e.getMessage()); } return false; } finally { try { mfc.close(); } catch (IOException e) { e.printStackTrace(); } } } } catch (Exception e) { e.printStackTrace(); if (callBack != null) { callBack.isSusses(false, "写卡异常: " + e.getMessage()); } return false; } } else { if (callBack != null) { callBack.isSusses(false, "用户卡数据为空"); } } return false; } /** * 写卡 @@ -245,7 +322,6 @@ } return false; } /** * 修改密码 @@ -399,8 +475,6 @@ return false; } /** * 初始化卡 * @@ -467,6 +541,5 @@ } return false; } } baselibrary/src/main/java/com/dayu/baselibrary/tools/nfc/NfcWriteAdapter.java
@@ -42,6 +42,22 @@ return false; } /** * 写用户数据(带回调) * * @param userCard 用户卡数据 * @param sector 扇区 * @param callBack 回调接口 * @return 是否成功 */ public boolean writeUserData(BaseUserCardCard userCard, int sector, NFCCallBack callBack) { switch (BaseNfcActivity.adapterType) { case ModelUtils.defaultType: return nativeNfcWriteHelper.writeUserData(userCard, sector, callBack); } return false; } @Override public boolean writeData(byte[] str, int a, int b) { switch (BaseNfcActivity.adapterType) { generallibrary/src/main/java/com/dayu/general/activity/NewCard2Activity.kt
@@ -13,15 +13,23 @@ import com.dayu.baselibrary.view.TitleBar.ClickType_LEFT_IMAGE import com.dayu.general.BaseApplication import com.dayu.general.R import com.dayu.general.bean.card.UserCard import com.dayu.general.bean.db.CardRegistrationBean import com.dayu.general.bean.net.ClientInfo import com.dayu.general.bean.net.NewCardDataResult import com.dayu.general.bean.net.PaymentMethod import com.dayu.general.bean.net.PaymentMethodResponse import com.dayu.general.dao.BaseDaoSingleton import com.dayu.general.databinding.ActivityNewCardGeBinding import com.dayu.general.net.ApiManager import com.dayu.general.net.BaseResponse import com.dayu.general.tool.CardCommon.Companion.USER_CARD_TYPE_1 import com.dayu.general.tool.NfcReadHelper import com.dayu.general.tool.NfcWreatHelper import com.dayu.general.utils.DateUtils import com.tencent.bugly.crashreport.CrashReport import kotlinx.coroutines.launch import java.util.Calendar /** * Description: 用户开卡界面(同步修改白卡密码) @@ -50,43 +58,17 @@ // 客户ID private var clientId: String = "" private lateinit var clientInfo : ClientInfo // 是否已读卡 private var isReadCard: Boolean = false private var orderId:String="" companion object { private const val TAG = "NewCard2Activity" } // 支付方式数据类 data class PaymentMethod( val id: Long, val name: String, val remarks: String, val deleted: Int ) // 支付方式接口返回数据类 data class PaymentMethodResponse( val itemTotal: Any?, val obj: List<PaymentMethod>, val pageCurr: Any?, val pageSize: Any?, val pageTotal: Any? ) // 用户信息数据类 data class ClientInfo( val clientId: String, val clientNum: String, val name: String, val districtNum: String, val phone: String, val idCard: String, val villageName: String, val address: String, val cardCount: Int, val operateDt: String ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -134,7 +116,7 @@ object : SubscriberListener<BaseResponse<ClientInfo>>() { override fun onNext(response: BaseResponse<ClientInfo>) { if (response.success) { val clientInfo = response.content clientInfo = response.content!! if (clientInfo != null) { // 显示客户信息到界面 displayClientInfo(clientInfo) @@ -337,33 +319,37 @@ // 构建请求参数 val params = HashMap<String, Any>() params["cardAddr"] = cardPhysicalId // 水卡地址(物理ID) params["clientNum"] = binding.newCardFarmerCode.text.toString() // 农户编号 params["cardCost"] = (cardFee * 100).toInt() // 购卡金额(工本费)转为分 params["amount"] = (rechargeAmount * 100).toInt() // 充值金额转为分 params["clientId"] = clientId // 农户ID params["cardCost"] = cardFee // 购卡金额(工本费)(元) params["amount"] = rechargeAmount // 充值金额(元) params["paymentId"] = paymentId // 支付方式ID params["remarks"] = remark // 备注 params["protocol"] = "p206V1_0_1" // 协议 params["operator"] = BaseApplication.userId // 操作人ID // 执行卡片激活API请求 ApiManager.getInstance().requestPostLoading( this, "sell/card/active", String::class.java, "terminal/card/termActiveCard", NewCardDataResult::class.java, params, object : SubscriberListener<BaseResponse<String>>() { override fun onNext(response: BaseResponse<String>) { object : SubscriberListener<BaseResponse<NewCardDataResult>>() { override fun onNext(response: BaseResponse<NewCardDataResult>) { if (response.success) { orderId=response.content?.orderNo.toString() // 保存开卡信息到数据库 val cardRegistration = CardRegistrationBean( cardNumber = cardPhysicalId, userName = binding.newCardUserName.text.toString(), idCard = binding.newCardIdCard.text.toString(), farmerCode = binding.newCardFarmerCode.text.toString(), clientId = clientId, cardFee = cardFee, remark = binding.newCardRemark.text.toString(), paymentMethod = paymentId.toInt(), isReported = true, isCardWritten = true isCardWritten = true, operatorId = orderId, ) // 使用协程在后台线程中保存数据 @@ -371,13 +357,31 @@ try { BaseDaoSingleton.getInstance(this@NewCard2Activity) .cardRegistrationDao().insert(cardRegistration) Toast.makeText( this@NewCard2Activity, "开卡成功", Toast.LENGTH_SHORT ).show() setResult(RESULT_OK) finish() Intent(this@NewCard2Activity, NfcWreatActivity::class.java).apply { putExtra("cardType", USER_CARD_TYPE_1) putExtra("orderId", orderId) putExtra("cardAddr", cardPhysicalId) var userCard = UserCard() userCard.areaNumber =clientInfo.districtNum userCard.userCode =clientInfo.clientNum userCard.phoneNumber =clientInfo.phone userCard.userCodeNumber = response.content?.cardNum?.toInt()!! userCard.projectCode = response.content?.projectNo?.toInt()!! userCard.balance = response.content?.balance?.toInt()!! // userCard.surplusWater = response.content?.surplusWater?.toInt()!! userCard.waterPrice = response.content?.waterPrice?.toFloat()!! // userCard.electricPrice = response.content?.electricPrice?.toFloat()!! userCard.rechargeDate = DateUtils.parseStringToCalendar(response.content?.time) putExtra("userCard", userCard) startActivity(this) } } catch (e: Exception) { CrashReport.postCatchedException(e) Toast.makeText( generallibrary/src/main/java/com/dayu/general/activity/NfcWreatActivity.kt
@@ -5,6 +5,7 @@ import com.dayu.baselibrary.net.subscribers.SubscriberListener import com.dayu.baselibrary.utils.ToastUtil import com.dayu.general.bean.card.ClearCard import com.dayu.general.bean.card.UserCard import com.dayu.general.tool.CardCommon import com.dayu.general.databinding.ActivityNfcWriteGeBinding import com.dayu.general.net.ApiManager @@ -22,6 +23,7 @@ var cardType = "" var orderId = "" var cardAddr = "" private lateinit var userCard: UserCard override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -37,6 +39,12 @@ cardType = intent?.getStringExtra("cardType") ?: "" orderId = intent?.getStringExtra("orderId") ?: "" cardAddr = intent?.getStringExtra("cardAddr") ?: "" if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { userCard = intent?.getSerializableExtra("userCard", UserCard::class.java)!! } else { userCard = (intent?.getSerializableExtra("userCard") as? UserCard)!! } if (cardType.isNotEmpty()) { when (cardType) { CardCommon.CLEAN_CARD_TYPE -> { @@ -68,6 +76,12 @@ } } } CardCommon.USER_CARD_TYPE_1 -> { binding?.cardData?.text = "写用户卡" nfcWreatHelper.writeUserData(userCard) } } } else { ToastUtil.show("卡片错误,当前刷的卡与刚刚的卡不一致") generallibrary/src/main/java/com/dayu/general/bean/card/UserCard.kt
@@ -12,7 +12,7 @@ */ class UserCard : BaseUserCardCard(), Serializable { var cardType: String = USER_CARD_TYPE_1 // 卡类型:A1终端写卡 A8刷卡开泵后值 A2叠加充值 var areaNumber: Int = 0 // 国家行政区域号(12位BCD,精确到村) var areaNumber: String = "" // 国家行政区域号(12位BCD,精确到村) var userCode: String = "" // 用户编号BCD var userCodeNumber: Int = 0 // 用户卡编号(HEX) var phoneNumber: String = "" // 手机号(BCD) @@ -55,7 +55,7 @@ userCard.apply { // 解析国家行政区域号(0-5位) val areaCodeBytes = zero.copyOfRange(0, 6) areaNumber = BcdUtil.bcdToStr(areaCodeBytes).toInt() areaNumber = BcdUtil.bcdToStr(areaCodeBytes) // 解析用户卡编号(6-7位) val userCodeNumberBytes = zero.copyOfRange(6, 8) generallibrary/src/main/java/com/dayu/general/bean/db/CardRegistrationBean.kt
@@ -10,7 +10,7 @@ val cardNumber: String, // IC卡卡号 val userName: String, // 姓名 val idCard: String, // 身份证号 val farmerCode: String, // 农户编号 val clientId: String, // 农户Id val cardFee: Double, // 工本费 val remark: String, // 备注 val paymentMethod: Int, // 支付方式 generallibrary/src/main/java/com/dayu/general/bean/net/NewCardInfo.kt
New file @@ -0,0 +1,32 @@ package com.dayu.general.bean.net // 支付方式数据类 data class PaymentMethod( val id: Long, val name: String, val remarks: String, val deleted: Int ) // 支付方式接口返回数据类 data class PaymentMethodResponse( val itemTotal: Any?, val obj: List<PaymentMethod>, val pageCurr: Any?, val pageSize: Any?, val pageTotal: Any? ) // 用户信息数据类 data class ClientInfo( val clientId: String, val clientNum: String, val name: String, val districtNum: String, val phone: String, val idCard: String, val villageName: String, val address: String, val cardCount: Int, val operateDt: String ) generallibrary/src/main/java/com/dayu/general/bean/net/NewCardResult.kt
New file @@ -0,0 +1,10 @@ package com.dayu.general.bean.net data class NewCardDataResult( var projectNo: String, var cardNum: String, var balance: String, var waterPrice: String, var time: String, var orderNo: String ) generallibrary/src/main/java/com/dayu/general/tool/NfcWreatHelper.kt
@@ -146,6 +146,32 @@ } /** * 写卡(异步) * * @param userCard 用户卡内容 * @param callBack 操作结果和消息回调 */ fun writeUserDataAsync(userCard: UserCard, callBack: NFCCallBack): Disposable { showLoading() val disposable = Observable.fromCallable { writeUserData(userCard, callBack) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ result -> hideLoading() // 结果已经在writeUserData中通过callBack回调了 }, { error -> hideLoading() error.printStackTrace() callBack.isSusses(false, "异步写卡异常: ${error.message}") }) compositeDisposable.add(disposable) return disposable } /** * 写卡 * * @param userCard 用户卡内容 @@ -161,6 +187,22 @@ } /** * 写卡 * * @param userCard 用户卡内容 * @param callBack 回调接口 */ fun writeUserData(userCard: UserCard, callBack: NFCCallBack): Boolean { try { return adapter.writeUserData(userCard, 7, callBack) } catch (e: java.lang.Exception) { e.printStackTrace() callBack.isSusses(false, "写卡异常: ${e.message}") } return false } /** * 修改密码(异步) * * @param ps 密码列表 generallibrary/src/main/java/com/dayu/general/utils/DateUtils.kt
New file @@ -0,0 +1,30 @@ package com.dayu.general.utils import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale object DateUtils { private const val DATE_PATTERN = "yyyy-MM-dd HH:mm:ss" private val sdf by lazy { SimpleDateFormat(DATE_PATTERN, Locale.getDefault()) } /** * 将字符串转换为 Calendar 对象 * @param dateStr 时间字符串,格式:yyyy-MM-dd HH:mm:ss * @return 解析后的 Calendar 对象,失败返回 null */ fun parseStringToCalendar(dateStr: String?): Calendar? { if (dateStr.isNullOrEmpty()) return null return try { val date = sdf.parse(dateStr) val calendar = Calendar.getInstance() calendar.time = date ?: return null calendar } catch (e: Exception) { e.printStackTrace() null } } }