Das Zend Framework und die eBay trading API – Teil 4

Die ersten drei Teile dieser Reihe hatten sich mit der theoretischen und praktischen Implementierung des User Consent Flow Prozesses, der für die Authentifizierung des Nutzers mit und der Verwendung der eBay Trading API notwendig ist, befasst. Im vierten und letzten Teil sollen die Implementierungen der letzten drei Teile (Teil 1, Teil 2, Teil 3) dieser Reihe in die Controller und Views umgesetzt und so ein visueller Anmelde- und Authentifizierungsprozess geschaffen werden.

Was wird Teil 4 dieses Guides zeigen?

Wir werden einen Prozess schaffen, der es dem Nutzer erlaubt den eBay User Consent Flow mit Hilfe unserer Webapplikation zu durchschreiten. Dieser Prozess soll möglichst unkompliziert, direkt und intuitiv bedienbar sein. Ich empfehle also die Verwendung von Ajax-Methoden um das User Interface und den darzustellenden Prozess zu visualisieren. Wie das Zend Framework mit Ajax Anfragen umgehen kann wird hier also auch Thema sein.

Warum Ajax?

Wenn wir uns eben an den Ablauf des (in Teil 1 ausführlich beschriebenen) Consent Flow Prozesses erinnern: Der Benutzer muss selbst nur wenige Klicks und Eingaben machen – namentlich die Anmeldung auf der eBay Login-Seite zu der er weitergeleitet wird. Im Hintergrund muss unsere Applikation allerdings zwei Anfragen machen. (1) Eine SessionID von der eBay trading API anfragen und (2) nach der Rückkehr des BenutzersDer eBay User Consent Flow zur Applikation den mit der SessionID verknüpften Auth-Token anfragen.

Hier empfehle ich Ajax: Dem Benutzer soll visualisiert werden, dass sich hinter den Kulissen etwas tut und nicht lange auf den Seitenaufbau warten müssen (die API-Anfragen dauern ein paar wenige Sekunden). Wir werden also die Seite ausliefern, und von dieser eine Ajax-Anfrage starten, die die getSessionID und später die fetchToken Actionen anstoßen wird. Der Benutzer wird ein Lade-Grafik sehen und damit merken, dass sich etwas tut. Die Weiterleitung soll vollautomatisch erfolgen. Das Ergebnis sieht also keinerlei Actionen vom Benutzer auf unserer Applikation vor. Er muss lediglich warten bis er zu eBay weiter geleitet wird und sich dort anmelden kann.

Die benötigten Actions

Wie in Teil 2 bereits aufgestellt brauchen wir neben dem Ebayauth Controller folgende fünf Actions:

  • index (stößt den Consent Flow an)
  • step1 (ist Ziel eines Ajax-Requests – übernimmt getSessionID)
  • success (bei erfolgreichem Login auf eBay wird der Benutzer hierhin weitergeleitet)
  • step2 (ist Ziel eines Ajax-Requests – übernimmt fetchToken)
  • und denied (bei fehlgeschlagenem oder abgebrochenen Login)

und vier Views für den Controller Ebayauth:

  • index.phtml
  • step1.ajax.phtml
  • success.phtml
  • step2.ajax.phtml
  • und denied.phtml

Ajax Requests erkennen und entsprechend handeln

Um die Unterscheidung zwischen ‘normalem’ Request und einem Ajax-Request können wir einen Context-Switcher verwenden, den uns das Zend Framework zur Verfügung stellt. Dieser muss in der init()-Methode des Controllers initialisiert werden uns sieht in unserem Fall so aus:

$contextSwitch = $this->_helper->getHelper('AjaxContext');
$contextSwitch->addActionContext('step1', 'html') // wir geben html zurück
              ->addActionContext('step2', 'html') // möglich wäre auch xml oder json
              ->initContext();

// Das übrige Layout abschalten
if($this->_request->isXmlHttpRequest()) {
     $this->_helper->layout->disableLayout();
}

Unsere zwei step Actions benötigen noch eine kleine Fallunterscheidung. Wir möchten sie nur ausführen lassen, wenn es sich tatsächlich um einen Ajax-Request handelt:

if(!$this->_request->isXmlHttpRequest()) {
    $this->_redirect('/ebayauth/index'); // zum Start des Auth-Prozesses umleiten
}

Der Controller Ebayauth

Springen wir gleich in den Code:

public function indexAction() {}

public function step1Action()
{
    if(!$this->_request->isXmlHttpRequest()) {
        $this->_redirect('/ebayauth/index');
    }

    // die getSessionID API-Anfrage durchführen
    $tokenAdapter = new Ebay_Auth_ConsentFlow();
    $return = $tokenAdapter->getSessionID();

    // Wir müssen die SessionID in einer Datenbank oä. zwischenspeichern
    $modelAccount = new Model_Account();

    if($return != false) {
        // zwischenspeichern - bitte durch eigenen Implementierung ersetzen
        $modelAccount->writeEbaySessionId($this->accountID, $return['sessionId']);
        if(isset($return->ShortMessage)) {
            // bei Fehler ist ShortMessage teil der API Rückgabe
            $this->view->error = (string)$return->ShortMessage;
        } else {
            $this->view->redirectURL = $return['redirectUrl'];
        }
    } else {
        $this->view->error = 'Keine Verbindung zu eBay.';
    }
}

