为什么在 LinkedIn 上分享 API return 400 错误请求?

Why Share on LinkedIn API return 400 Bad Request?

我正在尝试通过其 Share on LinkedIn API using a PHP library LinkedIn-Client API post LinkedIn 共享更新。我已经成功地授权了用户并且我得到了从它返回的访问令牌。我将令牌与此共享 API 调用一起使用。这是我的代码:

$linkedInOAuth = new Happyr\LinkedIn\LinkedIn(LINKEDIN_APP_ID, LINKEDIN_APP_SECRET);

if ($accessToken) { // assume that it is retrieved from session
    $linkedInOAuth->setAccessToken($accessToken);

    $postParams = array(
        "content" => array(
            'description' => "I'm so exciting to share a post using API."
        ),
        "visibility" => array(
            "code" => "connnections-only"
        )
    );

    $result = $linkedInOAuth->api(
        "v1/people/~/shares",
        array("format" => "json"),
        "POST",
        $postParams
    );
}

但是我从这个 API 调用中返回了 400 错误请求错误。

Fatal error: Uncaught GuzzleException: 400: Client error response [url] https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=xxxxxxx [status code] 400 [reason phrase] Bad Request thrown in ...\vendor\happyr\linkedin-api-client\src\Happyr\LinkedIn\Http\GuzzleRequest.php on line 26

可能是什么问题?

[更新于 2015-04-30 3:00 下午 UTC]

LinkedIn-Client API uses Guzzle 内部用于 HTTP 请求。我尝试直接使用 GuzzleHttp 而不使用 Happyr\LinkedIn\LinkedIn->api(),但同样的错误并且没有成功。

if ($accessToken) {
    $url = 'https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=' . $accessToken;

    $client = new GuzzleHttp\Client();

    $response = $client->post($url, array(
        'headers' => array(
            'Content-Type' => 'application/json',
            'x-li-format'  => 'json'
        ),
        'json' => array(
            'comment' => 'Check out developer.linkedin.com!',
            'content' => array(
                'description' => 'I\'m so exciting to share a post using API.'
            ),
            'visibility' => array(
                'code' => 'connections-only'
            )
        )
    ));
}

Fatal error: Uncaught exception 'GuzzleHttp\Exception\ClientException' with message 'Client error response [url] https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=xxxxx [status code] 400 [reason phrase] Bad Request' in \vendor\guzzlehttp\guzzle\src\Exception\RequestException.php:89 Stack trace: #0 \vendor\guzzlehttp\guzzle\src\Subscriber\HttpError.php(33): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Message\Request), Object(GuzzleHttp\Message\Response)) #1 \vendor\guzzlehttp\guzzle\src\Event\Emitter.php(109): GuzzleHttp\Subscriber\HttpError->onComplete(Object(GuzzleHttp\Event\CompleteEvent), 'complete') #2 \vendor\guzzlehttp\guzzle\src\RequestFsm.php(91): GuzzleHttp\Event\Emitter->emit('complete', Object(Guz in \vendor\guzzlehttp\guzzle\src\Exception\RequestException.php on line 89

[更新于 2015-05-05 9:40 AM UTC]

我复制并使用了 Share on LinkedIn API page 的 xml 和 json 个例子。这次,错误更改为内部服务器错误。

if ($accessToken) {
    $format = 'xml';
    $url = 'https://api.linkedin.com/v1/people/~/shares?format='.$format.'&oauth2_access_token=' . $connect->accessToken;
    $postParams = array(
        "xml" => "
            <share>
                <comment>Check out developer.linkedin.com!</comment>
                <content>
                    <title>LinkedIn Developer Resources</title>
                    <description>Leverage LinkedIn's APIs to maximize engagement</description>
                    <submitted-url>https://developer.linkedin.com</submitted-url>
                    <submitted-image-url>https://example.com/logo.png</submitted-image-url>
                </content>
                <visibility>
                    <code>anyone</code>
                </visibility>
            </share>",
        "json" => array(
            "comment" => "Check out developer.linkedin.com!",
            "content" => array(
                "title" => "LinkedIn Developers Resources",
                "description" => "Leverage LinkedIn's APIs to maximize engagement",
                "submitted-url" => "https://developer.linkedin.com",
                "submitted-image-url" => "https://example.com/logo.png"
            ),
            "visibility" => array(
                "code" => "anyone"
            )
        )
    );

    $client = new GuzzleHttp\Client();

    if ($format === 'xml') {
        $response = $client->post($url, array(
            'body' => $postParams['xml']
        ));
    } else {
        $response = $client->post($url, array(
            'headers' => array(
                'Content-Type' => 'application/json',
                'x-li-format'  => 'json'
            ),
            'json' => $postParams['json']
        ));
    }
}

Fatal error: Uncaught exception 'GuzzleHttp\Exception\ServerException' with message 'Server error response [url] https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=xxxx [status code] 500 [reason phrase] Internal Server Error'

