info("开始执行 订阅消息推送 队列:" . json_encode($data, JSON_UNESCAPED_UNICODE)); // 获取被推送用户信息 $params = array(); $params['user_id'] = $data['sub_data']['push_user_id']; $user = User::getOne($params); if (empty($user)){ Log::getInstance()->error("订阅消息推送执行失败:未查询到被推送用户信息"); return Result::ACK; } try { // 验证发送参数 if (empty($data['sub_data']['params']['data'])){ Log::getInstance()->error("订阅消息推送执行失败:无推送数据"); $this->saveErrorPushLog($user['user_type'],$data['sub_data'],"无推送数据"); return Result::DROP; } // 处理发送参数 $send_data = array(); foreach ($data['sub_data']['params']['data'] as $key => $item){ $send_data[$key] = [ "value" => $item ]; } if (empty($send_data)){ Log::getInstance()->error("订阅消息推送执行失败:发送参数处理失败"); $this->saveErrorPushLog($user['user_type'],$data['sub_data'],"发送参数处理失败"); return Result::DROP; } Log::getInstance()->info("订阅消息推送数据记录:" . json_encode($send_data,JSON_UNESCAPED_UNICODE)); // 获取open_id $UserService = new UserService(); $open_id = $UserService->getOpenIdWithUserId($user['user_id'],$user['user_type']); if (empty($open_id)){ Log::getInstance()->error("订阅消息推送执行失败:未获取到被推送用户open_id"); $this->saveErrorPushLog($user['user_type'],$data['sub_data'],"未获取到被推送用户open_id"); // 执行发送短信步骤 $this->addSendSmsMessageQueue($data['sms_data']); return Result::ACK; } // 处理发送环境 // $miniprogram_state = "developer"; $miniprogram_state = "trial"; if (env("APP_ENV") == "prod"){ $miniprogram_state = "formal"; } $options = [ "template_id" => $data['sub_data']['wx_template_id'], "page" => $data['sub_data']['params']['page'] ?: "", "touser" => $open_id, "data" => $send_data, "miniprogram_state" => $miniprogram_state, "lang" => "zh_CN", ]; // 发起推送 $Wechat = new Wechat($user['user_type']); $result = $Wechat->sendSubscribeMessage($options); if (empty($result)){ Log::getInstance()->error("订阅消息推送执行失败:推送失败"); $this->saveErrorPushLog($user['user_type'],$data['sub_data'],"推送失败"); } if (!isset($result['errcode'])){ Log::getInstance()->error("订阅消息推送执行失败:推送失败,返回值错误" . json_encode($result,JSON_UNESCAPED_UNICODE)); $this->saveErrorPushLog($user['user_type'],$data['sub_data'],"推送失败,返回值错误"); } if ($result['errcode'] == 43101){ Log::getInstance()->error("订阅消息推送执行失败:用户拒绝接收消息"); $this->saveErrorPushLog($user['user_type'],$data['sub_data'],"用户拒绝接收消息"); // 执行发送短信步骤 $this->addSendSmsMessageQueue($data['sms_data']); return Result::ACK; } Log::getInstance()->info("订阅消息推送执行成功"); $this->saveSuccessPushLog($user['user_type'],$data['sub_data']); } catch (\Exception $e) { Log::getInstance()->error("订阅消息推送执行失败:" . $e->getMessage()); $this->saveErrorPushLog($user['user_type'],$data['sub_data'],$e->getMessage()); } return Result::ACK; } /** * 记录成功日志 * @param string|int $user_type 用户类型 * @param array $sub_data 需发送的订阅消息数据 * @return void */ private function saveSuccessPushLog(string|int $user_type,array $sub_data): void { $data = array(); $data['to_user_id'] = $sub_data['push_user_id']; $data['user_type'] = $user_type; $data['type'] = 2; $data['status'] = 1; $data['content'] = json_encode($sub_data['params'],JSON_UNESCAPED_UNICODE); $log_message_push = LogMessagePush::addLogMessagePush($data); if (empty($log_message_push)){ Log::getInstance()->error("订阅消息推送成功,增加推送日志失败:" . json_encode($data,JSON_UNESCAPED_UNICODE)); } } /** * 记录成功日志 * @param string|int $user_type 用户类型 * @param array $sub_data 需发送的订阅消息数据 * @param string $fail_reason 失败原因 * @return void */ private function saveErrorPushLog(string|int $user_type,array $sub_data,string $fail_reason): void { $data = array(); $data['to_user_id'] = $sub_data['push_user_id']; $data['user_type'] = $user_type; $data['type'] = 2; $data['status'] = 2; $data['fail_reason'] = $fail_reason ?: ""; $data['content'] = json_encode($sub_data['params'],JSON_UNESCAPED_UNICODE); $log_message_push = LogMessagePush::addLogMessagePush($data); if (empty($log_message_push)){ Log::getInstance()->error("订阅消息推送成功,增加推送日志失败:" . json_encode($data,JSON_UNESCAPED_UNICODE)); } } /** * 添加短信队列 * 接收所有异常 * 只返回true,失败情况不处理 * @param array $sms_data 短信发送参数 * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ private function addSendSmsMessageQueue(array $sms_data): void { try { if (empty($sms_data)){ // 无需发送短信 Log::getInstance()->info("无数据需添加短信推送队列"); return; } Log::getInstance()->info("添加短信推送队列"); // 增加至发送短信队列 $message = new SendSmsMessageProducer($sms_data); $producer = $this->container->get(Producer::class); $res = $producer->produce($message); if (!$res) { Log::getInstance()->error("添加短信推送队列失败" . json_encode($sms_data,JSON_UNESCAPED_UNICODE)); } } catch (\Exception $e) { Log::getInstance()->error("添加短信推送队列失败" . $e->getMessage()); } Log::getInstance()->info("添加短信推送队列成功"); } /** * 获取数据库订阅消息模版 * 接收所有异常 * 异常记录log,不进行处理 * @param string|int $user_type 用户类型 * @param string $template_title 模版名称 * @return array * @throws ClientExceptionInterface * @throws ContainerExceptionInterface * @throws DecodingExceptionInterface * @throws NotFoundExceptionInterface * @throws RedirectionExceptionInterface * @throws ServerExceptionInterface * @throws TransportExceptionInterface */ public function getSubTemplate(string|int $user_type, string $template_title): array { try { Log::getInstance()->info("获取数据库消息订阅模版"); // 获取订阅消息模版数据 $params = array(); $params['client_type'] = $user_type; // 客户端类型(1:患者端 2:医师端 3:药师端) $params['template_title'] = $template_title; $sub_template = SubTemplate::getOne($params); if (empty($sub_template)){ // 下载消息模版数据 Log::getInstance()->info("消息模版:" . $template_title . " 在数据库中为空"); $this->downSubTemplate($user_type); // 重新获取订阅消息模版 $params = array(); $params['client_type'] = $user_type; // 客户端类型(1:患者端 2:医师端 3:药师端) $params['template_title'] = $template_title; $sub_template = SubTemplate::getOne($params); } } catch (\Exception $e) { Log::getInstance()->error("获取数据库消息订阅模版失败:" . $e->getMessage()); } if (empty($sub_template)){ return []; }else{ return $sub_template->toArray(); } } /** * 下载消息订阅模版 * 接收所有异常 * 只返回true,失败情况不处理 * @param string|int $user_type * @return void * @throws ClientExceptionInterface * @throws ContainerExceptionInterface * @throws DecodingExceptionInterface * @throws NotFoundExceptionInterface * @throws RedirectionExceptionInterface * @throws ServerExceptionInterface * @throws TransportExceptionInterface */ private function downSubTemplate(string|int $user_type): void { try { Log::getInstance()->info("下载微信消息订阅模版"); $weChat = new Wechat($user_type); $result = $weChat->getTemplate(); if (empty($result)){ return; } $template = json_decode($result, true); foreach ($template['data'] as $item) { $params = array(); $params['wx_template_id'] = $item['priTmplId']; $sub_template = SubTemplate::getOne($params); if (empty($sub_template)) { // 新增模版 $data = array(); $data['client_type'] = 1; $data['wx_template_id'] = $item['priTmplId']; $data['template_title'] = $item['title']; $data['template_type'] = $item['type']; $data['template_content'] = $item['content']; $sub_template = SubTemplate::addSubTemplate($data); if (empty($sub_template)) { // 此处添加失败不做处理,记录log, Log::getInstance()->error("下载微信消息订阅模版失败:" . json_encode($data,JSON_UNESCAPED_UNICODE)); } } } } catch (\Exception $e) { Log::getInstance()->error("下载微信消息订阅模版失败:" . $e->getMessage()); } Log::getInstance()->info("下载微信消息订阅模版成功"); } }