wang hou sheng 1 year ago
parent fc6382e62e
commit 8a35cbe224
  1. 76
      app/api/controller/Ocr.php
  2. 67
      app/api/service/Ocr.php
  3. 16
      app/api/service/Setting.php
  4. 7
      app/common/enum/Setting.php
  5. 259
      app/common/library/baidu/OcrCard.php
  6. 128
      app/common/library/baidu/OcrLicense.php
  7. 25
      app/common/model/store/Setting.php
  8. 2
      app/store/controller/Setting.php

@ -0,0 +1,76 @@
<?php
namespace app\api\controller;
use app\api\model\UploadFile;
use cores\exception\BaseException;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\response\Json;
class Ocr extends Controller
{
/**
* @notes:身份证识别
* @return Json
* @throws BaseException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author: wanghousheng
*/
public function checkCard(): Json
{
$img_id = intval($this->request->post('img_id'));
if (!$img_id) {
return $this->renderError('图片ID不能为空');
}
$img_url = '';
$file = UploadFile::detail($img_id);
if (!empty($file)) {
$file = $file->toArray();
$img_url = $file['preview_url'];
}
if (!$img_url) {
return $this->renderError('图片不存在');
}
$type = intval($this->request->post('type', 1));
$result = \app\api\service\Ocr::checkCard($img_url, $type);
if (!empty($result['status']) && !empty($result['data'])) {
return $this->renderSuccess($result['data']);
}
return $this->renderError($result['msg']);
}
/**
* @notes:营业执照识别
* @return Json
* @throws BaseException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author: wanghousheng
*/
public function checkLicense(): Json
{
$img_id = intval($this->request->post('img_id'));
if (!$img_id) {
return $this->renderError('图片ID不能为空');
}
$img_url = '';
$file = UploadFile::detail($img_id);
if (!empty($file)) {
$file = $file->toArray();
$img_url = $file['preview_url'];
}
if (!$img_url) {
return $this->renderError('图片不存在');
}
$result = \app\api\service\Ocr::checkLicense($img_url);
if (!empty($result['status']) && !empty($result['data'])) {
return $this->renderSuccess($result['data']);
}
return $this->renderError($result['msg']);
}
}

@ -0,0 +1,67 @@
<?php
declare (strict_types=1);
namespace app\api\service;
use app\api\service\User as UserService;
use app\common\library\baidu\OcrCard;
use app\common\library\baidu\OcrLicense;
use app\common\service\BaseService;
use cores\exception\BaseException;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
class Ocr extends BaseService
{
/**
* @notes:获取配置
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author: wanghousheng
*/
/**
* @notes:
* @param string $img_url //证件地址 可外网访问的
* @param int $type //1 正面 2反面
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException|BaseException
* @author: wanghousheng
*/
public static function checkCard(string $img_url, int $type = 1): array
{
// 当前用户ID
UserService::getCurrentLoginUserId();
$config = Setting::getOcr();
$clientSecret = !empty($config['secret_key']) ? $config['secret_key'] : '';
$clientId = !empty($config['access_key']) ? $config['access_key'] : '';
$obj = new OcrCard($clientId, $clientSecret);
return $obj->checkCard($img_url, $type);
}
/**
* @notes:营业执照识别
* @param string $img_url
* @return array
* @throws BaseException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @author: wanghousheng
*/
public static function checkLicense(string $img_url): array
{
// 当前用户ID
UserService::getCurrentLoginUserId();
$config = Setting::getOcr();
$clientSecret = !empty($config['secret_key']) ? $config['secret_key'] : '';
$clientId = !empty($config['access_key']) ? $config['access_key'] : '';
$obj = new OcrLicense($clientId, $clientSecret);
return $obj->check($img_url);
}
}

