问题
function tratar_hotmail(){
$client_id = '0xxxxxxxxxxxxxxxx2';
$client_secret = 'Wyyyyyyyyyyyyyyyyyp';
$redirect_uri = 'http://example.com/';
$auth_code = $_GET["code"];
$fields=array(
'code'=> urlencode($auth_code),
'client_id'=> urlencode($client_id),
'client_secret'=> urlencode($client_secret),
'redirect_uri'=> urlencode($redirect_uri),
'grant_type'=> urlencode('authorization_code')
);
$post = '';
foreach($fields as $key=>$value) { $post .= $key.'='.$value.'&'; }
$post = rtrim($post,'&');
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,'https://login.live.com/oauth20_token.srf');
curl_setopt($curl,CURLOPT_POST,5);
curl_setopt($curl,CURLOPT_POSTFIELDS,$post);
curl_setopt($curl, CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);
$result = curl_exec($curl);
curl_close($curl);
$response = json_decode($result);
$accesstoken = $response->access_token;
$url = 'https://apis.live.net/v5.0/me/contacts?access_token='.$accesstoken.'';
$xmlresponse = curl_file_get_contents($url);
echo $xmlresponse;
$xml = json_decode($xmlresponse, true);
foreach($xml['data'] as $emails)
{
echo $emails['name'];
}
}
wich outputs:
{ "error": { "code": "request_token_invalid", "message": "The access token isn't valid." } }
So how can i get the request_access_token ?
-EDIT-
Forgot the curl function
function curl_file_get_contents($url)
{
$curl = curl_init();
$userAgent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)';
curl_setopt($curl,CURLOPT_URL,$url); //The URL to fetch. This can also be set when initializing a session with curl_init().
curl_setopt($curl,CURLOPT_RETURNTRANSFER,TRUE); //TRUE to return the transfer as a string of the return value of curl_exec() instead of outputting it out directly.
curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,5); //The number of seconds to wait while trying to connect.
curl_setopt($curl, CURLOPT_USERAGENT, $userAgent); //The contents of the "User-Agent: " header to be used in a HTTP request.
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE); //To follow any "Location: " header that the server sends as part of the HTTP header.
curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE); //To automatically set the Referer: field in requests where it follows a Location: redirect.
curl_setopt($curl, CURLOPT_TIMEOUT, 10); //The maximum number of seconds to allow cURL functions to execute.
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); //To stop cURL from verifying the peer's certificate.
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
$contents = curl_exec($curl);
curl_close($curl);
return $contents;
}
回答1:
Here's a class I've just thrown together for talking to the API:
<?php
// Note: the test script below assumes this is in a
// file called class.liverestapiconsumer.php
class LiveRESTAPIConsumer {
protected $accessTokenURI = 'https://login.live.com/oauth20_token.srf';
protected $restAPIBaseURI = 'https://apis.live.net/v5.0';
protected $appId;
protected $appSecret;
protected $accessToken;
protected $accessTokenExpires;
public function __construct($appId = NULL, $appSecret = NULL, $accessToken = NULL, $accessTokenExpires = NULL) {
$this->setAppId($appId);
$this->setAppSecret($appSecret);
$this->setAccessToken($accessToken);
$this->setAccessTokenExpires($accessTokenExpires);
}
public function getAppId() {
return $this->appId;
}
public function setAppId($appId) {
$this->appId = $appId;
}
public function getAppSecret() {
return $this->appSecret;
}
public function setAppSecret($appSecret) {
$this->appSecret = $appSecret;
}
public function getAccessToken() {
return $this->accessToken;
}
public function setAccessToken($accessToken) {
$this->accessToken = $accessToken;
}
public function getAccessTokenExpires() {
return $this->accessTokenExpires;
}
public function setAccessTokenExpires($accessTokenExpires) {
$this->accessTokenExpires = $accessTokenExpires;
}
public function accessTokenIsExpired() {
return $this->accessTokenExpires <= time();
}
public function fetchAccessToken($code, $redirectURI) {
if (!isset($code, $redirectURI, $this->appId, $this->appSecret)) {
throw new \Exception('Cannot fetch access token without an authorization code, redirect URI, application id and application secret');
}
$postFields = array(
'client_id' => $this->appId,
'client_secret' => $this->appSecret,
'code' => $code,
'redirect_uri' => $redirectURI,
'grant_type' => 'authorization_code'
);
$bodyData = http_build_query($postFields);
$headers = array(
'Content-Type: application/x-www-form-urlencoded'
);
$ch = curl_init($this->accessTokenURI);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyData);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if (!$response = curl_exec($ch)) {
throw new \Exception('cURL request failed');
} else if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != 200) {
throw new \Exception('Live API returned an error response code: '.curl_getinfo($ch, CURLINFO_HTTP_CODE));
} else if (!$responseObj = json_decode($response)) {
throw new \Exception('Cannot decode API response as JSON; data: '.$response);
} else if (!isset($responseObj->access_token)) {
throw new \Exception('Live API did not return an access token; error: '.$responseObj->error_description);
}
$this->setAccessToken($responseObj->access_token);
$this->setAccessTokenExpires(time() + $responseObj->expires_in);
}
protected function normalizeAPIPath($path) {
return $path[0] == '/' ? $path : '/'.$path;
}
public function apiCall($method, $path, array $params = array(), $data = NULL) {
if (!isset($this->accessToken)) {
throw new \Exception('Cannot make API requests without an access token');
} else if ($this->accessTokenIsExpired()) {
throw new \Exception('The currently defined access token has expired');
}
$ch = curl_init();
$url = $this->restAPIBaseURI.$this->normalizeAPIPath($path);
if ($params) {
$url .= '?'.http_build_query($params);
}
curl_setopt($ch, CURLOPT_URL, $url);
$method = trim(strtoupper($method));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
$headers = array();
$headers[] = 'Authorization: Bearer '.$this->accessToken;
if ((array) $data) {
$bodyData = json_encode($data);
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyData);
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if (!$response = curl_exec($ch)) {
throw new \Exception('cURL request failed');
} else if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != 200) {
throw new \Exception('Live API returned an error response code: '.curl_getinfo($ch, CURLINFO_HTTP_CODE));
} else if (!$responseObj = json_decode($response)) {
throw new \Exception('Cannot decode API response as JSON; data: '.$response);
}
return $responseObj;
}
}
...and the test script (yes, I am fully aware that my HTML skills are terrible - I don't write very much of it):
<?php
session_start();
require 'class.liverestapiconsumer.php';
// Your details as assigned by Microsoft
$appId = '<your client id>';
$appSecret = '<your client secret>';
// The public (internet) URL of this script
$localUrl = 'http://example.com/path/to/file.php';
// Work out whether we have a valid access token or not
$haveAccessToken = FALSE;
$accessTokenExpiresIn = 'N/A';
if (isset($_SESSION['accessToken'])) {
$now = time();
$haveAccessToken = $now < $_SESSION['accessTokenExpires'];
$accessTokenExpiresIn = ($_SESSION['accessTokenExpires'] - $now).' seconds';
if (!$haveAccessToken || isset($_GET['destroy'])) {
unset($_SESSION['accessToken'], $_SESSION['accessTokenExpires']);
}
if (isset($_GET['destroy'])) {
header('HTTP/1.1 302 Found');
header('Location: '.$localUrl);
}
}
function parse_body_data($str) {
$result = array();
$items = preg_split('/[\r\n]+/', $str, -1, PREG_SPLIT_NO_EMPTY);
foreach ($items as $item) {
$item = explode(':', $item, 2);
if (count($item) !== 2) {
return FALSE;
}
$result[trim($item[0])] = trim($item[1]);
}
return $result;
}
?>
<html>
<head>
<title>Live API Test</title>
<style>
div.label {
margin-top: 10px;
}
</style>
</head>
<body>
<div>Do we have an access token? <b><?php echo $haveAccessToken ? 'Yes <sup>(<a href="?destroy">destroy</a>)</sup>' : 'No'; ?></b> (Expires: <?php echo $accessTokenExpiresIn; ?>)</div>
<?php
if (isset($_POST['path'])) { // get something from the API
do { // do-while so we can easily break out of it on error
$client = new LiveRESTAPIConsumer($appId, $appSecret, $_SESSION['accessToken'], $_SESSION['accessTokenExpires']);
$path = $_POST['path'];
$method = $_POST['method'];
$paramStr = trim($_POST['params']);
$params = array();
if (!empty($paramStr)) {
parse_str($paramStr, $params);
}
if (($body = parse_body_data($_POST['body'])) === FALSE) {
echo "<div>Error: Body data invalid</div>";
break;
}
try {
$result = $client->apiCall($method, $path, $params, $body);
// The class returns the response data decoded to an object, so json_encode() it again for display
echo '
Result:
<pre>'.json_encode($result, JSON_PRETTY_PRINT).'</pre>
';
} catch (\Exception $e) {
echo "<div>Exception: ".$e->getMessage()."</div>";
break;
}
} while(FALSE);
echo '<div><a href="'.$localUrl.'">Back</a></div>';
} else if (isset($_GET['code'])) { // handle redirect from live API
try {
$client = new LiveRESTAPIConsumer($appId, $appSecret);
$client->fetchAccessToken($_GET['code'], $localUrl);
$_SESSION['accessToken'] = $client->getAccessToken();
$_SESSION['accessTokenExpires'] = $client->getAccessTokenExpires();
echo '
<div>Successfully retrieved access token: '.$_SESSION['accessToken'].'</div>
<div><a href="'.$localUrl.'">Go to form</a></div>
';
} catch (\Exception $e) {
echo '
<div>Exception: '.$e->getMessage().'</div>
<div><a href="'.$localUrl.'">Back</a></div>
';
}
} else if ($haveAccessToken) { // Output form
echo '
<form action="'.$localUrl.'" method="post">
<div>
<div class="label">API Path</div>
<div><input name="path" type="text"></div>
</div>
<div>
<div class="label">Parameters (query string)</div>
<div><input name="params" type="text"></div>
</div>
<div>
<div class="label">Method</div>
<div>
<select name="method">
<option value="GET">GET</option>
<option value="POST">POST</option>
<option value="PUT">PUT</option>
<option value="DELETE">DELETE</option>
<option value="MOVE">MOVE</option>
<option value="COPY">COPY</option>
</select>
</div>
</div>
<div>
<div class="label">Body Data (key: value, newline separated)</div>
<div><textarea name="body" rows="10" cols="40"></textarea></div>
</div>
<input type="submit" value="Send Request">
</form>
<a href="http://msdn.microsoft.com/en-us/library/live/hh243648" target="_blank">API Reference</a>
';
} else { // Don't have access token yet
$opts = array(
'client_id' => $appId,
'scope' => 'wl.basic',
'response_type' => 'code',
'redirect_uri' => $localUrl
);
echo '<div><a href="https://login.live.com/oauth20_authorize.srf?'.htmlspecialchars(http_build_query($opts)).'">Get access token</a></div>';
}
?>
</body>
</html>
All the parts that I think need explanation are commented. If you have any questions let me know.
Note that I haven't extensively tested the class, and it may be lacking when it comes to the more advanced API functionality. Seems to work fairly well for simple contact manipulation though.
回答2:
In addition to the answer of DaveRandom and the comment of saveATcode: You should submit the redirect url given in $localUrl
as a valid redirect url at account live application. They must be exactly the same or else you will get the 'The provided value for the input parameter 'redirect_uri' is not valid....' message. I just mentioned it because mine had a typo and i experienced the same error.
来源:https://stackoverflow.com/questions/14215563/hotmail-get-contacts-with-curl-using-api