php调用腾讯云api遇到的问题汇总
这里在ThinkPHP环境下编写的代码,如要移植到其他框架,换到相关函数即可
1、php的curl写法
将curl整合到公共工具包中,当中在本地php5.3环境下正常运行,后移植到服务器linux上php版本5.6不可用,经过查阅资料发现5.3以后的版本新增了CURLOPT_SAFE_UPLOAD支持curlfile方式传输,5.6CURLOPT_SAFE_UPLOAD默认false,所以需要做兼容处理(标红处)
/**
* 发送HTTP请求方法
* @param string $url 请求URL
* @param array $params 请求参数
* @param string $method 请求方法GET/POST
* @return array $data 响应数据
*/
public static function http($url, $params, $method = 'GET', $header = array(), $multi = false){
$opts = array(
CURLOPT_TIMEOUT => 60,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_HTTPHEADER => $header
);
// 上传文件方式兼容版本,优先使用curlfile
if (class_exists('\CURLFile')) {
$opts[CURLOPT_SAFE_UPLOAD] = true;
} else {
if (defined('CURLOPT_SAFE_UPLOAD')) {
$opts[CURLOPT_SAFE_UPLOAD] = false;
}
}
/* 根据请求类型设置特定参数 */
switch(strtoupper($method)){
case 'GET':
$opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
break;
case 'POST':
//判断是否传输文件
$opts[CURLOPT_URL] = $url;
$opts[CURLOPT_HEADER] = 0;
$opts[CURLOPT_POST] = true;
$opts[CURLOPT_POSTFIELDS] = $params;
break;
default:
throw new Exception('不支持的请求方式!');
}
/* 初始化并执行curl请求 */
$ch = curl_init();
curl_setopt_array($ch, $opts);
$data = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if($error) throw new Exception('请求发生错误:' . $error);
return $data;
}
2、腾讯云api的鉴权签名如何编写,查询腾讯云api文档后,集成到HttpClient中,如下
/**
* 生成腾讯云api的鉴权签名
* @param $appid 自己的腾讯云appid
* @param $bucket 腾讯文档说是废弃了,随意填写
* @param $secret_id 自己的开发api秘钥
* @param $secret_key 自己的开发api秘钥
* @return array 返回三种签名(普通签名,单次签名,多次签名)
*/
public static function generateTencetAuth($appid,$bucket,$secret_id,$secret_key) {
// 拼接签名串
$expired = time() + 2592000;
$onceExpired = 0;
$current = time();
$rdm = rand();
$userid = "0";
$fileid = "";
$srcStr = 'a='.$appid.'&b='.$bucket.'&k='.$secret_id.'&e='.$expired.'&t='.$current.'&r='.$rdm.'&u='
.$userid.'&f=';
$srcWithFile = 'a='.$appid.'&b='.$bucket.'&k='.$secret_id.'&e='.$expired.'&t='.$current.'&r='.$rdm.'&u='
.$userid.'&f='.$fileid;
$srcStrOnce= 'a='.$appid.'&b='.$bucket.'&k='.$secret_id.'&e='.$onceExpired .'&t='.$current.'&r='.$rdm
.'&u='.$userid.'&f='.$fileid;
// 生成签名
$signStr = base64_encode(hash_hmac('SHA1', $srcStr, $secret_key, true).$srcStr);
$srcWithFile = base64_encode(hash_hmac('SHA1', $srcWithFile , $secret_key, true).$srcWithFile );
$signStrOnce = base64_encode(hash_hmac('SHA1',$srcStrOnce,$secret_key, true).$srcStrOnce);
return ["signStr" => $signStr,"srcWithFile" => $srcWithFile,"signStrOnce" => $signStrOnce];
}
3、调用接口(这里放文字识别样例)
/**
* 通用 OCR 技术提供图片整体文字的检测和识别服务,返回文字框位置与文字内容。
* 支持多场景、任意版面下整图文字的识别,以及中英文、字母、数字的识别。
* 应用场景:印刷文档识别、广告图文字识别、街景店招识别、菜单识别、视频标题识别、互联网头像文字识别等。
* 客户端提交form表单,带上图片文件,参数名“ocr_image”这可以自定
*/
private function generalOcr() {
// 处理上传的图片
if($_FILES['ocr_image']['error'] < 4) {
$cfg = array(
'rootPath' => './Public/upload/qcloud/ocr/general/', // 保存根路径,这里换成你项目的存放路径
'exts' => array('jpg', 'png', 'jpeg'),// 设置附件上传类型
'maxSize' => 4194304 ,// 设置附件上传大小
);
$up = new \Think\Upload($cfg); // 实例化文件上传类
// 方法执行成功,返回附件信息
$z = $up -> uploadOne($_FILES['ocr_image']); // 上传一张图片
if(!$z) {
die(parent::returnQcloud(-1,array(),"图片上传失败"));
}
// 大图路径,这里的路址只是我自己保存到数据库的路径名,忽略
$imagePath = $up -> rootPath.$z['savepath'].$z['savename'];
// 本地路径,这里只是拼出我的项目的根路径,你可以使用realpath()函数传入相对路径获得根路径
$localImagePath = explode(PROJECT_NAME,__DIR__)[0].PROJECT_NAME.substr($imagePath,1);
$localImagePath = str_replace("\\","/",$localImagePath);
}else{
die(parent::returnQcloud(-1,array(),"图片异常"));
}
//定义一个要发送的目标URL;
$url = C("QCLOUD_OCR_URL_GENERAL");// 这里我存在配置文件里,你可以自己配置
//定义传递的参数数组;
$params['appid']=C("TENCENT_APP_ID");// 这里我存在配置文件里,你可以自己配置
$params['bucket']=C("TENCENT_BUCKET");// 这里我存在配置文件里,你可以自己配置
// php curl上传文件版本兼容,这里解决php版本curl文件兼容问题
if (class_exists('\CURLFile')) {
$params['image'] = new \CURLFile($localImagePath);// php版本5.6以后
} else {
$params['image'] = '@' . $localImagePath;// php版本5.6之前
}
$authorization = HttpClient::generateTencetAuth(C("TENCENT_APP_ID"),C("TENCENT_BUCKET"),C("TENCENT_SECRET_ID"),C("TENCENT_SECRET_KEY"));// 获取腾讯鉴权签名
// 请求头
$header = []; //储存Header头信息
$header[] = 'Host: recognition.image.myqcloud.com';
$header[] = 'Authorization: '.$authorization["signStr"];// 这里使用普通签名
$header[] = 'Content-Type: multipart/form-data';
//$header[] = 'Content-Type: application/json';
$result = HttpClient::http($url,$params,"POST",$header);
$resArray = json_decode($result); // 将返回json字符串转为array
$code = $resArray->{"code"};
$data = $resArray->{"data"};
$message = $resArray->{"message"};
$resString ='';
// 处理图像返回数据
if($code == 0) {
$items = $data->{"items"};
foreach($items as $v) {
$resString .= $v->{"itemstring"};
}
}
// 请求记录存入数据库
$log["code"] = $code;
$log["response"] = $resString;
$log["api_type"] = "general";
$log["remark"] = $imagePath;
D("Qcloud_log")->add($log);
// 返回到客户端
die(parent::returnQcloud($code,$resString,$message));
}
4、其他问题
1)linux下文件权限比较严格,建议将上传文件目录权限设置为640,具体命令:chmod -R 640 upload
2)对于curlfile问题详情参见https://segmentfault.com/a/1190000000725185 或者 https://blog.csdn.net/austindev/article/details/54844724
3)对于腾讯api返回数据处理参考官方文档
本文为胖虎原创文章,转载无需和我联系,但请注明来自胖虎博客panghucat.cn