|
|
<?php
error_reporting(0);
/* 频道对照表 */
$n = [
'dfws' => 1, // 东方卫视
'shxwzh' => 2, // 上海新闻综合
'shds' => 4, // 上海都市
'dycj' => 5, // 第1财经
'hhxd' => 9, // 哈哈炫动
'wxty' => 10, // 五星体育
'mdy' => 11, // 上海魔都眼
'jsrw' => 12, // 上海新纪实
];
/* 没有传 id 就默认东方卫视 */
$id = $_GET['id'] ?? 'dfws';
if (!isset($n[$id])) exit('unknown channel');
/* 公共参数 */
$t = time();
$nonce = getnonce(8);
$version = '2.32.2';
$secret = '28c8edde3d61a0411511d3b1866f0636';
/* 计算签名 */
$base = "Api-Version=v1&channel_id={$n[$id]}&nonce={$nonce}&platform=pc×tamp={$t}&version={$version}&{$secret}";
$sign = md5(md5($base));
/* 请求头 */
$h = [
"api-version: v1",
"nonce:{$nonce}",
"m-uuid:" . gen_uuid(),
"platform:pc",
"version:{$version}",
"timestamp:{$t}",
"sign:{$sign}",
];
/* 拉取加密播放地址 */
$url = "https://kapi.kankanews.com/content/pc/tv/channel/detail?channel_id={$n[$id]}";
$resp = json_decode(get($url, $h), true);
if (empty($resp['result']['live_address'])) {
http_response_code(503);
exit('get live_address failed');
}
$encrypted = $resp['result']['live_address'];
$live = decrypted($encrypted);
if (!$live) {
http_response_code(503);
exit('decrypt failed');
}
/* 不同频道不同处理 */
if ($id === 'shds' || $id === 'hhxd') {
/* 返回 302 跳转 */
$playurl = trim(strstr(m3u8($live), 'https'));
header("Location: $playurl");
exit;
}
/* 其它频道:返回拼装后的 m3u8 */
$burl = dirname($live) . '/';
$playurl = preg_replace('/(.*\.ts)/i', $burl . '$1', m3u8($live));
header('Content-Type: application/vnd.apple.mpegurl');
echo $playurl;
exit;
/* ---------- 工具函数 ---------- */
function get($url, $header)
{
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_REFERER => 'https://live.kankanews.com/',
CURLOPT_HTTPHEADER => $header,
CURLOPT_TIMEOUT => 5,
]);
$d = curl_exec($ch);
curl_close($ch);
return $d;
}
function m3u8($url)
{
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_REFERER => 'https://live.kankanews.com/',
CURLOPT_TIMEOUT => 5,
]);
$d = curl_exec($ch);
curl_close($ch);
return $d;
}
/* 8 位随机 nonce */
function getnonce($len)
{
$b = base_convert(mt_rand(1, 36 ** $len), 10, 36);
return substr(str_pad($b, $len, '0', STR_PAD_LEFT), -$len);
}
/* 22 位 m-uuid */
function gen_uuid()
{
$c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$u = '';
for ($i = 0; $i < 22; $i++) {
$u .= $c[mt_rand(0, 61)];
}
return $u;
}
/* RSA 公钥解密 */
function decrypted($str)
{
$key = "-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP5hzPUW5RFeE2xBT1ERB3hHZI
Votn/qatWhgc1eZof09qKjElFN6Nma461ZAwGpX4aezKP8Adh4WJj4u2O54xCXDt
wzKRqZO2oNZkuNmF2Va8kLgiEQAAcxYc8JgTN+uQQNpsep4n/o1sArTJooZIF17E
tSqSgXDcJ7yDj5rc7wIDAQAB
-----END PUBLIC KEY-----";
$pu = openssl_pkey_get_public($key);
if (!$pu) return '';
$detail = openssl_pkey_get_details($pu);
$chunk = $detail['bits'] / 8;
$parts = str_split(base64_decode($str), $chunk);
$out = '';
foreach ($parts as $p) {
$tmp = '';
openssl_public_decrypt($p, $tmp, $pu);
$out .= $tmp;
}
return $out;
}
|
|