前言
在联合think-swoole+easywechat扩大应用的时候,须要思考curl兼容swoole携程问题,request兼容swoole框架,因为easywechat底层还是通过$_POST或者其余来获取申请参数。
还有就是好多的接口根本没有。须要本人写,因为这里装置的是5.0的版本。在6.0版本后easywecaht不在写操作接口的相干逻辑只提供了一些受权后的接口封装、申请封装、日志封装等等。集体还是感觉5.0版本够用了。而后就抉择了5.0的版本来开发。5.0版本中例如,直播这块的接口逻辑须要本人写点、企业微信进群配置这些等等。上面咱们就看具体的实例教程:
装置
装置think-swoole
composer require topthink/think-swoole
装置easywechat
composer require overtrue/wechat:~5.0 -vvv
应用前配置
请在app/AppService.php的boot办法内减少配置默认申请类
use Yurun\Util\Swoole\Guzzle\SwooleHandler; DefaultHandler::setDefaultHandler(SwooleHandler::class);
例如这里实例化一个企业微信相干的
use EasyWeChat\Work\Application;use Yurun\Util\Swoole\Guzzle\SwooleHandler;$type = 'user';$config=[ 'corp_id'=>'', 'token'=>'',];//实例化企业微信$application[$type] = Factory::work($config);//这里是为了兼容swoole的curl携程$application[$type]['guzzle_handler'] = SwooleHandler::class;$request = request();//在swoole模式运行下,须要从think\request下获取申请信息,这一步非常重要$application[$type]->rebind('request', new Request($request->get(), $request->post(), [], [], [], $request->server(), $request->getContent()));$this->application[$type]->register(new ServiceProvider());
应用前这些配置都须要减少的。这里也能够封装成类来进行调用
为什么要用type来辨别实例化类型:
因为在企业微信下会有多种服务实例化对象,例如客户、自建利用、通讯录都会产生不同的实例化对象
构建企业微信服务首先革新下方才实例化的形式:
use crmeb\services\wechat\groupChat\ServiceProvider;use Yurun\Util\Swoole\Guzzle\SwooleHandler;use EasyWeChat\Work\Application;use Symfony\Component\HttpFoundation\Request;class Work extends BaseApplication{ /** * @var WorkConfig */ protected $config; /** * @var Application[] */ protected $application = []; /** * @var string */ protected $configHandler; /** * @var string[] */ protected static $property = [ 'groupChat' => 'external_contact', 'groupChatWelcome' => 'external_contact_message_template' ]; /** * Work constructor. */ public function __construct() { /** @var WorkConfig config */ $this->config = app()->make(WorkConfig::class); $this->debug = DefaultConfig::value('logger'); } /** * 设置获取配置 * @param string $handler * @return $this */ public function setConfigHandler(string $handler) { $this->configHandler = $handler; return $this; } /** * @return Work */ public static function instance() { return app()->make(static::class); } /** * 获取实例化句柄 * @param string $type * @return Application */ public function application(string $type = WorkConfig::TYPE_USER){ $config = $this->config->all(); $config = array_merge($config, $this->config->setHandler($this->configHandler)->getAppConfig($type)); if (!isset($this->application[$type])) { $this->application[$type] = Factory::work($config); $this->application[$type]['guzzle_handler'] = SwooleHandler::class; $request = request(); $this->application[$type]->rebind('request', new Request($request->get(), $request->post(), [], [], [], $request->server(), $request->getContent())); $this->application[$type]->register(new ServiceProvider()); } return $this->application[$type]; }}
企业微信服务
这里阐明下,swoole外面尽量少用静态方法,而这里应用了的起因是,应用了app->make()实例化了以后类。
use think\Response;/** * 服务端 * @return Response * @throws BadRequestException * @throws InvalidArgumentException * @throws InvalidConfigException * @throws \ReflectionException */public static function serve(): Response{ $make = self::instance(); $make->application()->server->push($make->pushMessageHandler); $response = $make->application()->server->serve(); return response($response->getContent());}首先设置pushMessageHandler类,关上app/AppService.php。在register办法中注册服务器相应事件类 ,例如app\listener\wechat\WorkListener 类引入use crmeb\services\wechat\config\HttpCommonConfig;use crmeb\services\wechat\config\LogCommonConfig;use crmeb\services\wechat\config\WorkConfig;use app\services\work\WorkConfigServices;public function register(){ //实例化企业微信配置 $this->app->bind(WorkConfig::class, function () { return (new WorkConfig(new LogCommonConfig(), $this->app->make(HttpCommonConfig::class))) ->setHandler(WorkConfigServices::class); }); //企业微信 $this->app->bind(Work::class, function () { return (new Work)->setPushMessageHandler(WorkListener::class) ->setConfigHandler(WorkConfigServices::class); });}
肯定要配置企业微信服务器相应的事件类WorkListener这里列举出WorkListener类外面事件类型
<?phpnamespace app\listener\wechat;use app\services\user\label\UserLabelServices;use app\services\work\WorkClientServices;use app\services\work\WorkDepartmentServices;use app\services\work\WorkGroupChatServices;use app\services\work\WorkMemberServices;use EasyWeChat\Kernel\Contracts\EventHandlerInterface;/** * 企业微信服务音讯解决 * Class WorkListener * @package app\listener\wechat */class WorkListener implements EventHandlerInterface{ public function handle($payload = null) { $response = null; switch ($payload['MsgType']) { case 'event': switch ($payload['Event']) { case 'change_contact'://通讯录事件 $this->changeContactEvent($payload); break; case 'change_external_chat'://客户群事件 $this->changeExternalChatEvent($payload); break; case 'change_external_contact'://客户事件 $this->externalContactEvent($payload); break; case 'change_external_tag'://客户标签事件 $this->changeExternalTagEvent($payload); break; case 'batch_job_result'://异步工作实现告诉 $this->batchJobResultEvent($payload); break; } break; case 'text'://文本音讯 break; case 'image'://图片音讯 break; case 'voice'://语音音讯 break; case 'video'://视频音讯 break; case 'news'://图文音讯 break; case 'update_button'://模板卡片更新音讯 break; case 'update_template_card'://更新点击用户的整张卡片 break; } return $response; } public function batchJobResultEvent(array $payload) { switch ($payload['JobType']) { case 'sync_user'://增量更新成员 break; case 'replace_user'://全量笼罩成员 break; case 'invite_user'://邀请成员关注 break; case 'replace_party'://全量笼罩部门 break; } } /** * 企业微信通讯录事件 * @param array $payload * @return null */ public function changeContactEvent(array $payload) { $response = null; try { switch ($payload['ChangeType']) { case 'create_user'://新增成员事件 break; case 'update_user'://更新成员事件 break; case 'delete_user'://删除成员事件 break; case 'create_party'://新增部门事件 break; case 'update_party'://更新部门事件 break; case 'delete_party'://删除部门事件 break; case 'update_tag'://标签成员变更事件 break; } } catch (\Throwable $e) { \think\facade\Log::error([ 'message' => '企业微信通讯录事件产生谬误:' . $e->getMessage(), 'payload' => $payload, 'file' => $e->getFile(), 'line' => $e->getLine() ]); } return $response; } /** * 客户事件 * @param array $payload * @return |null */ public function externalContactEvent(array $payload) { $response = null; try { switch ($payload['ChangeType']) { case 'add_external_contact'://增加企业客户事件 /** @var WorkClientServices $make */ $make = app()->make(WorkClientServices::class); $make->createClient($payload); break; case 'edit_external_contact'://编辑企业客户事件 /** @var WorkClientServices $make */ $make = app()->make(WorkClientServices::class); $make->updateClient($payload); break; case 'del_external_contact': /** @var WorkClientServices $make */ $make = app()->make(WorkClientServices::class); $make->deleteClient($payload); break; case 'add_half_external_contact'://内部联系人免验证增加成员事件 break; case 'del_follow_user'://删除跟进成员事件 /** @var WorkClientServices $make */ $make = app()->make(WorkClientServices::class); $make->deleteFollowClient($payload); break; case 'transfer_fail'://客户接替失败事件 break; } } catch (\Throwable $e) { \think\facade\Log::error([ 'message' => '客户事件产生谬误:' . $e->getMessage(), 'payload' => $payload, 'file' => $e->getFile(), 'line' => $e->getLine() ]); } return $response; } /** * 客户群事件 * @param array $payload */ public function changeExternalChatEvent(array $payload) { try { switch ($payload['ChangeType']) { case 'create'://客户群创立事件 break; case 'update'://客户群变更事件 break; case 'dismiss'://客户群遣散事件 break; } } catch (\Throwable $e) { \think\facade\Log::error([ 'message' => $e->getMessage(), 'payload' => $payload, 'file' => $e->getFile(), 'line' => $e->getLine() ]); } } /** * 客户标签事件 * @param array $payload */ public function changeExternalTagEvent(array $payload) { switch ($payload['ChangeType']) { case 'create'://企业客户标签创立事件 break; case 'update'://企业客户标签变更事件 break; case 'delete'://企业客户标签删除事件 break; case 'shuffle'://企业客户标签重排事件 break; } }}
上面提供了残缺的类
BaseApplication类
use crmeb\services\wechat\contract\BaseApplicationInterface;/** * Class BaseApplication * @package crmeb\services\wechat */abstract class BaseApplication implements BaseApplicationInterface{ //app端 const APP = 'app'; //h5端、公众端 const WEB = 'web'; //小程序端 const MINI = 'mini'; //开发平台 const OPEN = 'open'; //pc端 const PC = 'pc'; /** * 拜访端 * @var string */ protected $accessEnd; /** * @var array */ protected static $property = []; /** * @var string */ protected $pushMessageHandler; /** * Debug * @var bool */ protected $debug = true; /** * 设置音讯解决类 * @param string $handler * @return $this */ public function setPushMessageHandler(string $handler) { $this->pushMessageHandler = $handler; return $this; } /** * 设置拜访端 * @param string $accessEnd * @return $this */ public function setAccessEnd(string $accessEnd) { if (in_array($accessEnd, [self::APP, self::WEB, self::MINI])) { $this->accessEnd = $accessEnd; } return $this; } /** * 主动获取拜访端 * @param \think\Request $request * @return string */ public function getAuthAccessEnd(\think\Request $request) { if (!$this->accessEnd) { try { if ($request->isApp()) { $this->accessEnd = self::APP; } else if ($request->isPc()) { $this->accessEnd = self::PC; } else if ($request->isWechat() || $request->isH5()) { $this->accessEnd = self::WEB; } else if ($request->isRoutine()) { $this->accessEnd = self::MINI; } else { $this->accessEnd = self::WEB; } } catch (\Throwable $e) { $this->accessEnd = self::WEB; } } return $this->accessEnd; } /** * 记录谬误日志 * @param \Throwable $e */ protected static function error(\Throwable $e) { static::instance()->debug && \think\facade\Log::error([ 'error' => $e->getMessage(), 'line' => $e->getLine(), ' file' => $e->getFile() ]); } /** * 申请日志 * @param string $message * @param $request * @param $response */ protected static function logger(string $message, $request, $response) { $debug = static::instance()->debug; if ($debug) { \think\facade\Log::info([ 'message' => $message, 'request' => json_encode($request), 'response' => json_encode($response) ]); } } /** * @param $name * @param $arguments * @return mixed */ public static function __callStatic($name, $arguments) { if (in_array($name, array_keys(static::$property))) { $name = static::$property[$name]; return static::instance()->application()->{$name}; } throw new WechatException('办法不存在'); }}BaseApplicationInterface接口类namespace crmeb\services\wechat\contract;/** * Interface BaseApplicationInterface * @package crmeb\services\wechat\contract */interface BaseApplicationInterface{ /** * @return mixed */ public static function instance(); /** * @return mixed */ public function application();}
最初
如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star:http://github.crmeb.net/u/defu不胜感激 !
收费获取源码地址:http://www.crmeb.com
PHP学习手册:https://doc.crmeb.com
技术交换论坛:https://q.crmeb.com