@ -13,9 +13,9 @@ declare (strict_types=1);
namespace app\api\service; namespace app\api\service;
use app\api\model\Setting as SettingModel; use app\api\model\Setting as SettingModel;
use app\common\enum\Setting as SettingEnum;
use app\common\library\helper; use app\common\library\helper;
use app\common\service\BaseService; use app\common\service\BaseService;
use app\common\enum\Setting as SettingEnum;
/** /**
* 服务类:商城设置 * 服务类:商城设置
@ -138,6 +138,20 @@ class Setting extends BaseService
return helper::pick($values, ['enabled', 'provider', 'config']); return helper::pick($values, ['enabled', 'provider', 'config']);
} }
/**
* @notes:获取ocr设置
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author: wanghousheng
*/
public static function getOcr(): array
{
$values = SettingModel::getItem(SettingEnum::OCR);
return helper::pick($values, ['secret_key', 'access_key']);
}
/** /**
* 获取分类页模板设置 * 获取分类页模板设置
* @return array|mixed * @return array|mixed

@ -24,6 +24,9 @@ class Setting extends EnumBasics
// 交易设置 // 交易设置
const TRADE = 'trade'; const TRADE = 'trade';
//ocr设置
const OCR = 'ocr';
// 短信通知 // 短信通知
const SMS = 'sms'; const SMS = 'sms';
@ -98,6 +101,10 @@ class Setting extends EnumBasics
'value' => self::FULL_FREE, 'value' => self::FULL_FREE,
'describe' => '满额包邮设置', 'describe' => '满额包邮设置',
], ],
self::OCR => [
'value' => self::OCR,
'describe' => 'ocr设置',
],
self::REGISTER => [ self::REGISTER => [
'value' => self::REGISTER, 'value' => self::REGISTER,
'describe' => '账户注册设置', 'describe' => '账户注册设置',

@ -0,0 +1,259 @@
<?php
namespace app\common\library\baidu;
use DateTime;
class OcrCard
{
const CARDURL = 'https://aip.baidubce.com/rest/2.0/ocr/v1/idcard';
const TOKENURL = 'https://aip.baidubce.com/oauth/2.0/token';
private int $status = 1;
private string $msg = 'success';
private array $data = [];
private string $clientId;
private string $clientSecret;
public function __construct(string $clientId, string $clientSecret)
{
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
}
/**
* @notes:图片状态
* @param string $key
* @author: wanghousheng
*/
private function imageStatus(string $key)
{
$this->status = 0;
switch ($key) {
case 'normal':
$this->status = 1;
break;
case 'reversed_side':
$this->msg = '身份证正反面颠倒';
break;
case 'non_idcard':
$this->msg = '上传的图片中不包含身份证';
break;
case'blurred':
$this->msg = '身份证模糊';
break;
case'other_type_card':
$this->msg = '非身份证类型照';
break;
case'over_exposure':
$this->msg = '身份证关键字段反光或过曝';
break;
case'over_dark':
$this->msg = '身份证欠曝(亮度过低)';
break;
default:
"不合法的证件照";
break;
}
}
private function riskType(string $key)
{
$this->status = 0;
switch ($key) {
case 'normal':
$this->status = 1;
break;
case 'copy':
$this->msg = '不能上传复印件';
break;
case 'temporary':
$this->msg = '临时身份证';
break;
case'screen':
$this->msg = '身份证翻拍';
break;
default:
"不合法的证件照";
break;
}
}
private function resultHandle(): array
{
return ['status' => $this->status, 'msg' => $this->msg, 'data' => $this->data];
}
/**
* @notes:验证身份证正面信息
* @param $data
* @return void
* @author: wanghousheng
*/
private function validateFrontData($data): void
{
$address = '';
$card_no = '';
$birthday = '';
$username = '';
$sex = '';
$nation = '';
if (!empty($data->log_id) && !empty($data->image_status) && !empty($data->words_result) && !empty($data->words_result_num)) {
$this->imageStatus($data->image_status);
if (!$this->status) {
return;
}
if (!empty($data->risk_type)) {
$this->riskType($data->risk_type);
if (!$this->status) {
return;
}
}
$words_result_num = intval($data->words_result_num);
if ($words_result_num != 6) {
$this->msg = '身份信息不全';
return;
}
//身份信息
$arr = $data->words_result;
if (!empty($arr->住址->words)) {
$address = $arr->住址->words;
}
if (!empty($arr->公民身份号码->words)) {
$card_no = $arr->公民身份号码->words;
}
if (!empty($arr->出生->words)) {
$birthday = $arr->出生->words;
$date = DateTime::createFromFormat('Ymd', $birthday);
$birthday = $date->format('Y-m-d');
}
if (!empty($arr->姓名->words)) {
$username = $arr->姓名->words;
}
if (!empty($arr->性别->words)) {
$sex = $arr->性别->words;
}
if (!empty($arr->民族->words)) {
$nation = $arr->民族->words;
}
} else {
$this->msg = '接口异常';
}
$this->data = compact('address', 'sex', 'nation', 'birthday', 'username', 'card_no');
}
/**
* @notes:验证身份证反面信息
* @param $data
* @return void
* @author: wanghousheng
*/
private function validateBackData($data): void
{
$invalid_date = '';
$issuance_office = '';
$issuance_date = '';
if (!empty($data->log_id) && !empty($data->image_status) && !empty($data->words_result) && !empty($data->words_result_num)) {
$this->imageStatus($data->image_status);
if (!$this->status) {
return;
}
if (!empty($data->risk_type)) {
$this->riskType($data->risk_type);
if (!$this->status) {
return;
}
}
$words_result_num = intval($data->words_result_num);
if ($words_result_num != 3) {
$this->msg = '身份信息不全';
return;
}
//身份信息
$arr = $data->words_result;
if (!empty($arr->失效日期->words)) {
$invalid_date = $arr->失效日期->words;
$date = DateTime::createFromFormat('Ymd', $invalid_date);
$invalid_date = $date->format('Y-m-d');
}
if (!empty($arr->签发机关->words)) {
$issuance_office = $arr->签发机关->words;
}
if (!empty($arr->签发日期->words)) {
$issuance_date = $arr->签发日期->words;
$date = DateTime::createFromFormat('Ymd', $issuance_date);
$issuance_date = $date->format('Y-m-d');
}
} else {
$this->msg = '接口异常';
}
$this->data = compact('invalid_date', 'issuance_date', 'issuance_office');
}
/**
* @notes:获取token
* @return mixed|string
* @author: wanghousheng
*/
private function getToken()
{
$token = '';
$data['grant_type'] = 'client_credentials';
$data['client_id'] = $this->clientId;
$data['client_secret'] = $this->clientSecret;
$result = $this->post(self::TOKENURL, $data);
if (!empty($result->access_token)) {
$token = $result->access_token;
} else {
$this->msg = '获取token失败';
}
return $token;
}
/**
* @notes:
* @param string $img_url //证件地址 可外网访问的
* @param int $type //1 正面 2反面
* @return array
* @author: wanghousheng
*/
public function checkCard(string $img_url, int $type = 1): array
{
$token = $this->getToken();
if (!$token) {
return $this->resultHandle();
}
$data['url'] = $img_url;
$data['id_card_side'] = 'front';
if ($type != 1) {
$data['id_card_side'] = 'back';
}
$data['detect_risk'] = 'true';
$url = self::CARDURL . '?access_token=' . $token;
$result = $this->post($url, $data);
if ($type == 1) {
$this->validateFrontData($result);
} else {
$this->validateBackData($result);
}
return $this->resultHandle();
}
private function post(string $url, array $postData)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response);
}
}

