<?php
namespace app\component\AliSdk;
use think\facade\Env;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use app\common\ImgConverToData;
use app\common\exception\CommonException;
use app\common\exception\RuntimeException;
/**
* 身份证自动识别
*/
class IdcardOcrService
{
/**
* API url
*
* @var string
*/
protected $url = 'https://dm-51.data.aliyun.com/rest/160601/ocr/ocr_idcard.json';
/**
* API appCode
*
* @var string
*/
protected $appCode = 'f29a4ae1e9104be5b8b2473434a897f5';
protected $sideType = array('face', 'back');
/**
* API errorMsg
*
* @var string
*/
protected $errorMsg = array(
'400' => 'URL错误',
'403' => '没有购买,或者购买次数用尽,或者URL错误',
'408' => '超时',
'413' => 'request body太大',
'450' => '后端服务队列满,请求被拒绝,重试即可',
'460' => '上传的body不符合json格式要求,是非法json',
'461' => '输入Json中缺少image键',
'462' => '从URL下载图像失败',
'463' => '输入图像不是对应服务的图像,如身份证服务请求的不是身份证',
'464' => 'OCR识别失败',
'469' => '内部异常',
'502' => '识别程序超时并断开连接',
'503' => 'API网关等待超时断开连接',
);
/**
* Logger
*
* @var LoggerInterface
*/
protected $logger;
public function __construct()
{
$this->setLogger();
}
public function setLogger()
{
$logger = new Logger('AliyunSDK');
$logger->pushHandler(new StreamHandler(rtrim(Env::get('RUNTIME_PATH'), '/') . '/log/aliyun.log', Logger::DEBUG));
$this->logger = $logger;
return $this;
}
/**
* 身份证识别
*
* @param [type] $idcardPath 身份证路径
* @param [type] $side 正面/反面 face/back
* @return void
*/
public function ocr($idcardPath, $side = 'face')
{
if (empty($idcardPath)) {
throw new RuntimeException('文件不存在!');
}
if (!in_array($side, $this->sideType)) {
throw CommonException::IDCARD_SIDE_ERROR();
}
$imgConverToData = new ImgConverToData();
$imgConverToData->getImgDir($idcardPath);
$imgData = $imgConverToData->img2Data();
$params = array();
$params['image'] = base64_encode($imgData);
$params["configure"] = json_encode(array(
"side" => $side
));
return $this->_post($this->url, $params);
}
protected function _post($url, $params = array())
{
$headers = array();
$headers[] = 'Authorization: APPCODE ' . $this->appCode;
$headers[] = 'Content-type: application/json; charset=UTF-8';
$curl = curl_init();
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_FAILONERROR, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
if (1 == strpos("$" . $url, "https://")) {
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
}
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($params));
$response = curl_exec($curl);
$curlinfo = curl_getinfo($curl);
$header = substr($response, 0, $curlinfo['header_size']);
$body = substr($response, $curlinfo['header_size']);
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$context = array(
'CURLINFO' => $curlinfo,
'HEADER' => $header,
'BODY' => $body,
);
if ($code != 200) {
$this->logger && $this->logger->error('IDCARD_OCR_ERROR', $context);
throw new RuntimeException($this->errorMsg[$code], $code);
}
$result = json_decode($body, true);
if (empty($result)) {
$result = array('detailedMsg' => $body);
}
return $result;
}
}
返回示例
正面返回结果:
{
"address" : "浙江省杭州市余杭区文一西路969号", #地址信息
"config_str" : "{\\\"side\\\":\\\"face\\\"}", #配置信息,同输入configure
"face_rect":{
"angle": -90,
"center":{
"x" : 952,
"y" : 325.5
},
"size":{
"height":181.99,
"width":164.99
}
}, #人脸位置,center表示人脸矩形中心坐标,size表示人脸矩形长宽,angle表示矩形顺时针旋转的度数。
"name" : "张三", #姓名
"nationality": "汉", #民族
"num" : "1234567890", #身份证号
"sex" : "男", #性别
"birth" : "20000101", #出生日期
"nationality" : "汉", #民族
"success" : true #识别结果,true表示成功,false表示失败
}
反面返回结果:
{
"config_str" : "{\\\"side\\\":\\\"back\\\"}",#配置信息,同输入configure
"start_date" : "19700101", #有效期起始时间
"end_date" : "19800101", #有效期结束时间
"issue" : "杭州市公安局", #签发机关
"success" : true #识别结果,true表示成功,false表示失败
}