apiKey =AdminConfig::getConfigValue('baidu_api','baidu'); $this->secretKey =AdminConfig::getConfigValue('baidu_secret','baidu'); $this->textinappid =AdminConfig::getConfigValue('textin_api','textin'); $this->textinsecret =AdminConfig::getConfigValue('textin_secret','textin'); parent::_initialize(); } // 获取识别类型 public function getTypes() { $this->success('', OcrType::field('id,name')->select()); } //上传识别 public function getOcr() { $params = $this->request->post(); if (!$params['type_id'] || !$params['file_id']) { $this->error('参数缺失'); } $img = cdnurl(File::getUrl($params['file_id']), true); $img_type = substr(strrchr($img, '.'), 1); if (!in_array($img_type, ['jpg', 'jpeg', 'png', 'bmp'])) { $this->error('图片类型不对,请上传jpg/jpeg/png/bmp等格式图片'); } $action = OcrType::where('id', $params['type_id'])->value('action'); $url = $this->curl . $action . '?access_token=' . $this->getAccessToken(); $imgcontent = file_get_contents($img); $imgcontent = base64_encode($imgcontent); $bodys = array( 'image' => $imgcontent ); $res = Http::post($url, $bodys); Log::write('ocr返回结果 ' . $this->auth->id . '----请求:' . $url . '=====:' . $res); $result = json_decode($res, true); if (isset($result['error_code'])) { $this->error($result['error_msg'], null, $result['error_code']); } $params['ocr_result'] = is_array($res) ? json_encode($res) : $res; $data = $this->resultReturn($params['type_id'], $result['words_result']); $saveRes = true; Db::startTrans(); try { $params['log_id'] = $result['log_id']; $params['staff_id'] = $this->auth->id; $params['file_url'] = $img; $params['money'] = $data['money'] ?? 0; $model = new Ocr(); $saveRes = $model->allowField(true)->save($params); Db::commit(); } catch (Exception $e) { Db::rollback(); $this->error($e->getMessage()); } if ($saveRes) { $this->success('识别成功', array_merge($data, ['log_id' => $result['log_id']])); } } // 获取accesstoken public function getAccessToken() { $key = 'ocr_token_'; if ($token = Cache::get($key)) { return $token; } $url = 'https://aip.baidubce.com/oauth/2.0/token'; $post_data['grant_type'] = 'client_credentials'; $post_data['client_id'] = $this->apiKey; $post_data['client_secret'] = $this->secretKey; $o = ""; foreach ($post_data as $k => $v) { $o .= "$k=" . urlencode($v) . "&"; } $post_data = substr($o, 0, -1); $res = Http::post($url, $post_data); Log::write('ocr获取accestoken: ' . $this->auth->id . '----' . json_encode($post_data) . '===结果:' . $res); if (!$res) { $this->error('请联系管理员,识别失败!'); } $result = json_decode($res, true); if (isset($result['error'])) { $this->error('请联系管理员,识别失败!'); } Cache::set($key, $result['access_token'], 2592000); return $result['access_token']; } public function resultReturn($type, $result) { $data = []; switch ($type) { case 1: //1 增值税发票识别 $data = [ 'InvoiceType' => $result['InvoiceType'],// 发票种类 'InvoiceTypeOrg' => $result['InvoiceTypeOrg'],// 发票名称 'InvoiceCode' => $result['InvoiceCode'],// 发票代码 'InvoiceNum' => $result['InvoiceNum'],// 发票号码 'InvoiceDate' => $result['InvoiceDate'],// 开票日期 'PurchaserName' => $result['PurchaserName'],// 购方名称 'PurchaserRegisterNum' => $result['PurchaserRegisterNum'],// 购方纳税人识别号 'PurchaserAddress' => $result['PurchaserAddress'],// 购方地址及电话 'PurchaserBank' => $result['PurchaserBank'],// 购方开户行及账号 'Password' => $result['Password'],// 密码区 'Province' => $result['Province'],// 省 'City' => $result['City'],// 市 'Agent' => $result['Agent'],// 是否代开 'CommodityName' => $result['CommodityName'],// 货物名称 ['row':行号,'word':内容'] 'CommodityType' => $result['CommodityType'],// 规格型号 ['row':行号,'word':内容'] 'CommodityUnit' => $result['CommodityUnit'],// 单位 ['row':行号,'word':内容'] 'CommodityNum' => $result['CommodityNum'],// 数量 ['row':行号,'word':内容'] 'CommodityPrice' => $result['CommodityPrice'],// 单价 ['row':行号,'word':内容'] 'CommodityAmount' => $result['CommodityAmount'],// 金额 ['row':行号,'word':内容'] 'CommodityTaxRate' => $result['CommodityTaxRate'],// 税率 ['row':行号,'word':内容'] 'CommodityTax' => $result['CommodityTax'],// 税额 ['row':行号,'word':内容'] 'CommodityPlateNum' => $result['CommodityPlateNum'] ?? [],// 车牌号 ['row':行号,'word':内容'] 'CommodityVehicleType' => $result['CommodityVehicleType'] ?? [],// 类型 ['row':行号,'word':内容'] 'CommodityStartDate' => $result['CommodityStartDate'] ?? [],// 通行日期起 ['row':行号,'word':内容'] 'CommodityEndDate' => $result['CommodityEndDate'] ?? [],// 通行日期止 ['row':行号,'word':内容'] 'OnlinePay' => $result['OnlinePay'] ?? '',// 电子支付标识 'SellerName' => $result['SellerName'],// 销售方名称 'SellerRegisterNum' => $result['SellerRegisterNum'],// 销售方纳税人识别号 'SellerAddress' => $result['SellerAddress'],// 销售方地址及电话 'SellerBank' => $result['销售方开户行及账号'],// 销售方地址及电话 'TotalAmount' => $result['TotalAmount'],// 合计金额 'money' => $result['TotalAmount'],// 合计金额 'TotalTax' => $result['TotalTax'],// 合计税额 'AmountInWords' => $result['AmountInWords'],// 价税合计(大写) 'AmountInFiguers' => $result['AmountInFiguers'],// 价税合计(小写) 'NoteDrawer' => $result['NoteDrawer'],// 开票人 'Remarks' => $result['Remarks'],// 备注 ]; break; case 2: //2 增值税发票验真 $data = [ 'InvoiceType' => $result['InvoiceType'], // 发票类型 'InvoiceCode' => $result['InvoiceCode'], // 发票代码 'InvoiceNum' => $result['InvoiceNum'], // 发票号码 'InvoiceDate' => $result['InvoiceDate'], // 开票日期 'AmountInFiguers' => $result['AmountInFiguers'], // 合计金额小写 'money' => $result['AmountInFiguers'],// 合计金额 'AmountInWords' => $result['AmountInWords'], // 合计金额大写 'CommodityName' => $result['CommodityName'], // 商品名称 [['word':'餐费','row':1]] 'CommodityUnit' => $result['CommodityUnit'], // 商品单位 [['word':'餐费','row':1]] ]; break; case 3: //3 定额发票识别 $data = [ 'invoice_code' => $result['invoice_code'], // 发票代码 'invoice_number' => $result['invoice_number'], // 发票号码 'invoice_rate' => $result['invoice_code'], // 金额 'location' => $result['location'], // 发票所在地 'invoice_rate_lowercase' => $result['invoice_rate_lowercase'], // 发票金额小写 'money' => $result['invoice_rate_lowercase'],// 合计金额 'province' => $result['province'], // 省 'city' => $result['city'] ?? '', // 市 ]; break; case 4: //4 通用机打发票识别 $data = [ 'InvoiceType' => $result['InvoiceType'],// 发票种类 'InvoiceCode' => $result['InvoiceCode'],// 发票代码 'InvoiceNum' => $result['InvoiceNum'],// 发票号码 'InvoiceDate' => $result['InvoiceDate'],// 开票日期 'AmountInWords' => $result['AmountInWords'],// 合计金额大写 'AmountInFiguers' => $result['AmountInFiguers'],// 合计金额小写 'money' => $result['AmountInFiguers'],// 合计金额 'CommodityName' => $result['CommodityName'],// 货物名称 ['row':行号,'word':内容'] 'CommodityUnit' => $result['CommodityUnit'],// 商品单位 ['row':行号,'word':内容'] 'CommodityPrice' => $result['CommodityPrice'],// 商品单价 ['row':行号,'word':内容'] 'CommodityNum' => $result['CommodityNum'],// 商品数量 ['row':行号,'word':内容'] 'CommodityAmount' => $result['CommodityAmount'],// 商品金额 ['row':行号,'word':内容'] 'IndustrySort' => $result['IndustrySort'],// 行业分类 'MachineNum' => $result['MachineNum'],// 机打号码 'CheckCode' => $result['CheckCode'],// 校验码 'SellerName' => $result['SellerName'],// 销售方名称 'SellerRegisterNum' => $result['SellerRegisterNum'],// 销售方纳税人识别号 'PurchaserName' => $result['PurchaserName'],// 购买方名称 'PurchaserRegisterNum' => $result['PurchaserRegisterNum'],// 购买方纳税人识别 'TotalTax' => $result['TotalTax'],// 合计税额 'Province' => $result['Province'], // 省 'City' => $result['City'], // 市 ]; break; case 5: //5 火车票识别 $data = [ 'ticket_num' => $result['ticket_num'], // 车票号 'starting_station' => $result['starting_station'], // 始发站 'train_num' => $result['train_num'], // 车次号 'destination_station' => $result['destination_station'], // 到达站 'date' => $result['date'], // 出发日期 'ticket_rates' => $result['ticket_rates'], // 车票金额 'money' => $result['ticket_rates'],// 合计金额 'seat_category' => $result['ticket_rates'], // 席别 'name' => $result['name'], // 乘客姓名 'id_num' => $result['id_num'], // 身份证号 'serial_number' => $result['serial_number'], // 序列号 'sales_station' => $result['sales_station'], // 售站 'time' => $result['time'], // 时间 'seat_num' => $result['seat_num'], // 座位号 ]; break; case 6: //6 出租车票识别 $data = [ 'InvoiceCode' => $result['InvoiceCode'], // 发票代号 'InvoiceNum' => $result['InvoiceNum'], // 发票号码 'TaxiNum' => $result['TaxiNum'], // 车牌号 'Date' => $result['Date'], // 日期 'Time' => $result['Time'], // 上下车时间 'PickupTime' => $result['PickupTime'], // 上车时间 'DropoffTime' => $result['DropoffTime'], // 下车时间 'Fare' => $result['Fare'], // 金额 'money' => $result['Fare'],// 合计金额 'FuelOilSurcharge' => $result['FuelOilSurcharge'], // 燃油附加费 'CallServiceSurcharge' => $result['CallServiceSurcharge'], // 叫车服务费 'TotalFare' => $result['TotalFare'], // 总金额 'Location' => $result['Location'], // 开票城市 'PricePerkm' => $result['PricePerkm'], // 单价 'Distance' => $result['Distance'], // 里程 'province' => $result['province'] ?? '', // 省 'city' => $result['city'] ?? '', // 市 ]; break; case 7: //7 飞机行程单识别 $data = [ 'name' => $result['name'], // 里程 'starting_station' => $result['starting_station'], // 始发站 'destination_station' => $result['destination_station'], // 目的站 'flight' => $result['flight'], // 航班号 'date' => $result['date'], // 日期 'ticket_number' => $result['ticket_number'], // 电子客票号码 'fare' => $result['fare'], // 票价 'money' => $result['fare'],// 'dev_fund' => $result['dev_fund'], // 民航发展基金/基建费 'fuel_surcharge' => $result['fuel_surcharge'], // 燃油附加费 'other_tax' => $result['其他税费'], // 民航发展基金/基建费 'ticket_rates' => $result['ticket_rates'], // 合计金额 'issued_date' => $result['issued_date'], // 填开日期 'id_num' => $result['id_num'], // 身份证号 'carrier' => $result['carrier'], // 承运人 'time' => $result['time'], // 时间 'issued_by' => $result['issued_by'], // 订票渠道 'serial_number' => $result['serial_number'], // 印刷序号 'insurance' => $result['insurance'], // 保险费 'fare_basis' => $result['fare_basis'], // 客票级别 'class' => $result['class'], // 座位等级 'agent_code' => $result['agent_code'], // 销售单位号 'endorsement' => $result['endorsement'], // 签注 'allow' => $result['allow'], // 免费行李 ]; break; case 8: //8 汽车票识别 $data = [ 'InvoiceCode' => $result['InvoiceCode'], // 发票代码 'InvoiceNum' => $result['InvoiceNum'], // 发票号码 'Date' => $result['Date'], // 日期 'Time' => $result['Time'], // 时间 'StartingStation' => $result['StartingStation'], // 出发站 'Fare' => $result['Fare'], // 金额 'money' => $result['fare'],// 'IdNum' => $result['IdNum'], // 身份证号 'DestinationStation' => $result['DestinationStation'], // 到达站 'Name' => $result['Name'], // 姓名 'InvoiceTime' => $result['InvoiceTime'], // 开票日期 ]; break; case 9: //9 过路过桥费发票识别 $data = [ 'InvoiceCode' => $result['InvoiceCode'], // 发票代码 'InvoiceNum' => $result['InvoiceNum'], // 发票号码 'Entrance' => $result['Entrance'], // 入口 'Exit' => $result['Exit'], // 出口 'Date' => $result['Date'], // 日期 'Time' => $result['Time'], // 时间 'Fare' => $result['Fare'], // 金额 'money' => $result['fare'],// 'province' => $result['province'] ?? '', // 省 'city' => $result['city'] ?? '', // 市 ]; break; case 10: //10 船票识别 $data = [ 'InvoiceType' => $result['InvoiceType'], // 发票类型 'InvoiceCode' => $result['InvoiceCode'], // 发票代码 'InvoiceNum' => $result['InvoiceNum'], // 发票号码 'StartingStation' => $result['StartingStation'], // 出发地点 'DestinationStation' => $result['DestinationStation'], // 到达地点 'Fare' => $result['Fare'], // 金额 'money' => $result['fare'],// 'InvoiceDate' => $result['InvoiceDate'], // 开票日期 ]; break; case 11: //11 网约车行程单识别 $data = [ 'ServiceProvider' => $result['ServiceProvider'], // 服务商 'StartTime' => $result['StartTime'], // 行程开始时间 'EndTime' => $result['EndTime'], // 行程结束时间 'Phone' => $result['Phone'], // 行程人手机号 'ApplicationDate' => $result['ApplicationDate'], // 申请日期 'TotalFare' => $result['TotalFare'], // 总金额 'City' => $result['City'], // 城市 'Fare' => $result['Fare'], // 金额 'money' => $result['fare'],// 'Items' => $result['Items'], // [['PickupTime'=>上车时间,'PickupDate'=>上车日期,'CarType'=>车型,'Distance'=>里程,'StartPlace'=>起点,'DestinationPlace'=>终点]] ]; break; case 12: //12 通用票据识别 $data = [ ['location' => $result['location'],// [['left'=>'','top'=>'','width'=>'','height'=>'']] 'words' => $result['words']],// 识别结果字符串 ]; break; case 13: // 车牌 $data = ['number' => $result['number'],// 识别结果字符串 ]; break; case 14: // 名片 $data = [ 'name' => $result['NAME'][0], 'mobile' => $result['MOBILE'][0], 'company' => $result['COMPANY'][0], 'addr' => $result['ADDR'][0], 'email' => $result['EMAIL'][0], 'tel' => $result['TEL'][0], ]; break; default: break; } return $data; } //名片识别 https://www.textin.com/market/detail/business_card public function business_card(){ $file_id=input('file_id'); if(empty($file_id)){ $this->error('图片不能为空'); } // 请登录后前往 “工作台-账号设置-开发者信息” 查看 x-ti-app-id $app_id = $this->textinappid; if(empty($app_id)){ $this->error('后台未设置textinappid,请联系管理员'); } // 请登录后前往 “工作台-账号设置-开发者信息” 查看 x-ti-secret-code $secret_code = $this->textinsecret; if(empty($app_id)){ $this->error('后台未设置textinsecret,请联系管理员'); } // 名片识别 $url = 'https://api.textin.com/robot/v1.0/api/business_card'; $img=File::getUrl($file_id); $headers = [ 'x-ti-app-id:' . $app_id, 'x-ti-secret-code:' . $secret_code ]; $fileData = file_get_contents('.'.$img); // 读取文件 $response = $this->post($url, $headers, $fileData); $ocrResult = json_decode($response, true); Log::info($ocrResult); // 获取 身份证号 和 姓名 $result =isset( $ocrResult['result'] )? $ocrResult['result'] : ''; if ($result) { $list = $result['item_list']; $data=[]; foreach ($list as $v){ $data[$v['key']]=['name'=>$v['description'],'value'=>$v['value']]; } $textin_field =AdminConfig::getConfigValue('textin_field','textin'); if($textin_field){ $textin_field=json_decode($textin_field,true); }else{ $textin_field=[]; } $result=[]; foreach ($textin_field as $field => $val) { if (isset($data[$field]) && $val) { $result[$val] = $data[$field]; } } $this->success('请求成功',$result); } $this->error('识别失败'); } /** * Post请求 * * @param string $url 地址 * @param array $headers Http Header * @param string $body 内容 * @return string */ function post($url, $headers, $body) { $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $body); $response = curl_exec($ch); curl_close($ch); return $response; } }