test.php 文件
<?php
require('function.php');
require_once('request.php');
// $request = new request();
// $ret = $request->request('https://www.baidu.com/', [], 'GET');
// dump($ret);
require('tencent/im/im.php');
$im = new im();
// 导入单个帐号
$ret = $im->account_import();
dump($ret);
// 创建群聊
$ret = $im->create_group();
dump($ret);
执行结果:
im.php文件
<?php
require_once('TLSSigAPIv2.php'); //tencent/im/
require_once('request.php');
$TLSSigAPIv2 = new TLSSigAPIv2();
$request = new request();
class im
{
private $key = ''; // 私钥
private $sdkappid = ; // appid
private $identifier = 'administrator'; // App管理员帐号(腾讯云-即时IM-基本配置-帐号管理员)
private $usersig; // 对上面的app管理员帐号签名
private $random; // 0 - 4294967295 的 随机数
public function __construct()
{
$this->usersig = $GLOBALS['TLSSigAPIv2']->genSig($this->identifier); // 对管理员帐号签名
$this->random = mt_rand(100000, 999999); // 生成随机数
}
public function account_import()
{
$url = 'https://console.tim.qq.com/v4/im_open_login_svc/account_import';
$contenttype = [
'Identifier' => 'test',
'Nick' => 'test',
'FaceUrl' => '',
];
$url .= '?sdkappid=' . $this->sdkappid .
'&identifier=' . $this->identifier .
'&usersig=' . $this->usersig .
'&random=' . $this->random .
'&contenttype=json';
return $GLOBALS['request']->request($url, json_encode($contenttype), 'POST');
}
public function create_group()
{
$url = 'https://console.tim.qq.com/v4/group_open_http_svc/create_group';
$contenttype = [
'Owner_Account' => 'test', // 群主的 UserId(选填)
'Type' => 'Public', // 群组类型:Private/Public/ChatRoom/AVChatRoom/BChatRoom(必填)
'Name' => '东京大学相亲群', // 群名称(必填)
'GroupId' => '1234656', // 用户自定义群组 ID(选填)
];
$url .= '?sdkappid=' . $this->sdkappid .
'&identifier=' . $this->identifier .
'&usersig=' . $this->usersig .
'&random=' . $this->random .
'&contenttype=json';
return $GLOBALS['request']->request($url, json_encode($contenttype), 'POST');
}
}
TLSSigAPIv2.php
<?php
class TLSSigAPIv2 {
private $key = 你的私钥;
private $sdkappid = 你的appid;
/**
* 用于 url 的 base64 encode
* '+' => '*', '/' => '-', '=' => '_'
* @param string $string 需要编码的数据
* @return string 编码后的base64串,失败返回false
* @throws \Exception
*/
private function base64_url_encode($string) {
static $replace = Array('+' => '*', '/' => '-', '=' => '_');
$base64 = base64_encode($string);
if ($base64 === false) {
throw new \Exception('base64_encode error');
}
return str_replace(array_keys($replace), array_values($replace), $base64);
}
/**
* 用于 url 的 base64 decode
* '+' => '*', '/' => '-', '=' => '_'
* @param string $base64 需要解码的base64串
* @return string 解码后的数据,失败返回false
* @throws \Exception
*/
private function base64_url_decode($base64) {
static $replace = Array('+' => '*', '/' => '-', '=' => '_');
$string = str_replace(array_values($replace), array_keys($replace), $base64);
$result = base64_decode($string);
if ($result == false) {
throw new \Exception('base64_url_decode error');
}
return $result;
}
/**
* 使用 hmac sha256 生成 sig 字段内容,经过 base64 编码
* @param $identifier 用户名,utf-8 编码
* @param $curr_time 当前生成 sig 的 unix 时间戳
* @param $expire 有效期,单位秒
* @param $base64_userbuf base64 编码后的 userbuf
* @param $userbuf_enabled 是否开启 userbuf
* @return string base64 后的 sig
*/
private function hmacsha256($identifier, $curr_time, $expire, $base64_userbuf, $userbuf_enabled) {
$content_to_be_signed = "TLS.identifier:" . $identifier . "\n"
. "TLS.sdkappid:" . $this->sdkappid . "\n"
. "TLS.time:" . $curr_time . "\n"
. "TLS.expire:" . $expire . "\n";
if (true == $userbuf_enabled) {
$content_to_be_signed .= "TLS.userbuf:" . $base64_userbuf . "\n";
}
return base64_encode(hash_hmac( 'sha256', $content_to_be_signed, $this->key, true));
}
/**
* 生成签名。
*
* @param $identifier 用户账号
* @param int $expire 过期时间,单位秒,默认 180 天
* @param $userbuf base64 编码后的 userbuf
* @param $userbuf_enabled 是否开启 userbuf
* @return string 签名字符串
* @throws \Exception
*/
private function __genSig($identifier, $expire, $userbuf, $userbuf_enabled) {
$curr_time = time();
$sig_array = Array(
'TLS.ver' => '2.0',
'TLS.identifier' => strval($identifier),
'TLS.sdkappid' => intval($this->sdkappid),
'TLS.expire' => intval($expire),
'TLS.time' => intval($curr_time)
);
$base64_userbuf = '';
if (true == $userbuf_enabled) {
$base64_userbuf = base64_encode($userbuf);
$sig_array['TLS.userbuf'] = strval($base64_userbuf);
}
$sig_array['TLS.sig'] = $this->hmacsha256($identifier, $curr_time, $expire, $base64_userbuf, $userbuf_enabled);
if ($sig_array['TLS.sig'] === false) {
throw new \Exception('base64_encode error');
}
$json_str_sig = json_encode($sig_array);
if ($json_str_sig === false) {
throw new \Exception('json_encode error');
}
$compressed = gzcompress($json_str_sig);
if ($compressed === false) {
throw new \Exception('gzcompress error');
}
return $this->base64_url_encode($compressed);
}
/**
* 生成签名
*
* @param $identifier 用户账号
* @param int $expire 过期时间,单位秒,默认 180 天
* @return string 签名字符串
* @throws \Exception
*/
public function genSig($identifier, $expire=86400*180) {
return $this->__genSig($identifier, $expire, '', false);
}
/**
* 带 userbuf 生成签名。
* @param $identifier 用户账号
* @param int $expire 过期时间,单位秒,默认 180 天
* @param string $userbuf 用户数据
* @return string 签名字符串
* @throws \Exception
*/
public function genSigWithUserBuf($identifier, $expire, $userbuf) {
return $this->__genSig($identifier, $expire, $userbuf, true);
}
/**
* 验证签名。
*
* @param string $sig 签名内容
* @param string $identifier 需要验证用户名,utf-8 编码
* @param int $init_time 返回的生成时间,unix 时间戳
* @param int $expire_time 返回的有效期,单位秒
* @param string $userbuf 返回的用户数据
* @param string $error_msg 失败时的错误信息
* @return boolean 验证是否成功
* @throws \Exception
*/
private function __verifySig($sig, $identifier, &$init_time, &$expire_time, &$userbuf, &$error_msg) {
try {
$error_msg = '';
$compressed_sig = $this->base64_url_decode($sig);
$pre_level = error_reporting(E_ERROR);
$uncompressed_sig = gzuncompress($compressed_sig);
error_reporting($pre_level);
if ($uncompressed_sig === false) {
throw new \Exception('gzuncompress error');
}
$sig_doc = json_decode($uncompressed_sig);
if ($sig_doc == false) {
throw new \Exception('json_decode error');
}
$sig_doc = (array)$sig_doc;
if ($sig_doc['TLS.identifier'] !== $identifier) {
throw new \Exception("identifier dosen't match");
}
if ($sig_doc['TLS.sdkappid'] != $this->sdkappid) {
throw new \Exception("sdkappid dosen't match");
}
$sig = $sig_doc['TLS.sig'];
if ($sig == false) {
throw new \Exception('sig field is missing');
}
$init_time = $sig_doc['TLS.time'];
$expire_time = $sig_doc['TLS.expire'];
$curr_time = time();
if ($curr_time > $init_time+$expire_time) {
throw new \Exception('sig expired');
}
$userbuf_enabled = false;
$base64_userbuf = '';
if (isset($sig_doc['TLS.userbuf'])) {
$base64_userbuf = $sig_doc['TLS.userbuf'];
$userbuf = base64_decode($base64_userbuf);
$userbuf_enabled = true;
}
$sigCalculated = $this->hmacsha256($identifier, $init_time, $expire_time, $base64_userbuf, $userbuf_enabled);
if ($sig != $sigCalculated) {
throw new \Exception('verify failed');
}
return true;
} catch (\Exception $ex) {
$error_msg = $ex->getMessage();
return false;
}
}
/**
* 带 userbuf 验证签名。
*
* @param string $sig 签名内容
* @param string $identifier 需要验证用户名,utf-8 编码
* @param int $init_time 返回的生成时间,unix 时间戳
* @param int $expire_time 返回的有效期,单位秒
* @param string $error_msg 失败时的错误信息
* @return boolean 验证是否成功
* @throws \Exception
*/
public function verifySig($sig, $identifier, &$init_time, &$expire_time, &$error_msg) {
$userbuf = '';
return $this->__verifySig($sig, $identifier, $init_time, $expire_time, $userbuf, $error_msg);
}
/**
* 验证签名
* @param string $sig 签名内容
* @param string $identifier 需要验证用户名,utf-8 编码
* @param int $init_time 返回的生成时间,unix 时间戳
* @param int $expire_time 返回的有效期,单位秒
* @param string $userbuf 返回的用户数据
* @param string $error_msg 失败时的错误信息
* @return boolean 验证是否成功
* @throws \Exception
*/
public function verifySigWithUserBuf($sig, $identifier, &$init_time, &$expire_time, &$userbuf, &$error_msg) {
return $this->__verifySig($sig, $identifier, $init_time, $expire_time, $userbuf, $error_msg);
}
}
request.php
<?php
class request
{
private $curl;
private $query = '';
private $user_agent = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36';
public function __construct()
{
$this->curl = curl_init(); // 初始化
}
public function request($url, $data = [], $type = 'GET')
{
$ret= '';
switch ($type)
{
case 'GET';
$ret = $this->get($url, $data);
break;
case 'POST';
$ret = $this->post($url, $data);
break;
}
return $ret;
}
// 模拟浏览器get请求
public function get($url, $data)
{
if ($data) {
foreach ($data as $key => $value) {
$this->query .= $key . '=' . $value;
}
$url .= '?' . $this->query;
}
curl_setopt($this->curl, CURLOPT_PROXY, $GLOBALS ['proxy']);//代理服务器地址
curl_setopt($this->curl, CURLOPT_URL, $url); // 要访问的地址
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
curl_setopt($this->curl, CURLOPT_USERAGENT, $this->user_agent); // 模拟用户使用的浏览器
@curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
curl_setopt($this->curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
curl_setopt($this->curl, CURLOPT_HTTPGET, 1); // 发送一个常规的Post请求
curl_setopt($this->curl, CURLOPT_COOKIEFILE, $GLOBALS ['cookie_file']); // 读取上面所储存的Cookie信息
curl_setopt($this->curl, CURLOPT_TIMEOUT, 120); // 设置超时限制防止死循环
curl_setopt($this->curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
$tmpInfo = curl_exec($this->curl); // 执行操作
return $tmpInfo;
}
// 模拟浏览器post请求
public function post($url, $data)
{
//代理服务器地址
curl_setopt($this->curl, CURLOPT_PROXY, $GLOBALS ['proxy']);
curl_setopt($this->curl, CURLOPT_URL, $url); // 要访问的地址
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
curl_setopt($this->curl, CURLOPT_USERAGENT, $this->user_agent); // 模拟用户使用的浏览器
@curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
curl_setopt($this->curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
curl_setopt($this->curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
curl_setopt($this->curl, CURLOPT_COOKIEFILE, $GLOBALS ['cookie_file']); // 读取上面所储存的Cookie信息
curl_setopt($this->curl, CURLOPT_TIMEOUT, 120); // 设置超时限制防止死循环
curl_setopt($this->curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
$tmpInfo = curl_exec($this->curl); // 执行操作
return $tmpInfo;
}
public function __destruct()
{
//关闭URL请求
curl_close($this->curl);
}
}