Guest post: Utilizzare le Graph API di Facebook in una Universal Windows app

Questo post è stato scritto da Matteo Pagani , Windows AppConsult Engineer in Microsoft

Qualche tempo fa, sempre su questo blog, avevo scritto un articolo dedicato ad una nuova libreria, rilasciata da un team di Microsoft, per integrare Facebook all’interno di un’applicazione Windows / Windows Phone 8.1 o Windows 10.

La libreria, nel frattempo, si è evoluta ed ha aggiunto nuove funzionalità: in particolar modo, ora è molto più semplice ed efficace interagire con le Graph API di Facebook, ovvero il sistema di API REST che il celebre social network mette a disposizione per integrare i propri servizi in applicazioni di terze parti. Ho deciso, perciò, di scrivere una versione aggiornata dell’articolo, che metta in luce le differenze rispetto alla release originale e le nuove funzionalità.

Le istruzioni per installare la libreria e configurare l’integrazione con Facebook rimangono invariate, quindi potete fare riferimento al post originale. In sintesi, le operazioni da compiere sono:

  1. Registrare una nuova applicazione sul portale sviluppatori di Facebook (http://developers.facebook.com)

  2. Recuperare il SID dell’applicazione Windows, ovvero l’identificativo univoco che lo Store assegna ad ogni app. Volendo, sfruttando la classe WebAuthenticationBroker, è possibile recuperare anche un identificativo temporaneo, senza dover necessariamente registrare l’applicazione sullo Store, tramite il seguente metodo:

     string sid = WebAuthenticationBroker.
                 GetCurrentApplicationCallbackUri().ToString();
    
  3. Il SID ha un formato di questo tipo:

    ms-app://s-1-15-2-2031376880-2039615047-2889735989-2649504141-752107641-3656655002-2863893494/

    Specificare l’SSID appena recuperato all’interno del portale sviluppatori di Facebook, all’interno del campo Windows Store Id. Occorre ricordarsi di rimuovere il protocollo ms-app:// iniziale e lo slash ( / ) finale (quindi, riprendendo il SID di esempio precedente, il valore da inserire sarebbe s-1-15-2-2031376880-2039615047-2889735989-2649504141-752107641-3656655002-2863893494)

  4. Scaricare la libreria da GitHub e aggiungere alla vostra soluzione il progetto più appropriato in base al tipo di applicazione che si sta sviluppando. Ad esempio, se state sviluppando una Universal Windows app per Windows 10, dovrete aggiungere il progetto FBSDK-UWP.vcxproj, contenuto all’interno del percorso winsdkfb\FBWinSDK\FBSDK-UWP\FBSDK-UWP.

A questo punto siete pronti per utilizzare la libreria all’interno della vostra applicazione. Vediamo, innanzitutto, cosa è cambiato rispetto a quanto descritto nel post originale.

La procedura di login

L’autenticazione verso i servizi di Facebook utilizza, come tante altre realtà di questo tipo, il protocollo oAuth: l’utente non inserirà mai le sue credenziali direttamente nell’applicazione, ma lo farà all’interno di una web view il cui contenuto viene gestito direttamente dal fornitore del servizio (Facebook, in questo caso). Se le credenziali sono valide Facebook ci restituirà un token, che ci permetterà di effettuare tutte le successive chiamate verso le API del social network. Questo approccio garantisce maggiore sicurezza all’utente, dato che uno sviluppatore potenzialmente malevolo non entrerà mai in possesso delle credenziali dell’utente.

L’SDK di Facebook ci permette di semplificare il flusso di login e di risparmiare parecchio lavoro: la procedura di generazione della web view e di autenticazione dell’utente sarà gestita in automatico e la libreria si farà carico di restituirci un oggetto (di tipo FBUser) con tutte le informazioni sull’utente loggato, oltrel alla possibilità di interagire con le Graph API.

Ecco come appare la procedura di login:

 private async void OnLogin(object sender, RoutedEventArgs e)
{
    FBSession session = FBSession.ActiveSession;
    session.WinAppId = Sid;
    session.FBAppId = AppId;

    List<string> permissionList = new List<string>();
    permissionList.Add("public_profile");
    permissionList.Add("email");

    FBPermissions permissions = new FBPermissions(permissionList);
    var result = await session.LoginAsync(permissions);
    if (result.Succeeded)
    {
        //do something
    }
}

Innanzitutto si recupera un riferimento alla sessione corrente tramite la proprietà statica FBSession.ActiveSession. In caso non si sia ancora fatto login, questa proprietà non conterrà alcuna informazione: dobbiamo procedere, perciò, a valorizzare le proprietà principali e a chiamare il metodo di login.

Le prime proprietà fondamentali da impostare sono WinAppId e FBAppId. La prima rappresenta il SID dell’applicazione, ovvero l’identificativo che abbiamo specificato nel portale di Facebook. Come anticipato all’inizio del post, possiamo semplicemente recuperarlo utilizzato la classe WebAuthenticationBroker, come nell’esempio seguente:

 string Sid = WebAuthenticationBroker.GetCurrentApplicationCallbackUri()
             .ToString(); 

FbAppId, invece è l’identificativo unico dell’applicazione assegnato da Facebook, che possiamo recuperare dal portale sviluppatori, nella pagina principale della nostra app:

clip_image002

Il passo successivo è definire a quali dati dell’utente vogliamo accedere, tramite il meccanismo dei permessi. Trovate un elenco completo dei permessi consentiti da Facebook nella documentazione all’indirizzo https://developers.facebook.com/docs/facebook-login/permissions

È importante sottolineare che, come impostazione predefinita, Facebook consente in automatico solamente di accedere ad alcuni permessi base, come public_profile (per accedere alle informazioni che l’utente ha reso pubbliche) o email. I permessi più avanzati (come quelli che consentono la pubblicazione di contenuti a nome dell’utente) richiedono che l’applicazione sul portale sviluppatori di Facebook superi un processo di review, durante il quale i gestori del social network verificheranno le motivazioni e i casi d’uso per i quali volete utilizzare tali funzionalità avanzate. Non va confuso con il processo di certificazione dell’applicazione Windows, che invece è effettuato da Microsoft e serve per validare l’app prima della pubblicazione sullo Store.

La gestione dei permessi è uno dei meccanismi che è cambiato rispetto alla versione precedente dell’SDK. Ora vengono specificati all’interno di una collezione di stringhe, che va passata come parametro in fase di inizializzazione della classe FBPermissions. Infine, tale oggetto contenente la lista di permessi va passato al metodo LoginAsync() , che avvierà la procedura di login vera e propria.

Se l’utente non si è mai loggato in precedenza, quello che vedrà sarà un popup con, all’interno, la pagina di login di Facebook, nella quale dovrà immettere le sue credenziali e confermare di voler concedere all’applicazione i permessi che abbiamo richiesto.

clip_image004

Una volta completata l’autenticazione, l’SDK ci restituisce un oggetto di tipo FBResult con il risultato dell’operazione. Tramite la proprietà booleana Succeded possiamo verificare se il login è andato a buon fine o meno: in caso affermativo, possiamo procedere ad effettuare ulteriori operazioni con le API di Facebook.

Se volessimo recuperare le principali informazioni sull’utente che ha fatto login, possiamo sfruttare la proprietà User della classe FBSession, che sarà ora valorizzata correttamente. L’esempio seguente mostra come sfruttare questa proprietà per recuperare il nome dell’utente:

 var result = await session.LoginAsync(permissions);
if (result.Succeeded)
{
    string name = session.User.Name;
}

Interagire con le Graph API

Come anticipato all’inizio del post, le Graph API sono un set di API REST offerte da Facebook che consentono di effettuare le operazioni più disparate, come pubblicare un post a nome dell’utente, effettuare un like, ecc.

Vediamo come l’SDK ci può aiutare ad interagire con tali API, ipotizzando come esempio di voler recuperare l’indirizzo e-mail dell’utente: non si tratta, infatti, di una delle informazioni base esposte dal profilo pubblico. Non troveremo, perciò, una proprietà di nome Email all’interno della classe FBUser, ma dovremo recuperarla proprio tramite le Graph API.

Come tutte le principali API REST, ogni operazione è definita da:

  1. Un endpoint, ovvero l’indirizzo che dobbiamo contattare per interagire con il servizio. Nel caso dell’indirizzo email, dobbiamo sfruttare l’endpoint https://graph.facebook.com/v2.5/me, seguito dal parametro in query string fields con il nome dei campi aggiuntivi che vogliamo recuperare. Nel nostro caso, l’url completo sarà https://graph.facebook.com/v2.5/me?fields=email.
  2. Un metodo del protocollo HTTP, da utilizzare con l’endpoint. Tipicamente, quando si tratta di un’operazione di lettura, si utilizza il metodo GET; operazioni di scrittura (come la pubblicazione di un post su Facebook), invece, solitamente sfruttano il metodo POST. Il nostro scenario ricade nel primo caso, perciò dovremo effettuare una GET.

La prima cosa che ci serve, prima di effettuare l’operazione vera e propria, è una classe che mappi la risposta che ci sarà restituita dai servizi di Facebook. Per questo ci possiamo aiutare con il Graph API Explorer, un tool che consente di simulare l’esecuzione di chiamate verso le Graph API e che troviamo all’indirizzo https://developers.facebook.com/tools/explorer

Il tool presenta una barra degli indirizzi, all’interno della quale possiamo specificare l’endpoint e il metodo del protocollo HTTP che vogliamo utilizzare. Dopo aver premuto il pulsante Submit, nella schermata principale vedremo la risposta in formato JSON restituita dalle Graph API. Se facessimo un test con l’endpoint /me?fields=email, vedremmo che il JSON restituito ha questo formato:

 {
  "email": "mymail@mail.com",
  "id": "10203404048039813"
} 

Visual Studio ci mette a disposizione un pratico metodo per convertire questo JSON in una classe. Ci basta aggiungere una nuova classe al progetto e, una volta aperto il file, aprire il menu Edit di Visual Studio e scegliere Paste Special -> Paste JSON as classes.

Visual Studio genererà per noi una classe con la seguente definizione:

 public class UserProfile
{
    public string id { get; set; }

    public string email { get; set; }
}

Per soddisfare i requisiti dell’SDK di Facebook, però, ci manca un ulteriore elemento: un metodo statico che sia in grado di deserializzare il JSON restituito dal servizio per ottenere un oggetto di tipo UserProfile. Lo creiamo aiutandoci con la popolare libreria JSON.NET, che dobbiamo preventivamente installare tramite NuGet (https://www.nuget.org/packages/Newtonsoft.Json/).

Ecco come appare la definizione completa della classe:

 public class UserProfile
{
    public string id { get; set; }

    public string email { get; set; }

    public static UserProfile FromJson(string jsonText)
    {
        UserProfile profile = JsonConvert.
                              DeserializeObject<UserProfile>(jsonText);
        return profile;
    }
}

Il metodo FromJson() sfrutta la classe JsonConvert per prendere il JSON restituito da Facebook (incluso come parametro in ingresso) e trasformarlo in un oggetto di tipo UserProfile, che viene restituito al chiamante.

Per capire il perché di questa necessità, vediamo il codice completo dell’interazione con le Graph API, che commenterò successivamente:

 private async void OnGet(object sender, RoutedEventArgs e)
{
    string endpoint = "/me";

    PropertySet parameters = new PropertySet();
    parameters.Add("fields", "email");

    FBSingleValue value = new FBSingleValue(endpoint, parameters, 
                                            UserProfile.FromJson);
    FBResult graphResult = await value.GetAsync();

    if (graphResult.Succeeded)
    {
        UserProfile profile = graphResult.Object as UserProfile;
        string name = profile?.email;
        MessageDialog dialog = new MessageDialog(name);
        await dialog.ShowAsync();
    }
}

Il primo passo è definire l’endpoint: è importante sottolineare come i parametri in query string non vadano aggiunti direttamente all’URL, ma separatamente sfruttando la collezione PropertySet. In caso contrario, otterremo degli errori in fase di esecuzione: questo perché l’SDK, dietro le quinte, si fa carico in automatico di impostare l’url base delle API e di aggiungere l’access token recuperato dietro le quinte in fase di login.

Come potete notare, infatti, come endpoint abbiamo specificato solo /me e non l’URL completo, comprensivo del dominio https://graph.facebook.com/v2.5/: non è necessario, dato che ci pensa l’SDK a farlo per noi.

L’uso della proprietà PropertySet è piuttosto semplice: si tratta di una collezione, in cui aggiungere una serie di coppie costituite da chiave (il nome della proprietà, nel nostro caso fields) e valore (il valore della proprietà, nel nostro caso email). Il modo in cui vengono sfruttate queste proprietà dipende dal tipo di richiesta. Nel nostro caso, trattandosi di un’operazione di tipo GET, i parametri saranno aggiunti in query string. Nel caso, invece, si fosse trattato di una POST, i parametri sarebbero aggiunti direttamente nel corpo della richiesta.

Ora scopriamo perché abbiamo definito, in precedenza, un metodo nella classe UserProfile per la conversione del JSON: le operazioni con le Graph API vengono effettuate tramite la classe FBSingleValue che richiede, tra i parametri di inizializzazione, proprio un riferimento a tale metodo statico.

I primi due parametri, invece, sono l’endpoint e la collezione di tipo PropertySet che contiene i parametri della richiesta.

Ora siamo pronti per eseguire la richiesta: anche in questo caso, il metodo da chiamare cambia a seconda del tipo di operazione da eseguire. Nel nostro caso si tratta di una GET, quindi sfruttiamo il metodo asincrono GetAsync() della classe FBSingleValue.

Esattamente come nell’operazione di login ci viene restituito un oggetto di tipo FBResult, che ci permette di utilizzare la proprietà Succeded per determinare se l’operazione sia andata a buon fine o meno. La differenza è che ora abbiamo anche un risultato da elaborare, che troviamo all’interno della proprietà Result. Si tratta, però, di un generico object, dato che le Graph API possono ritornare risultati di tipo differente. Dobbiamo, perciò, fare un cast al tipo che ci aspettiamo (nel nostro caso, UserProfile) prima di poter manipolare il risultato. Il resto sta a noi, in base alla nostra logica applicativa: nell’esempio, ci limitiamo a mostrare a video, con una finestra di dialogo, l’indirizzo email dell’utente loggato.

L’approccio appena visto vale per qualsiasi tipo di operazione con le Graph API. Ciò che dovremmo cambiare, rispetto al codice precedente, sono:

  1. L’endpoint
  2. I parametri da impostare all’interno della collezione PropertySet, in base alla definizione delle API.
  3. La classe da creare per mappare il risultato della risposta in formato JSON.
  4. Il metodo della classe FBSingleValue da chiamare per eseguire l’operazione.

Ad esempio, se invece di recuperare l’indirizzo e-mail dell’utente avessimo voluto pubblicare un post sulla sua bacheca, avremmo utilizzato il seguente codice:

 private async void OnPost(object sender, RoutedEventArgs e)
{
    PropertySet parameters = new PropertySet();
    parameters.Add("title", "Microsoft");
    parameters.Add("link", "https://www.microsoft.com/en-us/default.aspx");
    parameters.Add("description", "Microsoft home page");
    parameters.Add("message", "Posting from my Universal Windows app.");

    string path = "/me/feed";

    FBSingleValue sval = new FBSingleValue(path, parameters, 
                                           FBReturnObject.FromJson);
    FBResult fbresult = await sval.PostAsync();

    if (fbresult.Succeeded)
    {
        // Posting succeeded
    }
    else
    {
        // Posting failed
    }
} 

La differenza principale rispetto all’esempio precedente è che, in questo caso, si tratta di un’operazione “di scrittura”: di conseguenza, non si sfrutta più il comando GET, ma POST e, di conseguenza, il metodo PostAsync() della classe FBSingleValue. Vi ricordo, come anticipato all’inizio del post, che questo secondo esempio non funzionerà immediatamente: è necessario, infatti, richiedere il permesso publish_actions, che viene concesso solo nel momento in cui Facebook ha approvato la nostra applicazione.

In conclusione

Nel corso di questo post abbiamo visto come sfruttare la nuova SDK di Facebook per Windows per effettuare operazioni avanzate con le Graph API. Per ulteriori esempi di codice, potete fare riferimento al progetto su GitHub (https://github.com/microsoft/winsdkfb) e alla documentazione ufficiale (http://microsoft.github.io/winsdkfb/). Happy coding!