Offline prístup k Facebook dátam

Ak vytvárate aplikácie alebo hry pre Facebook, skôr či neskôr narazíte na problém: ako pristupovať k dátam užívateľa bez toho, aby musel byť prihlásený a aktívne pracovať s vašou aplikáciou.

Napríklad: Dovolenkové odpočítavanie pre Verne.sk. Užívateľ zadá miesto a dátum svojej dovolenky, a aplikácia mu každých pár dní automaticky pridá post do jeho profilu v znení: “Jano ide do Kazachstanu už o 10 dní!” Toto uvidia všetci jeho kamaráti v jeho profile a aj vo svojom news feede.

Ak sa majú tieto posty generovať automaticky, je zrejmé, že sa nemôžeme spoliehať na neustálu prítomnosť užívateľa, a teda budeme musieť získať prístup k jeho profilu aj vtedy, keď je offline. S novým Facebook Graph API to nie je také hrozné, ako to bolo pred rokom-dvoma. Poďme na to.

Poznámka: Celý problém bude demonštrovaný na akomsi pseudo-kóde, ktorý však bez problémov doplníte na plne funkčný kód pre váš obľúbený framework. Celá trieda je Controller; jednotlivé protected metódy zodpovedajú jedntlivým akciám v našom MVC frameworku (a prislúchajú k nim HTML šablóny). Podobne to funguje v Cake PHP, Ruby on Rails, atď.

Táto aplikácia pracuje v IFRAME móde. To znamená, že na stránke http://apps.facebook.com/vasa-aplikacia bude IFRAME, do ktorého sa natiahne aplikácia z vášho servera.

Začíname

Najprv si stiahneme Facebook PHP SDK. V balíku sa nachádza knižnica facebook.php. Tú budeme vkladať cez require_once() na začiatku nášho skriptu.

Teraz nasleduje privátna metóda, ktorá zabezpečí fungovanie facebook session, teda umožní pracovať prihlásenému užívateľovi s našou aplikáciou.

private
    $fb,       // Objekt pre pristup k Facebook Graph API
    $user,     // ID prihlaseneho uzivatela
    $profile;  // Profil prihlaseneho uzivatela

private function initFacebook() {
    // Vytvorime objekt, prostrednictvom ktoreho pristupujeme
    // k Facebook Graph API
    $this->fb = new Facebook(array(
      'appId'  => '143480202330060',
      'secret' => '2a256aac9e1fafca59c42e6855351a7c',
      'cookie' => true,
    ));

    // Skusime obnovit session, ak sme uz predtym boli prihlaseni
    if ($this->fb->getSession()) {

        // ID uzivatela
        $this->user = $this->fb->getUser();

        // Uzivatelska session
        $this->session = $this->fb->getSession();
    }
}

Túto metódu musíme zavolať pri každej interakcii s facebook serverom (ak ide o samostatná načítanie stránky). Sama však nezabezpečí prihlásenie užívateľa – len obnoví už existujúcu session.

Prihlásenie

Aby sme sa mohli prihlásiť, potrebujeme samozrejme inicializovať facebook API, a potom už len overiť, či existuje funkčná session. Ak nie, presmerujeme užívateľa na prihlasovaciu URL. Pri prihlasovaní, resp. schvaľovaní aplikácie, nám užívateľ zároveň dá špeciálne práva, o ktoré ho požiadame: napr. právo zapisovať novinky do jeho news feedu, používať jeho profil, aj keď je on sám odhlásený, kontaktovať ho e-mailom, atď. Následne je presmerovaný naspäť na našu aplikáciu. Niekedy je potrebný ešte jeden refresh – všetko rieši táto jednoduchá metóda, ktorá je zároveň “hlavnou podstránkou” našej aplikácie:

protected function index() {
    $this->initFacebook();

    // Ak este nemame funkcnu session, potrebujeme sa prihlasit
    if (!$this->session) {
        // Tato URL obsahuje ziadost o ziskanie roznych prav,
        // napr. offline_access
        $loginUrl = $this->fb->getLoginUrl(array(
            "req_perms" => "publish_stream,offline_access",
            "canvas"    => 1,
            "fbconnect" => 0
        ));
        // Presmerujeme cele okno browsera (nie len iframe) na login URL
        echo("<script type='text/javascript'>");
        echo("top.location.href = '$loginUrl';");
        echo("</script>");
        exit;
    }

    // Vyskusame ziskat profilove informacie;
    // ak sa nepodarilo, potrebujeme este jeden refresh
    try {
        $this->profile = $this->fb->api("/me");
    } catch(FacebookApiException $e) {
        header("location: /verne/index");
        exit;
    }

    // Tu mozeme zobrazit samotnu aplikaciu - jej hlavnu stranku
}

