hotmail get contacts with curl using api

久未见 提交于 2019-12-04 21:37:42
DaveRandom

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!