服务返回的 code 不为 0 时抛出异常

This commit is contained in:
czp3009 2019-02-19 17:29:02 +08:00
parent a63698c381
commit 192b6cd9ac
6 changed files with 75 additions and 3 deletions

View File

@ -1,10 +1,12 @@
package com.hiczp.bilibili.api
import com.hiczp.bilibili.api.exception.BilibiliApiException
import com.hiczp.bilibili.api.passport.PassportAPI
import com.hiczp.bilibili.api.passport.model.LoginResponse
import com.hiczp.bilibili.api.retrofit.ParamType
import com.hiczp.bilibili.api.retrofit.interceptor.CommonHeaderInterceptor
import com.hiczp.bilibili.api.retrofit.interceptor.CommonParamInterceptor
import com.hiczp.bilibili.api.retrofit.interceptor.FailureResponseInterceptor
import com.hiczp.bilibili.api.retrofit.interceptor.SortAndSignInterceptor
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
import mu.KotlinLogging
@ -76,6 +78,7 @@ class BilibiliClient(
"ts" to { Instant.now().epochSecond.toString() }
))
addInterceptor(SortAndSignInterceptor(ParamType.FORM_URL_ENCODED, billingClientProperties.appSecret))
addInterceptor(FailureResponseInterceptor)
//log
if (logLevel != HttpLoggingInterceptor.Level.NONE) {
@ -92,9 +95,14 @@ class BilibiliClient(
.create(PassportAPI::class.java)
}
//TODO 验证码
/**
* 登陆
* v3 登陆接口会同时返回 cookies token
*
* @throws BilibiliApiException 用户名与密码不匹配或者需要验证码
*/
@Throws(BilibiliApiException::class)
suspend fun login(username: String, password: String): LoginResponse {
//取得 hash 和 RSA 公钥
val (hash, key) = passportAPI.getKey().await().data.let { data ->

View File

@ -0,0 +1,11 @@
package com.hiczp.bilibili.api.exception
import com.hiczp.bilibili.api.retrofit.CommonResponse
import java.io.IOException
/**
* 当服务器返回的 code 不等于 0 时抛出
*/
class BilibiliApiException(
commonResponse: CommonResponse
) : IOException(commonResponse.msg ?: commonResponse.message)

View File

@ -10,7 +10,7 @@ data class GetKeyResponse(
@SerializedName("data")
var `data`: Data,
@SerializedName("ts")
var ts: Int // 1550219688
var ts: Long // 1550219688
) {
data class Data(
@SerializedName("hash")

View File

@ -10,7 +10,7 @@ data class LoginResponse(
@SerializedName("data")
var `data`: Data,
@SerializedName("ts")
var ts: Int // 1550219689
var ts: Long // 1550219689
) {
data class Data(
@SerializedName("cookie_info")

View File

@ -2,11 +2,19 @@ package com.hiczp.bilibili.api.retrofit
import com.google.gson.annotations.SerializedName
/**
* 通用实体, 可表示无 data 的响应 错误响应
* code 0 表示正常响应, 此时 message null
* code 不为 0 表示错误响应, 此时 data 可能是各种类型
* 一些 API 同时有 msg message
*/
data class CommonResponse(
@SerializedName("code")
var code: Int, // 0
@SerializedName("msg")
var msg: String?,
@SerializedName("message")
var message: String?,
@SerializedName("ts")
var ts: Int // 1550546539
var timestamp: Long // 1550546539
)

View File

@ -0,0 +1,45 @@
package com.hiczp.bilibili.api.retrofit.interceptor
import com.google.gson.Gson
import com.google.gson.JsonParser
import com.hiczp.bilibili.api.exception.BilibiliApiException
import com.hiczp.bilibili.api.retrofit.CommonResponse
import okhttp3.Interceptor
import okhttp3.Response
/**
* 如果服务器返回的 code 不为 0 则抛出异常
*/
object FailureResponseInterceptor : Interceptor {
private val jsonParser = JsonParser()
@Suppress("SpellCheckingInspection")
private val gson = Gson()
override fun intercept(chain: Interceptor.Chain): Response {
val response = chain.proceed(chain.request())
val body = response.body()
if (!response.isSuccessful || body == null || body.contentLength() == 0L) return response
//获取字符集
val contentType = body.contentType()
val charset = if (contentType == null) {
Charsets.UTF_8
} else {
contentType.charset(Charsets.UTF_8)!!
}
//拷贝流并读取其内容
val jsonObject = body.source().also {
it.request(Long.MAX_VALUE)
}.buffer.clone().inputStream().reader(charset).let {
jsonParser.parse(it).asJsonObject
}
//判断 code 是否为 0
if (jsonObject["code"].asInt != 0) {
throw BilibiliApiException(gson.fromJson(jsonObject, CommonResponse::class.java))
}
return response
}
}