我尝试使用 Linkedins Rest API 上传文本、图像和链接 (https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/share-on-linkedin#create-图像共享)。但我没有成功。上传帖子返回错误:错误 :: /content/article/thumbnail :: 无效的 Urn 格式。前缀无效。瓮 urn:li:digitalmediaAsset:...
这是我的代码。有什么想法或提示吗?
// upload image $uploadUrl = 'https://api.linkedin.com/rest/assets?action=registerUpload'; $requestData = [ 'registerUploadRequest' => [ 'recipes' => ['urn:li:digitalmediaRecipe:feedshare-image'], 'owner' => 'urn:li:person:'. $this->provider->linkedin_id, ], ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $uploadUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $this->provider->social_access_token, 'Linkedin-Version: '. $this->linkedin_version, 'Content-Type: application/json', ]); $response = curl_exec($ch); // get asset id $responseArray = json_decode($response, true); $assetId = $responseArray['value']['asset']; $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 200) { // upload picture to url received in response $imagePath = rex_path::media($used_machine->pics[0]); $uploadUrl = $responseArray['value']['uploadMechanism']['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest']['uploadUrl']; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $uploadUrl); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents($imagePath)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $this->provider->social_access_token, 'Content-Type: '. mime_content_type($imagePath), ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 201) { $this->log('Image "'. $used_machine->pics[0].'" for used machine "'. trim($used_machine->manufacturer .' '. $used_machine->name) .'" uploded. Asset ID: '. $assetId); } else { // failure uploading image $this->log('Failure uploading image "'. $used_machine->pics[0].'" for used machine "'. trim($used_machine->manufacturer .' '. $used_machine->name) .'". API answer: '. $response); $return = false; } } // upload post if($assetId !== '') { $postUrl = 'https://api.linkedin.com/rest/posts'; $postData = [ 'author' => 'urn:li:person:'. $this->provider->linkedin_id, 'commentary' => $used_machine->manufacturer .' '. $used_machine->name .': '. \Sprog\Wildcard::get('d2u_machinery_export_linkedin_details', $this->provider->clang_id), 'contentLandingPage' => $used_machine->getUrl(true), 'visibility' => 'PUBLIC', 'distribution' => [ 'feedDistribution' => 'MAIN_FEED', 'targetEntities' => [], 'thirdPartyDistributionChannels' => [] ], 'content' => [ 'article' => [ 'source' => $used_machine->getUrl(true), 'thumbnail' => $assetId, 'title' => $used_machine->manufacturer .' '. $used_machine->name, 'description' => $used_machine->teaser ] ], 'lifecycleState' => 'PUBLISHED', 'isReshareDisabledByAuthor' => false ]; $headers = [ 'Authorization: Bearer '. $this->provider->social_access_token, 'X-Restli-Protocol-Version: 2.0.0', 'Linkedin-Version: '. $this->linkedin_version, 'Content-Type: application/json', ]; $ch = curl_init($postUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData)); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $responseHeaders = substr($response, 0, $headerSize); curl_close($ch); if ($httpCode === 201) { // Published successfully $exported_used_machine->export_action = ''; $exported_used_machine->export_timestamp = date('Y-m-d H:i:s'); // Get post id $headerLines = explode("\r\n", $responseHeaders); $xRestliId = null; foreach ($headerLines as $headerLine) { if (strpos($headerLine, 'x-restli-id:') === 0) { $xRestliId = trim(substr($headerLine, 12)); break; } } if ($xRestliId !== null) { $exported_used_machine->provider_import_id = $response['id']; $exported_used_machine->save(); } else { echo "x-restli-id nicht im Header gefunden"; } $this->log('Post for used machine "'. trim($used_machine->manufacturer .' '. $used_machine->name) .'" on stream of '. $this->provider->linkedin_id .' published (post id: '. $xRestliId .')'); } else { // Failure publishing post $this->log('Failure posting used machine "'. trim($used_machine->manufacturer .' '. $used_machine->name) .'" on stream of '. $this->provider->linkedin_id .': '. $response); $return = false; } }
P粉3373859222024-04-04 17:55:01
这里是工作代码(Linkedin API 版本 202306)。请参阅:
// upload image, see https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/images-api?view=li-lms-2023-08&tabs=http#managing-image-asset $uploadUrl = 'https://api.linkedin.com/rest/images?action=initializeUpload'; $requestData = [ 'initializeUploadRequest' => [ 'owner' => 'urn:li:person:'. $this->provider->linkedin_id, ], ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $uploadUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $this->provider->social_access_token, 'Linkedin-Version: '. $this->linkedin_version, 'Content-Type: application/json', ]); $response = curl_exec($ch); // get asset id $responseArray = json_decode($response, true); $assetId = $responseArray['value']['image']; $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 200) { // upload picture to url received in response $imagePath = rex_path::media($used_machine->pics[0]); $uploadUrl = $responseArray['value']['uploadUrl']; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $uploadUrl); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents($imagePath)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $this->provider->social_access_token, 'Content-Type: '. mime_content_type($imagePath), ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode == 201) { $this->log('Image "'. $used_machine->pics[0].'" for used machine "'. trim($used_machine->manufacturer .' '. $used_machine->name) .'" uploded. Asset ID: '. $assetId); } else { // failure uploading image $this->log('Failure uploading image "'. $used_machine->pics[0].'" for used machine "'. trim($used_machine->manufacturer .' '. $used_machine->name) .'". API answer: '. $response); $return = false; } } // upload post, see https://learn.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares/posts-api?view=li-lms-2023-08&tabs=http#create-a-post if($assetId !== '') { $postUrl = 'https://api.linkedin.com/rest/posts'; $postData = [ 'author' => 'urn:li:person:'. $this->provider->linkedin_id, 'commentary' => $used_machine->manufacturer .' '. $used_machine->name .': '. \Sprog\Wildcard::get('d2u_machinery_export_linkedin_details', $this->provider->clang_id), 'contentLandingPage' => $used_machine->getUrl(true), 'visibility' => 'PUBLIC', 'distribution' => [ 'feedDistribution' => 'MAIN_FEED', 'targetEntities' => [], 'thirdPartyDistributionChannels' => [] ], 'content' => [ 'article' => [ 'source' => $used_machine->getUrl(true), 'thumbnail' => $assetId, 'title' => $used_machine->manufacturer .' '. $used_machine->name, 'description' => $used_machine->teaser ] ], 'lifecycleState' => 'PUBLISHED', 'isReshareDisabledByAuthor' => false ]; $headers = [ 'Authorization: Bearer '. $this->provider->social_access_token, 'X-Restli-Protocol-Version: 2.0.0', 'Linkedin-Version: '. $this->linkedin_version, 'Content-Type: application/json', ]; $ch = curl_init($postUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData)); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode === 201) { // Published successfully $exported_used_machine->export_action = ''; $exported_used_machine->export_timestamp = date('Y-m-d H:i:s'); // Get post id $headerLines = explode("\r\n", $response); $xRestliId = null; foreach ($headerLines as $headerLine) { if (0 === strpos($headerLine, 'x-restli-id:')) { $xRestliId = trim(substr($headerLine, 12)); break; } } if (null !== $xRestliId) { $exported_used_machine->provider_import_id = $xRestliId; } $exported_used_machine->save(); $this->log('Post for used machine "'. trim($used_machine->manufacturer .' '. $used_machine->name) .'" on stream of '. $this->provider->linkedin_id .' published'. (null !== $xRestliId ? ' (post id: '. $xRestliId .')' : '.')); } else { // Failure publishing post $this->log('Failure posting used machine "'. trim($used_machine->manufacturer .' '. $used_machine->name) .'" on stream of '. $this->provider->linkedin_id .': '. $response); $return = false; } }