Importing Windows Live Contacts

陌路散爱 提交于 2019-12-10 10:58:27

问题


I've started with importing contacts from live. Now I don't know what MS is thinking, but they seriously do overcomplicate everything they put their hands to.

For my app, it's very important that I get a phone number. So important in fact, that should you not have a phone number, your contact is skipped. With my method I can't see any phone numbers. I assumed that it would be shown if I loop through each contact one by one, but alas, no love.

Here is my method:

$import_id = time();
$client_id = "xxx";
$redirect_uri = 'redirecturi';
$client_secret = "xxx";
$code = $_GET['code'];
$grant_type = "authorization_code";

$post = "client_id=$client_id&redirect_uri=$redirect_uri&client_secret=$client_secret&code=$code&grant_type=$grant_type";
$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,false);
$result = curl_exec($curl);
curl_close($curl);
$token = json_decode($result);
$access_token = $token->access_token;
$user_id = $token->user_id;

$url = "https://apis.live.net/v5.0/me/contacts?access_token=$access_token";
$response =  curl_file_get_contents($url);
$response = json_decode($response);
foreach($response->data as $contact) {
    $contact_details = curl_file_get_contents("https://apis.live.net/v5.0/" . $contact->id . "?access_token=$access_token");
    debug($contact_details);
}
die();

However, I'm only getting info back like this (this person I know has a contact number as I can see it when I view him on people.live.com):

{
   "id": "contact.id", 
   "first_name": "Danie", 
   "last_name": "Van den Heever", 
   "name": "Danie Van den Heever", 
   "is_friend": false, 
   "is_favorite": false, 
   "user_id": "userid", 
   "email_hashes": [
      "emailhash"
   ], 
   "updated_time": "2014-09-17T12:11:10+0000"
}

My permission request url (which defines the scopes) looks like this:

https://login.live.com/oauth20_authorize.srf?client_id=clientidkey&scope=wl.basic%20wl.offline_access&response_type=code&redirect_uri=redirecturi

Should I add more scopes to get the contact number? If so, which scopes? Or is this not possible?


回答1:


The solution is to use an undocumented scope wl.contacts_phone_numbers, there is a risk that it'll become deprecated or just locked down and only Microsoft-approved clients will be able to use it, but in the meantime it works.

Also you do not need to do an extra request for every contact, the contact object you get from me/contacts already has the phone numbers in a phones object.

By the way, here's the code I used while testing this, I used a REST client library which avoids copy/pasting the long and repetitive cURL parameters each time and turns the requests into one-liners.

Code to ask for permission :

$params = ["client_id" => "...", "scope" => "wl.basic wl.contacts_phone_numbers", "response_type" => "code", "redirect_uri" => "http://sanctuary/contacts_callback.php"];

header("Location: https://login.live.com/oauth20_authorize.srf?".http_build_query($params));

Note the extra wl.contacts_phone_numbers scope in the permission request.

Code to get access token and retrieve contacts :

// Composer's autoloader, required to load libraries installed with it
// in this case it's the REST client
require "vendor/autoload.php";

// exchange the temporary token for a reusable access token
$resp = GuzzleHttp\post("https://login.live.com/oauth20_token.srf", ["body" => ["client_id" => "...", "client_secret" => "...", "code" => $_GET["code"], "redirect_uri" => "http://sanctuary/contacts_callback.php", "grant_type" => "authorization_code"]])->json();
$token = $resp["access_token"];

// REST client object that will send the access token by default
// avoids writing the absolute URL and the token each time
$client = new GuzzleHttp\Client(["base_url" => "https://apis.live.net/v5.0/", "defaults" => ["query" => ["access_token" => $token]]]);

// get all the user's contacts
$contacts = $client->get("me/contacts")->json()["data"];

// iterate over contacts
foreach ($contacts as $contact) {
    // if that contact has a phone number object
    if (array_key_exists("phones", $contact)) {
        // iterate over each phone number
        foreach ($contact["phones"] as $phone) {
            // if number isn't blank
            if (!empty($phone)) {
                // do whatever you want with that number
            }
        }
    }
}

Here's what me/contacts looks like with the extra scope (minus a few line breaks and personal info) :

Array (
    [data] => Array (
            [0] => Array (
                    [id] => contact...
                    [first_name] => ...
                    [last_name] => ...
                    [name] => ...
                    [is_friend] => 
                    [is_favorite] => 
                    [user_id] => 
                    [email_hashes] => ...
                    [updated_time] => ...
                    [phones] => Array ( // what you asked for
                            [personal] => 
                            [business] => 
                            [mobile] => +337...
                        )
                )
        )
)



回答2:


From reading the documentation, phone numbers are part of the User object.

To fetch their phone numbers, you would;

  • Grab a list of their contacts (which you've done)
  • Iterate through the result set
  • Grab the user id from the contact response. (Key id)
  • Make a request to the User collection (with the wl.phone_numbers scope)
  • See if the phone numbers are null or not
    • If they are NULL, skip the iteration

An example phones object (in the User response);

"phones": {
   "personal": "(555) 555-1212", 
   "business": "(555) 111-1212", 
   "mobile": null
} 

So;

$arrUser = json_decode($strResponse, true);

if( is_null($arrUser['phones']['personal']) 
     AND is_null($arrUser['phones']['business']
      AND is_null($arrUser['phones']['mobile']) ) {
   //No phone numbers
   //Assuming you're in a loop, fetching a user object for each contact - skip the iteration & move onto the next contact.
   continue;
}


来源:https://stackoverflow.com/questions/25908398/importing-windows-live-contacts

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