Create an Image Share over LinkedIn API V2 not wor

2019-08-20 08:14发布

问题:

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

Linkedin describes your image binary file upload prozess 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, and will only consist of 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:

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'),

    ]