From c151bd5ff0e0f071304d8bc343f2bbc519e72912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=96=B0=E6=89=8D?= Date: Sat, 28 Aug 2021 16:31:33 +0800 Subject: [PATCH 1/7] =?UTF-8?q?[=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96](mast?= =?UTF-8?q?er):=20=E5=8E=BB=E9=99=A4=E8=B0=83=E8=AF=95=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api-server/app/core/work-employee/src/Logic/SyncLogic.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/api-server/app/core/work-employee/src/Logic/SyncLogic.php b/api-server/app/core/work-employee/src/Logic/SyncLogic.php index 2c2c93ac..3f564ceb 100644 --- a/api-server/app/core/work-employee/src/Logic/SyncLogic.php +++ b/api-server/app/core/work-employee/src/Logic/SyncLogic.php @@ -174,8 +174,6 @@ protected function dealEmployee($corpIds) } } - dump("fileQueueData:"); - dump($fileQueueData); //上传图片 if (!empty($fileQueueData)) { file_upload_queue($fileQueueData); From 873ecc0a017885b6e44002c828b51ba7e0b6bf39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=96=B0=E6=89=8D?= Date: Tue, 31 Aug 2021 09:34:36 +0800 Subject: [PATCH 2/7] =?UTF-8?q?[=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96](mast?= =?UTF-8?q?er):=20=E4=BC=98=E5=8C=96=E4=BC=9A=E8=AF=9D=E5=AD=98=E6=A1=A3?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=96=B9=E5=BC=8F=E8=87=B3=E7=A7=92=E7=BA=A7?= =?UTF-8?q?=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/src/Action/Dashboard/Upload.php | 5 +- .../core/corp/src/Action/Dashboard/Update.php | 8 + .../app/core/corp/src/Logic/AppTrait.php | 64 +---- .../corp/src/QueueService/WeWorkCallback.php | 2 + .../app/core/corp/src/Utils/WeWorkFactory.php | 169 +++++++++++ api-server/app/core/sync-data/composer.json | 39 +++ .../src/Annotation/DynamicCrontab.php | 54 ++++ .../src/Contract/DataFetcherInterface.php | 33 +++ .../sync-data/src/DynamicCrontabManager.php | 266 ++++++++++++++++++ .../DynamicCrontabRegisterListener.php | 53 ++++ .../src/Task/AbstractSyncDataTask.php | 71 +++++ .../src/Contract/WorkMessageContract.php | 18 ++ .../src/Event/MessageArchiveRawEvent.php | 31 ++ .../src/Event/MessageReceivedRawEvent.php | 31 ++ .../src/Fetcher/MessageDataFetcher.php | 135 +++++++++ .../Listener/MessageArchiveRawListener.php | 61 ++++ .../Listener/MessageReceivedRawListener.php | 50 ++++ .../src/Logic/{Store.php => StoreLogic.php} | 111 ++------ .../Process/MessageMediaConsumerProcess.php | 25 ++ .../src/Queue/MessageMediaSyncQueue.php | 75 +++++ .../src/Queue/MessageReceivedRawQueue.php | 30 ++ .../src/QueueService/StoreApply.php | 26 -- .../src/Service/WorkMessageService.php | 35 +++ .../src/Task/MessageSyncDataTask.php | 31 ++ .../core/work-message/src/Task/WxMsgPull.php | 51 ---- .../src/Utils/MessageArchiveFactory.php | 65 +++++ api-server/app/utils/src/File.php | 19 ++ api-server/composer.json | 3 +- api-server/config/autoload/async_queue.php | 11 + 29 files changed, 1355 insertions(+), 217 deletions(-) create mode 100644 api-server/app/core/corp/src/Utils/WeWorkFactory.php create mode 100644 api-server/app/core/sync-data/composer.json create mode 100644 api-server/app/core/sync-data/src/Annotation/DynamicCrontab.php create mode 100644 api-server/app/core/sync-data/src/Contract/DataFetcherInterface.php create mode 100644 api-server/app/core/sync-data/src/DynamicCrontabManager.php create mode 100644 api-server/app/core/sync-data/src/Listener/DynamicCrontabRegisterListener.php create mode 100644 api-server/app/core/sync-data/src/Task/AbstractSyncDataTask.php create mode 100644 api-server/app/core/work-message/src/Event/MessageArchiveRawEvent.php create mode 100644 api-server/app/core/work-message/src/Event/MessageReceivedRawEvent.php create mode 100644 api-server/app/core/work-message/src/Fetcher/MessageDataFetcher.php create mode 100644 api-server/app/core/work-message/src/Listener/MessageArchiveRawListener.php create mode 100644 api-server/app/core/work-message/src/Listener/MessageReceivedRawListener.php rename api-server/app/core/work-message/src/Logic/{Store.php => StoreLogic.php} (75%) create mode 100644 api-server/app/core/work-message/src/Process/MessageMediaConsumerProcess.php create mode 100644 api-server/app/core/work-message/src/Queue/MessageMediaSyncQueue.php create mode 100644 api-server/app/core/work-message/src/Queue/MessageReceivedRawQueue.php delete mode 100644 api-server/app/core/work-message/src/QueueService/StoreApply.php create mode 100644 api-server/app/core/work-message/src/Task/MessageSyncDataTask.php delete mode 100644 api-server/app/core/work-message/src/Task/WxMsgPull.php create mode 100644 api-server/app/core/work-message/src/Utils/MessageArchiveFactory.php diff --git a/api-server/app/core/common/src/Action/Dashboard/Upload.php b/api-server/app/core/common/src/Action/Dashboard/Upload.php index ae3093ce..57f637c2 100644 --- a/api-server/app/core/common/src/Action/Dashboard/Upload.php +++ b/api-server/app/core/common/src/Action/Dashboard/Upload.php @@ -13,6 +13,7 @@ use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\RequestMapping; use League\Flysystem\Filesystem; +use MoChat\App\Utils\File; use MoChat\Framework\Action\AbstractAction; use MoChat\Framework\Constants\ErrorCode; use MoChat\Framework\Exception\CommonException; @@ -46,10 +47,8 @@ public function handle(Filesystem $filesystem): array $originalFilename = $this->request->post('name', false) ?: $file->getClientFilename(); // 不再支持自定义path - $path = date('Y/md/Hi'); $extension = $file->getExtension(); - $filename = strval(microtime(true) * 10000) . uniqid() . '.' . $extension; - $pathFileName = $path . '/' . $filename; + $pathFileName = File::generateFullFilename($extension); try { $stream = fopen($file->getRealPath(), 'r+'); diff --git a/api-server/app/core/corp/src/Action/Dashboard/Update.php b/api-server/app/core/corp/src/Action/Dashboard/Update.php index 76585036..2c3abbae 100644 --- a/api-server/app/core/corp/src/Action/Dashboard/Update.php +++ b/api-server/app/core/corp/src/Action/Dashboard/Update.php @@ -16,6 +16,7 @@ use Hyperf\HttpServer\Annotation\RequestMapping; use MoChat\App\Corp\Action\Dashboard\Traits\RequestTrait; use MoChat\App\Corp\Contract\CorpContract; +use MoChat\App\Corp\Utils\WeWorkFactory; use MoChat\App\Rbac\Middleware\PermissionMiddleware; use MoChat\Framework\Action\AbstractAction; use MoChat\Framework\Constants\ErrorCode; @@ -48,6 +49,12 @@ class Update extends AbstractAction */ private $logger; + /** + * @Inject() + * @var WeWorkFactory + */ + protected $weWorkFactory; + /** * @RequestMapping(path="/dashboard/corp/update", methods="put") * @Middlewares({ @@ -78,6 +85,7 @@ public function handle(): array try { ## 数据入表 $this->corpService->updateCorpById($corpId, $params); + $this->weWorkFactory->unbindApp((int) $corpId); } catch (\Throwable $e) { $this->logger->error(sprintf('%s [%s] %s', '企业微信授信更新失败', date('Y-m-d H:i:s'), $e->getMessage())); $this->logger->error($e->getTraceAsString()); diff --git a/api-server/app/core/corp/src/Logic/AppTrait.php b/api-server/app/core/corp/src/Logic/AppTrait.php index 092d4a13..8ee7b1e2 100644 --- a/api-server/app/core/corp/src/Logic/AppTrait.php +++ b/api-server/app/core/corp/src/Logic/AppTrait.php @@ -11,72 +11,38 @@ namespace MoChat\App\Corp\Logic; use EasyWeChat\Work\Application; -use MoChat\App\Corp\Contract\CorpContract; -use MoChat\App\WorkAgent\Contract\WorkAgentContract; -use MoChat\Framework\Constants\ErrorCode; -use MoChat\Framework\Exception\CommonException; -use MoChat\Framework\WeWork\WeWork; +use MoChat\App\Corp\Utils\WeWorkFactory; trait AppTrait { /** * 根据微信企业ID获取easyWechat实例. + * * @param int|string $corpId 微信corpid或企业表corpId - * @param string $type ... - * @return Application ... + * @param string $type + * + * @return Application */ public function wxApp($corpId, string $type = 'user'): Application { - if (is_int($corpId)) { - $corMethod = 'getCorpById'; - } else { - $corMethod = 'getCorpsByWxCorpId'; - } - $corp = make(CorpContract::class)->{$corMethod}($corpId, [ - 'id', 'employee_secret', 'contact_secret', 'wx_corpid' - ]); - if (empty($corp)) { - throw new CommonException(ErrorCode::SERVER_ERROR, sprintf('无该企业:[%s]', $corpId)); - } - - $config['corp_id'] = $corp['wxCorpid']; - switch ($type) { - case 'user': - $config['secret'] = $corp['employeeSecret']; - break; - case 'contact': - $config['secret'] = $corp['contactSecret']; - break; - default: - throw new CommonException(ErrorCode::SERVER_ERROR, sprintf('wxApp方法无此类型:[%s]', $type)); + $weWorkFactory = make(WeWorkFactory::class); + if ($type === 'user') { + return $weWorkFactory->getUserApp($corpId); } - return make(WeWork::class)->app($config); + return $weWorkFactory->getContactApp($corpId); } /** - * 根据企业微信应用id获取信息. + * 获取三方应用或自建应用实例 + * * @param int|string $agentId + * + * @return Application */ public function wxAgentApp($agentId): Application { - $agentFunc = is_int($agentId) ? 'getWorkAgentById' : 'getWorkAgentByWxAgentId'; - $agent = make(WorkAgentContract::class)->{$agentFunc}($agentId, [ - 'id', 'wx_secret', 'corp_id', - ]); - if (empty($agent)) { - throw new CommonException(ErrorCode::SERVER_ERROR, sprintf('无该应用:[%s]', $agentId)); - } - ## 根据corpId 查 wxCorpid - $corp = make(CorpContract::class)->getCorpById($agent['corpId'], [ - 'id', 'wx_corpid', - ]); - - $config = [ - 'corp_id' => $corp['wxCorpid'], - 'secret' => $agent['wxSecret'], - ]; - - return make(WeWork::class)->app($config); + $weWorkFactory = make(WeWorkFactory::class); + return $weWorkFactory->getAgentApp($agentId); } } diff --git a/api-server/app/core/corp/src/QueueService/WeWorkCallback.php b/api-server/app/core/corp/src/QueueService/WeWorkCallback.php index 1e57d196..8c9e4025 100644 --- a/api-server/app/core/corp/src/QueueService/WeWorkCallback.php +++ b/api-server/app/core/corp/src/QueueService/WeWorkCallback.php @@ -15,6 +15,7 @@ use MoChat\App\WorkDepartment\Event\DeleteDepartmentRawEvent; use MoChat\App\WorkDepartment\Event\UpdateDepartmentRawEvent; use MoChat\App\WorkEmployee\Event\DeleteEmployeeRawEvent; +use MoChat\App\WorkMessage\Event\MessageArchiveRawEvent; use Psr\EventDispatcher\EventDispatcherInterface; use Hyperf\AsyncQueue\Annotation\AsyncQueueMessage; use MoChat\App\WorkEmployee\Event\CreateEmployeeRawEvent; @@ -83,6 +84,7 @@ protected function getEvents() 'event.change_contact.update_party' => UpdateDepartmentRawEvent::class, 'event.change_contact.delete_party' => DeleteDepartmentRawEvent::class, 'event.change_contact.update_tag' => UpdateContactTagRawEvent::class, + 'event.conversation_archive' => MessageArchiveRawEvent::class ]; } } diff --git a/api-server/app/core/corp/src/Utils/WeWorkFactory.php b/api-server/app/core/corp/src/Utils/WeWorkFactory.php new file mode 100644 index 00000000..ab4670f9 --- /dev/null +++ b/api-server/app/core/corp/src/Utils/WeWorkFactory.php @@ -0,0 +1,169 @@ +userApps[$corpId]) && $this->userApps[$corpId] instanceof Application) { + return $this->userApps[$corpId]; + } + + return $this->userApps[$corpId] = $this->makeApp($corpId, 'user'); + } + + /** + * 获取客户联系应用实例 + * + * @param string|int $corpId 企业id + * + * @return Application + */ + public function getContactApp($corpId): Application + { + if (isset($this->contactApps[$corpId]) && $this->contactApps[$corpId] instanceof Application) { + return $this->contactApps[$corpId]; + } + + return $this->contactApps[$corpId] = $this->makeApp($corpId, 'contact'); + } + + /** + * 获取三方应用或自建应用实例 + * + * @param string|int $agentId 应用id + * + * @return Application + */ + public function getAgentApp($agentId): Application + { + if (isset($this->agentApps[$agentId]) && $this->agentApps[$agentId] instanceof Application) { + return $this->agentApps[$agentId]; + } + + return $this->agentApps[$agentId] = $this->makeAgentApp($agentId); + } + + /** + * 解绑通讯录和客户联系应用实例(当企业信息发生变化的时候) + * + * @param string|int $corpId + */ + public function unbindApp($corpId) + { + if (isset($this->contactApps[$corpId])) { + unset($this->contactApps[$corpId]); + } + + if (isset($this->userApps[$corpId])) { + unset($this->userApps[$corpId]); + } + } + + /** + * 解绑三方应用实例(当应用信息发生变化的时候) + * + * @param string|int $agentId + */ + public function unbindAgentApp($agentId) + { + if (isset($this->agentApps[$agentId])) { + unset($this->agentApps[$agentId]); + } + } + + protected function makeApp($corpId, string $type) + { + if (is_int($corpId)) { + $corMethod = 'getCorpById'; + } else { + $corMethod = 'getCorpsByWxCorpId'; + } + $corp = make(CorpContract::class)->{$corMethod}($corpId, [ + 'id', 'employee_secret', 'contact_secret', 'wx_corpid' + ]); + if (empty($corp)) { + throw new CommonException(ErrorCode::SERVER_ERROR, sprintf('无该企业:[%s]', $corpId)); + } + + $config['corp_id'] = $corp['wxCorpid']; + switch ($type) { + case 'user': + $config['secret'] = $corp['employeeSecret']; + break; + case 'contact': + $config['secret'] = $corp['contactSecret']; + break; + default: + throw new CommonException(ErrorCode::SERVER_ERROR, sprintf('wxApp方法无此类型:[%s]', $type)); + } + + return make(WeWork::class)->app($config); + } + + /** + * 根据企业微信应用id获取信息. + * @param int|string $agentId + * + * @return Application + */ + protected function makeAgentApp($agentId): Application + { + $agentFunc = is_int($agentId) ? 'getWorkAgentById' : 'getWorkAgentByWxAgentId'; + $agent = make(WorkAgentContract::class)->{$agentFunc}($agentId, [ + 'id', 'wx_secret', 'corp_id', + ]); + if (empty($agent)) { + throw new CommonException(ErrorCode::SERVER_ERROR, sprintf('无该应用:[%s]', $agentId)); + } + ## 根据corpId 查 wxCorpid + $corp = make(CorpContract::class)->getCorpById($agent['corpId'], [ + 'id', 'wx_corpid', + ]); + + $config = [ + 'corp_id' => $corp['wxCorpid'], + 'secret' => $agent['wxSecret'], + ]; + + return make(WeWork::class)->app($config); + } +} \ No newline at end of file diff --git a/api-server/app/core/sync-data/composer.json b/api-server/app/core/sync-data/composer.json new file mode 100644 index 00000000..fa0a68f9 --- /dev/null +++ b/api-server/app/core/sync-data/composer.json @@ -0,0 +1,39 @@ +{ + "name": "mochat/app-sync-data", + "description": "MoChat 核心应用-同步数据", + "license": "GPL-3.0", + "keywords": [ + "php", + "mochat", + "scrm" + ], + "homepage": "https://mo.chat", + "support": { + "docs": "https://mochat.wiki", + "issues": "https://github.com/mochat-cloud/mochat/issues", + "pull-request": "https://github.com/mochat-cloud/mochat/pulls", + "source": "https://github.com/mochat-cloud/mochat" + }, + "require": { + "php": ">=7.3" + }, + "autoload": { + "psr-4": { + "MoChat\\App\\SyncData\\": "src/" + } + }, + "config": { + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "dev-master" + } + }, + "bin": [ + ], + "scripts": { + "cs-fix": "php-cs-fixer fix $1", + "test": "phpunit --colors=always" + } +} diff --git a/api-server/app/core/sync-data/src/Annotation/DynamicCrontab.php b/api-server/app/core/sync-data/src/Annotation/DynamicCrontab.php new file mode 100644 index 00000000..f5a3ffdc --- /dev/null +++ b/api-server/app/core/sync-data/src/Annotation/DynamicCrontab.php @@ -0,0 +1,54 @@ +bindMainProperty('scheduleRule', $value); + if (! empty($this->scheduleRule)) { + $this->scheduleRule = str_replace('\\', '', $this->scheduleRule); + } + } + + public function collectClass(string $className): void + { + $this->parseSchedule($className); + parent::collectClass($className); + } + + protected function parseSchedule(string $className): void + { + if (is_string($this->schedule)) { + $this->schedule = [$className, $this->schedule]; + } + } +} diff --git a/api-server/app/core/sync-data/src/Contract/DataFetcherInterface.php b/api-server/app/core/sync-data/src/Contract/DataFetcherInterface.php new file mode 100644 index 00000000..a3872dfd --- /dev/null +++ b/api-server/app/core/sync-data/src/Contract/DataFetcherInterface.php @@ -0,0 +1,33 @@ +crontabManager = $crontabManager; + $this->logger = $logger; + $this->config = $config; + $this->cache = $cache; + } + + /** + * Handle the Event when the event is triggered, all listeners will + * complete before the event is returned to the EventDispatcher. + */ + public function register() + { + $crontabs = $this->parseCrontabs(); + $this->crontabRegister($crontabs); + } + + public function schedule(DynamicCrontabAnnotation $annotation) + { + $callbackParams = $this->callSchedule($annotation->schedule); + $lastCallbackParams = $this->getLastCallbackParams($annotation->name); + $this->setCallbackParams($annotation->name, $callbackParams); + [$addParams, $deleteParams] = $this->diffParams($callbackParams, $lastCallbackParams); + + $crontabs = []; + if (!empty($addParams)) { + foreach ($addParams as $addParam) { + $crontabs[] = $this->buildCrontabByAnnotation($annotation, $addParam); + } + } + + if (!empty($deleteParams)) { + foreach ($deleteParams as $deleteParam) { + $crontabs[] = $this->buildCrontabByAnnotation($annotation, $deleteParam, true); + } + } + + $this->crontabRegister($crontabs); + } + + protected function callSchedule(callable $schedule) + { + [$class, $method] = $schedule; + if ($class && $method && class_exists($class) && method_exists($class, $method)) { + $instance = make($class); + return $instance->{$method}(); + } + + return []; + } + + protected function crontabRegister(array $crontabs) + { + foreach ($crontabs as $crontab) { + if ($crontab instanceof Crontab && $this->crontabManager->register($crontab)) { + if ($this->config->get('debug.crontab', false)) { + $this->logger->debug(sprintf('Crontab %s have been registered.', $crontab->getName())); + } + } + } + } + + protected function diffParams(array $currentParams, array $lastParams): array + { + $add = array_diff($lastParams, $currentParams); + $delete = array_diff($currentParams, $lastParams); + return [$add, $delete]; + } + + protected function getLastCallbackParams(string $name) + { + $lastCallbackParams = $this->cache->get($this->getCacheKey($name)); + + if (empty($lastCallbackParams)) { + return []; + } + + return $lastCallbackParams; + } + + protected function setCallbackParams(string $name, array $params) + { + $this->cache->set($this->getCacheKey($name), $params, -1); + } + + private function getCacheKey(string $name) + { + return sprintf("mochat:dynamicCrontab:%s", $name); + } + + private function parseCrontabs(): array + { + $configCrontabs = $this->config->get('crontab.dynamic_crontab', []); + $annotationCrontabs = AnnotationCollector::getClassesByAnnotation(DynamicCrontabAnnotation::class); + $crontabs = []; + foreach (array_merge($configCrontabs, $annotationCrontabs) as $crontab) { + $dynamicCrontabs = []; + if ($crontab instanceof DynamicCrontabAnnotation) { + $dynamicCrontabs = $this->buildCrontabsByAnnotation($crontab); + } + if (empty($dynamicCrontabs)) { + continue; + } + + foreach ($dynamicCrontabs as $dynamicCrontab) { + if ($dynamicCrontab instanceof Crontab) { + $crontabs[$crontab->getName()] = $dynamicCrontab; + } + } + } + return array_values($crontabs); + } + + private function buildCrontabsByAnnotation(DynamicCrontabAnnotation $annotation): array + { + $crontabs = [$this->buildScheduleCrontabByAnnotation($annotation)]; + $callbackParams = $this->callSchedule($annotation->schedule); + $this->setCallbackParams($annotation->name, $callbackParams); + if (empty($callbackParams)) { + return $crontabs; + } + + foreach ($callbackParams as $callbackParam) { + $crontabs[] = $this->buildCrontabByAnnotation($annotation, $callbackParam); + } + + return $crontabs; + } + + private function buildCrontabByAnnotation(DynamicCrontabAnnotation $annotation, $callbackParam, bool $isCancel = false): Crontab + { + $crontab = $this->buildBaseCrontab($annotation); + + if (isset($annotation->name)) { + $name = $annotation->name; + if (is_string($callbackParam) || is_numeric($callbackParam) || is_int($callbackParam)) { + $name = $name . '-' . (string)$callbackParam; + } else { + $name = $name . '-' . sha1(serialize($callbackParam)); + } + $crontab->setName($name); + } + + if (isset($annotation->callback)) { + $callback = $annotation->callback; + $callback[2] = [$callbackParam]; + $crontab->setCallback($callback); + } + + if ($isCancel) { + $crontab->setEnable(false); + } + + return $crontab; + } + + private function buildScheduleCrontabByAnnotation(DynamicCrontabAnnotation $annotation): Crontab + { + $crontab = $this->buildBaseCrontab($annotation); + + isset($annotation->name) && $crontab->setName($annotation->name.'-schedule'); + $crontab->setCallback([$this, 'schedule', $annotation]); + + return $crontab; + } + + private function buildBaseCrontab(DynamicCrontabAnnotation $annotation) + { + $crontab = new Crontab(); + isset($annotation->type) && $crontab->setType($annotation->type); + isset($annotation->rule) && $crontab->setRule($annotation->rule); + isset($annotation->scheduleRule) && $crontab->setRule($annotation->scheduleRule); + isset($annotation->singleton) && $crontab->setSingleton($annotation->singleton); + isset($annotation->mutexPool) && $crontab->setMutexPool($annotation->mutexPool); + isset($annotation->mutexExpires) && $crontab->setMutexExpires($annotation->mutexExpires); + isset($annotation->onOneServer) && $crontab->setOnOneServer($annotation->onOneServer); + isset($annotation->memo) && $crontab->setMemo($annotation->memo); + isset($annotation->enable) && $crontab->setEnable($this->resolveCrontabEnableMethod($annotation->enable)); + return $crontab; + } + + /** + * @param array|bool $enable + */ + private function resolveCrontabEnableMethod($enable): bool + { + if (is_bool($enable)) { + return $enable; + } + + $className = reset($enable); + $method = end($enable); + + try { + $reflectionClass = ReflectionManager::reflectClass($className); + $reflectionMethod = $reflectionClass->getMethod($method); + + if ($reflectionMethod->isPublic()) { + if ($reflectionMethod->isStatic()) { + return $className::$method(); + } + + $container = ApplicationContext::getContainer(); + if ($container->has($className)) { + return $container->get($className)->{$method}(); + } + } + + $this->logger->info('Crontab enable method is not public, skip register.'); + } catch (\ReflectionException $e) { + $this->logger->error('Resolve crontab enable failed, skip register.'); + } + + return false; + } +} \ No newline at end of file diff --git a/api-server/app/core/sync-data/src/Listener/DynamicCrontabRegisterListener.php b/api-server/app/core/sync-data/src/Listener/DynamicCrontabRegisterListener.php new file mode 100644 index 00000000..313ef9f9 --- /dev/null +++ b/api-server/app/core/sync-data/src/Listener/DynamicCrontabRegisterListener.php @@ -0,0 +1,53 @@ +dynamicCrontabManager = $dynamicCrontabManager; + } + + /** + * @return string[] returns the events that you want to listen + */ + public function listen(): array + { + return [ + BeforeProcessHandle::class, + BeforeCoroutineHandle::class, + ]; + } + + /** + * Handle the Event when the event is triggered, all listeners will + * complete before the event is returned to the EventDispatcher. + */ + public function process(object $event) + { + $this->dynamicCrontabManager->register(); + } +} diff --git a/api-server/app/core/sync-data/src/Task/AbstractSyncDataTask.php b/api-server/app/core/sync-data/src/Task/AbstractSyncDataTask.php new file mode 100644 index 00000000..f19609e3 --- /dev/null +++ b/api-server/app/core/sync-data/src/Task/AbstractSyncDataTask.php @@ -0,0 +1,71 @@ +getDataSource(); + } + + public function execute($id) + { + $data = $this->pull($id); + if (!empty($data)) { + $this->syncData($id, $data); + } + } + + /** + * 拉取客户端数据 + * + * @param array $dataSource + * @return array + */ + protected function pull($id): array + { + return $this->getDataFetcher($id)->pull(); + } + + /** + * 获取数据源,返回数组中 key 必须是唯一id + * + * @return array + */ + protected function getDataSource(): array + { + return $this->getDataFetcher()->getDataSource(); + } + + /** + * 获取数据获取客户端 + * + * @param int|string $id + * @return DataFetcherInterface + */ + abstract protected function getDataFetcher($id = null): DataFetcherInterface; + + /** + * 同步数据 + * + * @param int|string $id + * @param array $data + * + * @return mixed + */ + protected function syncData($id, array $data) + { + return $this->getDataFetcher($id)->syncData($data); + } +} \ No newline at end of file diff --git a/api-server/app/core/work-message/src/Contract/WorkMessageContract.php b/api-server/app/core/work-message/src/Contract/WorkMessageContract.php index 2e0fc4cd..023063b2 100644 --- a/api-server/app/core/work-message/src/Contract/WorkMessageContract.php +++ b/api-server/app/core/work-message/src/Contract/WorkMessageContract.php @@ -154,4 +154,22 @@ public function getWorkMessageByCorpIdRoomIdMsgTypeKeyword(int $corpId, array $r * 最后一条群信息. */ public function getWorkMessagesRangeByIdCorpIdWxRoomIdMsgTime(int $corpId, int $roomId, array $columns = ['*']): array; + + /** + * 获取最近一条seq. + * @param int $corpId + * + * @return int ... + */ + public function getWorkMessageLastSeqByCorpId(int $corpId): int; + + /** + * 设置最后一次更新的seq + * + * @param int $corpId + * @param int $seq + * + * @return mixed + */ + public function updateWorkMessageLastSeqByCorpId(int $corpId, int $seq); } diff --git a/api-server/app/core/work-message/src/Event/MessageArchiveRawEvent.php b/api-server/app/core/work-message/src/Event/MessageArchiveRawEvent.php new file mode 100644 index 00000000..e7ad91c5 --- /dev/null +++ b/api-server/app/core/work-message/src/Event/MessageArchiveRawEvent.php @@ -0,0 +1,31 @@ +message = $message; + } +} \ No newline at end of file diff --git a/api-server/app/core/work-message/src/Event/MessageReceivedRawEvent.php b/api-server/app/core/work-message/src/Event/MessageReceivedRawEvent.php new file mode 100644 index 00000000..74d99102 --- /dev/null +++ b/api-server/app/core/work-message/src/Event/MessageReceivedRawEvent.php @@ -0,0 +1,31 @@ +corpId = $corpId; + $this->messages = $messages; + } +} \ No newline at end of file diff --git a/api-server/app/core/work-message/src/Fetcher/MessageDataFetcher.php b/api-server/app/core/work-message/src/Fetcher/MessageDataFetcher.php new file mode 100644 index 00000000..3bb3757a --- /dev/null +++ b/api-server/app/core/work-message/src/Fetcher/MessageDataFetcher.php @@ -0,0 +1,135 @@ +init((int)$corpId); + } + } + + public static function get(int $id): MessageDataFetcher + { + if (isset(static::$dataFetchers[$id]) && static::$dataFetchers[$id] instanceof MessageDataFetcher) { + return static::$dataFetchers[$id]; + } + + return static::$dataFetchers[$id] = new static($id); + } + + public function getDataSource(): array + { + $dataSources = $this->messageConfigService->getWorkMessageConfigsByDoneStatus(['corp_id']); + if (empty($dataSources)) { + return []; + } + + return array_column($dataSources, 'corpId'); + } + + public function pull(int $limit = self::MESSAGE_LIMIT): array + { + $messages = $this->sdk->getDecryptChatData($this->getLastSeq(), $limit); + + if (empty($messages)) { + return $messages; + } + + $maxSeq = $this->getMaxSeq($messages); + $this->setLastSeq($maxSeq); + return $messages; + } + + public function syncData(array $data) + { + if (!empty($data)) { + $this->messageReceivedRaw->handle($this->corpId, $data); + } + } + + private function init(int $corpId) + { + $this->corpId = $corpId; + $this->sdk = $this->messageArchiveFactory->get($corpId); + $this->workMessageService = make(WorkMessageContract::class, [$corpId]); + } + + private function setLastSeq(int $seq) + { + $this->workMessageService->updateWorkMessageLastSeqByCorpId($this->corpId, $seq); + return $this; + } + + private function getLastSeq() + { + return $this->workMessageService->getWorkMessageLastSeqByCorpId($this->corpId); + } + + private function getMaxSeq(array $data): int + { + return (int) max(array_column($data, 'seq')); + } +} \ No newline at end of file diff --git a/api-server/app/core/work-message/src/Listener/MessageArchiveRawListener.php b/api-server/app/core/work-message/src/Listener/MessageArchiveRawListener.php new file mode 100644 index 00000000..f829841d --- /dev/null +++ b/api-server/app/core/work-message/src/Listener/MessageArchiveRawListener.php @@ -0,0 +1,61 @@ +message; + $corpService = make(CorpContract::class); + $corp = $corpService->getCorpsByWxCorpId($message['ToUserName'], ['id']); + + if (empty($corp)) { + return; + } + + $messageDataFetcher = MessageDataFetcher::get((int)$corp['id']); + $data = $messageDataFetcher->pull(200); + + if (!empty($data)) { + $messageDataFetcher->syncData($data); + } + } +} \ No newline at end of file diff --git a/api-server/app/core/work-message/src/Listener/MessageReceivedRawListener.php b/api-server/app/core/work-message/src/Listener/MessageReceivedRawListener.php new file mode 100644 index 00000000..bd853827 --- /dev/null +++ b/api-server/app/core/work-message/src/Listener/MessageReceivedRawListener.php @@ -0,0 +1,50 @@ +corpId; + $messages = $event->messages; + $messageStoreLogic = $this->container->get(StoreLogic::class); + $messageStoreLogic->handle($corpId, $messages); + } +} \ No newline at end of file diff --git a/api-server/app/core/work-message/src/Logic/Store.php b/api-server/app/core/work-message/src/Logic/StoreLogic.php similarity index 75% rename from api-server/app/core/work-message/src/Logic/Store.php rename to api-server/app/core/work-message/src/Logic/StoreLogic.php index 11ab9b60..9f94b114 100644 --- a/api-server/app/core/work-message/src/Logic/Store.php +++ b/api-server/app/core/work-message/src/Logic/StoreLogic.php @@ -14,18 +14,19 @@ use Hyperf\DbConnection\Db; use Hyperf\Di\Annotation\Inject; use Hyperf\Redis\Redis; -use League\Flysystem\Filesystem; use MoChat\App\Corp\Contract\CorpContract; +use MoChat\App\Utils\File; use MoChat\App\WorkContact\Contract\WorkContactContract; use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract; use MoChat\App\WorkMessage\Constants\MsgType; use MoChat\App\WorkMessage\Contract\WorkMessageConfigContract; use MoChat\App\WorkMessage\Contract\WorkMessageContract; use MoChat\App\WorkMessage\Contract\WorkMessageIndexContract; +use MoChat\App\WorkMessage\Queue\MessageMediaSyncQueue; use MoChat\App\WorkRoom\Contract\WorkRoomContract; use MoChat\WeWorkFinanceSDK\WxFinanceSDK; -class Store +class StoreLogic { /** * @Inject @@ -39,12 +40,6 @@ class Store */ protected $corpService; - /** - * @Inject - * @var WorkMessageConfigContract - */ - protected $msgConfigClient; - /** * @var WorkMessageContract */ @@ -75,15 +70,10 @@ class Store protected $contactService; /** - * @Inject - * @var Filesystem + * @Inject() + * @var MessageMediaSyncQueue */ - protected $fileSystem; - - /** - * @var WxFinanceSDK - */ - protected $sdk; + protected $messageMediaSyncQueue; /** * @Inject @@ -91,42 +81,17 @@ class Store */ private $logger; - public function handle(int $corpId, int $limit = 100): void + public function handle(int $corpId, array $data): void { $this->workMessageService = make(WorkMessageContract::class, [$corpId]); - ## 查询微信配置 - $corp = $this->corpService->getCorpById($corpId, ['id', 'wx_corpid']); - $corpConfig = $this->msgConfigClient->getWorkMessageConfigByCorpId($corpId, ['id', 'chat_rsa_key', 'chat_secret']); - $rsa = json_decode($corpConfig['chatRsaKey'], true); - $this->logger->info(sprintf("开始拉取会话消息,corpId: %d", (int) $corpId)); - ## 获取会话数据 - $this->sdk = WxFinanceSDK::init([ - 'corpid' => $corp['wxCorpid'], - 'secret' => $corpConfig['chatSecret'], - 'private_keys' => [ - $rsa['version'] => $rsa['privateKey'], - ], - ]); - while (true) { - $msgIndex = $this->workMessageService->getWorkMessageIndexEndSeq(); - $chatData = $this->sdk->getDecryptChatData($msgIndex, $limit); - if (empty($chatData)) { - $this->logger->info('wxMsgPull::stoneTag::会话消息为空::seq.' . $msgIndex); - break; - } - - $this->logger->info('wxMsgPull::stoneTag::会话消息拉取成功::seq.' . $msgIndex); - $this->pullUpdate($corpId, $chatData); - unset($chatData); - } + $this->pullUpdate($corpId, $data); } /** * 企业聊天信息更新. * @param $corpId ... * @param array $chatData ... - * @throws \League\Flysystem\FileExistsException */ protected function pullUpdate($corpId, array $chatData): void { @@ -188,7 +153,7 @@ protected function handleData(array $data, int $corpId): array 'tolist_id' => json_encode($tolistId), 'tolist_type' => $toListType, 'msg_type' => $allMsgType[$item['msgtype']], - 'content' => json_encode($this->contentFormat($item), JSON_UNESCAPED_UNICODE), + 'content' => json_encode($this->contentFormat($corpId, $item), JSON_UNESCAPED_UNICODE), 'msg_time' => (string) $item['msgtime'], 'wx_room_id' => $item['roomid'], 'room_id' => $roomId, @@ -318,10 +283,9 @@ protected function userIdFormat(string $wxRoomId, string $toUserId): array /** * 处理消息内容. * @param array $data 消息数组 - * @throws \League\Flysystem\FileExistsException ... * @return array ... */ - protected function contentFormat(array $data): array + protected function contentFormat(int $corpId, array $data): array { $msgType = $data['msgtype']; if ($msgType === 'docmsg') { @@ -331,23 +295,26 @@ protected function contentFormat(array $data): array } if (! isset($content['item'])) { - return $this->sdkFileIdToOss($content, $msgType); + return $this->asyncDownloadSdkFile($corpId, $data['msgid'], $msgType, $content); } - $items = array_map(function ($item) { - return $this->sdkFileIdToOss(json_decode($item['content'], true), $item['type']); + $msgId = $data['msgid']; + $items = array_map(function ($item) use ($corpId, $msgId) { + return $this->asyncDownloadSdkFile($corpId, $msgId, json_decode($item['content'], true), $item['type']); }, $content['item']); return ['item' => $items]; } /** * 文件地址处理. - * @param array $content ... - * @param string $msgType ... - * @throws \League\Flysystem\FileExistsException ... - * @return array ... + * + * @param int $corpId + * @param string $msgId + * @param string $msgType + * @param array $content + * @return array */ - protected function sdkFileIdToOss(array $content, string $msgType): array + protected function asyncDownloadSdkFile(int $corpId, string $msgId, string $msgType, array $content): array { ## 加类型 $content['type'] = $msgType; @@ -357,17 +324,12 @@ protected function sdkFileIdToOss(array $content, string $msgType): array } // 图片是jpg格式、语音是amr格式、视频是mp4格式、文件格式类型包括在消息体内,表情分为动图与静态图,在消息体内定义 - $file = false; switch ($msgType) { case 'image': $ext = 'jpg'; break; case 'voice': $ext = 'amr'; - ## 转mp3 - $amrFile = $this->sdk->getMediaData($content['sdkfileid'], $ext); - $file = $this->ffmpegToMp3($amrFile); - file_exists($amrFile->getRealPath()) && unlink($amrFile->getRealPath()); break; case 'video': $ext = 'mp4'; @@ -381,36 +343,11 @@ protected function sdkFileIdToOss(array $content, string $msgType): array default: $ext = ''; } - $file || $file = $this->sdk->getMediaData($content['sdkfileid'], $ext); - $content['ossPath'] = date('Y/m/d/His/') . random_int(0, 100) . '/' . $file->getFilename(); -// $this->fileSystem->writeStream($content['ossPath'], fopen($file->getRealPath(), 'rb')); - file_upload_queue([ - [$file->getRealPath(), $content['ossPath'], 1], - ]); -// unlink($file->getRealPath()); - return $content; - } + $content['path'] = File::generateFullFilename($ext); + $this->messageMediaSyncQueue->handle($corpId, $msgId, $content['sdkfileid'], $content['path'], $ext); - /** - * 音频转MP3. - * @param \SplFileInfo $file ... - * @return \SplFileInfo ... - */ - protected function ffmpegToMp3(\SplFileInfo $file): \SplFileInfo - { - try { - ## 转mp3 - $ffmpeg = \FFMpeg\FFMpeg::create(); - $audio = $ffmpeg->open($file->getRealPath()); - - $format = new \FFMpeg\Format\Audio\Mp3(); - $mp3Path = $file->getPath() . '/' . md5((string) time()) . '.mp3'; - $audio->save($format, $mp3Path); - return new \SplFileInfo($mp3Path); - } catch (\Exception $e) { - return $file; - } + return $content; } /** diff --git a/api-server/app/core/work-message/src/Process/MessageMediaConsumerProcess.php b/api-server/app/core/work-message/src/Process/MessageMediaConsumerProcess.php new file mode 100644 index 00000000..b97a1ce1 --- /dev/null +++ b/api-server/app/core/work-message/src/Process/MessageMediaConsumerProcess.php @@ -0,0 +1,25 @@ +get($corpId); + $file = $messageArchive->getMediaData($sdkFileId, $extension); + + if ($extension === 'amr') { + $file = $this->amrToMp3($file); + } + + $filesystem = make(Filesystem::class); + $filesystem->writeStream($path, fopen($file->getRealPath(), 'rb')); + + $this->updateMediaSyncStatus($corpId, $msgId); + } catch (\Throwable $e) { + + } finally { + isset($file) && file_exists($file->getRealPath()) && unlink($file->getRealPath()); + } + } + + /** + * 音频转MP3. + * @param \SplFileInfo $file ... + * @return \SplFileInfo ... + */ + protected function amrToMp3(\SplFileInfo $file): \SplFileInfo + { + try { + ## 转mp3 + $ffmpeg = \FFMpeg\FFMpeg::create(); + $audio = $ffmpeg->open($file->getRealPath()); + + $format = new \FFMpeg\Format\Audio\Mp3(); + $mp3Path = $file->getPath() . '/' . strval(microtime(true) * 10000) . uniqid() . '.mp3'; + $audio->save($format, $mp3Path); + return new \SplFileInfo($mp3Path); + } catch (\Exception $e) { + return $file; + } finally { + isset($mp3Path) && file_exists($mp3Path) && file_exists($file->getRealPath()) && unlink($file->getRealPath()); + } + } + + protected function updateMediaSyncStatus(int $corpId, string $msgId) + { + // TODO 更新媒体文件同步状态 + } +} \ No newline at end of file diff --git a/api-server/app/core/work-message/src/Queue/MessageReceivedRawQueue.php b/api-server/app/core/work-message/src/Queue/MessageReceivedRawQueue.php new file mode 100644 index 00000000..07db3217 --- /dev/null +++ b/api-server/app/core/work-message/src/Queue/MessageReceivedRawQueue.php @@ -0,0 +1,30 @@ +dispatch(new MessageReceivedRawEvent($corpId, $messages)); + } +} \ No newline at end of file diff --git a/api-server/app/core/work-message/src/QueueService/StoreApply.php b/api-server/app/core/work-message/src/QueueService/StoreApply.php deleted file mode 100644 index 820e73d2..00000000 --- a/api-server/app/core/work-message/src/QueueService/StoreApply.php +++ /dev/null @@ -1,26 +0,0 @@ -handle($corpId, 50); - } -} diff --git a/api-server/app/core/work-message/src/Service/WorkMessageService.php b/api-server/app/core/work-message/src/Service/WorkMessageService.php index 5dabd150..6b64169a 100644 --- a/api-server/app/core/work-message/src/Service/WorkMessageService.php +++ b/api-server/app/core/work-message/src/Service/WorkMessageService.php @@ -12,10 +12,12 @@ use Hyperf\Database\Query\Builder; use Hyperf\DbConnection\Db; +use Hyperf\Di\Annotation\Inject; use Hyperf\Utils\Str; use MoChat\App\WorkMessage\Contract\WorkMessageContract; use MoChat\App\WorkMessage\Model\WorkMessage; use MoChat\Framework\Service\AbstractService; +use Psr\SimpleCache\CacheInterface; class WorkMessageService extends AbstractService implements WorkMessageContract { @@ -29,6 +31,12 @@ class WorkMessageService extends AbstractService implements WorkMessageContract */ protected $query; + /** + * @Inject() + * @var CacheInterface + */ + protected $cache; + /** * {@inheritdoc} */ @@ -365,4 +373,31 @@ protected function toCamel(array $data): array } return $newData; } + + /** + * 获取最近一条seq. + * @param int $corpId + * + * @return int ... + */ + public function getWorkMessageLastSeqByCorpId(int $corpId): int + { + if ($seq = $this->cache->get(sprintf("mochat:messageLastSeq:%d", $corpId))) { + return (int) $seq; + } + return (int) $this->query->where('corp_id', $corpId)->orderBy('msg_time', 'desc')->limit(1)->value('seq'); + } + + /** + * 设置最后一次更新的seq + * + * @param int $corpId + * @param int $seq + * + * @return mixed + */ + public function updateWorkMessageLastSeqByCorpId(int $corpId, int $seq) + { + return $this->cache->set(sprintf("mochat:messageLastSeq:%d", $corpId), $seq, -1); + } } diff --git a/api-server/app/core/work-message/src/Task/MessageSyncDataTask.php b/api-server/app/core/work-message/src/Task/MessageSyncDataTask.php new file mode 100644 index 00000000..3ac03feb --- /dev/null +++ b/api-server/app/core/work-message/src/Task/MessageSyncDataTask.php @@ -0,0 +1,31 @@ +corConfigClient->getWorkMessageConfigsByDoneStatus(['id', 'corp_id']); - $this->logger->info('会话内容存档' . date('Y-m-d H:i:s', time())); - foreach ($corpConfig as $corp) { - $this->storeApply->handle($corp['corpId']); - } - } -} diff --git a/api-server/app/core/work-message/src/Utils/MessageArchiveFactory.php b/api-server/app/core/work-message/src/Utils/MessageArchiveFactory.php new file mode 100644 index 00000000..57c7f47b --- /dev/null +++ b/api-server/app/core/work-message/src/Utils/MessageArchiveFactory.php @@ -0,0 +1,65 @@ +getCorpInfo($corpId); + $rsa = json_decode($corp['config']['chatRsaKey'], true); + return WxFinanceSDK::init([ + 'corpid' => $corp['wxCorpid'], + 'secret' => $corp['config']['chatSecret'], + 'private_keys' => [ + $rsa['version'] => $rsa['privateKey'], + ], + ]); + } + + public function get(int $corpId): WxFinanceSDK + { + if (isset($this->messageArchives[$corpId]) && $this->messageArchives[$corpId] instanceof WxFinanceSDK) { + return $this->messageArchives[$corpId]; + } + + return $this->messageArchives[$corpId] = $this->make($corpId); + } + + private function getCorpInfo(int $corpId): array + { + $corpInfo = $this->corpService->getCorpById($corpId, ['id', 'wx_corpid']); + $corpInfo['config'] = $this->messageConfigService->getWorkMessageConfigByCorpId($corpId, ['id', 'chat_rsa_key', 'chat_secret']); + return $corpInfo; + } +} \ No newline at end of file diff --git a/api-server/app/utils/src/File.php b/api-server/app/utils/src/File.php index ce89cce4..cede7492 100644 --- a/api-server/app/utils/src/File.php +++ b/api-server/app/utils/src/File.php @@ -69,6 +69,25 @@ public static function download(string $url, string $localPath) return realpath(rtrim($root, '/') . '/' . $localPath); } + /** + * 生成完整的文件名 + * + * @param string $extension + * @param string $path + * + * @return string + */ + public static function generateFullFilename(string $extension, string $path = '') + { + if (empty($path)) { + $path = date('Y/md/Hi'); + } + + $filename = strval(microtime(true) * 10000) . uniqid() . '.' . $extension; + $pathFileName = $path . '/' . $filename; + return ltrim($pathFileName, '/'); + } + protected static function logger(): \Psr\Log\LoggerInterface { $loggerFactory = \Hyperf\Utils\ApplicationContext::getContainer()->get(\Hyperf\Logger\LoggerFactory::class); diff --git a/api-server/composer.json b/api-server/composer.json index 86cd8005..145d83b2 100755 --- a/api-server/composer.json +++ b/api-server/composer.json @@ -109,7 +109,8 @@ "MoChat\\App\\WorkDepartment\\": "app/core/work-department/src/", "MoChat\\App\\WorkEmployee\\": "app/core/work-employee/src/", "MoChat\\App\\WorkMessage\\": "app/core/work-message/src/", - "MoChat\\App\\WorkRoom\\": "app/core/work-room/src/" + "MoChat\\App\\WorkRoom\\": "app/core/work-room/src/", + "MoChat\\App\\SyncData\\": "app/core/sync-data/src/" }, "files": [ "app/utils/src/Functions.php" diff --git a/api-server/config/autoload/async_queue.php b/api-server/config/autoload/async_queue.php index 29f66ea4..c3030dca 100755 --- a/api-server/config/autoload/async_queue.php +++ b/api-server/config/autoload/async_queue.php @@ -100,4 +100,15 @@ 'limit' => 10, ], ], + 'message_media' => [ + 'driver' => \Hyperf\AsyncQueue\Driver\RedisDriver::class, + 'channel' => 'message_media.queue', + 'timeout' => 10, + 'retry_seconds' => 5, + 'handle_timeout' => 300, + 'processes' => 1, + 'concurrent' => [ + 'limit' => 50, + ], + ], ]; From d8d7cc2c2af6cfe2d3217f51f47fa5d3a16666c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=96=B0=E6=89=8D?= Date: Tue, 31 Aug 2021 11:19:45 +0800 Subject: [PATCH 3/7] =?UTF-8?q?[Bug=E4=BF=AE=E5=A4=8D](master):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BE=A4=E8=A3=82=E5=8F=98=E7=BE=A4=E6=AC=A2?= =?UTF-8?q?=E8=BF=8E=E8=AF=AD=E9=93=BE=E6=8E=A5=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api-server/plugin/mochat/room-fission/src/Logic/StoreLogic.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api-server/plugin/mochat/room-fission/src/Logic/StoreLogic.php b/api-server/plugin/mochat/room-fission/src/Logic/StoreLogic.php index c1cffba4..5e029ad2 100644 --- a/api-server/plugin/mochat/room-fission/src/Logic/StoreLogic.php +++ b/api-server/plugin/mochat/room-fission/src/Logic/StoreLogic.php @@ -229,7 +229,7 @@ private function createRoomFission(array $params): int */ private function handleWelcome(int $corpId, array $welcome, string $pic_url): string { - $url = Url::getAuthRedirectUrl(3, $corpId); + $url = Url::getAuthRedirectUrl(8, $corpId, ['parent_union_id' => '', 'wx_user_id' => '']); $easyWeChatParams['text']['content'] = $welcome['text']; $easyWeChatParams['link'] = ['title' => $welcome['link_title'], 'picurl' => $pic_url, 'desc' => $welcome['link_desc'], 'url' => $url]; ##EasyWeChat添加入群欢迎语素材 From 83e254a87ac6ba6e5f597694620bf46b864c907c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=96=B0=E6=89=8D?= Date: Tue, 31 Aug 2021 11:20:09 +0800 Subject: [PATCH 4/7] =?UTF-8?q?[Bug=E4=BF=AE=E5=A4=8D](master):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=BB=E5=8A=A1=E5=AE=9D=E6=AC=A2=E8=BF=8E?= =?UTF-8?q?=E8=AF=AD=E9=93=BE=E6=8E=A5=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mochat/work-fission/src/Action/Dashboard/Store.php | 1 - .../mochat/work-fission/src/Logic/ContactCallBackLogic.php | 2 +- .../plugin/mochat/work-fission/src/Logic/StoreLogic.php | 5 +---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/api-server/plugin/mochat/work-fission/src/Action/Dashboard/Store.php b/api-server/plugin/mochat/work-fission/src/Action/Dashboard/Store.php index 00e3305a..eae3f16d 100644 --- a/api-server/plugin/mochat/work-fission/src/Action/Dashboard/Store.php +++ b/api-server/plugin/mochat/work-fission/src/Action/Dashboard/Store.php @@ -46,7 +46,6 @@ class Store extends AbstractAction * }) * @RequestMapping(path="/dashboard/workFission/store", methods="post") * @throws \JsonException - * @throws \League\Flysystem\FileExistsException * @return array 返回数组 */ public function handle(): array diff --git a/api-server/plugin/mochat/work-fission/src/Logic/ContactCallBackLogic.php b/api-server/plugin/mochat/work-fission/src/Logic/ContactCallBackLogic.php index 99cdd362..0f79ac08 100644 --- a/api-server/plugin/mochat/work-fission/src/Logic/ContactCallBackLogic.php +++ b/api-server/plugin/mochat/work-fission/src/Logic/ContactCallBackLogic.php @@ -102,7 +102,7 @@ public function getFission(int $id): array $data['content']['medium']['mediumContent']['title'] = $welcome['linkTitle']; $data['content']['medium']['mediumContent']['description'] = $welcome['linkDesc']; $data['content']['medium']['mediumContent']['imagePath'] = $welcome['linkCoverUrl']; - $data['content']['medium']['mediumContent']['imageLink'] = Url::getOperationBaseUrl() . '/auth/workFission?id=' . $contact['fissionId']; + $data['content']['medium']['mediumContent']['imageLink'] = Url::getAuthRedirectUrl(7, (int) $contact['fissionId']); return $data; } } diff --git a/api-server/plugin/mochat/work-fission/src/Logic/StoreLogic.php b/api-server/plugin/mochat/work-fission/src/Logic/StoreLogic.php index 1f3b2756..60823dad 100644 --- a/api-server/plugin/mochat/work-fission/src/Logic/StoreLogic.php +++ b/api-server/plugin/mochat/work-fission/src/Logic/StoreLogic.php @@ -99,8 +99,7 @@ public function __construct( /** * @param array $user 登录用户信息 * @param array $params 请求参数 - * @throws \JsonException - * @throws FileExistsException + * * @return array 响应数组 */ public function handle(array $user, array $params): array @@ -117,7 +116,6 @@ public function handle(array $user, array $params): array * 处理参数. * @param array $user 用户信息 * @param array $params 接受参数 - * @throws FileExistsException|\JsonException * @return array 响应数组 */ private function handleParam(array $user, array $params): array @@ -269,7 +267,6 @@ private function createQRcode(array $user, bool $auto_pass, array $employees) /** * @param $user * @param $complex - * @throws FileExistsException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \GuzzleHttp\Exception\GuzzleException */ From 127e49b5a2176be897ba0b39172a8e4f44ea3083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=96=B0=E6=89=8D?= Date: Tue, 31 Aug 2021 12:31:23 +0800 Subject: [PATCH 5/7] =?UTF-8?q?[Bug=E4=BF=AE=E5=A4=8D](master):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BE=A4=E6=89=93=E5=8D=A1=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=AF=BC=E5=85=A5=E5=90=8D=E7=A7=B0=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dashboard/src/views/roomClockIn/show.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dashboard/src/views/roomClockIn/show.vue b/dashboard/src/views/roomClockIn/show.vue index 2de6f1d9..7e69aef0 100755 --- a/dashboard/src/views/roomClockIn/show.vue +++ b/dashboard/src/views/roomClockIn/show.vue @@ -184,7 +184,7 @@