Vous avez peut-être entendu parler de Google Contacts Data API, une API permettant de récupérer le carnet d’adresse des comptes Google de manière officielle (fini les grabbers où l’on doit donner son login / password).

Le fonctionnement qui sera décrit ici utilise le mode sécurisé avec PHP 5 (non pris en charge par Zend_GData).

Cinématique de l’API dans le cas d’une récupération de contacts :

  • le fournisseur de service (vous) mets un lien spécial vers une page de Google
  • le client (l’utilisateur) clique sur le lien et arrive sur la page spéciale de Google qui lui explique que le site du fournisseur de service veut accéder à ses contacts et qu’il doit donner son accord
  • le client clique sur OK pour donner son accord et est redirigé sur une page spéciale de votre site avec en paramètre un token (jeton).
  • en interne, vous utilisez ce token pour demander un jeton de session, puis utilisez le nouveau jeton pour accéder à la liste de contact de l’utilisateur

Voyons donc maintenant la mise en oeuvre :

Première étape : vous devez créer un compte de fournisseur de service chez Google

  • Rendez vous sur le site : https://www.google.com/accounts/ManageDomains
  • Validez la propriété de son domaine (via un metatag dans les headers ou un fichier à la racine)
  • Entrez le chemin sur votre site vers lequel le visiteur sera redirigé à la confirmation de la demande (exemple: Target URL path prefix: http://www.monsite.com/import.php)
  • Donnez une description de votre service (pas utilisé pour le moment, mais sera peut-être affiché plus tard sur la page de demande de confirmation de Google)
  • Générez un certificat X.509 (c’est pas compliqué n’ayez pas peur ;-) ) :
    • Ouvrez un shell sur votre serveur
    • Taper :
    • openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \
        '/C=FR/ST=/L=Paris/CN=www.monsite.com' -keyout \
        gdata.key -out gdata.pem
      
  • Déplacez les 2 fichiers créés dans un endroit non accessible par le web
  • Uploadez le fichier gdata.pem dans l’interface de Google

Deuxième étape : créez l’url spéciale pour Google
Le format est le suivant :

https://www.google.com/accounts/AuthSubRequest?
scope=http%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds%2Fcontacts%2F
&session=1&secure=1
&next=http%3A%2F%2Fmonsite.com%2Fimport&hd=default

Vous n’avez qu’à modifier le texte en gras pour qu’il corresponde à votre script.

Troisième étape : créez le script d’import de contacts
C’est très simple, je vous passe un sample ;-)

function email2nickname($email) {
	$output = str_replace(array('.', '-', '_', ',', ':'), ' ', substr($email, 0, strpos($email, '@')));
	$output = str_replace(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), '', $output);
	$output = ucwords($output);
	return $output;
}

function _callGData($url, $token, $key) {
	$fp = fopen($key, 'r');
	$priv_key = fread($fp, 8192);
	fclose($fp);

	$nonce = '';
	for ($i=0 ; $i<5 ; $i++) {
		$nonce .= rand(1000, 9999);
	}

	$data = 'GET '.$url.' '.time().' '.$nonce;

	$pkeyid = openssl_get_privatekey($priv_key);
	openssl_sign($data, $signature, $pkeyid, OPENSSL_ALGO_SHA1);
	openssl_free_key($pkeyid);

	$sig = base64_encode($signature);

	$headers = array(
		'Authorization: AuthSub token="'.$token.'" data="'.$data.'" sig="'.$sig.'" sigalg="rsa-sha1"'
	);

	$ch = curl_init($url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_TIMEOUT, 60);
	curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

	return curl_exec($ch);
}

function grabGoogleContacts($token, $session = false) {
	$key = '/etc/ssl/gdata.key';	// change this 

	if(false === $session) {
		$session = _callGData('https://www.google.com/accounts/AuthSubSessionToken', $token, $key);

		if(strstr($session, '=')) {
			list(,$token) = explode('=', $session);
			$token = trim($token);
		}
		else return false;
	}	

	$data = _callGData('http://www.google.com/m8/feeds/contacts/default/base?max-results=9999', $token, $key);

	// lasy fix :-)
	$data = str_replace(array('gd:email', 'gd:phoneNumber'), array('gdemail', 'gdphoneNumber'), $data);

	$xml = new SimpleXMLElement($data);

	$grab = array();
	$grab['user'] = array('name'=>trim(strval($xml->author->name)), ‘email’=>trim(strval($xml->author->email)), ‘token’=>$token);
	$grab[’contacts’] = array();

	foreach ($xml->entry as $entry) {
		$name = trim(strval($entry->title));
		$email = trim(strval($entry->gdemail[’address’]));

		if(empty($name)) {
			// i don’t like email for nickname ;-)
			$name = email2nickname($email);
		}

		$grab[’contacts’][] = array(’name’=>$name, ‘email’=>$email);
	}

	return $grab;
}

if(isset($_GET[’token’])) {
	$grab = grabGoogleContacts($_GET[’token’]);
}
else {
	// nothing ?
}

Et voilà, maintenant c’est à vous de jouer, vous avez les bases, le sample précédant est plus un proof of concept qu’autre chose et vous devez le modifier pour calquer sur vos besoins et traiter les erreurs comme bon vous semble.

Plus d’informations : http://code.google.com/apis/contacts/

A suivre : la même chose, mais pour Live Data Contacts API de Microsoft.