feat(generallibrary): 优化开卡流程和界面
-调整了开卡界面布局,优化了用户信息展示
- 增加了客户ID字段,用于获取客户详细信息
- 修改了金额输入框的提示文本
- 优化了支付方式列表的展示
- 调整了注册新卡的逻辑
- 修改了搜索用户列表和结果的数据结构
| | |
| | | return nullptr; |
| | | } |
| | | |
| | | __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Decrypting sector %d", sector); |
| | | __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Encrypted data: %02X %02X %02X %02X %02X %02X", |
| | | encrypted_data[0], encrypted_data[1], encrypted_data[2], |
| | | encrypted_data[3], encrypted_data[4], encrypted_data[5]); |
| | | __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Using XOR key: %02X %02X %02X %02X %02X %02X", |
| | | XOR_KEYS[sector][0], XOR_KEYS[sector][1], XOR_KEYS[sector][2], |
| | | XOR_KEYS[sector][3], XOR_KEYS[sector][4], XOR_KEYS[sector][5]); |
| | | // __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Decrypting sector %d", sector); |
| | | // __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Encrypted data: %02X %02X %02X %02X %02X %02X", |
| | | // encrypted_data[0], encrypted_data[1], encrypted_data[2], |
| | | // encrypted_data[3], encrypted_data[4], encrypted_data[5]); |
| | | // __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Using XOR key: %02X %02X %02X %02X %02X %02X", |
| | | // XOR_KEYS[sector][0], XOR_KEYS[sector][1], XOR_KEYS[sector][2], |
| | | // XOR_KEYS[sector][3], XOR_KEYS[sector][4], XOR_KEYS[sector][5]); |
| | | |
| | | unsigned char decrypted[6]; |
| | | for (int i = 0; i < 6; i++) { |
| | | decrypted[i] = encrypted_data[i] ^ XOR_KEYS[sector][i]; |
| | | __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Byte %d: %02X ^ %02X = %02X", |
| | | i, encrypted_data[i], XOR_KEYS[sector][i], decrypted[i]); |
| | | // __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Byte %d: %02X ^ %02X = %02X", |
| | | // i, encrypted_data[i], XOR_KEYS[sector][i], decrypted[i]); |
| | | } |
| | | |
| | | std::string result; |
| | |
| | | result += hex; |
| | | } |
| | | |
| | | __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Decrypted result: %s", result.c_str()); |
| | | // __android_log_print(ANDROID_LOG_INFO, "GeBaseHelper", "Decrypted result: %s", result.c_str()); |
| | | return env->NewStringUTF(result.c_str()); |
| | | } |
| | | |
| | |
| | | jobject packageInfoObject = env->CallObjectMethod(packageManagerObject, getPackageInfoId, |
| | | packNameString, 64); |
| | | if (!packageInfoObject) { |
| | | __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get PackageInfo"); |
| | | // __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get PackageInfo"); |
| | | return env->NewStringUTF(""); |
| | | } |
| | | |
| | |
| | | jfieldID signaturefieldID = env->GetFieldID(packageInfoClass, "signatures", |
| | | "[Landroid/content/pm/Signature;"); |
| | | if (!signaturefieldID) { |
| | | __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature field ID"); |
| | | // __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature field ID"); |
| | | return env->NewStringUTF(""); |
| | | } |
| | | |
| | |
| | | jobjectArray signatureArray = (jobjectArray) env->GetObjectField(packageInfoObject, |
| | | signaturefieldID); |
| | | if (!signatureArray || env->GetArrayLength(signatureArray) == 0) { |
| | | __android_log_print(ANDROID_LOG_ERROR, "M1Card", "No signatures found"); |
| | | // __android_log_print(ANDROID_LOG_ERROR, "M1Card", "No signatures found"); |
| | | return env->NewStringUTF(""); |
| | | } |
| | | |
| | | // 获取第一个签名对象 |
| | | jobject signatureObject = env->GetObjectArrayElement(signatureArray, 0); |
| | | if (!signatureObject) { |
| | | __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature object"); |
| | | // __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature object"); |
| | | return env->NewStringUTF(""); |
| | | } |
| | | |
| | | // 获取签名字符串 |
| | | jstring signatureString = (jstring) env->CallObjectMethod(signatureObject, signToStringId); |
| | | if (!signatureString) { |
| | | __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature string"); |
| | | // __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature string"); |
| | | return env->NewStringUTF(""); |
| | | } |
| | | |
| | | // 获取签名字符串的UTF-8字符 |
| | | const char *signStrng = env->GetStringUTFChars(signatureString, 0); |
| | | if (!signStrng) { |
| | | __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature UTF chars"); |
| | | // __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to get signature UTF chars"); |
| | | return env->NewStringUTF(""); |
| | | } |
| | | |
| | |
| | | |
| | | // 解密并转换每个扇区密钥 |
| | | for (size_t i = 0; i < numKeys; i++) { |
| | | __android_log_print(ANDROID_LOG_DEBUG, "M1Card", "处理扇区 %zu 的密钥", i); |
| | | // __android_log_print(ANDROID_LOG_DEBUG, "M1Card", "处理扇区 %zu 的密钥", i); |
| | | |
| | | // 确保不会越界访问 |
| | | if (i * 12 + 6 > sizeof(ENCRYPTED_SECTOR_KEYS)) { |
| | | __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Index out of bounds"); |
| | | // __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Index out of bounds"); |
| | | break; |
| | | } |
| | | |
| | |
| | | jstring decrypted_str = decrypt_key(env, ENCRYPTED_SECTOR_KEYS + (i * 12), 6); |
| | | |
| | | if (!decrypted_str) { |
| | | __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to decrypt key for sector %zu", i); |
| | | // __android_log_print(ANDROID_LOG_ERROR, "M1Card", "Failed to decrypt key for sector %zu", i); |
| | | continue; |
| | | } |
| | | |
| | |
| | | |
| | | // 用户ID |
| | | private var userId: String = "" |
| | | |
| | | // 客户ID |
| | | private var clientId: String = "" |
| | | |
| | | companion object { |
| | | private const val TAG = "NewCard2Activity" |
| | |
| | | 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) |
| | | binding = ActivityNewCard1GeBinding.inflate(layoutInflater) |
| | | setContentView(binding.root) |
| | | |
| | | // 获取传递的clientId参数 |
| | | clientId = intent.getStringExtra("clientId") ?: "" |
| | | |
| | | initView() |
| | | |
| | | // 如果有clientId,获取客户信息 |
| | | if (clientId.isNotEmpty()) { |
| | | getClientInfo(clientId) |
| | | } |
| | | |
| | | // 获取支付方式 |
| | | getPaymentMethods() |
| | | initListener() |
| | | } |
| | | |
| | | |
| | | private fun initView() { |
| | | // 初始化标题栏返回按钮 |
| | |
| | | // 初始化NFC读卡容器,初始隐藏 |
| | | binding.nfcContainer.visibility = View.VISIBLE |
| | | |
| | | // 从Intent中获取用户信息(如果有) |
| | | val userName = intent.getStringExtra("userName") ?: "" |
| | | val rawIdCard = intent.getStringExtra("idCard") |
| | | val idCard = if (rawIdCard.isNullOrBlank()) "无" else rawIdCard |
| | | val farmerCode = intent.getStringExtra("farmerCode") ?: "" |
| | | userId = intent.getStringExtra("userId") ?: "" |
| | | |
| | | // 设置用户信息 |
| | | binding.newCardUserName.text = userName |
| | | binding.newCardIdCard.text = idCard |
| | | binding.newCardFarmerCode.text = farmerCode |
| | | |
| | | // 设置金额输入限制为两位小数 |
| | | binding.newCardRechargeAmount.addTextChangedListener(createDecimalTextWatcher()) |
| | | binding.newCardCardFee.addTextChangedListener(createDecimalTextWatcher()) |
| | | } |
| | | |
| | | /** |
| | | * 获取客户详细信息 |
| | | */ |
| | | private fun getClientInfo(clientId: String) { |
| | | ApiManager.getInstance().requestGetLoading( |
| | | this, |
| | | "terminal/client/getTermOne/$clientId", |
| | | ClientInfo::class.java, |
| | | null, |
| | | object : SubscriberListener<BaseResponse<ClientInfo>>() { |
| | | override fun onNext(response: BaseResponse<ClientInfo>) { |
| | | if (response.success) { |
| | | val clientInfo = response.content |
| | | if (clientInfo != null) { |
| | | // 显示客户信息到界面 |
| | | displayClientInfo(clientInfo) |
| | | } else { |
| | | Toast.makeText( |
| | | this@NewCard2Activity, |
| | | "获取客户信息失败: 返回数据为空", |
| | | Toast.LENGTH_SHORT |
| | | ).show() |
| | | } |
| | | } else { |
| | | Toast.makeText( |
| | | this@NewCard2Activity, |
| | | "获取客户信息失败: ${response.msg}", |
| | | Toast.LENGTH_SHORT |
| | | ).show() |
| | | } |
| | | } |
| | | |
| | | override fun onError(e: Throwable?) { |
| | | super.onError(e) |
| | | Toast.makeText( |
| | | this@NewCard2Activity, |
| | | "获取客户信息失败: ${e?.message ?: "网络异常"}", |
| | | Toast.LENGTH_SHORT |
| | | ).show() |
| | | } |
| | | } |
| | | ) |
| | | } |
| | | |
| | | /** |
| | | * 显示客户信息到界面 |
| | | */ |
| | | private fun displayClientInfo(clientInfo: ClientInfo) { |
| | | // 保存用户ID供后续使用 |
| | | userId = clientInfo.clientId |
| | | |
| | | // 显示用户基本信息 |
| | | binding.newCardUserName.text = clientInfo.name |
| | | binding.newCardIdCard.text = if (clientInfo.idCard.isBlank()) "无" else clientInfo.idCard |
| | | binding.newCardFarmerCode.text = clientInfo.clientNum |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 注册新卡 |
| | | */ |
| | | private fun registerNewCard() { |
| | | // 获取充值金额 |
| | | val rechargeAmountStr = binding.newCardRechargeAmount.text.toString() |
| | |
| | | // 处理用户点击事件 |
| | | // 传递用户信息到开卡界面 |
| | | val intent = Intent(this, NewCard2Activity::class.java) |
| | | intent.putExtra("userName", user.name) |
| | | intent.putExtra("idCard", user.idCard) |
| | | intent.putExtra("farmerCode", user.clientNum) |
| | | intent.putExtra("userId", user.id) |
| | | intent.putExtra("clientId", user.clientId) |
| | | startActivity(intent) |
| | | } |
| | | |
| | |
| | | val idCard: String? = null, // 身份证号 |
| | | val money: String? = null, // 卡余额 |
| | | val phone: String? = null, // 电话号码 |
| | | val stateName: String? = null // 状态名称 |
| | | val stateName: String? = null, // 状态名称 |
| | | val clientId: String? = null // 客户ID |
| | | ) |
| | | } |
| | |
| | | /** |
| | | * 用户信息 |
| | | */ |
| | | data class UserInfo ( |
| | | data class UserInfo( |
| | | val address: String? = null, // 地址 |
| | | val cardCount: Int? = null, // 卡数量 |
| | | val clientNum: String? = null, // 客户编号 |
| | |
| | | val idCard: String? = null, // 身份证 |
| | | val name: String? = null, // 姓名 |
| | | val operateDt: String? = null, // 操作日期 |
| | | val phone: String? = null // 电话 |
| | | val phone: String? = null, // 电话 |
| | | val clientId: String? = null // 客户ID |
| | | ) |
| | | } |
| | |
| | | android:layout_marginTop="24dp" |
| | | android:layout_marginEnd="16dp" |
| | | android:layout_marginBottom="24dp" |
| | | android:visibility="visible" |
| | | android:visibility="gone" |
| | | app:cardBackgroundColor="@android:color/white" |
| | | app:cardCornerRadius="12dp" |
| | | app:cardElevation="4dp" |
| | |
| | | android:layout_height="0dp" |
| | | android:fillViewport="true" |
| | | android:scrollbars="none" |
| | | android:visibility="gone" |
| | | app:layout_constraintBottom_toBottomOf="parent" |
| | | android:visibility="visible" |
| | | app:layout_constraintBottom_toTopOf="@+id/newCard_registBtn" |
| | | app:layout_constraintTop_toBottomOf="@+id/titleBar"> |
| | | |
| | | <LinearLayout |
| | |
| | | android:textColor="#333333" |
| | | android:textSize="18sp" |
| | | android:textStyle="bold" /> |
| | | <LinearLayout |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_marginBottom="12dp" |
| | | android:gravity="center_vertical" |
| | | android:orientation="horizontal"> |
| | | |
| | | <TextView |
| | | android:layout_width="105dp" |
| | | android:layout_height="wrap_content" |
| | | android:text="工本费:" |
| | | android:textColor="#666666" |
| | | android:textSize="@dimen/new_card_size" /> |
| | | |
| | | <LinearLayout |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:background="@drawable/edit_text_bg_selector" |
| | | android:orientation="horizontal" |
| | | android:gravity="center_vertical" |
| | | android:paddingStart="10dp" |
| | | android:paddingEnd="10dp" |
| | | android:paddingTop="8dp" |
| | | android:paddingBottom="8dp"> |
| | | |
| | | <EditText |
| | | android:id="@+id/newCard_cardFee" |
| | | android:layout_width="0dp" |
| | | android:layout_weight="1" |
| | | android:layout_height="wrap_content" |
| | | android:background="@null" |
| | | android:hint="请输入工本费(选填)" |
| | | android:inputType="numberDecimal" |
| | | android:textColor="#333333" |
| | | android:textColorHint="#BBBBBB" |
| | | android:textSize="@dimen/new_card_size" /> |
| | | |
| | | <TextView |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:text="元" |
| | | android:textColor="#666666" |
| | | android:textSize="@dimen/new_card_size" /> |
| | | </LinearLayout> |
| | | </LinearLayout> |
| | | <LinearLayout |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | |
| | | </LinearLayout> |
| | | </LinearLayout> |
| | | |
| | | <LinearLayout |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_marginBottom="12dp" |
| | | android:gravity="center_vertical" |
| | | android:orientation="horizontal"> |
| | | |
| | | <TextView |
| | | android:layout_width="105dp" |
| | | android:layout_height="wrap_content" |
| | | android:text="工本费:" |
| | | android:textColor="#666666" |
| | | android:textSize="@dimen/new_card_size" /> |
| | | |
| | | <LinearLayout |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:background="@drawable/edit_text_bg_selector" |
| | | android:orientation="horizontal" |
| | | android:gravity="center_vertical" |
| | | android:paddingStart="10dp" |
| | | android:paddingEnd="10dp" |
| | | android:paddingTop="8dp" |
| | | android:paddingBottom="8dp"> |
| | | |
| | | <EditText |
| | | android:id="@+id/newCard_cardFee" |
| | | android:layout_width="0dp" |
| | | android:layout_weight="1" |
| | | android:layout_height="wrap_content" |
| | | android:background="@null" |
| | | android:hint="请输入工本费(选填)" |
| | | android:inputType="numberDecimal" |
| | | android:textColor="#333333" |
| | | android:textColorHint="#BBBBBB" |
| | | android:textSize="@dimen/new_card_size" /> |
| | | |
| | | <TextView |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:text="元" |
| | | android:textColor="#666666" |
| | | android:textSize="@dimen/new_card_size" /> |
| | | </LinearLayout> |
| | | </LinearLayout> |
| | | |
| | | <LinearLayout |
| | | android:layout_width="match_parent" |
| | |
| | | </RadioGroup> |
| | | </LinearLayout> |
| | | </androidx.cardview.widget.CardView> |
| | | <TextView |
| | | android:id="@+id/newCard_registBtn" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="56dp" |
| | | android:layout_marginTop="15dp" |
| | | android:background="@color/bottom_color" |
| | | android:visibility="visible" |
| | | android:gravity="center" |
| | | android:text="确认开卡" |
| | | android:textColor="#FFFFFF" |
| | | android:textSize="16sp" /> |
| | | </LinearLayout> |
| | | </ScrollView> |
| | | |
| | | <TextView |
| | | android:id="@+id/newCard_registBtn" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="56dp" |
| | | android:background="@color/bottom_color" |
| | | android:gravity="center" |
| | | android:text="确认开卡" |
| | | android:textColor="#FFFFFF" |
| | | android:textSize="16sp" |
| | | android:visibility="visible" |
| | | app:layout_constraintBottom_toBottomOf="parent" |
| | | app:layout_constraintEnd_toEndOf="parent" |
| | | app:layout_constraintStart_toStartOf="parent" /> |
| | | |
| | | </androidx.constraintlayout.widget.ConstraintLayout> |