@ -0,0 +1,128 @@
<?php
namespace app\common\library\baidu;
class OcrLicense
{
const LICENSEURL = 'https://aip.baidubce.com/rest/2.0/ocr/v1/business_license';
const TOKENURL = 'https://aip.baidubce.com/oauth/2.0/token';
private int $status = 1;
private string $msg = 'success';
private array $data = [];
private string $clientId;
private string $clientSecret;
public function __construct(string $clientId, string $clientSecret)
{
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
}
public function check($img_url): array
{
$token = $this->getToken();
if (!$token) {
return $this->resultHandle();
}
$data['url'] = $img_url;
$data['risk_warn'] = 'true';
$url = self::LICENSEURL . '?access_token=' . $token;
$result = $this->post($url, $data);
$this->validateData($result);
return $this->resultHandle();
}
private function validateData($data)
{
$name = '';
$credit_code = '';
if (!empty($data->log_id) && !empty($data->words_result) && !empty($data->words_result_num)) {
if (!empty($data->risk_type)) {
$this->riskType($data->risk_type);
if (!$this->status) {
return;
}
}
$words_result_num = intval($data->words_result_num);
if ($words_result_num != 16) {
$this->msg = '证件信息不全';
return;
}
//身份信息
$arr = $data->words_result;
if (!empty($arr->单位名称->words)) {
$name = $arr->单位名称->words;
}
if (!empty($arr->社会信用代码->words)) {
$credit_code = $arr->社会信用代码->words;
}
} else {
$this->msg = '接口异常';
}
$this->data = compact('name', 'credit_code');
}
private function riskType(string $key)
{
$this->status = 0;
switch ($key) {
case 'normal':
$this->status = 1;
break;
case 'copy':
$this->msg = '不能上传复印件';
break;
case 'temporary':
$this->msg = '不能上传临时证件';
break;
case'screen':
$this->msg = '不能上传翻拍证件';
break;
default:
"不合法的证件照";
break;
}
}
private function resultHandle(): array
{
return ['status' => $this->status, 'msg' => $this->msg, 'data' => $this->data];
}
private function post(string $url, array $postData)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
$response = curl_exec($curl);
curl_close($curl);
return json_decode($response);
}
/**
* @notes:获取token
* @return mixed|string
* @author: wanghousheng
*/
private function getToken()
{
$token = '';
$data['grant_type'] = 'client_credentials';
$data['client_id'] = $this->clientId;
$data['client_secret'] = $this->clientSecret;
$result = $this->post(self::TOKENURL, $data);
if (!empty($result->access_token)) {
$token = $result->access_token;
} else {
$this->msg = '获取token失败';
}
return $token;
}
}

