Question

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'];
        }       
}

which outputs:

{ "error": { "code": "request_token_invalid", "message": "The access token isn't valid." } }

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;
}
Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top