Skip to content

Commit

Permalink
新增功能: 新增开发者凭证配置功能
Browse files Browse the repository at this point in the history
  • Loading branch information
xieyy committed Jan 22, 2025
1 parent c6ba9d3 commit 5024ec9
Show file tree
Hide file tree
Showing 13 changed files with 445 additions and 0 deletions.
21 changes: 21 additions & 0 deletions app/src/main/java/com/xyoye/dandanplay/ui/main/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.xyoye.dandanplay.ui.main

import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.MutableLiveData
Expand All @@ -22,6 +24,7 @@ import com.xyoye.dandanplay.BR
import com.xyoye.dandanplay.R
import com.xyoye.dandanplay.databinding.ActivityMainBinding
import com.xyoye.data_component.data.LoginData
import com.xyoye.user_component.ui.weight.DeveloperMenus
import kotlin.random.Random
import kotlin.system.exitProcess

Expand All @@ -47,6 +50,9 @@ class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(),
private var fragmentTag = ""
private var touchTime = 0L

// 标题栏菜单管理器
private lateinit var mMenus: DeveloperMenus

override fun initViewModel() =
ViewModelInit(
BR.viewModel,
Expand Down Expand Up @@ -86,10 +92,12 @@ class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(),
title = "弹弹play"
switchFragment(TAG_FRAGMENT_HOME)
}

R.id.navigation_media -> {
title = "媒体库"
switchFragment(TAG_FRAGMENT_MEDIA)
}

R.id.navigation_personal -> {
title = "个人中心"
switchFragment(TAG_FRAGMENT_PERSONAL)
Expand Down Expand Up @@ -123,6 +131,16 @@ class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(),
return super.onKeyDown(keyCode, event)
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
mMenus = DeveloperMenus.inflater(this, menu)
return super.onCreateOptionsMenu(menu)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
mMenus.onOptionsItemSelected(item)
return super.onOptionsItemSelected(item)
}

override fun getLoginLiveData(): MutableLiveData<LoginData> {
return viewModel.reLoginLiveData
}
Expand Down Expand Up @@ -158,6 +176,7 @@ class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(),
fragmentTag = tag
}
}

TAG_FRAGMENT_MEDIA -> {
val fragment = supportFragmentManager.findFragmentByTag(TAG_FRAGMENT_MEDIA)
if (fragment == null) {
Expand All @@ -174,6 +193,7 @@ class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(),
fragmentTag = tag
}
}

TAG_FRAGMENT_PERSONAL -> {
val fragment = supportFragmentManager.findFragmentByTag(TAG_FRAGMENT_PERSONAL)
if (fragment == null) {
Expand All @@ -190,6 +210,7 @@ class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(),
fragmentTag = tag
}
}

