Табличный виджет

Табличный виджет представляет собой Web приложение определённой структуры (данные выводятся в виде таблицы). Окно виджета представляет собой IFRAME с HTML документом внутри. Окно может изменять размеры по высоте и ширине, может перезагружаться и сворачиваться.

Загрузка содержимого виджета проходит через проксирущий скрипт на Desk.uz, который на основе полученного от источника виджета на другом сервере XML документа генерирует соответствующий HTML код и выводит его в окно виджета в браузере пользователя. Скрипт может передавать необходимые POST и GET данные, а также Cookies.

Основные требования

При разработке табличного XML виджета необходимо соблюдать следующие условия:
  • Содержимое виджета должно передаваться в XML формате определённой структуры, на основе которой генерируется соответствующий HTML код
  • Если есть необходимость передачи данных в формате HTML, то их нужно обрамлять тегом <![CDATA[ данные в html ]]>
  • Все внешние ссылки должны иметь параметр target=”_blank” и использовать абсолютные адреса
  • При использовании HTML и определении количества полей в будущей таблице нужно учитывать, что минимальная ширина окна виджета может составлять 300 px
  • Содержимое виджета должно передаваться в кодировке UTF-8

Авторизация виджета

При добавлении виджета в каталог Desk.uz разработчик получает идентификационные параметры для виджета - DESK_API_KEY и DESK_API_SECRET, с помощью которых будет осуществляться обмен данными между Desk.uz и источником виджета.

DESK_API_KEY - это идентификационный ключ, своего рода логин виджета.
DESK_API_SECRET - это секретный код, известный только Desk.uz и источнику виджета.

На стороне Desk.uz секретный код прописывается в настройках виджета в базе данных. При отправке запроса источнику виджета методом POST передаётся параметр desk_key, представляющий собой строку вида SHA1(DESK_API_SECRET + desk_time) и сам параметр desk_time, который является текущей меткой времени Unix (количество секунд, прошедших с начала Эпохи Unix до текущего времени) с микросекундами. На стороне источника виджета скрипт "знает" секретный код и может воспроизвести операцию и сравнить ключи. Если строки совпадают, значит, запрос пришел действительно от Desk.uz. При этом нужно проверять метку времени, чтобы она превышала значение метки времени последнего обращения (desk_time > last_time), чтобы не дать возможность повторной передачи одной и той же строки. Если проверки прошли, нужно сохранить новую (присланную) метку, например, в какой-нибудь файл для последующего использования.

