接口接入

This commit is contained in:
renhaoting 2025-12-08 18:12:28 +08:00
parent 0f06e04a4e
commit 1988f2448c
13 changed files with 430 additions and 36 deletions

View File

@ -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"
}

View File

@ -12,6 +12,7 @@ data class Account(
@Volatile
var cashCount: Float = 0F,
var bankInfo: BankInfo? = null,
val zeroBuyServerSecret: String = "",
)

View File

@ -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<ZeroBuyItem>?,
var mFinishedList: List<ZeroBuyItem>?,
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<Int>? = null,
val winners: List<Int>? = null,
val redeem_code: String? = null,
val completed: Boolean = false,
)

View File

@ -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)

View File

@ -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())
}
}

View File

@ -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<ViewBinding, UiState, ViewModel>() {
class ZeroBuyActivity : AppViewsEmptyViewModelActivity<ViewBinding>() {
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<ViewBinding, UiState, ViewModel>() {
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))

View File

@ -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<ZeroBuyResp>>(Result.Loading)
val ZeroBuyListData: StateFlow<Result<ZeroBuyResp>> = _ZeroBuyListData.asStateFlow()
private val _ZeroBuySecretData = MutableStateFlow<Result<String>>(Result.Loading)
val ZeroBuySecretData: StateFlow<Result<String>> = _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<String>(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<ZeroBuyResp>(result.data.string())?.apply {
mCurrentList = AndroidUtil.json2Object<List<ZeroBuyItem>>(CurrentPurchases)
mFinishedList = AndroidUtil.json2Object<List<ZeroBuyItem>>(FinishedPurchases)
}
_ZeroBuyListData.value = Result.Success(respObj!!)
}
is Result.Error -> {
_ZeroBuyListData.value = Result.Error(result.exception, result.message)
}
else -> { }
}
}
}
}

View File

@ -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<String, String> = emptyMap(),
@QueryMap params: Map<String, String> = emptyMap()
): ResponseBody
@FormUrlEncoded
@POST
suspend fun postRequest(
@Url url: String,
@HeaderMap headers: Map<String, String> = emptyMap(),
@FieldMap params: Map<String, String> = emptyMap()
): ResponseBody
@POST
suspend fun postJsonRequest(
@Url url: String,
@HeaderMap headers: Map<String, String> = emptyMap(),
@Body body: Any
): ResponseBody
}

View File

@ -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<String, String> = emptyMap(),
params: Map<String, String> = emptyMap()
): Result<ResponseBody> {
return executeRequest {
apiService.getRequest(url, headers, params)
}
}
suspend fun post(
url: String,
headers: Map<String, String> = emptyMap(),
params: Map<String, String> = emptyMap()
): Result<ResponseBody> {
return executeRequest {
apiService.postRequest(url, headers, params)
}
}
suspend fun postJson(
url: String,
body: Any,
headers: Map<String, String> = emptyMap()
): Result<ResponseBody> {
return executeRequest {
apiService.postJsonRequest(url, headers, body)
}
}
private suspend fun <T> executeRequest(requestBlock: suspend () -> T): Result<T> {
return try {
Result.Success(requestBlock())
} catch (e: IOException) {
Result.Error(e, "网络连接失败,请检查网络设置")
} catch (e: Exception) {
Result.Error(e, "未知错误: ${e.message}")
}
}
}

View File

@ -0,0 +1,7 @@
package com.gamedog.vididin.netbase
sealed class Result<out T> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Throwable, val message: String = exception.message ?: "Unknown error") : Result<Nothing>()
object Loading : Result<Nothing>()
}

View File

@ -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<String, String> = emptyMap()): Retrofit {
return retrofit ?: createRetrofit(baseUrl, headers).also { retrofit = it }
}
private fun createRetrofit(baseUrl: String, headers: Map<String, String>): 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()
}
}

View File

@ -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)?:""
}
}

View File

@ -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("-", "")
}
// finalthere's no other better way
return generateAndSaveRandomUUID(BaseApp.appContext())
return generateAndSaveRandomUUID(BaseApp.appContext()).replace("-", "")
}
/**