else -> {
throw RuntimeException("no match fragment")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.xyoye.common_component.config

import com.xyoye.mmkv_annotation.MMKVFiled
import com.xyoye.mmkv_annotation.MMKVKotlinClass

/**
* author: [email protected]
* time : 2025/1/22
* desc : 开发者配置表
*/

@MMKVKotlinClass(className = "DevelopConfig")
object DevelopConfigTable {

// AppId
@MMKVFiled
const val appId = ""

// App Secret
@MMKVFiled
const val appSecret = ""

// 是否已自动显示认证弹窗
@MMKVFiled
const val isAutoShowAuthDialog = false
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.xyoye.common_component.network.helper.AgentInterceptor
import com.xyoye.common_component.network.helper.AuthInterceptor
import com.xyoye.common_component.network.helper.BackupDomainInterceptor
import com.xyoye.common_component.network.helper.DecompressInterceptor
import com.xyoye.common_component.network.helper.DeveloperCertificateInterceptor
import com.xyoye.common_component.network.helper.DynamicBaseUrlInterceptor
import com.xyoye.common_component.network.helper.LoggerInterceptor
import com.xyoye.common_component.network.helper.SignatureInterceptor
Expand Down Expand Up @@ -45,6 +46,7 @@ class Retrofit private constructor() {
.writeTimeout(4, TimeUnit.SECONDS)
.hostnameVerifier { _, _ -> true }
.addInterceptor(SignatureInterceptor())
.addInterceptor(DeveloperCertificateInterceptor())
.addInterceptor(AgentInterceptor())
.addInterceptor(AuthInterceptor())
.addInterceptor(DecompressInterceptor())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.xyoye.common_component.network.helper

import com.xyoye.common_component.config.DevelopConfig
import com.xyoye.common_component.utils.SecurityHelper
import okhttp3.Interceptor
import okhttp3.Response

/**
* author: [email protected]
* time : 2025/1/22
* desc : 开发者凭证拦截器
*/
class DeveloperCertificateInterceptor : Interceptor {
companion object {
const val HEADER_APP_ID = "X-AppId"
const val HEADER_APP_SECRET = "X-AppSecret"
}


override fun intercept(chain: Interceptor.Chain): Response {
val oldRequest = chain.request()

// 官方应用,不做处理
if (SecurityHelper.getInstance().isOfficialApplication) {
return chain.proceed(oldRequest)
}

// 请求自带凭证,不做处理
val requestAppId = oldRequest.header(HEADER_APP_ID)
val requestAppSecret = oldRequest.header(HEADER_APP_SECRET)
if (requestAppId?.isNotEmpty() == true && requestAppSecret?.isNotEmpty() == true) {
return chain.proceed(oldRequest)
}

// 未配置凭证,不做处理
val appId = DevelopConfig.getAppId()
val appSecret = DevelopConfig.getAppSecret()
if (appId.isNullOrEmpty() || appSecret.isNullOrEmpty()) {
return chain.proceed(oldRequest)
}

// 添加凭证
return chain.proceed(
oldRequest.newBuilder()
.header(HEADER_APP_ID, appId)
.header(HEADER_APP_SECRET, appSecret).build()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,12 @@ object UserRepository : BaseRepository() {
.doPost {
Retrofit.danDanService.updatePassword(it)
}

/**
* 校验凭证
*/
suspend fun checkAuthenticate(appId: String, appSecret: String) = request()
.doGet {
Retrofit.danDanService.checkAuthenticate(appId, appSecret, 1)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.xyoye.common_component.network.service

import com.xyoye.common_component.network.helper.DeveloperCertificateInterceptor
import com.xyoye.common_component.network.request.RequestParams
import com.xyoye.data_component.data.AnimeDetailData
import com.xyoye.data_component.data.AnimeTagData
Expand All @@ -17,9 +18,11 @@ import com.xyoye.data_component.data.SearchAnimeData
import com.xyoye.data_component.data.SendDanmuData
import okhttp3.RequestBody
import okhttp3.ResponseBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Headers
import retrofit2.http.POST
import retrofit2.http.Path
Expand Down Expand Up @@ -116,4 +119,11 @@ interface DanDanService {

@POST("/api/v2/playhistory")
suspend fun addPlayHistory(@Body body: RequestBody): CommonJsonData

@GET("api/v2/login/renew")
suspend fun checkAuthenticate(
@Header(DeveloperCertificateInterceptor.HEADER_APP_ID) appId: String,
@Header(DeveloperCertificateInterceptor.HEADER_APP_SECRET) appSecret: String,
@Header("X-Auth") authMode: Int
): Response<ResponseBody>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.xyoye.user_component.ui.dialog

import android.app.Activity
import com.xyoye.common_component.base.BaseActivity
import com.xyoye.common_component.config.DevelopConfig
import com.xyoye.common_component.extension.startUrlActivity
import com.xyoye.common_component.network.repository.UserRepository
import com.xyoye.common_component.utils.SupervisorScope
import com.xyoye.common_component.weight.ToastCenter
import com.xyoye.common_component.weight.dialog.BaseBottomDialog
import com.xyoye.user_component.R
import com.xyoye.user_component.databinding.DialogDeveloperAuthenticateBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
* author: [email protected]
* time : 2025/1/22
* desc :
*/

class DeveloperAuthenticateDialog(
private val activity: Activity,
private val onAuthenticate: () -> Unit
) : BaseBottomDialog<DialogDeveloperAuthenticateBinding>(activity) {

private lateinit var binding: DialogDeveloperAuthenticateBinding

override fun getChildLayoutId(): Int {
return R.layout.dialog_developer_authenticate
}

override fun initView(binding: DialogDeveloperAuthenticateBinding) {
this.binding = binding

setTitle("开发者认证")

binding.inputAppId.setText(DevelopConfig.getAppId())
binding.inputAppSecret.setText(DevelopConfig.getAppSecret())

setNegativeText("忽略")
setNegativeListener {
dismiss()
}

setPositiveListener {
checkAuthenticate()
}

binding.tvReadDocument.setOnClickListener {
activity.startUrlActivity("https://github.com/kaedei/dandanplay-libraryindex/blob/master/api/OpenPlatform.md")
}
}

/**
* 开发者认证
*/
private fun checkAuthenticate() {
val appId = binding.inputAppId.text.toString()
val appSecret = binding.inputAppSecret.text.toString()

if (appId.isEmpty() || appSecret.isEmpty()) {
ToastCenter.showWarning("请输入AppId和AppSecret")
return
}

SupervisorScope.IO.launch {
loading(true)
val result = UserRepository.checkAuthenticate(appId, appSecret).getOrNull()
loading(false)
if (result != null && result.code() == 200) {
authenticateSuccess(appId, appSecret)
return@launch
}

if (result?.code() == 403) {
ToastCenter.showError("认证失败,凭证不被允许访问")
} else {
ToastCenter.showError("认证过程中发生意外,请稍后重试")
}
}
}

/**
* 显示/隐藏加载框
*/
private suspend fun loading(show: Boolean) {
if (activity is BaseActivity<*, *>) {
withContext(Dispatchers.Main) {
if (show) {
activity.showLoading()
} else {
activity.hideLoading()
}
}
}
}

/**
* 认证成功
*/
private fun authenticateSuccess(appId: String, appSecret: String) {
DevelopConfig.putAppId(appId)
DevelopConfig.putAppSecret(appSecret)
ToastCenter.showSuccess("认证成功")
onAuthenticate.invoke()
dismiss()
}
}
Loading

0 comments on commit 5024ec9

Please sign in to comment.