Примерно та же проверка осуществляется на стороне Desk.uz (для этого перед отправкой данных делается короткий запрос на получение только HTTP заголовков страницы без содержимого, при этом скрипт, обрабатывающий запросы на стороне источника виджета, отправляет заголовок Set-Cookie Deskuz_key со значением SHA1(DESK_API_SECRET + widget_time), где widget_time - метка времени, которая также присоединяется к получившемуся хешу символом «_».

Например, если

DESK_API_SECRET = adce48f99c504b62baa87007c4fb1e6422813cc0

widget_time = 1302179954.49

Hesh_sha1 = dc59ebe8b567cc59421bf53fd8a2876115c62698,

то значение

Cookie = dc59ebe8b567cc59421bf53fd8a2876115c62698_1302179954.49

Desk.uz сохраняет обновлённую метку времени в базе данных. Также заголовок Set-Cookie проверяется при получении ответа на запрос.

Помимо этого, при обмене данными используется своего рода «цифровая подпись», чтобы предотвратить подмену данных. Во время запроса отправляется параметр desk_signature в виде стоки SHA1(GET данные + POST данные + Cookie + DESK_API_SECRET). На стороне источника виджета эта строка проверяется. При ответе формируется строка SHA1(Содержимое ответа + DESK_API_SECRET) и отправляется в виде заголовка Set-Cookie Deskuz_signature, который также проверяется на стороне Desk.uz.

Если виджет написан с использованием языка PHP, то можно использовать готовый класс PHP API Desk.uz , который выполняет все выше описанные операции.

Пример использования PHP API Desk.uz для табличного XML виджета:

<?php /** * Пример кода табличного XML виджета для Desk.uz с использованием PHP API Desk.uz */ require_once('Deskuz_api/config.php'); //подключаем config require_once('Deskuz_api/consumer.php'); //подключаем api //Создаём объект Deskuz_Consumer с параметрами из конфига $consumer = New Deskuz_Consumer(DESK_API_KEY,DESK_API_SECRET,DESK_TIME_STORAGE); /* Проводится начальная обработка запроса. До вызова методов ($consumer->begin,
$consumer->complete, $consumer->make_signature) вывод каких-либо данных делать не
следует, т.к. они посылают HTTP заголовки (Set-Cookie), если всё же требуется выводить
данные, используйте php функции для буферизации вывода ob_start(), ob_end_flush().
*/ if ($consumer->begin()) {   //Основная обработка запроса и проверка его параметров   $consumer->complete();      $xml = '<?xml version="1.0" encoding="UTF-8"?>';   $xml .= '<content>';      //Если все проверки прошли нормально, можно формировать и выводить содержимое виджета   if($consumer->status == 'SUCCESS') {     /*     Если запрашивались персональные данные пользователя (desk_userid, desk_account),
и Desk.uz вернул их, то можно использовать их в дальнейшей логике виджета
    */     if (!empty($consumer->request_data['desk_account'])) {     /*     Здесь формируем содержимое в формате XML для определённого пользователя. Тут возможны запросы
к базе данных на получение нужной информации по пользователю, проверки есть ли такой пользователь
в базе.
    */       $xml .= '<title>Привет, '.$consumer->request_data['desk_account'].'</title>';       $xml .= '<updated>'.date('d.m.Y').'</updated>';       $xml .= '<error>0</error>';       $xml .= '<head bgcolor="#009900" textcolor="#ffffff">';       $xml .= '<title><name>date</name><label>Дата</label></title>';       $xml .= '<title><name>traffic</name><label>Трафик</label></title>';       $xml .= '<title><name>sum</name><label>Сумма</label></title>';       $xml .= '<title><name>balance</name><label>Баланс</label></title>';       $xml .= '</head>';       $xml .= '<items oddbgcolor="#ececec">';       $xml .= '<item><date>12.10.2010</date>';       $xml .= '<traffic>86.85МБ</traffic>';       $xml .= '<sum>02.50</sum>';       $xml .= '<balance>$ 5.64</balance></item>';       $xml .= '<item><date>14.10.2010</date>';       $xml .= '<traffic>100.00МБ</traffic>';       $xml .= '<sum>03.20</sum>';       $xml .= '<balance>$ 4.38</balance></item>';       $xml .= '<item><date>15.10.2010</date>';       $xml .= '<traffic>96.32МБ</traffic>';       $xml .= '<sum>02.97</sum>';       $xml .= '<balance>$ 1.44</balance></item>';       $xml .= '<item><date>20.10.2010</date>';       $xml .= '<traffic>211.40МБ</traffic>';       $xml .= '<sum>06.51</sum>';       $xml .= '<balance>$ -5.39</balance></item>';       $xml .= '</items>';       $xml .= '<links>';       $xml .= '<link><src>http://somewhere.uz/cabinet</src><label>Личный кабинет</label></link>';       $xml .= '<link><src>http://somewhere.uz/pay</src><label>Оплата</label></link>';       $xml .= '</links>';     }     else {       $xml .= '<error>Вы ещё не зарегистрированы в нашей системе</error>';     }   }   else {     //Если возникли ошибки, можно вывести их в какой-нибудь лог-файл     foreach ($consumer->error as $err) {       file_put_contents('file.log',date('d.m.Y H:i:s').' '.$err.'\n ',FILE_APPEND);     }     $xml .= '<error>Извините, на данный момент нет данных</error>';   }   $xml .= '</content>';   //Генерируем и посылаем подпись к содержимому   $consumer->make_signature($xml);   $response = new SimpleXMLElement($xml);   //Выводим содержимое   print $response->asXML();    } ?>


Скрипт такого содержания сгенерирует виджет вида:


Структура XML для табличных виджетов (стандартный шаблон)

<?xml version="1.0" encoding="UTF-8"?> <content> <title>Заголовок виджета</title> <updated>03.12.2010 18:35</updated> <!-- Дата обновления данных в формате дд.мм.гггг чч:мм --> <error>0</error> <!-- Текст ошибки, если нет данных --> <head bgcolor="#000000" textcolor="#FFFFFF"> <!-- Поля таблицы, можно задать цвет фона и текста шапки таблицы -->  <title>    <name>field1</name> <!-- Название поля 1 -->    <label>Заголовок поля 1</label>  </title>  <!-- ... -->  <title>    <name>fieldn</name> <!-- Название поля n -->    <label>Заголовок поля n</label>  </title> </head> <items oddbgcolor="#ECECEC"> <!-- Данные в соответствие с полями, можно задать цвет фона строки для чередования -->  <item>    <field1>Данные</field1>    <!-- ... -->    <fieldn>Данные</fieldn>  </item>  <!-- ... -->  <item>  <!-- ... -->  </item> </items> <links> <!-- Список дополнительных ссылок -->  <link>    <src>http://somewhere.uz/cabinet</src>    <label>Личный кабинет</label>  </link>  <!-- ... -->  <link>  <!-- ... -->  </link> </links> </content>

Структура XML для табличных виджетов (шаблон "Индикатор")

Данный тип виджета предназначен для вывода кратких данных о состоянии какой-либо услуги, например, об остатке средств на счету. Здесь имеется 3 заданных поля, в которых отображаются данные о сервисе (название услуги, ссылка на внешний источник, к примеру, кабинет пользователя, название самого сервиса), значение показателя (в данном случае остаток средств) и индикатор, сигнализирующий пользователю о состоянии услуги (будет красным, если, например, на счету пользователя не осталось средств).

<?xml version="1.0" encoding="UTF-8"?> <content> <updated>03.12.2010 18:35</updated> <!-- Дата обновления данных в формате дд.мм.гггг чч:мм --> <error>0</error><!-- Текст ошибки, если нет данных --> <type>indicator</type> <items> <!-- Данные --> <item>  <service>   <title>Состояние счета</title> <!-- Название услуги -->   <link>http://somewhere.uz/cabinet</link>   <provider>Провайдер</provider>  </service>  <value alt="Баланс">34.512</value> <!-- Показатель (значение) -->  <status alt="Пополните счёт">2</status> <!-- Статус индикатора (1-зелёный (норма), 2-жёлтый (предупреждение), 3-красный (тревога)) --> </item> </items> </content>

Виджет "Индикатор":

Авторизация

Логин