前文说到,关于直播列表的直播间数据显示,考虑到网络延迟等问题,得依赖于腾讯云直播的“查看直播中的流”接口,来实时对业务数据进行同步,加之,这个接口相对而言,实时性还不错,可是,关于这个接口的调取上,会有一些坑,因为这个接口比较实用,因此,有必要,简单地说说。
问题部分
吐槽的话,就不说了,因为,我已经在《关于腾讯云“请求签名Signature”踩的坑》说过,之所以,还写这篇帖子,是因为,吐槽的那篇文,没有代码相关的东西,此篇补充一下。
腾讯云,关于签名这块,有个坑,就是,你在查找签名的过程中,可能会误入歧途,因为,腾讯云的文档中,关于签名的有好几篇,而且,还跟孪生兄弟似的,长大还差不多,一旦找不对,可能就会让你很头疼,因此,文章的末尾,附加了相关的地址,可供查看。
同步直播流接口,按腾讯云上的文档说法,一秒可以请求500次,通过验证,也发现这个接口,确实比“消息通知”的断流回调靠谱的多。但是,写这个接口的时候,可能会出现以下这个问题:
Signature报错
The provided credentials could not be validated. Please check your signature is correct。
这个问题,一方面,可能是你文档没找准确,误入歧途;另一方面,可能是参数的问题,不能缺,也不能不对,具体《关于腾讯云“请求签名Signature”踩的坑》可供相关参考。
还有,就是参数的拼接,也可能会导致这个问题的发生。很多人,PHP的,都可能会用http_build_query()这个函数,在一些签名处理的时候,来拼接参数,但是,注意了,这个函数的参数,可不止一个,它还有三个参数,其中最要命的就是PHP在5.4.0版本以后,加的第四个参数,编码类型。如果不了解,不注意,这个问题,那你最后,可能会浪费很多时间在这个地方。因此,考虑到这个问题,简单起见,还是通过遍历追加的方式处理比较靠谱。
代码部分
/**
* 查询腾讯云直播流数据情况
*/
public function live_status_data()
{
$count = $this->get_count_num('teacher_live_room',
'clive_room_id',['clive_room_status >'=>0]);
if(!$count) return [];
$pages = ceil( $count / self::STREAM_PAGE_SIZE );
$return = [];
for($i=1; $i<=$pages; $i++) {
$params = [
'Action'=>'DescribeLiveStreamOnlineList',
'DomainName'=>$this->match_domain()['push'],
'Version'=>'2018-08-01',
'Timestamp'=>time(),
'PageNum'=>$i,
'PageSize'=>self::STREAM_PAGE_SIZE,
'Nonce'=>mt_rand(1000,9999).time(),
'SecretId'=>$this->live_config['id'],
];
$res = $this->getUrl($this->splice_string($params));
$data = json_decode($res, true);
if(isset($data['Response']['OnlineInfo'])){
$return[] = $data['Response']['OnlineInfo'];
}
}
return $return;
}
/**
* 拼接 实时获取直播间状态的 URL地址
* @param array $params
* @return string
*/
public function splice_string($params)
{
$url = 'https://live.tencentcloudapi.com/?';
$params['Signature'] = urlencode($this->produce_signature($params));
$signStr = '';
foreach ( $params as $key => $value ) {
$signStr = $signStr . $key . "=" . $value . "&";
}
$signStr = substr($signStr, 0, -1);
return $url.$signStr;
}
/**
* 生成 signature
* @param array $params
* @return string
*/
public function produce_signature($params)
{
$string = $this->splicing_signature_origion_string($params);
return $this->signature($string);
}
/**
* 生成签名 - 拼接签名原文字符串
* @param array $params
* @return mixed
*/
private function splicing_signature_origion_string($params)
{
ksort($params);
$signStr = '';
foreach ( $params as $key => $value ) {
$signStr = $signStr . $key . "=" . $value . "&";
}
$signStr = substr($signStr, 0, -1);
$method = 'GET';
$domain = 'live.tencentcloudapi.com/';
return $method.$domain.'?'.$signStr;
}
/**
* 生成签名 - 生成签名
* @param string $srcStr
* @return mixed
*/
private function signature($srcStr)
{
$secretKey = $this->live_config['key'];
$signStr = base64_encode(hash_hmac('sha1', $srcStr, $secretKey, true));
return $signStr;
}
/**
* GET方式 - 请求数据
* @param string $url
* @return mixed
*/
public function getUrl($url)
{
// echo $url;exit();
$header = array(
'Content-Type: application/x-www-form-urlencoded',
);
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 超时设置,以秒为单位
curl_setopt($curl, CURLOPT_TIMEOUT, 1);
// 超时设置,以毫秒为单位
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
// 设置请求头
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
//执行命令
$data = curl_exec($curl);
// 打印返回的内容
curl_close($curl);
return $data;
}
好了,同步流接口就说这么多,下一篇,说说“消息通知”相关的东西,虽然,“消息通知”回调这块有不靠谱的地方,但也并非全都无用。
The End! 2020/04/17 15:25:50
-----------------------------------------------------------------------------------------------------------------------
附加:
查看直播中的流地址,https://cloud.tencent.com/document/product/267/20472
签名的文档地址https://cloud.tencent.com/document/api/267/20460