按 HAR 抓包对齐原版协议: 补 api.php 取配置 + 识别业务码 403 + 按试用配额限源
依据用户提供的 HAR(e.ac19.cn, Reqable): 原版客户端是三步
1) POST /api.php action=get_config&device_id=<mac> (表单 + Dalvik UA)
2) GET /i.php 参数与 App 完全一致
3) GET /music/do.php 参数与 App 完全一致, 返回真源 CDN 地址
发现并修复三处差异:
1. 我们从未调 api.php(原版取址前必调)
→ KtvJsBridge.rawCleanPost(): 干净 POST + Content-Type 表单 + Dalvik UA
(UA 由本机 Build.VERSION.RELEASE/MODEL/ID 拼出, 与 HAR 同形态)
→ SongUrlResolver.ensureConfig(): 缓存 30 分钟, 桥不可用则跳过
→ SongApiClient 注入 POST 通道
2. 风控拒绝的真实形态是 HTTP 200 + 业务码 403
{"code":403,"msg":"请求被拒绝:检测到异常行为"} —— 不是 HTTP 403
→ i.php / do.php 两处业务码 403 都置 sawForbidden(诊断不再误判为"没有地址")
3. 无视试用配额: api.php 给出 trial_times=2 / trial_duration=5
→ 一次取址最多尝试 trial_times 个源(原先 9 个源全扫会把额度瞬间打光)
请求头分工与 HAR 一致: i.php/do.php 只有 Host+Accept 的干净 GET;
仅 api.php 带表单 Content-Type 与 Dalvik UA。
日志: 远程一条 SOURCE-CONFIG trial_enabled=… trial_times=…; 原始 JSON/卡密提示只写本地。
本机实测: api.php 返回与 HAR 相同配置; do.php 返回 code=403 检测到异常行为
(本出口 IP 处于风控/未授权: network_verification=true + 卡密机制, 额度按 IP 计)。
版本号按规则 3: 1.5.8(40) → 1.5.9(41); 按要求未打包
验证: compileReleaseKotlin + 单元测试(9 例全过)
This commit is contained in:
@@ -216,6 +216,29 @@ class KtvJsBridge(context: Context) {
|
||||
return NativeBridge().request("GET", url, null, headers, timeoutMs)
|
||||
}
|
||||
|
||||
/**
|
||||
* **干净 POST**(原版客户端调 `api.php` 取配置的形态,2026-10 依据 HAR 实测补上)。
|
||||
*
|
||||
* HAR 实测原版:`POST http://<host>/api.php`,
|
||||
* `Content-Type: application/x-www-form-urlencoded`,
|
||||
* UA 为 `Dalvik/2.1.0 (Linux; U; Android 12; SM-G9730 Build/…)`,body 为
|
||||
* `action=get_config&device_id=<mac>`;而 `i.php`/`do.php` 仍是**只有 Host+Accept**
|
||||
* 的干净 GET([rawCleanGet])。这里按同样分工实现。
|
||||
*/
|
||||
fun rawCleanPost(url: String, form: String, timeoutMs: Int = 8_000): String {
|
||||
val headers = JSONObject()
|
||||
.put("Accept", "*/*")
|
||||
.put("Content-Type", "application/x-www-form-urlencoded")
|
||||
.put("User-Agent", dalvikUserAgent())
|
||||
.toString()
|
||||
return NativeBridge().request("POST", url, form, headers, timeoutMs)
|
||||
}
|
||||
|
||||
/** 原版客户端形态的 UA(Dalvik + 本机 Android 版本/型号/Build)。 */
|
||||
private fun dalvikUserAgent(): String =
|
||||
"Dalvik/2.1.0 (Linux; U; Android ${android.os.Build.VERSION.RELEASE}; " +
|
||||
"${android.os.Build.MODEL} Build/${android.os.Build.ID})"
|
||||
|
||||
fun isDestroyed(): Boolean = destroyed
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user