1
votes

I use the api version 2.0 and want to create an image share.

LinkedIn describes your image binary file upload process here: https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/share-on-linkedin?context=linkedin/consumer/context#create-a-text-share

If you follow the instructions you will get a 400 HTTP error. I add the Content-Type in the header and get a 201 HTTP status with the X-RestLi-Id in the header. So far so good!

If I want to show my created post on LinkedIn (https://www.linkedin.com/in/me/detail/recent-activity/) I can't find the post with image.

How to fix it? Anybody got an idea?

PHP code:

$imageRequestData = array(
    "registerUploadRequest" => array(
        "recipes" => array(
            "urn:li:digitalmediaRecipe:feedshare-image"
        ),
        "owner" => $urn, // Person URN === urn:li:person:XXXX
        "serviceRelationships" => array(
            array(
                "relationshipType" => "OWNER",
                "identifier" => "urn:li:userGeneratedContent"
            )
        )
    )
);
$image_request = $this->post('v2/assets?action=registerUpload', $imageRequestData);

$headers = array();
$headers[] = 'Authorization: Bearer ' . $this->accessToken;
$headers[] = 'X-Restli-Protocol-Version: 2.0.0';
$headers[] = 'Content-Type: ' . mime_content_type($image_path);  //ex. image/png
$ch = curl_init();
$options = array(
    CURLOPT_HEADER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_URL => $image_request['message']['value']['uploadMechanism']
      ['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest']['uploadUrl'],
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_POST => true,
    CURLOPT_CONNECTTIMEOUT => $this->connectTimeout,
    CURLOPT_TIMEOUT => $this->timeout,
    CURLOPT_POSTFIELDS => array("upload-file" => new CURLFile($image_path))
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);


$content = array(
    'author' => $urn, // Person URN === urn:li:person:XXX
    'lifecycleState' => 'PUBLISHED',
    'specificContent' => array(
        "com.linkedin.ugc.ShareContent" => array(
            'shareCommentary' => array(
                "text" => $comment,
            ),
            'shareMediaCategory' => 'IMAGE',
                // NONE - The share does not contain any media, only text.
                // ARTICLE - The share contains a URL.
                // IMAGE - The Share contains an image.
            'media' => array(
                    "status" => "READY",
                    "media" => $image_request['message']['value']['asset']
                )
        )
    ),
    "visibility" => array(
        "com.linkedin.ugc.MemberNetworkVisibility" => "PUBLIC"
    )
);


$postfields = json_encode($content);
$headers = array();
$headers[] = 'x-li-format: json';
$headers[] = 'Authorization: Bearer ' . $this->accessToken;
$headers[] = 'Content-Type: application/json';
$headers[] = 'Content-Length: ' . strlen($postfields);
$headers[] = 'X-Restli-Protocol-Version: 2.0.0';
$ch = curl_init();
$options = array(
    CURLOPT_HEADER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_URL => 'https://api.linkedin.com/v2/ugcPosts',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_POST => true,
    CURLOPT_CONNECTTIMEOUT => $this->connectTimeout,
    CURLOPT_TIMEOUT => $this->timeout,
    CURLOPT_POSTFIELDS => $postfields
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
1

1 Answers

2
votes

You need to change your request to PUT and keep default for SSL VerifyPeer:

$headers = array();
$headers[] = 'Authorization: Bearer ' . $this->accessToken;
$headers[] = 'X-Restli-Protocol-Version: 2.0.0';
$headers[] = 'Content-Type: multipart/form-data';
$ch = curl_init();
$options = array(
    CURLOPT_HEADER => true,
    CURLOPT_CUSTOMREQUEST => 'PUT', //need to set custom request to PUT instead of post
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_URL => $image_request['message']['value']['uploadMechanism']
        ['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest']['uploadUrl'],
    CURLOPT_HTTPHEADER => $headers,
    // CURLOPT_SSL_VERIFYPEER => false, //keep default options
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_POST => true,
    CURLOPT_CONNECTTIMEOUT => $this->connectTimeout,
    CURLOPT_TIMEOUT => $this->timeout,
    CURLOPT_POSTFIELDS => array("upload-file" => new CURLFile($image_path))
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

Or use GuzzleHttp\Client to simplify the upload:

$client =new \GuzzleHttp\Client();
$client->request('PUT',
    $image_request['message']['value']['uploadMechanism'] // ↵
        ['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest']['uploadUrl'],
    [
        'headers' => [
            'Authorization' => 'Bearer ' . $this->accessToken
        ],
        'body' => fopen($image_path, 'r'),
    ]