php调用腾讯云api遇到的问题汇总

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返回数据处理参考官方文档