这里只是一个快速的猜测,但在将它发送到 API.

之前,您可能需要将 json_encode 添加到 $postParams
$result = $linkedInOAuth->api(
    "v1/people/~/shares",
    array("format" => "json"),
    "POST",
    json_encode($postParams),
);

或者

如果这不起作用,我还注意到 Linkedin 文档说了以下内容。您可以尝试添加这两个 headers(如果您还没有的话)。

By default, all API calls expect input in XML format, however if it is more covienent for your application to submit data in JSON format, you can inform the APIs that they will be receiving a JSON-formatted payload by including the following two HTTP header values in the call:

Content-Type: application/json

x-li-format: json

你的JSONpost身材需要矫正。检查:

https://developer.linkedin.com/docs/share-on-linkedin

您需要遵循其中一种格式。

  1. 通过包含 URL

    的评论分享
    {
      "comment": "Check out developer.linkedin.com! http://linkd.in/1FC2PyG",
      "visibility": {
        "code": "anyone"
      }
    }
    
  2. 分享特定值

    {
      "comment": "Check out developer.linkedin.com!",
      "content": {
        "title": "LinkedIn Developers Resources",
        "description": "Leverage LinkedIn's APIs to maximize engagement",
        "submitted-url": "https://developer.linkedin.com",  
        "submitted-image-url": "https://example.com/logo.png"
      },
      "visibility": {
        "code": "anyone"
      }  
    }
    

根据 the Github issue of Happyr\LinkedIn-API-client, some updates have been made in 0.5.0,它解决了我的问题。但是,LinkedIn 对其分享的文档不明确 API。必须注意以下信息:

  1. comment栏位为分享更新内容。名字comment让人迷惑。
  2. 使用字段comment,URL在分享更新内容中可选
  3. content 字段表示您正在共享的 URL 内容的快照。更清楚地描述,它反映了 open graph meta 标签;
    • content.title 覆盖 <meta property="og:title" content="..." />
    • content.description 覆盖 <meta property="description" content="..." />
    • content.title 覆盖 <meta property="og:title" content="..." />
    • content.submitted-url 覆盖 <meta property="og:url" content="..." />
    • content.submitted-image-url 覆盖 <meta property="og:image" content="..." />
  4. 当使用content字段时,需要submitted-url字段。其余的是可选的。如果缺少,400 Bad Request 将 return.
  5. LinkedIn Share API 示例代码中包含的 URL 会导致 500 内部服务器错误。它们不应该用于测试目的。

以下是API使用Happyr\LinkedIn-API-client的正确用法。

(1) Happyr\LinkedIn - 使用字段 comment

$linkedInOAuth = new Happyr\LinkedIn\LinkedIn(LINKEDIN_APP_ID, LINKEDIN_APP_SECRET);
// retrieve $accessToken from db or session
$linkedInOAuth->setAccessToken($accessToken);

$postParams = array(
    'json' => array(
        "comment" => "PHPLucidFrame - The simple, lightweight and flexible web application development framework http://phplucidframe.sithukyaw.com",
        "visibility" => array(
            "code" => "anyone"
        )
    )
);

$result = $linkedInOAuth->post('v1/people/~/shares', $postParams);

(2) Happyr\LinkedIn - 使用字段 content

$linkedInOAuth = new Happyr\LinkedIn\LinkedIn(LINKEDIN_APP_ID, LINKEDIN_APP_SECRET);
// retrieve $accessToken from db or session
$linkedInOAuth->setAccessToken($accessToken);

$postParams = array(
    'json' => array(
        "content" => array(
            "title" => "PHPLucidFrame",
            "description" => "The simple, lightweight and flexible web application development framework",
            "submitted-url" => "http://phplucidframe.sithukyaw.com"
        ),
        "visibility" => array(
            "code" => "anyone"
        )
    )
);

$result = $linkedInOAuth->post('v1/people/~/shares', $postParams);

以下是API使用GuzzleHttp的正确用法。

(3) GuzzleHttp - 使用字段 comment

// retrieve $accessToken from db or session
$url = 'https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=' . $accessToken;
$client = new GuzzleHttp\Client();
$response = $client->post($url, array(
    "json" => array(
        "comment" => "PHPLucidFrame - The simple, lightweight and flexible web application development framework http://phplucidframe.sithukyaw.com",
        "visibility" => array(
            "code" => "anyone"
        )
    )
));

(4) GuzzleHttp - 使用字段 content

// retrieve $accessToken from db or session
$url = 'https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=' . $accessToken;
$client = new GuzzleHttp\Client();
$response = $client->post($url, array(
    "json" => array(
        "content" => array(
            "title" => "PHPLucidFrame",
            "description" => "The simple, lightweight and flexible web application development framework",
            "submitted-url" => "http://phplucidframe.sithukyaw.com"
        ),
        "visibility" => array(
            "code" => "anyone"
        )
    )
));

字段 commentcontent 也可以一起使用。