V tomto momente máme prihláseného užívateľa, máme jeho ID v $this->user a jeho profil v $this->profile. Navyše máme povolený offline_access, čiže jeho session v $this->session je permanentná – teda aj keď sa odhlási, stále môžeme pracovať s jeho kontom. Okrem toho máme právo publish_stream, čiže môžeme posielať v jeho mene správy do feedov.

Posielanie správ do feedu

Teraz si ukážeme, ako používať Facebook Graph API. Jednoduchý príklad sme videli v predošlej metóde. Stačí zavolať $this->fb->api(“/path”) a získame (alebo odošleme) príslušné dáta. Napríklad $this->fb->api(“/me”) vráti asociatívne pole (hash) s profilovými údajmi práve prihláseného užívateľa. $this->fb->api(“/me/friends”) získa pole jeho priateľov, $this->fb->api(“/me/feed”) zase  správy z jeho feedu. Niektoré z týchto “ciest” (API volaní) vedia nie len pasívne získavať údaje, ale aj vytvárať nové záznamy – napr. /me/feed slúži aj na odosielanie nových správ. Okrem nasledujúceho príkladu odporúčam prelistovať dokumentáciu a referenčnú príručku API.

private function sendToFeed() {
    $this->initFacebook();

    try {
        $this->fb->api(
            "/me/feed",
            "post",
            array(
                "message" => "Hlavný text správy",
                "picture" => "URL k obrázku na našom serveri",
                "link"    => "URL na nejakú našu stránku",
                "name"    => "Nadpis pre Link",
                "caption" => "Ďalší nadpis pre Link",
                "description" => "Popis pre Link"
            )
        );
    } catch (Exception $e) {
        echo($e);
    }
}

Offline prístup

Ak potrebujeme pracovať s užívateľovým kontom aj vtedy, keď on v tejto chvíli nevyužíva aplikáciu, využijeme offline_access, teda právo, ktoré sme získali pri prihlásení. Použitie spočíva v dvoch jednoduchých krokoch.

  1. Uložíme si jeho session. V našom prípade stačí niekam do databázy uložiť serializované pole $this->session. To môžeme urobiť prakticky kedykoľvek po jeho prihlásení. Aplikácia pre Verne.sk tak urobí vtedy, keď užívateľ vyplní dovolenkovú destináciu a odošle formulár. V tom prípade si do databázy uložím užívateľove ID a serialize($this->session). Okrem toho môže byť vhodné si do DB uložiť aj ďalšie dáta, napríklad serializovať jeho profil, získaný volaním $this->fb->api(“/me”) – každé takéto volanie je totiž značne pomalé a preto je vhodnejšie uložiť si tieto relatívne statické dáta dopredu, a nepýtať ich v druhom kroku, kde potrebujeme hromadne spracovať mnoho užívateľov.
  2. Potom môžeme s jeho kontom pracovať kedykoľvek. Stačí obnoviť jeho session z databázy, čo demonštruje ďalší príklad. Túto akciu volá CRON v určenú hodinu a funguje nezávisle od toho, či je užívateľ prihlásený alebo nie.
protected function cronSendToFeed() {
    global $db;

    $this->initFacebook();

    // Ziskame vsetky zaznamy z databazy
    // (volanie nasho DB API... vrati pole asociativnych poli)
    $contacts = $db->getArray("
        SELECT contact_id, session
        FROM contacts
    ");

    foreach ($contacts as $contact) {
        // Rekonstruujeme session, ktoru sme kedysi ulozili do databazy
        $this->fb->setSession(unserialize($contact["session"]));

        // Kazdemu uzivatelovi pridame spravu do feedu
        try {
            $this->fb->api(
                "/me/feed",
                "post",
                array(
                    "message" => "Hlavný text správy",
                    "picture" => "URL k obrázku na našom serveri",
                    "link"    => "URL na nejakú našu stránku",
                    "name"    => "Nadpis pre Link",
                    "caption" => "Ďalší nadpis pre Link",
                    "description" => "Popis pre Link"
                )
            );
        } catch (Exception $e) {
            echo($e);
        }
    }
}

Záver

Je dôležité si uvedomiť, že užívateľ môže tieto špeciálne práva našej aplikácii odobrať, prípadne úplne odinštalovať našu aplikáciu. Preto je vhodné obaľovať jednotlivé API volania do try { } blokov, aby sme sa vyhli zbytočným pádom aplikácie.

Navyše odobratie práva publikovať správy vo feede je veľmi jednoduché – pri zmazaní správy vo feede, ktorú vytvorila vaša aplikácia, sa facebook opýta, či chce užívateľ zároveň zrušiť právo publish_stream pre vašu aplikáciu. Preto je vhodné používať toto právo rozumne a nepreháňať to so “spamovaním” užívateľských profilov.



Komentáre