前言
众所周知 easywechat 非常强大,里面包含微信平台的所有功能例如 公众号、小程序、开放平台、企业号等功能。
正好我这边接到需求要开发一个身份证识别的功能,考虑到扩展性,决定参考 easywechat 的管理模式开发一个自己的包。下面是主要步骤和代码包结构如下:
因为是公司内部项目所以放弃用composer管理包,至于如何用composer管理可以看教程
1、 主要文件和目录说明:
目录:
src/Ai 表示腾讯的识别模块,可以新建其它模块(类似 easywechat 的 miniProgram、OfficialAccount 等模块)
src/Ai/Ocr 表示腾讯识别的Ocr模块(类似 OfficialAccount 授权登录、菜单、消息等模块)
src/config 表示配置文件位置
src/Kernel 表示容器管理,核心模块
文件:
src/Ai/Ocr/Client.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 服务
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 应用服务管理包括自动注册服务、服务发现等功能
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)
return ['app_id' => env('APP_ID','xxx'),'secret_id' => env('SECRET_ID','xxx'),'secret_key' => env('SECRET_KEY', 'xxx'), | |
]; |
src/Kernel/ServiceContainer.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
namespace Tencent\src; | |
class Facade extends \Illuminate\Support\Facades\Facade | |
{protected static function getFacadeAccessor(){return 'ocr';} | |
} |
src/ServiceProvider.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!
以后其它类似的功能也可以这么做