public function successAction() {}

public function step2Action()
{
    if(!$this->_request->isXmlHttpRequest()) {
        $this->_redirect('/ebayauth/index');
    }

    // die im step1 zwischengespeicherte SessionID aus der Datenbank holen
    $modelAccount = new Model_Account();
    $sessionId = $modelAccount->getEbaySessionId($this->accountID);

    // die fetchToken API Anfrage ausführen
    $tokenAdapter = new Ebay_Auth_ConsentFlow();
    $return = $tokenAdapter->getToken($sessionId);

    if($return != false) {
        // auch hier wieder eigenen Implementierung Verwenden
        $modelAccount->writeEbayTokenId($this->accountID, $return['token'], $return['expiration']);
        if(isset($return->ShortMessage)) {
            $this->view->error = (string)$return->ShortMessage;
        } else {
            // Hier festlegen wohin umgeleitet werden soll
            $this->view->redirectURL = '/'; // zurück zur Startseiten
            $this->view->expiration = $return['expiration'];
        }
    } else {
        $this->view->error = 'Keine Verbindung zu eBay';
    }
}

public function deniedAction() {}

Die drei Actions index, success und denied benötigen keine Methoden im Controller. Der JavaScript, der den Ajax-Request anstößt coden wir einfach fest in die views ein.

Die Views

Das hier ist der index view (index.phtml). Wir binden ein JavaScript ein und rufen die Funktion shootAjaxHtml() auf.

<div>
    <div id="loader" class="redirect"><img src="/images/preloader.gif" /> Weiterleitung an eBay wird vorbereitet ...
        <script type="text/javascript">shootAjaxHtml('/ebay/step1', 'loader')</script>
    </div>
</div>

Der step1.ajax.phtml View:

<?php if(isset($this->redirectURL)) { ?>
<p>Automatische Weiterleitung zu eBay in wenigen Sekunden. <a href="<?php echo($this->redirectURL); ?>" title="Weiterleitung">Oder hier klicken.</a></p>
<script type="text/javascript">window.location = '<?php echo($this->redirectURL); ?>';</script>
<?php } elseif(isset($this->error)) { ?>
<p class="error"><strong>Fehler:</strong> <?php echo $this->error; ?></p>
<?php } ?>

success.phtml:

<div>
    <div id="loader" class="redirect"><img src="<?php echo SKINPATH; ?>/images/preloader.gif" /> eBay Anmeldung wird abgeschlossen ...
        <script type="text/javascript">shootAjaxHtml('/ebay/authgettoken', 'loader')</script>
    </div>
</div>

Und step2.ajax.phtml:

<?php if(isset($this->redirectURL)) { ?>
<p class="info">Die Verknüpfung des Benutzerkontos mit eBay verliert am <?php echo date('d.m.Y', strtotime($this->expiration)); ?> um <?php echo date('H:m', strtotime($this->expiration)); ?> Uhr seine Gültigkeit.</p>
<p><a href="/ebay" class="black" title="Zurück zur Startseite">Weiter</a></p>
<?php } elseif(isset($this->error)) { ?>
<p class="error"><strong>Fehler:</strong> <?php echo $this->error; ?></p>
<?php } ?>

Im denied View gebe ich nur eine Fehlermeldung wie “Anmeldung fehlgeschlagen”.

Der JavaScript (mit mootools):

function shootAjaxHtml(action, loaderid)
{
    var remote = new Request.HTML({
        url: action + "?format=html",
        onSuccess: function(html) {
            $(loaderid).getParent('div').empty().adopt(html);
        },
        onFailure: function(xhr) {
            $(loaderid).getParent('div').empty().adopt(new Element('p').set('text', 'Es ist ein Fehler aufgetreten: ' +xhr.status +' ' +xhr.statusText).addClass('error'));
        }}).get();
}

Und damit sind wir auch schon fertig.

Ich hoffe die ersten drei Teile dieser Einführung in eine Mögliche Implementierung des Consent Flows der eBay trading API in eine Webapplikation mit dem Zend Framework waren gut verständlich und konnten einen guten Überblick über die benötigten Implementierungsschritte geben. Teil vier hat anhand von Codebeispielen gezeigt, wie man den Consent Flow möglichst benutzerfreundlich umsetzen kann.

Empfehlungen, Anmerkungen, Verbesserungsvorschläge? Dazu sind die Kommentare da!

  • Share/Bookmark
Leave a comment

0 Comments.

Leave a Reply


[ Ctrl + Enter ]