体现接口 调用

This commit is contained in:
renhaoting 2025-12-10 19:21:11 +08:00
parent 2ebaf58f56
commit 1a3b70076a
7 changed files with 244 additions and 7 deletions

View File

@ -10,6 +10,9 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application <application

View File

@ -14,8 +14,10 @@ object VidiConst {
const val WATCH_AD_FOR_CONVERT_GOLD_2_CASH = 6 const val WATCH_AD_FOR_CONVERT_GOLD_2_CASH = 6
/**
* Withdraw related const
*/
const val WITHDRAW_MD5KEY = "eonline~#*^%$@!~0702"

View File

@ -126,8 +126,20 @@ class WithDrawActivity : AppViewsEmptyViewModelActivity<ViewBinding>(), OnTabSty
override fun ViewBinding.initListeners() { override fun ViewBinding.initListeners() {
registerEvents({ data-> registerEvents({ data->
updateUICashTotal() when (data?.mEventType) {
}, VididinEvents.Event_Account_Cash_Changed) 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() { override fun ViewBinding.initObservers() {

View File

@ -2,6 +2,11 @@ package com.gamedog.vididin.features.withdraw
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope 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.PayInitReq
import com.gamedog.vididin.beans.req.PayoutCheckReq import com.gamedog.vididin.beans.req.PayoutCheckReq
import com.gamedog.vididin.beans.req.PayoutReq import com.gamedog.vididin.beans.req.PayoutReq
@ -28,9 +33,11 @@ class WithdrawViewModel : ViewModel() {
fun withdrawInit() { fun withdrawInit() {
viewModelScope.launch { viewModelScope.launch {
val requestParam = PayInitReq().applyInitFields()
_InitData.value = Result.Loading _InitData.value = Result.Loading
_InitData.value = NetworkUtil.callApi { _InitData.value = NetworkUtil.callApi {
NetworkUtil.apiservice().withdrawInit(PayInitReq()) NetworkUtil.apiservice().withdrawInit(requestParam)
} }
} }
} }
@ -38,21 +45,42 @@ class WithdrawViewModel : ViewModel() {
fun withdrawPayout() { fun withdrawPayout() {
viewModelScope.launch { viewModelScope.launch {
val requestParam = PayoutReq().applyInitFields().apply {
// TODO -
}
_PayoutResult.value = Result.Loading _PayoutResult.value = Result.Loading
_PayoutResult.value = NetworkUtil.callApi { _PayoutResult.value = NetworkUtil.callApi {
NetworkUtil.apiservice().withdrawPayout(PayoutReq()) NetworkUtil.apiservice().withdrawPayout(requestParam)
} }
} }
} }
fun withdrawCheck() { fun withdrawCheck() {
viewModelScope.launch { viewModelScope.launch {
val requestParam = PayoutCheckReq().applyInitFields().apply {
// TODO -
}
_CheckResult.value = Result.Loading _CheckResult.value = Result.Loading
_CheckResult.value = NetworkUtil.callApi { _CheckResult.value = NetworkUtil.callApi {
NetworkUtil.apiservice().withdrawCheck(PayoutCheckReq()) NetworkUtil.apiservice().withdrawCheck(requestParam)
} }
} }
} }
private fun <T : PayInitReq> 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
}
} }

View File

@ -2,6 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application> <application>
<activity android:name=".util.permission.PermissionActivity" android:exported="false" /> <activity android:name=".util.permission.PermissionActivity" android:exported="false" />

View File

@ -1,5 +1,7 @@
package com.ama.core.architecture.util package com.ama.core.architecture.util
import java.nio.charset.Charset
import java.nio.charset.StandardCharsets
import java.security.MessageDigest import java.security.MessageDigest
object MD5Util { object MD5Util {
@ -22,4 +24,97 @@ object MD5Util {
null 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();
}*/
} }

View File

@ -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> = NetworkInterface.getNetworkInterfaces()
while (interfaces.hasMoreElements()) {
val networkInterface = interfaces.nextElement()
val addresses: java.util.Enumeration<InetAddress> = 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
}
}