共计 9762 个字符,预计需要花费 25 分钟才能阅读完成。
前言
在联合 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 类外面事件类型
<?php
namespace 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