123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- <?php
- namespace App\Services\Smm;
- use App\Services\Contracts\SmmPlatformInterface;
- use Carbon\Carbon;
- use Illuminate\Http\Request;
- use Illuminate\Support\Facades\Http;
- class YoutubeService implements SmmPlatformInterface
- {
- protected $clientId;
- protected $clientSecret;
- // 构造函数,传入配置信息
- public $configData = [];
- public function __construct($configData) {
- $this->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) {
- }
- }
|