From 1988f2448cb839c3f1f75b68469c5e218b5d3ea2 Mon Sep 17 00:00:00 2001 From: renhaoting <370797079@qq.com> Date: Mon, 8 Dec 2025 18:12:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=8E=A5=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/gamedog/vididin/VidiConst.kt | 7 +- .../java/com/gamedog/vididin/beans/Account.kt | 1 + .../com/gamedog/vididin/beans/ZeroBuyResp.kt | 32 ++++++ .../gamedog/vididin/di/GlobalInterceptor.kt | 34 +++---- .../gamedog/vididin/di/GlobalInterceptor2.kt | 98 +++++++++++++++++++ .../vididin/features/zero/ZeroBuyActivity.kt | 51 ++++++++-- .../vididin/features/zero/ZeroBuyViewModel.kt | 79 +++++++++++++++ .../com/gamedog/vididin/netbase/ApiService.kt | 36 +++++++ .../gamedog/vididin/netbase/NetworkUtil.kt | 56 +++++++++++ .../com/gamedog/vididin/netbase/Result.kt | 7 ++ .../gamedog/vididin/netbase/RetrofitUtil.kt | 49 ++++++++++ .../gamedog/vididin/request/RequestUtil.kt | 10 ++ .../ama/core/architecture/util/DeviceUtil.kt | 6 +- 13 files changed, 430 insertions(+), 36 deletions(-) create mode 100644 app/src/main/java/com/gamedog/vididin/beans/ZeroBuyResp.kt create mode 100644 app/src/main/java/com/gamedog/vididin/di/GlobalInterceptor2.kt create mode 100644 app/src/main/java/com/gamedog/vididin/features/zero/ZeroBuyViewModel.kt create mode 100644 app/src/main/java/com/gamedog/vididin/netbase/ApiService.kt create mode 100644 app/src/main/java/com/gamedog/vididin/netbase/NetworkUtil.kt create mode 100644 app/src/main/java/com/gamedog/vididin/netbase/Result.kt create mode 100644 app/src/main/java/com/gamedog/vididin/netbase/RetrofitUtil.kt diff --git a/app/src/main/java/com/gamedog/vididin/VidiConst.kt b/app/src/main/java/com/gamedog/vididin/VidiConst.kt index b25b204..a79c435 100644 --- a/app/src/main/java/com/gamedog/vididin/VidiConst.kt +++ b/app/src/main/java/com/gamedog/vididin/VidiConst.kt @@ -3,6 +3,7 @@ package com.gamedog.vididin object VidiConst { + const val URL_DISCORD: String = "https://www.baidu.com" const val URL_GAME: String = "https://www.baidu.com" @@ -29,8 +30,12 @@ object VidiConst { const val PER_CASH_COST_GOLD_NUM = 1000 const val WATCH_AD_REWARD_GOLD = 200 + const val ZEROBUY_SECRET: String = "1f04c57a" + const val ZEROBUY_APPID: String = "com.vididin.real.money.game" + +} + -} \ No newline at end of file diff --git a/app/src/main/java/com/gamedog/vididin/beans/Account.kt b/app/src/main/java/com/gamedog/vididin/beans/Account.kt index eb4c5cf..0a9295a 100644 --- a/app/src/main/java/com/gamedog/vididin/beans/Account.kt +++ b/app/src/main/java/com/gamedog/vididin/beans/Account.kt @@ -12,6 +12,7 @@ data class Account( @Volatile var cashCount: Float = 0F, var bankInfo: BankInfo? = null, + val zeroBuyServerSecret: String = "", ) diff --git a/app/src/main/java/com/gamedog/vididin/beans/ZeroBuyResp.kt b/app/src/main/java/com/gamedog/vididin/beans/ZeroBuyResp.kt new file mode 100644 index 0000000..553dcd0 --- /dev/null +++ b/app/src/main/java/com/gamedog/vididin/beans/ZeroBuyResp.kt @@ -0,0 +1,32 @@ +package com.gamedog.vididin.beans + + +data class ZeroBuyResp ( + val Code: Int, + val Message: String, + + val UserId: Int, + val CurrentPurchases: String, + val FinishedPurchases: String, + var mCurrentList: List?, + var mFinishedList: List?, + val Content: String, +) + + +data class ZeroBuyItem ( + val id:Int = 0, + val title: String? = null, + val start_time:Long = 0, + val end_time:Long = 0, + val target_num:Int = 0, + val cost:Int = 0, + val price: String? = null, + val image:Int = 0, + val current_users: List? = null, + val winners: List? = null, + val redeem_code: String? = null, + val completed: Boolean = false, +) + + diff --git a/app/src/main/java/com/gamedog/vididin/di/GlobalInterceptor.kt b/app/src/main/java/com/gamedog/vididin/di/GlobalInterceptor.kt index 80e96f5..8d0a3bd 100644 --- a/app/src/main/java/com/gamedog/vididin/di/GlobalInterceptor.kt +++ b/app/src/main/java/com/gamedog/vididin/di/GlobalInterceptor.kt @@ -28,31 +28,21 @@ class GlobalInterceptor : Interceptor { val timeSec = RequestUtil.getTimestampSec() - val headersBuilder = Headers.Builder() - /* - .add("authorazation", "Bearer xxxxx") - .add("AUTH_DID", AppUtils.getAndroidID()) - .add("platform", AppConstant.APP_CLIENT) - .add("Authorization", "Bearer xxx") - .add("versionNum", "100") - */ - .add("User-Agent", "Android") - .add("Accept-Language", Locale.getDefault().toLanguageTag()) - .add("Content-Type", "application/json") - .add("Accept", "application/json") - .add("Accept-Charset", "utf-8") + val requestBuilder = chain.request().newBuilder() + .addHeader("User-Agent", "Android") + .addHeader("Accept-Language", Locale.getDefault().toLanguageTag()) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .addHeader("Accept-Charset", "utf-8") // server real defined - .add("ApplicationId", RequestUtil.Request_APPId) - .add("Timestamp", timeSec.toString()) - .add("Sign", RequestUtil.getRequestSign(timeSec)) - .add("DeviceId", DeviceUtil.generateDeviceId()) + .addHeader("ApplicationId", RequestUtil.Request_APPId) + .addHeader("Timestamp", timeSec.toString()) + .addHeader("Sign", RequestUtil.getRequestSign(timeSec)) + .addHeader("DeviceId", DeviceUtil.generateDeviceId()) + .addHeader("authorazation", "Bearer xxxxx") + request = requestBuilder.build() - - val headers = headersBuilder.build() - request = chain.request().newBuilder() - .headers(headers) - .build() val response = chain.proceed(request) diff --git a/app/src/main/java/com/gamedog/vididin/di/GlobalInterceptor2.kt b/app/src/main/java/com/gamedog/vididin/di/GlobalInterceptor2.kt new file mode 100644 index 0000000..ae2cecf --- /dev/null +++ b/app/src/main/java/com/gamedog/vididin/di/GlobalInterceptor2.kt @@ -0,0 +1,98 @@ +package com.gamedog.vididin.core.network.di + + +import android.util.Log +import com.ama.core.architecture.util.DeviceUtil +import com.gamedog.vididin.request.RequestUtil +import okhttp3.Headers +import okhttp3.Interceptor +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import okhttp3.ResponseBody +import okhttp3.ResponseBody.Companion.asResponseBody +import okio.Buffer +import java.io.IOException +import java.util.Locale + + +class GlobalInterceptor2 : Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + var request = chain.request() + val bodyStr = readBody(chain.request().body) + val emptyBody = "{}".toRequestBody("application/json;charset=utf-8".toMediaType()) + val requestBody = if (bodyStr.isNotBlank()) request.body else emptyBody + + + + val requestBuilder = chain.request().newBuilder() + .addHeader("User-Agent", "Android") + .addHeader("Accept-Language", Locale.getDefault().toLanguageTag()) + .addHeader("Content-Type", "application/json") + .addHeader("Accept", "application/json") + .addHeader("Accept-Charset", "utf-8") + // server real defined + .addHeader("ApplicationId", RequestUtil.Request_ZeroBuy_APPId) + .addHeader("DeviceId", DeviceUtil.generateDeviceId()) + .addHeader("authorazation", "Bearer xxxxx") + + request = requestBuilder.build() + + val response = chain.proceed(request) + + + if (true) { + try { + val contentStr = clone(response.body)?.string() + Log.d("RetroLog" , + """ + ———————————————— 请求 Start —————————————————————————————— + ${request.url} + ******** 请求头 ${request.method} ********: + ${getRequestHeadersString(request)} + ******** 请求体(当post等时) ********: + ${readBody(requestBody)} + ******** 请求响应 ********: + $contentStr + ———————————————— 请求 End ——————————————————————————————— + """.trimIndent() + ) + } catch (e: Exception) { + Log.d("RetroLog" , "GlobalInterceptor request.exception : ${e.localizedMessage}}") + } + } + + return response + } + + + fun getRequestHeadersString(request: Request): String { + val headers = request.headers + val headerCount = headers.size + + val sb = StringBuilder() + for (i in 0 until headerCount) { + val key = headers.name(i) + val value = headers.value(i) + sb.append("$key=$value\n") + } + return sb.toString() + } + + private fun readBody(body: RequestBody?): String { + val buffer = Buffer() + body?.writeTo(buffer) + return buffer.readUtf8() + } + + @Throws(IOException::class) + private fun clone(body: ResponseBody?): ResponseBody? { + val source = body?.source() + if (source?.request(Long.MAX_VALUE) == true) throw IOException("body too long!") + val bufferedCopy = source?.buffer?.clone() + return bufferedCopy?.asResponseBody(body.contentType(), body.contentLength()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gamedog/vididin/features/zero/ZeroBuyActivity.kt b/app/src/main/java/com/gamedog/vididin/features/zero/ZeroBuyActivity.kt index 97838e3..6ababed 100644 --- a/app/src/main/java/com/gamedog/vididin/features/zero/ZeroBuyActivity.kt +++ b/app/src/main/java/com/gamedog/vididin/features/zero/ZeroBuyActivity.kt @@ -4,23 +4,27 @@ import android.app.Activity import android.content.Intent import android.view.LayoutInflater import androidx.activity.viewModels -import com.ama.core.architecture.appBase.AppViewsActivity +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.ama.core.architecture.appBase.AppViewsEmptyViewModelActivity import com.ama.core.architecture.util.setOnClickBatch import com.gamedog.vididin.R +import com.gamedog.vididin.beans.ZeroBuyResp import com.gamedog.vididin.core.login.login.AccountManager import com.gamedog.vididin.features.zero.dialogs.ZeroBuyRulesDialog import com.gamedog.vididin.router.Router import dagger.hilt.android.AndroidEntryPoint -import kotlin.getValue +import kotlinx.coroutines.launch +import com.gamedog.vididin.netbase.Result import com.gamedog.vididin.databinding.ActivityZerobuyBinding as ViewBinding -import com.gamedog.vididin.main.MainUiState as UiState -import com.gamedog.vididin.main.MainViewModel as ViewModel + @AndroidEntryPoint -class ZeroBuyActivity : AppViewsActivity() { +class ZeroBuyActivity : AppViewsEmptyViewModelActivity() { + private val viewModel: ZeroBuyViewModel by viewModels() - override val mViewModel: ViewModel by viewModels() override fun inflateViewBinding(inflater: LayoutInflater) = ViewBinding.inflate(inflater) override fun ViewBinding.initViews() { @@ -58,20 +62,47 @@ class ZeroBuyActivity : AppViewsActivity() { override fun ViewBinding.initListeners() { //TODO("Not yet implemented") + requestData() } override fun ViewBinding.initObservers() { //TODO("Not yet implemented") } - override fun ViewBinding.onUiStateCollect(uiState: UiState) { - - } - private fun gotoLotteryRecords() { Router.WinRecord.startActivity(this) } + //----------------------- start ----------------------------- + + + private fun requestData() { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.ZeroBuyListData.collect { result -> + when (result) { + is Result.Loading -> { } + is Result.Success -> updateUIs(result.data) + is Result.Error -> { } + } + } + } + } + + viewModel.requestZeroBuyInfo() + } + + + + private fun updateUIs(data: ZeroBuyResp) { + + } + + + + + + //----------------------- end ----------------------------- companion object { internal fun startActivity(activity: Activity) { activity.startActivity(Intent(activity.applicationContext, ZeroBuyActivity::class.java)) diff --git a/app/src/main/java/com/gamedog/vididin/features/zero/ZeroBuyViewModel.kt b/app/src/main/java/com/gamedog/vididin/features/zero/ZeroBuyViewModel.kt new file mode 100644 index 0000000..5524122 --- /dev/null +++ b/app/src/main/java/com/gamedog/vididin/features/zero/ZeroBuyViewModel.kt @@ -0,0 +1,79 @@ +package com.gamedog.vididin.features.zero + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.ama.core.architecture.util.AndroidUtil +import com.ama.core.architecture.util.DeviceUtil +import com.gamedog.vididin.VidiConst +import com.gamedog.vididin.beans.ZeroBuyItem +import com.gamedog.vididin.beans.ZeroBuyResp +import com.gamedog.vididin.netbase.NetworkUtil +import com.gamedog.vididin.netbase.Result +import com.gamedog.vididin.request.RequestUtil +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +class ZeroBuyViewModel : ViewModel() { + private val _ZeroBuyListData = MutableStateFlow>(Result.Loading) + val ZeroBuyListData: StateFlow> = _ZeroBuyListData.asStateFlow() + + private val _ZeroBuySecretData = MutableStateFlow>(Result.Loading) + val ZeroBuySecretData: StateFlow> = _ZeroBuySecretData.asStateFlow() + + + fun requestZeroBuySecret() { + viewModelScope.launch { + _ZeroBuySecretData.value = Result.Loading + val operationVal = 1 + val curTimeSec = System.currentTimeMillis()/1000 + val signStr = RequestUtil.getZeroBuyRequestSign(curTimeSec, operationVal) + val requestHeaders = mapOf("Operation" to operationVal.toString(), "Timestamp" to curTimeSec.toString(), "Sign" to signStr) + + val result = NetworkUtil.get("${VidiConst.URL_ZERO_BUY}/anynameisok", requestHeaders) + + when (result) { + is Result.Success -> { + val respObj = AndroidUtil.json2Object(result.data.string()) + _ZeroBuySecretData.value = Result.Success(respObj!!) + } + is Result.Error -> { + _ZeroBuySecretData.value = Result.Error(result.exception, result.message) + } + else -> { } + } + } + } + + fun requestZeroBuyInfo() { + viewModelScope.launch { + _ZeroBuyListData.value = Result.Loading + + val operationVal = 0 + val curTimeSec = System.currentTimeMillis()/1000 + val signStr = RequestUtil.getZeroBuyRequestSign(curTimeSec, operationVal) + val requestHeaders = mapOf("Operation" to operationVal.toString(), "Timestamp" to curTimeSec.toString(), "Sign" to signStr) + + val requestParams = mapOf("AppId" to VidiConst.ZEROBUY_APPID, "DeviceId" to DeviceUtil.generateDeviceId()) + val result = NetworkUtil.get("${VidiConst.URL_ZERO_BUY}/anynameisok", requestHeaders, requestParams) + + when (result) { + is Result.Success -> { + val respObj = AndroidUtil.json2Object(result.data.string())?.apply { + mCurrentList = AndroidUtil.json2Object>(CurrentPurchases) + mFinishedList = AndroidUtil.json2Object>(FinishedPurchases) + } + + _ZeroBuyListData.value = Result.Success(respObj!!) + } + is Result.Error -> { + _ZeroBuyListData.value = Result.Error(result.exception, result.message) + } + else -> { } + } + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/gamedog/vididin/netbase/ApiService.kt b/app/src/main/java/com/gamedog/vididin/netbase/ApiService.kt new file mode 100644 index 0000000..1d298e1 --- /dev/null +++ b/app/src/main/java/com/gamedog/vididin/netbase/ApiService.kt @@ -0,0 +1,36 @@ +package com.gamedog.vididin.netbase + +import okhttp3.ResponseBody +import retrofit2.http.Body +import retrofit2.http.FieldMap +import retrofit2.http.FormUrlEncoded +import retrofit2.http.GET +import retrofit2.http.HeaderMap +import retrofit2.http.POST +import retrofit2.http.QueryMap +import retrofit2.http.Url + +interface ApiService { + + @GET + suspend fun getRequest( + @Url url: String, + @HeaderMap headers: Map = emptyMap(), + @QueryMap params: Map = emptyMap() + ): ResponseBody + + @FormUrlEncoded + @POST + suspend fun postRequest( + @Url url: String, + @HeaderMap headers: Map = emptyMap(), + @FieldMap params: Map = emptyMap() + ): ResponseBody + + @POST + suspend fun postJsonRequest( + @Url url: String, + @HeaderMap headers: Map = emptyMap(), + @Body body: Any + ): ResponseBody +} \ No newline at end of file diff --git a/app/src/main/java/com/gamedog/vididin/netbase/NetworkUtil.kt b/app/src/main/java/com/gamedog/vididin/netbase/NetworkUtil.kt new file mode 100644 index 0000000..0976c2b --- /dev/null +++ b/app/src/main/java/com/gamedog/vididin/netbase/NetworkUtil.kt @@ -0,0 +1,56 @@ +package com.gamedog.vididin.netbase + +import okhttp3.ResponseBody +import java.io.IOException + +object NetworkUtil { + + private val apiService: ApiService by lazy { + RetrofitUtil.getRetrofitInstance().create(ApiService::class.java) + } + + + suspend fun get( + url: String, + headers: Map = emptyMap(), + params: Map = emptyMap() + ): Result { + return executeRequest { + apiService.getRequest(url, headers, params) + } + } + + + suspend fun post( + url: String, + headers: Map = emptyMap(), + params: Map = emptyMap() + ): Result { + return executeRequest { + apiService.postRequest(url, headers, params) + } + } + + + suspend fun postJson( + url: String, + body: Any, + headers: Map = emptyMap() + ): Result { + return executeRequest { + apiService.postJsonRequest(url, headers, body) + } + } + + + private suspend fun executeRequest(requestBlock: suspend () -> T): Result { + return try { + Result.Success(requestBlock()) + } catch (e: IOException) { + Result.Error(e, "网络连接失败,请检查网络设置") + } catch (e: Exception) { + Result.Error(e, "未知错误: ${e.message}") + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gamedog/vididin/netbase/Result.kt b/app/src/main/java/com/gamedog/vididin/netbase/Result.kt new file mode 100644 index 0000000..d4b1783 --- /dev/null +++ b/app/src/main/java/com/gamedog/vididin/netbase/Result.kt @@ -0,0 +1,7 @@ +package com.gamedog.vididin.netbase + +sealed class Result { + data class Success(val data: T) : Result() + data class Error(val exception: Throwable, val message: String = exception.message ?: "Unknown error") : Result() + object Loading : Result() +} \ No newline at end of file diff --git a/app/src/main/java/com/gamedog/vididin/netbase/RetrofitUtil.kt b/app/src/main/java/com/gamedog/vididin/netbase/RetrofitUtil.kt new file mode 100644 index 0000000..16bfa4e --- /dev/null +++ b/app/src/main/java/com/gamedog/vididin/netbase/RetrofitUtil.kt @@ -0,0 +1,49 @@ +package com.gamedog.vididin.netbase + +import com.gamedog.vididin.VidiConst +import com.gamedog.vididin.core.network.di.GlobalInterceptor +import com.gamedog.vididin.core.network.di.GlobalInterceptor2 +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.util.concurrent.TimeUnit + +object RetrofitUtil { + + private var retrofit: Retrofit? = null + private const val DEFAULT_BASE_URL = VidiConst.URL_ZERO_BUY + + + fun getRetrofitInstance(baseUrl: String = DEFAULT_BASE_URL, headers: Map = emptyMap()): Retrofit { + return retrofit ?: createRetrofit(baseUrl, headers).also { retrofit = it } + } + + private fun createRetrofit(baseUrl: String, headers: Map): Retrofit { + val okHttpClient = OkHttpClient.Builder().apply { + // add request custom head + if (headers.isNotEmpty()) { + addInterceptor { chain -> + val originalRequest = chain.request() + val requestBuilder = originalRequest.newBuilder() + headers.forEach { (key, value) -> + requestBuilder.addHeader(key, value) + } + chain.proceed(requestBuilder.build()) + } + } + + // TODO - only enable in debug mode + addInterceptor(GlobalInterceptor2()) + + connectTimeout(30, TimeUnit.SECONDS) + readTimeout(30, TimeUnit.SECONDS) + writeTimeout(30, TimeUnit.SECONDS) + }.build() + + return Retrofit.Builder() + .baseUrl(baseUrl) + .client(okHttpClient) + .addConverterFactory(GsonConverterFactory.create()) + .build() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gamedog/vididin/request/RequestUtil.kt b/app/src/main/java/com/gamedog/vididin/request/RequestUtil.kt index 79d155c..a960468 100644 --- a/app/src/main/java/com/gamedog/vididin/request/RequestUtil.kt +++ b/app/src/main/java/com/gamedog/vididin/request/RequestUtil.kt @@ -1,12 +1,17 @@ package com.gamedog.vididin.request + +import com.ama.core.architecture.util.DeviceUtil import com.ama.core.architecture.util.MD5Util +import com.gamedog.vididin.VidiConst class RequestUtil private constructor(){ companion object { const val Request_APPId = "video1" const val Request_Sceret = "secret1" + const val Request_ZeroBuy_APPId = "com.vididin.real.money.game" + fun getTimestampSec(): Long { return System.currentTimeMillis()/1000 } @@ -16,6 +21,11 @@ class RequestUtil private constructor(){ return MD5Util.md5(signOrigin)?:"" } + // applicationId-timestamp-deviceId-operation-secret + fun getZeroBuyRequestSign(timeSec: Long, operation: Int): String { + var signOrigin = "${VidiConst.ZEROBUY_APPID}-${timeSec}-${DeviceUtil.generateDeviceId()}-$operation-${VidiConst.ZEROBUY_SECRET}" + return MD5Util.md5(signOrigin)?:"" + } } diff --git a/core/architecture/src/main/java/com/ama/core/architecture/util/DeviceUtil.kt b/core/architecture/src/main/java/com/ama/core/architecture/util/DeviceUtil.kt index 18771f6..bd31477 100644 --- a/core/architecture/src/main/java/com/ama/core/architecture/util/DeviceUtil.kt +++ b/core/architecture/src/main/java/com/ama/core/architecture/util/DeviceUtil.kt @@ -17,17 +17,17 @@ class DeviceUtil private constructor() { fun generateDeviceId(): String { val hardwareUUID = getHardwareUUID() if (hardwareUUID.isNotBlank()) { - return hardwareUUID + return hardwareUUID.replace("-", "") } // way2 val androidId = getAndroidId(BaseApp.appContext()) if (androidId != null && isValidAndroidId(androidId)) { - return UUID.nameUUIDFromBytes(androidId.toByteArray()).toString() + return UUID.nameUUIDFromBytes(androidId.toByteArray()).toString().replace("-", "") } // final:there's no other better way - return generateAndSaveRandomUUID(BaseApp.appContext()) + return generateAndSaveRandomUUID(BaseApp.appContext()).replace("-", "") } /**