@ -12,18 +12,14 @@ declare (strict_types=1);
namespace app\common\model\store; namespace app\common\model\store;
use cores\BaseModel; use app\common\enum\{file\Storage as StorageEnum,
use think\facade\Cache;
use app\common\library\helper;
use app\common\enum\{
Client as ClientEnum,
Setting as SettingEnum,
file\Storage as StorageEnum,
payment\Method as PaymentMethodEnum,
order\DeliveryType as DeliveryTypeEnum, order\DeliveryType as DeliveryTypeEnum,
Setting as SettingEnum,
setting\sms\Scene as SettingSmsSceneEnum, setting\sms\Scene as SettingSmsSceneEnum,
store\page\category\Style as PageCategoryStyleEnum store\page\category\Style as PageCategoryStyleEnum};
}; use app\common\library\helper;
use cores\BaseModel;
use think\facade\Cache;
/** /**
* 系统设置模型 * 系统设置模型
@ -164,6 +160,15 @@ class Setting extends BaseModel
'freight_rule' => '10', 'freight_rule' => '10',
] ]
], ],
// OCR设置
SettingEnum::OCR => [
'key' => SettingEnum::OCR,
'describe' => 'OCR设置',
'values' => [
'access_key' => '',
'secret_key' => '',
]
],
// 上传设置 // 上传设置
SettingEnum::STORAGE => [ SettingEnum::STORAGE => [
'key' => SettingEnum::STORAGE, 'key' => SettingEnum::STORAGE,

@ -12,8 +12,8 @@ declare (strict_types=1);
namespace app\store\controller; namespace app\store\controller;
use think\response\Json;
use app\store\model\Setting as SettingModel; use app\store\model\Setting as SettingModel;
use think\response\Json;
/** /**
* 系统设置 * 系统设置

Loading…
Cancel
Save