Nous sommes en train de développer une application qui permet de proposer nos rendez-vous Google Calendar via une application SPA Angular.
Découvrons ensemble les étapes pour réussir à lister les événements d’un de vos calendriers.
1. Créer un Service account depuis la Console Google developpeur
Rendez-vous ici : Google console developpers.
Puis créez un nouveau projet.
Précisez le nom du projet que vous souhaitez.
Configuration d’un compte de service
Après avoir cliqué sur Créer, cliquez sur Accéder à l’aperçu des APIs.
Puis sur Activer les API et les Services.
Rechercher Google Calendar.
Et sélectionnez le premier résultat et cliquez sur le bouton ACTIVER.
Puis, cliquez sur CREER DES IDENTIFIANTS.
IGNORER l’étape et cliquez sur le lien Compte de service
Sur la nouvelle page, vous avez un bouton CREER UN COMPTE DE SERVICE, cliquez dessus:
Enfin, renseignez les informations demandées :
Et choisissez un rôle (ou plusieurs) (par exemple, Propriétaire, Explorateur)
Après avoir cliqué sur Continuer, vous allez créer une clef.
Choisissez bien : une clef JSON, et cliquez sur le bouton CREER.
Et voilà, vous avez une popin qui apparait :
Et vous récupérez un fichier json (que l’on déposera dans notre projet api asp.net core)
2. Créer une API avec asp.net core
Créer un projet asp.net core, en choisissant le scaffolder MVC. (ce tutoriel fonctionne aussi avec les pages Razor).
3. Enregistrer le fichier récupéré depuis la Console développeur dans votre projet asp.net core
Le fichier json que vous avez récupéré depuis le Google Console, va être nécessaire pour se connecter.
Il contient la clef d’authentification (PRIVATE KEY), l’email du compte de service, …
Déposez-le à la racine de votre application asp.net core.
NOTE: le mieux sera d’utiliser les données secrètes locales (stockées dans le fichier secrets.json).
4. Préparer l’authentification Google Calendar depuis notre Controller
a) Installer la DLL depuis NuGet : Google.Apis.Calendar.V3
Installer la dll Google.Apis.Calendar.V3.dll depuis l’installeur NuGet, ou bien via la console.
b) Définition du SCOPE
Maintenant passons au dur, attaquons le code. Passons du côté Controller.
Ajoutez en donnée statique le SCOPE d’appel du calendrier (en sommes les droits d’accès) :
private static string[] _SCOPES = { CalendarService.Scope.Calendar };
c) Préparation d’un Credential pour se connecter
Il existe aujourd’hui beaucoup de ressources pour créer une authentification avec le fichier (ancien) p12.
Or, maintenant, Google conseille d’utiliser le fichier json que nous avons généré tout à l’heure.
Pour y arriver :
- Créer un Stream pour lire le contenu du fichier
- Utilisez un deserializer de fichier json (ici, il est proposé par la dll de Google Apis)
- Créer un ServiceAccountCredential pour autoriser la connection
Ca donne en code :
using (var fs = new FileStream(« google-api-token.json« , FileMode.Open, FileAccess.Read))
{
var credentialParameters =
NewtonsoftJsonSerializer.Instance.Deserialize<JsonCredentialParameters>(fs);
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(credentialParameters.ClientEmail)
{
Scopes = _SCOPES,
ProjectId = credentialParameters.ProjectId,
}.FromPrivateKey(credentialParameters.PrivateKey));
d) Création d’un CalendarService
Nous pouvons alors préparer un Service d’accès au calendriers : CalendarService.
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = « BookMyService »
});
Ici, le nom de l’application n’est pas essentielle (mettez le nom du projet asp.net core).
e) Récupération de la liste des Calendriers
Juste après, nous allons récupérer la liste des événements de notre calendrier.
Or, pour ça, il nous faut l’identifiant du calendrier à requêter.
Le plus simple ici, c’est de lister (pour nous, en test) tous les calendriers :
var result = service.CalendarList.List().Execute().Items;
A vous alors, en debug, de choisir le bon identifiant de calendrier. (voire de le mettre en config par exemple, ou le rendre paramétrable depuis l’url de l’api).
NOTE: Google propose d’utiliser “primary” pour récupérer le calendrier initial. Je vous recommande plus de choisir le bon identifiant, car primary ramène qu’une liste vide. (normal, ce compte n’a en fait pas d’agenda attitré)
f) On fait une pause : il faut partager le calendrier
Nous devons penser à partager l’agenda que l’on souhaite interroger avec le compte Service que l’on a créé !
Concrètement, cela donne un partage avec l’email que vous avez obtenu lors de la création du compte de Service.
(de type : {usernam}@[project id}.iam.gserviceaccount.com)
Sinon, on ne peut rien lire (les Items sont toujours à 0 éléments).
J’ai même créé un ticket en ce sens dans l’api google.calendar.
g) Listing des événements
Et ça y est, nous allons pouvoir retourner notre liste d’événements depuis notre API.
Créez tout d’abord une classe DTO qui va représenter l’événement. Ici, nous l’avons appelé Appointment :
public class Appointment
{
#region Internal methods
private DateTime GetDateFromString(string value)
{
string[] content = value.Split(‘-‘);
return new DateTime(int.Parse(content[0]),
int.Parse(content[1]),
int.Parse(content[2]));
}
#endregion
#region Properties
/// <summary>
/// Begin date of the appointment
/// </summary>
public DateTime? BeginDate { get; set; }
/// <summary>
/// End date of the appointment
/// </summary>
public DateTime? EndDate { get; set; }
/// <summary>
/// Sets the date from string
/// </summary>
public string BeginDateAsString
{
set
{
this.BeginDate = this.GetDateFromString(value);
}
}
/// <summary>
/// Sets the date from string
/// </summary>
public string EndDateAsString
{
set
{
this.EndDate = this.GetDateFromString(value);
}
}
#endregion
}
Et utilisez-la dans le retour de l’appel à l’API de Google Calendar :
List<Models.Appointment> list = new List<Models.Appointment>();
EventsResource.ListRequest request = service.Events.List(« email-compte-service@group.calendar.google.com »);
request.TimeMin = DateTime.Now;
request.ShowDeleted = false;
request.SingleEvents = true;
request.MaxResults = 10;
request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;
// List events.
Events events = request.Execute();
if (events.Items != null && events.Items.Count > 0)
{
foreach (var eventItem in events.Items)
{
Models.Appointment item = new Models.Appointment()
{
BeginDateAsString = eventItem.Start.Date,
EndDateAsString = eventItem.End.Date
};
list.Add(item);
}
}
else
{
throw new InvalidDataException(« No data result »);
}
And VOILA