isValid()) { return 2311; } $originalExtension = strtolower($file->getClientOriginalExtension()); //文件扩展名 if(!$originalExtension) $originalExtension = $file->guessExtension(); $realPath = $file->getRealPath(); //临时文件的绝对路径 $mimeType = $file->getClientMimeType(); // image/jpeg $fileSize = $file->getClientSize(); switch ($type) { case 1: // 图片 if (!in_array($originalExtension, ['jpg', 'png'])) { Log::logError('上传的图片类型为:', ['type' => $originalExtension, 'info' => $file->guessExtension() ], 'uploadMaterial'); return 2301; } if($fileSize > 10 * 1024 * 1024) { return 2306; } if($fileSize > 2 * 1024 * 1024) { $uploadToOss = 1; } list($width, $height, $imageType, $attr) = getimagesize($realPath); if($width * $height > 1555200) { return 2312; } break; case 2: // 语音 if (!in_array($originalExtension, ['amr'])) { return 2302; } if($fileSize > 2 * 1024 * 1024) { return 2307; } break; case 3: // 视频 if (!in_array($originalExtension, ['mp4'])) { return 2303; } # 视频文件大小限制 if($fileSize > 20 * 1024 * 1024) { return 2308; } break; case 4: # 文件大小限制20M if($fileSize > 20 * 1024 * 1024) { return 2318; } break; } // 上传文件 $filename = date('YmdHis') . '-' . uniqid() . '.' . $originalExtension; // 使用我们新建的uploads本地存储空间(目录) $result = Storage::disk('uploads')->put($filename, file_get_contents($realPath)); if(!$result) return 2304; $localFilePath = '../storage/uploads/'.$filename; if(!$uploadToOss && $type==1) { // 上传到腾讯 $fileUrl = MaterialService::uploadImg($corpid, $realPath); } else { $oss = new OssService('playlet'); $ossFile = $oss->upload($originalExtension, $localFilePath, $mimeType.'/'.date("Y-m-d",time())); $fileUrl = $ossFile['oss-request-url']; } // if($needMediaId) { // 需要获取素材mediaId // $mediaData = MaterialService::uploadMedia($corpid, $localFilePath, $type); // if(isset($mediaData['errcode']) && $mediaData['errcode']) { // EmailQueue::rPush('获取素材mediaId失败', json_encode($mediaData, JSON_UNESCAPED_UNICODE), ['xiaohua.hou@kuxuan-inc.com'], '获取素材mediaId失败'); // Log::logError('素材上传失败', $mediaData, 'UploadMaterial'); // return 2309; // } // // $mediaId = isset($mediaData['media_id']) ? $mediaData['media_id'] : ''; // $expireTime = time(); // if(!empty($mediaId)) // $expireTime = date('Y-m-d H:i:s', $mediaData['created_at'] + 86400 * 3 - 200); // } // @unlink($localFilePath); // 保存数据到素材表 $materialId = Material::insertGetId([ 'corpid' => $corpid, 'type' => $type, 'local_path' => $localFilePath, 'oss_url' => $fileUrl, 'media_id' => $mediaId, 'expire_at' => $expireTime ]); if(!$materialId) return 2310; $data = array_filter([ 'material_id' => $materialId, 'url' => $fileUrl, 'media_id' => $mediaId ]); } catch (\Exception $e) { EmailQueue::rPush('素材上传过程发生异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '素材上传过程发生异常'); Log::logError('素材上传过程发生异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage() ], 'UploadMaterial-Exception'); return 2305; } return 0; } /** * 上传朋友圈素材 * */ public static function uploadAttachment($corpid, $localFilePath, $type, $attachmentType, $retry=0) { # 获取AccessToken $accessToken = AuthorizeCorp::getAccessToken($corpid, '上传临时素材'); if(empty($accessToken)) { return false; } $requestUri = config('qyWechat.upload_attachment'); switch ($type) { case 1: // 图片 $requestUri .= $accessToken . '&media_type=image&attachment_type='.$attachmentType; break; case 2: // 普通文件 $requestUri .= $accessToken . '&media_type=file&attachment_type='.$attachmentType; break; case 3: // 视频 $requestUri .= $accessToken . '&media_type=video&attachment_type='.$attachmentType; break; } $response = HttpService::httpUpload($requestUri, $localFilePath); Log::logError('请求的URL:'.$requestUri, [ 'path' => $localFilePath, 'response' => $response, 'retry' => $retry ], 'HttpUploadAttachment'); $responseData = json_decode($response, true); $errCode = $responseData['errcode'] ?? -1; if(($response===false || $errCode != 0) && $retry<5) { // 发起重试 $retry++; Log::logInfo('上传朋友圈素材发起重试', [ 'corpid' => $corpid, 'path' => $localFilePath, 'retry' => $retry ], 'HttpUploadAttachment'); return MaterialService::uploadAttachment($corpid, $localFilePath, $type, $attachmentType, $retry); } if($response===false) { // 发起重试 return false; } return $responseData; } /** * 上传临时素材 * */ public static function uploadMedia($corpid, $localFilePath, $type, $retry=0) { # 获取AccessToken $accessToken = AuthorizeCorp::getAccessToken($corpid, '上传临时素材'); if(empty($accessToken)) { return false; } $requestUri = config('qyWechat.upload_media'); switch ($type) { case 1: // 图片 $requestUri .= $accessToken . '&type=image'; break; case 2: // 语音 $requestUri .= $accessToken . '&type=voice'; break; case 3: // 视频 $requestUri .= $accessToken . '&type=video'; break; case 4: // 文件 $requestUri .= $accessToken . '&type=file'; break; } $response = HttpService::httpUpload($requestUri, $localFilePath); Log::logError('请求的URL:'.$requestUri, [ 'corpid' => $corpid, 'path' => $localFilePath, 'response' => $response, 'retry' => $retry ], 'HttpUploadMedia'); $responseData = json_decode($response, true); $errCode = $responseData['errcode'] ?? -1; if(($response===false || $errCode != 0) && $retry<5) { // 发起重试 $retry++; Log::logInfo('上传临时素材发起重试', [ 'corpid' => $corpid, 'path' => $localFilePath, 'retry' => $retry ], 'HttpUploadMedia'); return MaterialService::uploadMedia($corpid, $localFilePath, $type, $retry); } return $responseData; } /** * 处理附件中的素材ID * */ public static function mediaIdReplace($attachments, $corpid, $prefix = 'WelcomeCodeSendTrace') { if(empty($attachments)) return []; foreach ($attachments as $key=>&$attachment) { # 处理附件信息中的素材id if(isset($attachment['image']['media_id'])) { // 非小程序类的附件 $materialId = $attachment['image']['media_id']; $mediaId = MaterialService::getMediaId($materialId, $corpid); if($mediaId===false) { Log::logInfo('【图片类】捕获到临时素材ID异常', [ 'attachment' => $attachments, 'corpid' => $corpid, 'media_id' => $materialId ], $prefix); unset($attachments[$key]); continue; } $attachment['image']['media_id'] = $mediaId; } elseif(isset($attachment['miniprogram']['pic_media_id'])) { $materialId = $attachment['miniprogram']['pic_media_id']; $mediaId = MaterialService::getMediaId($materialId, $corpid); if($mediaId===false) { Log::logInfo('【小程序】捕获到临时素材ID异常', [ 'attachment' => $attachments, 'corpid' => $corpid, 'media_id' => $materialId ], $prefix); unset($attachments[$key]); continue; } $attachment['miniprogram']['pic_media_id'] = $mediaId; } } Log::logInfo('处理附件中的素材ID:', [ 'corpid' => $corpid, 'attachments' => $attachments ], $prefix); return $attachments; } /** * 处理附件中的素材ID * */ public static function chatGroupWelcomeTemplateMediaIdReplace($attachments, $corpid, $prefix = 'WelcomeCodeSendTrace') { if(empty($attachments)) return []; foreach ($attachments as $key=>&$attachment) { # 处理附件信息中的素材id if(isset($attachments['image']['media_id'])) { // 非小程序类的附件 $materialId = $attachments['image']['media_id']; $mediaId = MaterialService::getMediaId($materialId, $corpid); if($mediaId===false) { Log::logInfo('【图片类】捕获到临时素材ID异常', [ 'attachment' => $attachments, 'corpid' => $corpid, 'media_id' => $materialId ], $prefix); unset($attachments[$key]); continue; } $attachments['image']['media_id'] = $mediaId; } elseif(isset($attachments['miniprogram']['pic_media_id'])) { $materialId = $attachments['miniprogram']['pic_media_id']; $mediaId = MaterialService::getMediaId($materialId, $corpid); if($mediaId===false) { Log::logInfo('【小程序】捕获到临时素材ID异常', [ 'attachment' => $attachments, 'corpid' => $corpid, 'media_id' => $materialId ], $prefix); unset($attachments[$key]); continue; } $attachments['miniprogram']['pic_media_id'] = $mediaId; } elseif(isset($attachments['file']['media_id'])){ $materialId = $attachments['file']['media_id']; $mediaId = MaterialService::getMediaId($materialId, $corpid, false, 4); if($mediaId===false) { Log::logInfo('【文件类】捕获到临时素材ID异常', [ 'attachment' => $attachments, 'corpid' => $corpid, 'media_id' => $materialId ], $prefix); unset($attachments[$key]); continue; } $attachments['file']['media_id'] = $mediaId; } elseif (isset($attachments['video']['media_id'])) { // 非小程序类的附件 $materialId = $attachments['video']['media_id']; $mediaId = MaterialService::getMediaId($materialId, $corpid, false, 3); if($mediaId===false) { Log::logInfo('【视频类】捕获到临时素材ID异常', [ 'attachment' => $attachments, 'corpid' => $corpid, 'media_id' => $materialId ], $prefix); unset($attachments[$key]); continue; } $attachments['video']['media_id'] = $mediaId; } } Log::logInfo('处理附件中的素材ID:', [ 'corpid' => $corpid, 'attachments' => $attachments ], $prefix); return $attachments; } /** * 处理附件中的雷达和推广链接信息 * @param array $attachments 附件信息 * @param string $corpid 企业id * @param string $userId 客服id * @param int $channel 渠道标识 1:朋友圈 2:群发消息 3:欢迎语 4:渠道活码 * @param int $ruleId 对应渠道的规则id。用于个人时可设置为0 * @param int $msgSendType 消息类型 0未知 1群发消息 2欢迎语 * @param string $state 授权链接中可携带的参数 * @return mixed * */ public static function radarAttachment($attachments, $corpid, $userId, $channel, $ruleId, $msgSendType=0, $isAttachment=false, $state='STATE') { try { if(empty($attachments)) return []; foreach ($attachments as $key=>&$attachment) { # 检验是否存在雷达类附件 $msgType = $attachment['msgtype'] ?? ''; if(empty($msgType)) { unset($attachments[$key]); continue; } if($msgType == 'radar') { Log::logInfo('检测到待处理的雷达附件', [ 'corpid' => $corpid, 'rule_id' => $ruleId, 'channel' => $channel, 'attachment' => $attachment ], 'radarAttachmentDealTrace'); $attachment['msgtype'] = 'link'; $radarId = $attachment['radar']['radar_id'] ?? 0; # 拼装雷达消息内容 $linkData = RadarService::getLinkMsgOfRadar($radarId, $corpid, $userId, $channel, $ruleId, $state); Log::logInfo('雷达消息转链接消息的结果为:', [ 'corpid' => $corpid, 'rule_id' => $ruleId, 'channel' => $channel, 'link_data' => $linkData ], 'radarAttachmentDealTrace'); if(empty($linkData)) { Log::logInfo('未获取到雷达信息', [ 'attachment' => $attachments, 'corpid' => $corpid ], 'RadarAttachmentDealTrace'); unset($attachments[$key]); continue; } if($isAttachment) { $linkData['media_id'] = $attachment['radar']['media_id']; } $attachment['link'] = $linkData; unset($attachment['radar']); Log::logInfo('最终替换完成的雷达转链接消息体为:', [ 'corpid' => $corpid, 'rule_id' => $ruleId, 'channel' => $channel, 'attachment' => $attachment ], 'radarAttachmentDealTrace'); } elseif ($msgType == 'promote') { Log::logInfo('检测到待处理的推广链接', [ 'corpid' => $corpid, 'rule_id' => $ruleId, 'channel' => $channel, 'attachment' => $attachment ], 'PromoteAttachmentDealTrace'); $attachment['msgtype'] = 'link'; # 获取推广链接 $jumpUrl = $attachment['promote']['jump_url'] ?? ''; if(empty($jumpUrl)) { Log::logInfo('未查询到推广链接信息', [ 'attachment' => $attachments, 'corpid' => $corpid ], 'PromoteAttachmentDealTrace'); unset($attachments[$key]); continue; } # 判断是否是剧集组推广链接。通过剧集组id、发送类型send_type确认 $playletGroupId = getUrlParams($jumpUrl, 'group_id'); $sendType = getUrlParams($jumpUrl, 'send_type'); Log::logInfo('剧集组id相关信息', [ 'group_id' => $playletGroupId, 'send_type' => $sendType, 'msg_send_type' => $msgSendType ], 'PromoteAttachmentDealTrace'); # 如果有就获取对应的剧集推广链接进行存储 if($playletGroupId && $sendType && $sendType==6 && $msgSendType) { // 剧集组对应剧生成推广链接 $jumpUrl .='&sender='.$userId.'&rule_id='.$ruleId.'&msg_type='.$msgSendType; Log::logInfo('跳转链接更新为:', [ 'jump_url' => $jumpUrl, ], 'PromoteAttachmentDealTrace'); $hasRecord = false; if($msgSendType == 2) { // 欢迎语消息类型,优先判断是否已有短剧记录信息 $hasRecord = MassMsgLinkRecord::where('corpid', $corpid)->where('sender', $userId) ->where('rule_id', $ruleId)->where('msg_type', $msgSendType) ->where('enable', 1)->exists(); } if(!$hasRecord) { # 查询剧集组对应创建者信息 $groupInfo = PlatformPlayletGroup::where('id', $playletGroupId)->where('enable', 1)->first(); # 查询剧集组对应的剧信息 $playletList = PlatformPlayletGroupDetail::where('group_id', $playletGroupId)->where('enable', 1)->get(); $pidList = []; foreach ($playletList as $playlet) { $errno = 0; $playletData = PlatformService::createLink( $playlet, $playlet['platform_id'], $playlet['account_id'], $groupInfo->sys_group_id, $groupInfo->admin_id, $errno ); if(empty($playletData) || $errno) { Log::logInfo('生成链接失败:', [ 'jump_url' => $jumpUrl, 'errno' => $errno, 'playlet_data' => $playletData, 'group_id' => $playletGroupId ], 'PromoteAttachmentDealTrace'); EmailQueue::rPush('群发消息生成推广链接失败', $playletGroupId.'-'.$errno.'-'.$ruleId, ['xiaohua.hou@kuxuan-inc.com'], '群发消息生成推广链接失败'); continue; } array_push($pidList, $playletData['pid']); # 记录对应推广信息 $recordResult = MassMsgLinkRecord::saveRecord( $corpid, $userId, $ruleId, $msgSendType, $playletGroupId, $playlet['playlet_id'], $playlet['platform_id'], $playlet['link_type'], $playlet['sort_order'], $playletData['path'], $playletData['desc'], $playletData['cover'], $playletData['pid'] ); if(!$recordResult) { Log::logError('剧集组推广信息记录失败:', [ 'corpid' => $corpid, 'rule_id' => $ruleId, 'user_id' => $userId, 'playlet' => $playlet, 'link_data' => $playletData ], 'PlayletLinkRecordSave'); } } if($msgSendType == 1) { // 更新群发消息的pid字段 MassMsg::where('id', $ruleId)->update(['is_draw' => 1, 'pids' => json_encode(array_filter($pidList))]); } } } # 处理推广链接 $link = MassMsgService::getPromoteLink($corpid, $jumpUrl); $linkData = $attachment['promote']; $linkData['url'] = $link; $attachment['link'] = $linkData; unset($attachment['promote']); Log::logInfo('最终替换完成的推广链接消息体为:', [ 'corpid' => $corpid, 'rule_id' => $ruleId, 'channel' => $channel, 'attachment' => $attachment ], 'PromoteAttachmentDealTrace'); } } } catch (\Exception $e) { Log::logError('处理附件中的雷达信息', [ 'line' => $e->getLine(), 'msg' => $e->getMessage(), 'attachments' => $attachments, 'is_attachment' => $isAttachment ], 'RadarAttachmentDeal-Exception'); return []; } return $attachments; } public static function promoteAttachments($corpid, $attachments, $prefix = 'addWelcomeTemplate') { if (empty($attachments)) return []; try{ if(isset($attachments['promote'])) { $attachment = $attachments['promote']; Log::logInfo('检测到待处理的推广链接', [ 'attachment' => $attachment ], $prefix.'Trace'); # 获取推广链接 $jumpUrl = $attachment['url'] ?? ''; if (empty($jumpUrl)) { Log::logInfo('未查询到推广链接信息', [ 'attachment' => $attachments, ], $prefix.'Trace'); unset($attachments['promote']); } # 处理推广链接 $link = MassMsgService::getPromoteLink($corpid, $jumpUrl); $attachment['url'] = $link; $attachments['link'] = $attachment; unset($attachments['promote']); Log::logInfo('最终替换完成的推广链接消息体为:', [ 'corpid' => $corpid, 'attachment' => $attachments ], $prefix.'Trace'); } } catch (\Exception $exception) { Log::logError('处理附件中的雷达信息', [ 'line' => $exception->getLine(), 'msg' => $exception->getMessage(), 'attachments' => $attachments, ], $prefix.'-Exception'); return []; } return $attachments; } /** * 处理附件中的素材ID(新) * */ public static function mediaIdDeal($attachments, $corpid) { if(empty($attachments)) return []; foreach ($attachments as $key=>&$attachment) { $msgType = $attachment['msgtype'] ?? ''; switch($msgType) { case 'image': $type = 1; $attachmentType = 1; $materialId = $attachment['image']['media_id']; break; case 'video': $type = 3; $attachmentType = 1; $materialId = $attachment['video']['media_id']; break; case 'link': $type = 1; $attachmentType = 1; $materialId = $attachment['link']['media_id']; break; case 'radar': $type = 1; $attachmentType = 1; $radarId = $attachment['radar']['radar_id']; $materialId = RadarCustomerDetail::where('id', $radarId)->where('enable', 1)->value('cover_id'); break; default: $materialId = ''; break; } if(empty($materialId)) { Log::logError('捕获到非预期的附件类型', [ 'corpid' => $corpid, 'attachment' => $attachment ], 'mediaIdDeal'); unset($attachments[$key]); continue; } Log::logInfo('附件id获取', [ 'material_id' => $materialId, 'corpid' => $corpid, 'type' => $type, 'attachment_type' => $attachmentType ], 'MediaIdDeal'); $mediaId = MaterialService::getMediaId($materialId, $corpid, true, $type, $attachmentType); if($mediaId===false) { EmailQueue::rPush('获取附件mediaId失败', json_encode($attachment, JSON_UNESCAPED_UNICODE), ['xiaohua.hou@kuxuan-inc.com'], '获取附件mediaId失败'); Log::logInfo('获取附件素材ID发生异常', [ 'attachment' => $attachment, 'corpid' => $corpid, 'type' => $type, 'attachment_type' => $attachmentType ], 'MediaIdDeal'); unset($attachments[$key]); continue; } $attachment[$msgType]['media_id'] = $mediaId; } return $attachments; } /** * 下载素材并获取临时素材ID * */ public static function getMediaId($materialId, $corpid, $forceRefresh=false, $type=1, $attachmentType=false) { try { $materialInfo = Material::select(['oss_url', 'media_id', 'expire_at', 'local_path', 'corpid']) ->where('id', $materialId)->where('type', $type)->first(); Log::logInfo('数据库中获取的附件信息', [ 'material_id' => $materialId, 'corpid' => $corpid, 'type' => $type, 'attachment_type' => $attachmentType, 'info' => $materialInfo->toArray() ], 'MediaIdDeal'); if(empty($materialInfo)) { return false; } if($materialInfo->corpid != $corpid) { $materialModel = new Material; $materialModel->corpid = $corpid; $materialModel->local_path = $materialInfo->local_path; $materialModel->type = $type; $materialModel->oss_url = $materialInfo->oss_url; $materialModel->media_id = null; $materialModel->expire_at = date('Y-m-d H:i:s'); $materialModel->save(); $materialId = $materialModel->id; $materialInfo = $materialModel; $forceRefresh = true; } Log::logInfo('检查下附件过期没', [ 'expire_at' => $materialInfo->expire_at, 'now' => date('Y-m-d H:i:s') ], 'MediaIdDeal'); if($materialInfo->expire_at <= date('Y-m-d H:i:s') || $forceRefresh === true) { // 临时素材已过期或要求强制刷新 Log::logInfo('数据库中附件信息过期了', [ 'material_id' => $materialId, 'corpid' => $corpid, 'type' => $type, 'attachment_type' => $attachmentType, ], 'MediaIdDeal'); $localFilePath = $materialInfo->local_path; if(!$localFilePath || !file_exists(public_path($localFilePath))) { $localFilePath = MaterialService::mediaDownload($materialInfo->oss_url, $type, $corpid); if($localFilePath === false) { Log::logInfo('数据库中附件本地path异常', [ 'material_id' => $materialId, 'corpid' => $corpid, 'type' => $type, 'attachment_type' => $attachmentType, ], 'MediaIdDeal'); return false; } } Log::logInfo('数据库中附件本地path', [ 'material_id' => $materialId, 'corpid' => $corpid, 'type' => $type, 'attachment_type' => $attachmentType, ], 'MediaIdDeal'); if($attachmentType === false) { $mediaData = MaterialService::uploadMedia($corpid, $localFilePath, $type); } else { $mediaData = MaterialService::uploadAttachment($corpid, $localFilePath, $type, $attachmentType); } Log::logInfo('新获取到的mediaData', [ 'material_id' => $materialId, 'corpid' => $corpid, 'type' => $type, 'attachment_type' => $attachmentType, 'mediaData' => $mediaData ], 'MediaIdDeal'); // @unlink($localFilePath); if((isset($mediaData['errcode']) && $mediaData['errcode']) || $mediaData === false) { EmailQueue::rPush('获取素材mediaId失败', json_encode($mediaData, JSON_UNESCAPED_UNICODE), ['xiaohua.hou@kuxuan-inc.com'], '获取素材mediaId失败'); Log::logError('素材ID获取失败', [ 'response' => $mediaData, 'material_id' => $materialId, 'corpid' => $corpid, ], 'MediaIdReplace'); return false; } $mediaId = $mediaData['media_id']; $expireTime = date('Y-m-d H:i:s', $mediaData['created_at'] + 86400 * 3 - 200); $result = Material::where('id', $materialId)->update([ 'local_path' => $localFilePath, 'media_id'=>$mediaId, 'expire_at'=>$expireTime ]); if(!$result) { Log::logError('素材ID更新失败',$materialInfo->toArray(), 'MediaIdReplace'); } } else { $mediaId = $materialInfo->media_id; } } catch (\Exception $e) { # 增加报警 EmailQueue::rPush('素材ID获取失败', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '素材ID获取失败'); Log::logError('素材ID获取失败', [ 'line' => $e->getLine(), 'msg' => $e->getMessage() ], 'MediaIdReplace'); return false; } return $mediaId; } /** * 下载多媒体资源到本地 * */ public static function mediaDownload($url, $type, $corpid) { $url = trim($url, "'"); $url = trim($url, '"'); if(empty($url)) return ''; switch($type) { case 1: $fileType = self::getImgType($url); break; case 3: $fileType = 'mp4'; break; default: $fileType = 'jpg'; } if($fileType === false) { Log::logError('图片后缀获取异常', [ 'url' => $url, 'type' => $type, 'corpid' => $corpid ], 'MediaDownload'); return false; } $save_dir = public_path('../storage/uploads/'); // $save_dir = '/mnt/playlet/storage/uploads/'; $fileName = md5($corpid.time().rand(100000,999999)).'.'.$fileType; try { //创建保存目录 if(!file_exists($save_dir)) { if(!mkdir($save_dir, 0777, true)) { EmailQueue::rPush('下载图片时目录创建失败', $save_dir, ['xiaohua.hou@kuxuan-inc.com'], '下载图片时目录创建失败'); Log::logError('创建目录失败,目录路径:'.$save_dir, [], 'CreateDir'); } } //获取远程文件所采用的方法 $ch = curl_init(); $timeout = 20; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $content = curl_exec($ch); curl_close($ch); $fp2 = @fopen($save_dir . $fileName, 'a'); fwrite($fp2, $content); fclose($fp2); unset($content, $url); } catch (\Exception $e) { EmailQueue::rPush('素材文件下载抛出异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '素材文件下载抛出异常'); Log::logError('素材文件下载抛出异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage(), 'path' => $save_dir ], 'CreateDir-Exception'); } return realpath($save_dir . $fileName); } /** * 获取图片类型 * */ public static function getImgType($url, $retry=0) { $suffix = ''; try { if(empty($suffix) && strstr($url, 'wx_fmt=') !== false) { // 公众号图片 $suffix = self::getUrlParam($url, 'wx_fmt'); } // Log::logInfo($url); if(empty($suffix) || $suffix=='other') { $info = getimagesize($url); $suffix = false; if($mime = $info['mime']){ $suffix = explode('/',$mime)[1]; } } if(empty($suffix)) { $suffix = pathinfo($url, PATHINFO_EXTENSION); } } catch(\Exception $e) { Log::logInfo('Error', [ 'url' => $url, 'msg' => $e->getMessage() ], 'Error'); $suffix = false; } if($suffix === false && $retry <3) { // 发起重试 $retry++; return self::getImgType($url, $retry); } return $suffix ? : false; } /** * 获取url指定参数 * */ public static function getUrlParam($url, $param){ $res = ''; $a = strpos($url,'?'); if($a!==false){ $str = substr($url,$a+1); $arr = explode('&',$str); foreach($arr as $k=>$v){ $tmp = explode('=',$v); if(!empty($tmp[0]) && !empty($tmp[1])){ $barr[$tmp[0]] = $tmp[1]; } } } if(!empty($barr[$param])){ $res = $barr[$param]; } return $res; } /** * 上传文件到oss * */ public static function uploadFileToOss($corpid, $type, $file,$isMaterial, &$data) { try{ if (empty($file) || !$file->isValid()) { return 2315; } $originalExtension = strtolower($file->getClientOriginalExtension()); //文件扩展名 if(!$originalExtension) $originalExtension = $file->guessExtension(); $realPath = $file->getRealPath(); //临时文件的绝对路径 $mimeType = $file->getClientMimeType(); // image/jpeg $fileSize = $file->getClientSize(); switch ($type) { case 1: // 图片 if ($isMaterial && !in_array($originalExtension, ['jpg', 'png'])) { Log::logError('上传的图片类型为:', ['type' => $originalExtension], 'uploadFileToOss'); return 2301; } if($fileSize > 10 * 1024 * 1024) { return 2306; } list($width, $height, $imageType, $attr) = getimagesize($realPath); if($isMaterial && $width * $height > 1555200) {// 上传素材时验证图片像素,单纯上传图片取消该限制 return 2312; } break; case 2: // 语音 if (!in_array($originalExtension, ['amr'])) { return 2302; } if($fileSize > 2 * 1024 * 1024) { return 2307; } break; case 3: // 视频 if (!in_array($originalExtension, ['mp4'])) { return 2303; } # 视频文件大小限制 if($fileSize > 20 * 1024 * 1024) { return 2308; } break; case 4: if (!in_array($originalExtension, ['pdf'])) { return 2313; } # 文件大小限制 if($fileSize > 20 * 1024 * 1024) { return 2316; } break; } // 上传文件 $filename = date('YmdHis') . '-' . uniqid() . '.' . $originalExtension; // 使用我们新建的uploads本地存储空间(目录) $result = Storage::disk('uploads')->put($filename, file_get_contents($realPath)); if(!$result) return 2314; $oss = new OssService('playlet'); $localFilePath = '../storage/uploads/'.$filename; $ossFile = $oss->upload($originalExtension, $localFilePath, $mimeType.'/'.date("Y-m-d",time())); $fileUrl = $ossFile['oss-request-url']; $data = array_filter([ 'url' => $fileUrl, 'local_path' => $localFilePath ]); } catch (\Exception $e) { EmailQueue::rPush('文件上传过程发生异常', $e->getTraceAsString(), [ 'xiaohua.hou@kuxuan-inc.com'], '文件上传过程发生异常'); Log::logError('文件上传过程发生异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage() ], 'UploadMaterial-Exception'); return 2317; } return 0; } public static function itemUrlReplace($attachments, $itemUrl) { if(empty($attachments)) return []; if(empty($itemUrl)) return $attachments; foreach ($attachments as $key=>&$attachment) { if(isset($attachment['link']['url'])) { $attachment['link']['url'] = $itemUrl; } if(isset($attachment['link']['jump_url'])) { $attachment['link']['jump_url'] = $itemUrl; } if(isset($attachment['promote']['jump_url'])) { $attachment['promote']['jump_url'] = $itemUrl; } if(isset($attachment['promote']['url'])) { $attachment['promote']['url'] = $itemUrl; } } return $attachments; } public static function turnToH5($attachments) { if(empty($attachments)) return []; foreach ($attachments as $key=>&$attachment) { # 图片类型media_id转换为mediaid if(isset($attachment['image']['media_id'])) { $attachment['image']['mediaid'] = $attachment['image']['media_id']; } # 图片类型 pic_url转换为 imgUrl if(isset($attachment['image']['pic_url'])) { $attachment['image']['imgUrl'] = $attachment['image']['pic_url']; } # 链接类型 picurl 转换为 imgUrl if(isset($attachment['link']['picurl'])) { $attachment['link']['imgUrl'] = $attachment['link']['picurl']; } # video类型media_id转换为mediaid if(isset($attachment['video']['media_id'])) { $attachment['video']['mediaid'] = $attachment['video']['media_id']; } # file类型media_id转换为mediaid if(isset($attachment['file']['media_id'])) { $attachment['file']['mediaid'] = $attachment['file']['media_id']; } # 小程序封面图替换 if(isset($attachment['miniprogram']['pic_url'])){ $attachment['miniprogram']['imgUrl']= $attachment['miniprogram']['pic_url']; } } return $attachments; } /** * 上传图片到企微 * */ public static function uploadImg($corpid, $filePath, $retry=0) { $accessToken = AuthorizeCorp::getAccessToken($corpid, '上传图片到企微'); if(empty($accessToken)) { return false; } $requestUri = config('qyWechat.upload_img'); $requestUri .= $accessToken; $response = HttpService::httpUpload($requestUri, $filePath); $responseData = json_decode($response, true); # 发起重试 if($response===false || $responseData['errcode'] == -1) { // 企微系统繁忙,发起重试 if($retry < 5) { Log::logInfo('企微系统繁忙,发起重试', [ 'retry' => $retry, 'response' => $responseData ], 'UploadImg'); $retry++; return MaterialService::uploadImg($filePath, $retry); } } Log::logInfo('上传图片到企微返回结果', [ 'retry' => $retry, 'corpid' => $corpid, 'response' => $responseData ], 'UploadImg'); return $responseData['url'] ?? ''; } /** * 通过图片链接上传资源到oss * */ public static function uploadFileByUrl($corpid, $imgUrl, &$ossUrl) { try{ # 下载图片 $realPath = MaterialService::mediaDownload($imgUrl, 1, $corpid); if($realPath === false) return 2319; # 上传图片 $originalExtension = MaterialService::getImgType($imgUrl); //文件扩展名 if($originalExtension === false) return 2319; $oss = new OssService('playlet'); $ossFile = $oss->upload($originalExtension, $realPath, 'image/'.date("Y-m-d",time())); # 上传成功删除本地图片 @unlink($realPath); # 返回oss链接 $ossUrl = $ossFile['oss-request-url']; } catch (\Exception $e) { EmailQueue::rPush('通过图片链接上传资源到oss流程出现异常', $e->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '创建朋友圈消息流程出现异常'); Log::logError('通过图片链接上传资源到oss流程出现异常', [ 'line' => $e->getLine(), 'msg' => $e->getMessage(), 'corpid' => $corpid, 'imgUrl' => $imgUrl ], 'uploadFileByUrl'); return 2319; } return 0; } }