前言
眾所周知 easywechat 非常強大,裡面包含微信平臺的所有功能例如 公眾號、小程式、開放平臺、企業號等功能。
正好我這邊接到需求要開發一個身份證識別的功能,考慮到擴充套件性,決定參考 easywechat 的管理模式開發一個自己的包。下面是主要步驟和程式碼包結構如下:
因為是公司內部專案所以放棄用composer管理包,至於如何用composer管理可以看教程
1、 主要檔案和目錄說明:
目錄:
src/Ai 表示騰訊的識別模組,可以新建其它模組(類似 easywechat 的 miniProgram、OfficialAccount 等模組)
src/Ai/Ocr 表示騰訊識別的Ocr模組(類似 OfficialAccount 授權登入、選單、訊息等模組)
src/config 表示配置檔案位置
src/Kernel 表示容器管理,核心模組
檔案:
src/Ai/Ocr/Client.php 表示具體業務處理類程式碼如下:
<?php
namespace Tecent\src\Ai\Ocr;
// 騰訊ocr認證
use Pimple\Container;
/**
* 處理具體業務邏輯
* Class Client
* @package Tencent\src\Ai\Ocr
*/
class Client
{
private $idCardUrl = 'https://recognition.image.myqcloud.com/ocr/idcard';
private $appid;
private $secret_id;
private $secret_key;
public function __construct($app)
{
// container 讀取配置檔案
$config = $app->getConfig();
$this->appid = $config['app_id'];
$this->secret_id = $config['secret_id'];
$this->secret_key = $config['secret_key'];
}
/**
* 身份證識別
* @Author lxy
* @Date 2021/4/20 * @param $cardType
* @param $urlList
* @return string
* @throws \GuzzleHttp\Exception\GuzzleException */ public function idCard($cardType, $urlList)
{
$client = new \GuzzleHttp\Client();
$signArr = $this->getSign();
$options = [
'headers' => [
'authorization' => $signArr['signStr'],
'content-type' => 'application/json'
],
'json' => [
'appid' => $this->appid,
'card_type' => $cardType,
'url_list' => $urlList,
]
];
$response = $client->request('POST', $this->idCardUrl, $options);
return $response->getBody()->getContents();
}
/**
* 行駛證駕駛證識別
* @Author lxy
* @Date 2021/4/20 */ public function drivinglicence($type, $imageurl)
{
$signArr = $this->getSign();
$client = new \GuzzleHttp\Client();
$options = [
'headers' => [
'content-type'=>'application/json',
'authorization' => $signArr['signStr'],
],
'json' => [
'appid' => $this->appid,
'type' => $type,
'url' => $imageurl,
],
];
$result = $client->request('POST','https://recognition.image.myqcloud.com/ocr/drivinglicence', $options);
return $result->getBody()->getContents();
}
/**
* 簽名
* @Author lxy
* @Date 2021/4/20 * @return array
*/
private function getSign()
{
$appid = $this->appid;
$bucket = "tencentyun";
$secret_id = $this->secret_id;
$secret_key = $this->secret_key;
$expired = time() + 2592000;
$onceExpired = 0;
$current = time();
$rdm = rand();
$userid = "0";
$fileid = "tencentyunSignTest";
$srcStr = 'a=' . $appid . '&b=' . $bucket . '&k=' . $secret_id . '&e=' . $expired . '&t=' . $current . '&r=' . $rdm . '&f=';
$srcWithFile = 'a=' . $appid . '&b=' . $bucket . '&k=' . $secret_id . '&e=' . $expired . '&t=' . $current . '&r=' . $rdm . '&f=' . $fileid;
$srcStrOnce = 'a=' . $appid . '&b=' . $bucket . '&k=' . $secret_id . '&e=' . $onceExpired . '&t=' . $current . '&r=' . $rdm
. '&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 compact('signStr', 'srcWithFile', 'signStrOnce');
}
}
src/Ai/Ocr/ServiceProvider.php 表示註冊一個 ocr 服務
<?php
namespace Tecent\src\Ai\Ocr;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
/**
* Register any application services.
* 參考:https://github.com/silexphp/Pimple
* Class ServiceProvider
* @package Tencent\src\Ai\Ocr
*/
class ServiceProvider implements ServiceProviderInterface
{
public function register(Container $app)
{
!isset($app['ocr']) && $app['ocr'] = function ($app) {
return new Client($app);
};
}
}
src/Ai/Application.php 應用服務管理包括自動註冊服務、服務發現等功能
<?php
namespace Tecent\src\Ai;
use Tecent\src\Ai\Ocr\ServiceProvider;
use Tecent\src\Kernel\ServiceContainer;
/**
* 定義一個application(裡面包含很多application services)
* application services 在建構函式裡面自動註冊
* Class Application
* @package Tencent\src\Ai
*/
class Application extends ServiceContainer
{
protected $providers = [
ServiceProvider::class,// 提供一個ocr圖片識別的服務
//... 可以註冊無數個,想寫多少就寫多少
];
}
src/config/tencent_cloud.php 配置檔案(如果有多個就不能這麼寫了,參考laravel-wechat)
<?php
return [
'app_id' => env('APP_ID','xxx'),
'secret_id' => env('SECRET_ID','xxx'),
'secret_key' => env('SECRET_KEY', 'xxx'),
];
src/Kernel/ServiceContainer.php 核心模組,服務註冊、服務發現
<?php
namespace Tecent\src\Kernel;
use Pimple\Container;
class ServiceContainer extends Container
{
/**
* @var string
*/
protected $id;
/**
* @var array
*/
protected $providers = [];
/**
* @var array
*/
protected $defaultConfig = [];
/**
* @var array
*/
protected $userConfig = [];
/**
* Constructor.
* 建構函式註冊服務(載入配置檔案)都是通過https://github.com/silexphp/Pimple這個包來完成的
* @param array $config
* @param array $prepends
* @param string|null $id
*/
public function __construct(array $config = [], array $prepends = [], string $id = null)
{
$this->registerProviders($this->getProviders());
parent::__construct($prepends);
$this->userConfig = $config;
$this->id = $id;
}
/**
* @return string
*/
public function getId()
{
return $this->id ?? $this->id = md5(json_encode($this->userConfig));
}
/**
* @return array
*/
public function getConfig()
{
$base = [
'http' => [
'timeout' => 30.0,
],
];
return array_replace_recursive($base, $this->defaultConfig, $this->userConfig);
}
/**
* Return all providers.
*
* @return array
*/
public function getProviders()
{
return $this->providers;
}
/**
* @param string $id
* @param mixed $value
*/
public function rebind($id, $value)
{
$this->offsetUnset($id);
$this->offsetSet($id, $value);
}
/**
* Magic get access.
* 說人話:這個魔術方法在呼叫時自動執行,從而例項化物件【Pimple的Using the defined services is also very easy:】
* @param string $id
*
* @return mixed
*/
public function __get($id)
{
return $this->offsetGet($id);
}
/**
* Magic set access.
* 魔術方法:設定一個例項或Defining Services,臥槽!
* @param string $id
* @param mixed $value
*/
public function __set($id, $value)
{
$this->offsetSet($id, $value);
}
/**
* 手動註冊物件
* @param array $providers
*/
public function registerProviders(array $providers)
{
foreach ($providers as $provider) {
parent::register(new $provider());
}
}
}
src/Facade.php
<?php
namespace Tencent\src;
class Facade extends \Illuminate\Support\Facades\Facade
{
protected static function getFacadeAccessor()
{
return 'ocr';
}
}
src/ServiceProvider.php
<?php
namespace Tencent\src;
use Dingo\Api\Provider\LaravelServiceProvider;
use Tecent\src\Ai\Application;
class ServiceProvider extends LaravelServiceProvider {
public function boot()
{
$this->publishes([realpath(__DIR__.'/config/tencent_cloud.php') => config_path('tencent_cloud.php')]);
}
/***
* 這裡我寫簡單了,可以寫一個陣列迴圈註冊服務。配置檔案也一樣,參考laravel-wechat的方式
*/
public function register()
{
$config = config('tencent_cloud');
$this->app->singleton('tencent.ocr', function ($app) use($config){
return new Application($config);
});
}
public function provides()
{
return ['ocr'];
}
}
到此全部完成,是不是很簡單。
下面是使用方法:
composer.json 裡新增一下自動載入
...
"autoload": {
"classmap": [
"database/seeds",
"database/factories",
"app/Libs/RongCloud",
"app/Libs/laravel-baidu",
"app/Libs/baidu",
"app/Libs/Tencent"
],
"psr-4": {
"App\\": "app/"
},
"files": [
"app/Include/fun_common.php"
]
...
},
app.php裡面providers陣列裡面加上服務
...
'providers' =>[
// 騰訊雲
Tencent\src\ServiceProvider::class,
],
...
釋出配置檔案
php artisan vendor:publish //選擇你要的釋出
使用:
public function tecentIdcard(Request $request)
{
$cardType = $request->card_type;
$cardUrlList = $request->url_list;
$result = app('tencent.ocr')->ocr->idCard($cardType, $cardUrlList);
return $this->response->array(json_decode($result,true));
}
.env 新增配置檔案
so easy!
以後其它類似的功能也可以這麼做
本作品採用《CC 協議》,轉載必須註明作者和本文連結