getWechatObj($channelId)->getOfficialAccount(); if ($isThumb) { $res = $officeAccount->material->uploadThumb($imgPath); } else { $res = $officeAccount->material->uploadImage($imgPath); } if (isset($res['errcode'])) { Log::error("图文上传失败:res:". json_encode($res, JSON_UNESCAPED_UNICODE) . "channel_id: {$channelId} image: {$image}"); } return $res; } catch (Exception | InvalidArgumentException $e) { Log::error("图片素材处理失败:errormsg: {$e->getMessage()} channel_id: {$channelId} image: {$imgPath}"); return ['errcode' => 201, 'errormsg' => $e->getMessage()]; } } /** * 删除微信历史消息 * @param $channelId * @param $msgId * @return array */ public function delWechatHistoryMessage($channelId,$msgId) { try { $officeAccount = $this->getWechatObj($channelId)->getOfficialAccount(); $res = $officeAccount->broadcasting->delete($msgId); Log::info('删除微信历史消息'.json_encode($res, JSON_UNESCAPED_UNICODE) . "wx_msg_id: ".$msgId); if ($res['errmsg'] != 'ok') { Log::error("删除微信历史消息失败:res:". json_encode($res, JSON_UNESCAPED_UNICODE) . "msgId: {$msgId}"); } return $res; }catch (Exception | InvalidArgumentException $e){ Log::error("删除微信历史消息失败:errormsg: {$e->getMessage()} msgId: {$msgId}"); return ['errcode' => 201, 'errormsg' => $e->getMessage()]; } } /** * 创建图文消息 * @param $adminInfo * @param $data * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string * @throws Exception * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException */ public function uploadNews($channelId, $data) { $officeAccount = $this->getWechatObj($channelId)->getOfficialAccount(); $res = $officeAccount->material->uploadArticle($data); if (isset($res['errcode'])) { Log::error("图文上传失败:res:". json_encode($res, JSON_UNESCAPED_UNICODE) . "channel_id: {$channelId} data:". json_encode($data, JSON_UNESCAPED_UNICODE)); return $res; } else { return $res; } } /** * 创建媒体库 * @param $adminId * @param $msgType * @param $msgContent * @return int|string * @throws \Exception */ public function createMedia($adminId, $msgType, $msgContent) { $media = [ 'admin_id' => $adminId, 'type' => $msgType, 'createtime' => time(), 'updatetime' => time(), ]; if (!Common::isJson($msgContent)) { throw new \Exception('图文参数不是json格式'); } //检测是否有null项 有的话清理掉 if (strrpos($msgContent, 'null') !== false) { $data = json_decode($msgContent, true); $data = array_filter($data); $msgContent = json_encode($data); } if ($msgType == 1) { //文本 $media['message_text'] = $msgContent; } elseif ($msgType == 2) { //图文 $media['message_json'] = $msgContent; } elseif ($msgType == 3) { //图片 $media['message_img'] = $msgContent; } $id = $this->getSendMessMediaModel()->allowField(true)->insertGetId($media); return $id; } /** * 消息预览接口 * @param array $channelIds 测试发送的渠道 * @param int $userId 接收用户id * @param int $msgType 1 文字 2 图文 3 图片 * @param array $message 消息结构 * @param array $others 其他参数 * @return array * @throws InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException */ public function sent(array $channelIds, int $userId, int $msgType, array $message, array $others = []) { if (!$channelIds || !is_array($channelIds)) { return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, 'channel_id参数错误'); } if (!$userId) { return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, 'user_id参数错误'); } if (!$message) { return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, '消息内容无效'); } $success = 0; try { $user = $this->getUserModel()->setConnect($userId)->where('id', $userId)->find(); if (!$user) { return LogService::toError(ErrorCode::DB_ERROR_SELECT, '无效的用户信息'); } foreach ($channelIds as $channelId) { //匹配出用户ID if (preg_match("/\d+/i", $userId, $matches)) { if (!empty($matches)) { if (empty($matches)) { //没有匹配到数字。错误 return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, '无法匹配到此用户'); } else { $userId = intval($matches[0]); } } } else { //没有匹配到数组,错误 return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, '无法匹配到此用户'); } if ($user->channel_id != $channelId) { return LogService::toError(ErrorCode::DB_ERROR_SELECT, '该渠道无法匹配到此用户'); } $officialAccount = $this->getWechatObj($channelId)->getOfficialAccount(); if (!$officialAccount) { return LogService::toError(ErrorCode::DB_ERROR_SELECT, '无效的服务号信息'); } if ($msgType == 1) { //文字消息 $content = ''; $str_list = []; foreach ($message as $item) { if (isset($item['url'])) { $str = ''; $str .= ""; $str .= $item['content']; $str .= ""; $str_list[] = $str; } else { if (isset($item['page'])){ $item['content'] = MiniProgramService::instance()->getMiniText($item['page'],$item['content'],$channelId); } $str_list[] = $item['content']; } } $content = implode("\n", $str_list); Log::info('高级群发消息content:'.$content); $res = $officialAccount->broadcasting->previewText($content, $user['openid']); if (isset($res['errcode']) && $res['errcode'] != 0) { throw new Exception("高级群发测试发送失败:" . $res['errmsg'], 201); } $success++; } elseif ($msgType == 2) { //图文消息 $newsCommentData = $newsData = $originData = []; $messageCount = count($message); foreach ($message as $k => $item) { $this->__setMiniBatch($item,$channelId); $article = [ 'title' => $item['title'], 'thumb_media_id' => '', 'digest' => '', 'auth' => '', 'show_cover' => 0, 'content' => $this->parseContentImage($channelId, $item['content']), 'source_url' => '', ]; if ($item['cover']) { $coverResult = $this->image2media($channelId, $item['cover'], 1); $article['thumb_media_id'] = $coverResult['media_id']; } else { throw new Exception("缺少封面图", 201); } //if ($messageCount > 1) { $article['digest'] = (isset($item['digest']) && !empty($item['digest'])) ? $item['digest'] : mb_substr(strip_tags($item['content']), 0, 64); //} $url = ''; if (isset($item['type'])) { $url = $this->buildUrl($channelId, $item); if (in_array($item['type'], [1, 3]) && empty($url)) { return LogService::toError(ErrorCode::DB_ERROR_SELECT, '活动状态失效,请重新配置'); } } $article['source_url'] = $url; $originData[] = $article; $articleObj = new Article($article); if ($item['need_open_comment'] == 1) { $articleObj->need_open_comment = 1; $articleObj->only_fans_can_comment = $article['only_fans_can_comment'] ?? 0; } $newsCommentData[] = $articleObj; } $mediaResult = $officialAccount->material->uploadArticle($newsCommentData); if (!empty($mediaResult['errcode']) && $mediaResult['errcode'] == 88000) { foreach ($originData as $article) { $newsData[] = new Article($article); } $mediaResult = $officialAccount->material->uploadArticle($newsData); } if (isset($mediaResult['media_id'])) { $mediaId = $mediaResult['media_id']; $res = $officialAccount->broadcasting->previewNews($mediaId, $user['openid']); if (isset($res['errcode']) && $res['errcode'] != 0) { throw new Exception("高级群发测试发送失败:" . $res['errmsg'], 201); } } else { throw new Exception("高级群发测试发送失败:" . $mediaResult['errmsg'], 201); } $success++; } elseif ($msgType == 3) { //图片消息 $imgPath = current($message); $mediaResult = $this->image2media($channelId, $imgPath['img_path']); if (isset($mediaResult['media_id'])) { $mediaId = $mediaResult['media_id']; $res = $officialAccount->broadcasting->previewImage($mediaId, $user['openid']); if (isset($res['errcode']) && $res['errcode'] != 0) { throw new Exception("高级群发测试发送失败:" . $res['errmsg'], 201); } } else { throw new Exception("高级群发测试发送失败:" . $mediaResult['errmsg'], 201); } $success++; } } } catch (Exception $e) { LogService::error("高级群发:error: {$e->getMessage()} 错误line: {$e->getLine()}"); return LogService::toError(ErrorCode::EXCEPTION, '未知错误'); } if($success>0){ return LogService::toSuccess(ErrorCode::SUCCESS, '发送完成'); }else{ return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, '发送失败'); } } /** * 处理内容中的图片 * @param $channelId * @param $content * @return mixed * @throws Exception * @throws InvalidArgumentException */ private function parseContentImage($channelId, $content) { $imgPaths = []; if (preg_match_all("/src=['|\"]([^\s]*)['|\"]/i", $content, $m)) { $imgPaths = $m[1]; } if ($imgPaths) { $mediaArr = []; foreach ($imgPaths as $k => $imgPath) { // if (is_file($imgPath) && file_exists($imgPath)) { $res = $this->image2media($channelId, $imgPath); $mediaArr[$k] = $res['url']; // } } $content = str_replace($imgPaths, $mediaArr, $content); } return $content; } /** * 返回链接地址 * @param $channelId * @param $params * @return string */ public function buildUrl($channelId, $params) { $type = $params['type']; $url = ''; switch ($type) { case 0: $url = $this->_buildBookUrl($channelId, $params); break; case 1: $url = $this->_buildActivityUrl($channelId, $params); break; case 2: $url = $this->_buildRecentUrl($channelId); break; case 3: $url = $this->_buildCampaignUrl($channelId, $params); break; default: break; } return $url; } /** * 处理小程序 */ public function __setMiniBatch(&$item,$channelId) { \app\main\service\LogService::info('图文消息-小程序1'.$item['content']); if (!isset($item['mini']) || empty($item['mini']) ){ return ''; } $miniContent = $item['mini']; foreach ($miniContent as $k =>$value){ if ($value['type'] == 3){//小程序卡片 $res = $this->image2media($channelId, $value['pic']); $value['pic'] = $res['url']; } $c = MiniProgramService::instance()->getMiniProgram($value,$channelId); if ($value['type'] == 4 && $c){//小程序码 $c = '