diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2778b5d..435d8d7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,6 +10,9 @@ + + + (), OnTabSty override fun ViewBinding.initListeners() { registerEvents({ data-> - updateUICashTotal() - }, VididinEvents.Event_Account_Cash_Changed) + when (data?.mEventType) { + VididinEvents.Event_Account_Cash_Changed -> { + updateUICashTotal() + } + + VididinEvents.EVENT_AD_WATCHED_FOR_WITHDRAW -> { + var withdrawNum: Float = (data.mData as Double).toFloat() + withdrawInit() + withdrawPayout() + withdrawCheck() + } + } + + }, VididinEvents.Event_Account_Cash_Changed, VididinEvents.EVENT_AD_WATCHED_FOR_WITHDRAW) } override fun ViewBinding.initObservers() { diff --git a/app/src/main/java/com/gamedog/vididin/features/withdraw/WithdrawViewModel.kt b/app/src/main/java/com/gamedog/vididin/features/withdraw/WithdrawViewModel.kt index c574c89..90c3aee 100644 --- a/app/src/main/java/com/gamedog/vididin/features/withdraw/WithdrawViewModel.kt +++ b/app/src/main/java/com/gamedog/vididin/features/withdraw/WithdrawViewModel.kt @@ -2,6 +2,11 @@ package com.gamedog.vididin.features.withdraw import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.ama.core.architecture.util.AndroidUtil +import com.ama.core.architecture.util.DeviceUtil +import com.ama.core.architecture.util.MD5Util +import com.ama.core.architecture.util.NetUtil +import com.gamedog.vididin.VidiConst import com.gamedog.vididin.beans.req.PayInitReq import com.gamedog.vididin.beans.req.PayoutCheckReq import com.gamedog.vididin.beans.req.PayoutReq @@ -28,9 +33,11 @@ class WithdrawViewModel : ViewModel() { fun withdrawInit() { viewModelScope.launch { + val requestParam = PayInitReq().applyInitFields() + _InitData.value = Result.Loading _InitData.value = NetworkUtil.callApi { - NetworkUtil.apiservice().withdrawInit(PayInitReq()) + NetworkUtil.apiservice().withdrawInit(requestParam) } } } @@ -38,21 +45,42 @@ class WithdrawViewModel : ViewModel() { fun withdrawPayout() { viewModelScope.launch { + val requestParam = PayoutReq().applyInitFields().apply { + // TODO - + } + _PayoutResult.value = Result.Loading _PayoutResult.value = NetworkUtil.callApi { - NetworkUtil.apiservice().withdrawPayout(PayoutReq()) + NetworkUtil.apiservice().withdrawPayout(requestParam) } } } fun withdrawCheck() { viewModelScope.launch { + val requestParam = PayoutCheckReq().applyInitFields().apply { + // TODO - + } + _CheckResult.value = Result.Loading _CheckResult.value = NetworkUtil.callApi { - NetworkUtil.apiservice().withdrawCheck(PayoutCheckReq()) + NetworkUtil.apiservice().withdrawCheck(requestParam) } } } + private fun T.applyInitFields(): T { + apply { + platform = "Android" + deviceid = DeviceUtil.generateDeviceId() + version = AndroidUtil.getAppVersionInfo() + ip = NetUtil.getLocalIpAddress() + ts = (System.currentTimeMillis()/1000).toString() + val signOrigin = "${VidiConst.WITHDRAW_MD5KEY}platform=${platform}deviceid=${deviceid}version=${version}ip=${ip}ts={ts}" + sign = MD5Util.md5ForWithDraw(signOrigin) + } + return this + } + } \ No newline at end of file diff --git a/core/architecture/src/main/AndroidManifest.xml b/core/architecture/src/main/AndroidManifest.xml index 643110e..3ccca87 100644 --- a/core/architecture/src/main/AndroidManifest.xml +++ b/core/architecture/src/main/AndroidManifest.xml @@ -2,6 +2,10 @@ + + + + diff --git a/core/architecture/src/main/java/com/ama/core/architecture/util/MD5Util.kt b/core/architecture/src/main/java/com/ama/core/architecture/util/MD5Util.kt index 065ebad..4ab5874 100644 --- a/core/architecture/src/main/java/com/ama/core/architecture/util/MD5Util.kt +++ b/core/architecture/src/main/java/com/ama/core/architecture/util/MD5Util.kt @@ -1,5 +1,7 @@ package com.ama.core.architecture.util +import java.nio.charset.Charset +import java.nio.charset.StandardCharsets import java.security.MessageDigest object MD5Util { @@ -22,4 +24,97 @@ object MD5Util { null } } + + /*fun md5ForWithDraw(input: String): String? { + return try { + val messageDigest = MessageDigest.getInstance("MD5") + val digestBytes = messageDigest.digest(input.toByteArray(Charsets.UTF_8)) + val hashValue = digestBytes.hashCode() + + + + val hexString = StringBuilder() + for (b in digestBytes) { + val hex = Integer.toHexString(0xFF and b.toInt()) + if (hex.length == 1) { + hexString.append('0') + } + hexString.append(hex) + } + hexString.toString() + } catch (e: Exception) { + e.printStackTrace() + null + } + }*/ + + + + /** + * MD5加密函数 + * @param original 原始字符串 + * @param charsetName 字符编码名称,默认为"UTF-8" + * @return 返回32位小写的MD5哈希字符串 + */ + fun md5ForWithDraw(input: String): String { + // 元宝 + val bytes = input.toByteArray(charset("UTF-8")) // 按指定字符集转换为字节数组[6](@ref) + val digest = MessageDigest.getInstance("MD5") // 获取MD5实例[6,7,8](@ref) + val hashBytes = digest.digest(bytes) // 计算MD5哈希值[6,7,8](@ref) + + // 将字节数组转换为十六进制字符串[6,8](@ref) + val hexString = StringBuilder() + for (byte in hashBytes) { + val hex = (byte.toInt() and 0xFF).toString(16) // 确保无符号转换[6](@ref) + if (hex.length == 1) { + hexString.append('0') // 单数位前补零[6,8](@ref) + } + hexString.append(hex) + } + return hexString.toString().lowercase() + + /* // 百度 + val md = MessageDigest.getInstance("MD5") + val inputBytes = input.toByteArray(StandardCharsets.UTF_8) + val hashBytes = md.digest(inputBytes) + + return hashBytes.joinToString("") { byte -> "%02x".format(byte) }*/ + + + /* // 豆包 + // 1. 对应C#: Encoding.GetEncoding(pCharSet).GetBytes("utf-8") + val charset = Charset.forName("UTF-8") + val tData = "utf-8".toByteArray(charset) + + // 2. 对应C#: new MD5CryptoServiceProvider().ComputeHash(tData) + val md5 = MessageDigest.getInstance("MD5") + val tHash = md5.digest(tData) + + // 3. 对应C#: 循环拼接两位小写十六进制(x2) + val tResult = StringBuilder(32) // 预初始化容量32,与C#一致 + for (i in tHash.indices) { + // 对应C#: tHash[i].ToString("x2") —— 格式化为两位十六进制(不足补0) + tResult.append(String.format("%02x", tHash[i])) + } + + // 4. 对应C#: ToString().ToLower()(注:%02x本身已是小写,此处保持ToLower()与原代码一致) + return tResult.toString().lowercase() + */ + + } + + + /* + private static string GetMD5(string pOriginal) + { + var tData = Encoding.GetEncoding(pCharSet).GetBytes("utf-8"); + var tHash = new MD5CryptoServiceProvider().ComputeHash(tData); + var tResult = new StringBuilder(32); + for (int i = 0; i < tHash.Length; i++) + { + tResult.Append(tHash[i].ToString("x2")); + } + return tResult.ToString().ToLower(); + }*/ + } \ No newline at end of file diff --git a/core/architecture/src/main/java/com/ama/core/architecture/util/NetUtil.kt b/core/architecture/src/main/java/com/ama/core/architecture/util/NetUtil.kt new file mode 100644 index 0000000..79ad13c --- /dev/null +++ b/core/architecture/src/main/java/com/ama/core/architecture/util/NetUtil.kt @@ -0,0 +1,93 @@ +package com.ama.core.architecture.util + +import android.annotation.SuppressLint +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities +import android.net.wifi.WifiManager +import com.ama.core.architecture.BaseApp +import java.net.Inet4Address +import java.net.InetAddress +import java.net.NetworkInterface + +@SuppressLint("StaticFieldLeak") +object NetUtil { + val context = BaseApp.appContext() + /** + * 获取本机IPv4地址 + * @param context 上下文对象 + * @return IPv4地址字符串,无网络连接时返回null + */ + fun getLocalIpAddress(): String? { + return when (getNetworkType()) { + NetworkType.WIFI -> getWifiIpAddress() + NetworkType.MOBILE -> getMobileIpAddress() + NetworkType.NONE -> null // 无网络连接 + } + } + + /** + * 获取当前网络类型 + */ + private fun getNetworkType(): NetworkType { + val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + val network = connectivityManager.activeNetwork ?: return NetworkType.NONE + val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return NetworkType.NONE + + return when { + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> NetworkType.WIFI + capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> NetworkType.MOBILE + else -> NetworkType.NONE + } + } + + /** + * 获取Wi-Fi网络下的IP地址 + */ + private fun getWifiIpAddress(): String? { + return try { + val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager + val wifiInfo = wifiManager.connectionInfo + val ipAddress = wifiInfo.ipAddress + intToIp(ipAddress) + } catch (e: Exception) { + e.printStackTrace() + null + } + } + + /** + * 获取移动数据网络下的IP地址 + */ + private fun getMobileIpAddress(): String? { + return try { + val interfaces: java.util.Enumeration = NetworkInterface.getNetworkInterfaces() + while (interfaces.hasMoreElements()) { + val networkInterface = interfaces.nextElement() + val addresses: java.util.Enumeration = networkInterface.inetAddresses + while (addresses.hasMoreElements()) { + val address = addresses.nextElement() + // 过滤回环地址、链路本地地址,且只返回IPv4地址[2,3](@ref) + if (!address.isLoopbackAddress && !address.isLinkLocalAddress && address is Inet4Address) { + return address.hostAddress + } + } + } + null + } catch (e: Exception) { + e.printStackTrace() + null + } + } + + /** + * 将整数形式的IP地址转换为字符串[1,2,4](@ref) + */ + private fun intToIp(ipAddress: Int): String { + return "${(ipAddress and 0xFF)}.${(ipAddress shr 8 and 0xFF)}.${(ipAddress shr 16 and 0xFF)}.${(ipAddress shr 24 and 0xFF)}" + } + + private enum class NetworkType { + WIFI, MOBILE, NONE + } +} \ No newline at end of file