configData = $configData; $this->clientId = env('SSM_INSTAGRAM_APP_ID'); $this->clientSecret = env('SSM_INSTAGRAM_APP_SECRET'); } /* * OAuth 2.0 授权登录 * 返回授权地址:https://example.com/fb-callback.php */ public function login() { $loginUrl = 'https://www.instagram.com/oauth/authorize' . '?' . http_build_query([ 'enable_fb_login'=>0, 'force_authentication'=>1, 'client_id' => $this->clientId, 'redirect_uri' => $this->redirectUri, 'scope' => 'instagram_business_basic,instagram_business_manage_messages,instagram_business_manage_comments,instagram_business_content_publish,instagram_business_manage_insights', 'response_type' => 'code', ]); return ['status'=>true, 'data' => ['url'=>$loginUrl]]; } /* * OAuth 2.0 授权回调 * 授权成功后,得到access_token,refresh_token等信息, 保存到数据库中 * 授权成功后,返回回调需要的数据 */ public function loginCallback(Request $request) { if (!$request->has('code')) { return ['status' => false, 'data' => '未收到授权代码']; } $code = $request->input('code'); // 1. 交换授权代码以获取短期访问令牌 $tokenResponse = Http::asForm()->post('https://api.instagram.com/oauth/access_token', [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'grant_type' => 'authorization_code', 'redirect_uri' => $this->redirectUri, 'code' => $code, ]); $tokenData = $tokenResponse->json(); if (!isset($tokenData['access_token'])) { return ['status' => false, 'data' => '错误:无法获取短期访问令牌 - ' ]; } $shortLivedToken = $tokenData['access_token']; // 2. 使用短期令牌交换长期令牌 $longLivedTokenResponse = Http::get('https://graph.instagram.com/access_token', [ 'grant_type' => 'ig_exchange_token', 'client_secret' => $this->clientSecret, 'access_token' => $shortLivedToken, ]); $longLivedTokenData = $longLivedTokenResponse->json(); if (!isset($longLivedTokenData['access_token'])) { return ['status' => false, 'data' => '错误:无法获取长期访问令牌 - ' ]; } $accessToken = $longLivedTokenData['access_token']; // 3. 获取用户信息 $userResponse = Http::get('https://graph.instagram.com/me', [ 'fields' => 'id,username', 'access_token' => $accessToken, ]); $userInfo = $userResponse->json(); if (!isset($userInfo['id']) || !isset($userInfo['username'])) { return ['status' => false, 'data' => '错误:无法获取用户信息 - ']; } $expiresInSeconds = $longLivedTokenData['expires_in']; // 当前时间 $now = Carbon::now(); $expiresAt = $now->copy()->addSeconds($expiresInSeconds); // 返回用户信息和长期访问令牌 return ['status' => true, 'data' => [ 'accessToken' => $accessToken, 'accessToken_expiresAt'=>$expiresAt, 'userName'=>$userInfo['username'],'userId'=>$userInfo['id'] ]]; } /* * 发布图片,可以发多个图片 * $imagePaths = ['/path/to/image1.jpg','/path/to/image2.jpg']; */ public function postImage($message, $imagePaths, $accessToken) { try { if (empty($imagePaths)) { return ['status' => false, 'data' => '错误:未提供图片路径']; } $igUserId = $this->configData['accountInfo']['account_id']; // If single image if (count($imagePaths) === 1) { $imagePath = $imagePaths[0]; // Create media container for single image $postData = [ 'image_url' => $imagePath, // Assuming images are publicly accessible 'caption' => $message, 'access_token' => $accessToken, ]; $containerResponse = Http::asForm()->post("https://graph.instagram.com/v21.0/{$igUserId}/media",$postData); $containerData = $containerResponse->json(); if (!isset($containerData['id'])) { return ['status' => false, 'data' => '错误:无法创建媒体容器 - ' . json_encode($containerData)]; } // Publish the container $publishResponse = Http::post("https://graph.instagram.com/v21.0/{$igUserId}/media_publish", [ 'creation_id' => $containerData['id'], 'access_token' => $accessToken, ]); $publishData = $publishResponse->json(); if (!isset($publishData['id'])) { return ['status' => false, 'data' => '错误:无法发布图片 - ' . json_encode($publishData)]; } $postIds = [$publishData['id']]; $requestContent = [$postData]; $responseContent = [$publishData]; return ['status' => true, 'data' => [ 'responseIds' => $postIds, 'requestContent' => $requestContent, 'responseContent' => $responseContent, ]]; } // For multiple images (carousel post) $children = []; $requestContent = []; $responseContent = []; foreach ($imagePaths as $imagePath) { $postData = [ 'image_url' => asset($imagePath), 'is_carousel_item' => true, 'access_token' => $accessToken, ]; $requestContent[] = [ 'url'=>"https://graph.instagram.com/v21.0/{$igUserId}/media", 'postData' => $postData, ]; $childResponse = Http::asForm()->post("https://graph.instagram.com/v21.0/{$igUserId}/media", $postData); $childData = $childResponse->json(); $responseContent[] = $childData; if (!isset($childData['id'])) { return ['status' => false, 'data' => '错误:无法创建子媒体容器 - ' . json_encode($childData)]; } $children[] = $childData['id']; } // Create carousel container $postData = [ 'media_type' => 'CAROUSEL', 'children' => implode(',', $children), 'caption' => $message, 'access_token' => $accessToken, ]; $requestContent[] = [ 'url'=>"https://graph.instagram.com/v21.0/{$igUserId}/media", 'postData' => $postData, ]; $carouselResponse = Http::asForm()->post("https://graph.instagram.com/v21.0/{$igUserId}/media",$postData ); $carouselData = $carouselResponse->json(); $responseContent[] = $carouselData; if (!isset($carouselData['id'])) { return ['status' => false, 'data' => '错误:无法创建轮播容器 - ' . json_encode($carouselData)]; } // Publish carousel $postData = [ 'creation_id' => $carouselData['id'], 'access_token' => $accessToken, ]; $requestContent[] = [ 'url'=>"https://graph.instagram.com/v21.0/{$igUserId}/media_publish", 'postData' => $postData, ]; $publishResponse = Http::post("https://graph.instagram.com/v21.0/{$igUserId}/media_publish", $postData); $publishData = $publishResponse->json(); $responseContent[] = $publishData; if (!isset($publishData['id'])) { return ['status' => false, 'data' => '错误:无法发布轮播 - ' . json_encode($publishData)]; } $postIds = [$publishData['id']]; return ['status' => true, 'data' => [ 'responseIds' => $postIds, 'requestContent' => $requestContent, 'responseContent' => $responseContent, ]]; } catch (\Exception $e) { //Log::error('Instagram postImage error: ' . $e->getMessage()); return ['status' => false, 'data' => '错误:' . $e->getMessage()]; } } /* * 发布视频,只能发一个视频 */ public function postVideo($message, $videoPath, $accessToken) { try { if (empty($videoPath)) { return ['status' => false, 'data' => '错误:未提供视频路径']; } $igUserId = $this->configData['accountInfo']['account_id']; $requestContent = []; $responseContent = []; // Create media container for video $postData = [ 'media_type' => 'REELS', 'video_url' => $videoPath, // Assuming video is publicly accessible 'caption' => $message, 'access_token' => $accessToken, ]; $requestContent[] = ['url'=>"https://graph.instagram.com/v21.0/{$igUserId}/media", 'postData' => $postData]; $containerResponse = Http::asForm()->post("https://graph.instagram.com/v21.0/{$igUserId}/media", $postData); $containerData = $containerResponse->json(); if (!isset($containerData['id'])) { return ['status' => false, 'data' => '错误:无法创建视频容器 - ' . json_encode($containerData)]; } $responseContent[] = $containerData; // Check container status (video processing may take time) $status = 'IN_PROGRESS'; $maxAttempts = 10; $attempt = 0; while ($status === 'IN_PROGRESS' && $attempt < $maxAttempts) { sleep(5); // Wait 5 seconds between checks $postData = [ 'fields' => 'status', 'access_token' => $accessToken, ]; $requestContent[] = ['url'=>"https://graph.instagram.com/{$containerData['id']}", 'postData' => $postData]; $statusResponse = Http::get("https://graph.instagram.com/{$containerData['id']}", $postData); $statusData = $statusResponse->json(); $status = $statusData['status'] ?? 'ERROR'; $attempt++; if ($status === 'ERROR') { return ['status' => false, 'data' => '错误:视频处理失败']; } $responseContent[] = $statusData; } if ($status !== 'FINISHED') { return ['status' => false, 'data' => '错误:视频处理超时']; } // Publish the video $postData = [ 'creation_id' => $containerData['id'], 'access_token' => $accessToken, ]; $requestContent[] = ['url'=>"https://graph.instagram.com/v21.0/{$igUserId}/media_publish", 'postData' => $postData]; $publishResponse = Http::post("https://graph.instagram.com/v21.0/{$igUserId}/media_publish",$postData); $publishData = $publishResponse->json(); if (!isset($publishData['id'])) { return ['status' => false, 'data' => '错误:无法发布视频 - ' . json_encode($publishData)]; } $responseContent[] = $publishData; $postIds = [$publishData['id']]; return ['status' => true, 'data' => [ 'responseIds' => $postIds, 'requestContent' => $requestContent, 'responseContent' => $responseContent, ]]; } catch (\Exception $e) { return ['status' => false, 'data' => '错误:' . $e->getMessage()]; } } public function getComments($postId) { } public function replyToComment($commentId) { } public function deleteComment($commentId) { } }