Advertisement
  1. Code
  2. PHP

Как создать Slack интерфейс для вашего PHP-приложения

Scroll to top
Read Time: 35 min

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Если вы следили за развитием инструментов командного общения в прошлом году или около того, я уверен, что вы много наслышаны о Slack. Не вдаваясь в детали, Slack является еще одним чат-приложением, предназначенным для бизнеса и команд, но из-за его внимания к деталям и расширяемости многие уже говорят, что этот инструмент значительно изменит нашу работу в будущем.

Как разработчики, мы находимся в хорошем положении, чтобы перейти на тренд и подумать о том, как мы можем использовать Slack в качестве пользовательского интерфейса на основе чата для наших приложений.

Вот почему в этом уроке вы узнаете, как начать работу с интегрированием вашего приложения PHP в Slack, сделав его отправкой сообщений на Slack-канал и ответом на слэш команды.

Вы можете загрузить исходный код учебника из репозитория GitHub или создать его самостоятельно, пройдя учебник.

Код учебника состоит из двух частей:

  • основа, но готовый интерфейс для общения с Slack
  • простой пример скрипта, который использует класс Slack для отправки уведомлений и ответа на слэш команду

Давайте начнем.

1. Создайте свое приложение и подключите его к Slack

Быстрый поиск в Google термина «Slack PHP» вызывает несколько различных интерфейсов Slack, созданных другими разработчиками, поэтому вы можете просто взять существующий проект и подключить его к вашему приложению.

Но API совсем не сложный, поэтому нет причин не развлекаться и подойти к проекту снизу вверх. Таким образом, вы узнаете, как выглядит API (и ваша интеграция). Всегда хорошо немного демистифицировать вещи.

В основе этого руководства лежит построение интерфейса Slack, но для его использования и тестирования там также понадобится приложение. Для этого я решил воспользоваться простым PHP-приложением, которое не использует никаких фреймворков.

Вот как работает приложение примера:

  1. При первом запуске приложения вы увидите кнопку «Добавить в Slack» для подключения приложения к каналу Slack.
  2. Нажатие на кнопку проведет вас через аутентификацию на основе OAuth на Slack. Когда приложение получит токен доступа из Slack, он сохранит его в текстовом файле, чтобы впоследствии использовать его для разговора с Slack.
  3. Когда аутентификация на основе OAuth будет завершена, приложение покажет простое текстовое поле, которое можно использовать для отправки приколотых уведомлений («О да, я робот!») на ваш канал Slack.
  4. Наконец, за кулисами приложение будет реагировать на слэш команды, которые вы или ваши товарищи по команде будут вводить на связанном канале Slack.
This is what our example application will look likeThis is what our example application will look likeThis is what our example application will look like

Вы можете запустить приложение на сервере с поддержкой PHP в Интернете или следовать инструкциям в этом руководстве и запускать его на своей локальной машине для разработки.

Демо-приложение предназначено только для демонстрационных целей, поэтому, в конце концов, вы, вероятно, возьмете интерфейс Slack и подключите его к существующему WordPress, Laravel или другому проекту PHP. На протяжении всего урока я поделюсь некоторыми идеями о том, как вы можете использовать класс интерфейса в реальном приложении вместо нашего простого демонстрационного приложения.

Шаг 1: Создание вашего приложения PHP.

Во-первых, давайте начнем с создания базовой архитектуры проекта и установки всех файлов по своим местам.

Если вы загрузили исходный код из GitHub, вы можете просто просмотреть этот шаг, чтобы убедиться, что вы понимаете, как этот код организован, а затем перейдите к следующему шагу.

Внутри каталога проекта создайте следующую структуру файлов:

  1. index.php: Файл для примера приложения описан выше.
  2. slack-interface: каталог, который будет содержать интерфейс Slack, который мы создадим в этом учебнике. Каталог будет содержать три файла:
    1. slack-interface/class-slack.php: Класс интерфейса Slack.
    2. slack-interface/class-slack-access.php: Класс для хранения информации доступа Slack и передачи ее в приложение с использованием интерфейса.
    3. отвисшей интерфейс / класс-отвисшей апи-exception.php: Класс исключения для передачи ошибок с интерфейса на используемый код.

Затем, с файлами на месте, давайте добавим некоторый контент для каждого из них, чтобы у нас была основа для разработки фактического функционала.

Начните с добавления основной HTML-формы и некоторого кода в index.php:

1
<?php
2
/**

3
 * A lightweight example script for demonstrating how to

4
 * work with the Slack API.

5
 */
6
 
7
// Include our Slack interface classes

8
require_once 'slack-interface/class-slack.php';
9
require_once 'slack-interface/class-slack-access.php';
10
require_once 'slack-interface/class-slack-api-exception.php';
11
12
use Slack_Interface\Slack;
13
use Slack_Interface\Slack_API_Exception;
14
15
//

16
// HELPER FUNCTIONS

17
//

18
19
/**

20
 * Initializes the Slack object.

21
 *

22
 * @return Slack    The Slack interface object

23
 */
24
function initialize_slack_interface() {
25
    return null;
26
}
27
28
/**

29
 * Executes an application action (e.g. 'send_notification').

30
 * 

31
 * @param Slack  $slack     The Slack interface object

32
 * @param string $action    The id of the action to execute

33
 *

34
 * @return string   A result message to show to the user

35
 */
36
function do_action( $slack, $action ) {
37
    $result_message = '';
38
39
    switch ( $action ) {
40
        default:
41
            break;
42
    }
43
44
    return $result_message;
45
}
46
47
//

48
// MAIN FUNCTIONALITY

49
//

50
51
// Setup the Slack interface

52
$slack = initialize_slack_interface();
53
54
// If an action was passed, execute it before rendering the page

55
$result_message = '';
56
if ( isset( $_REQUEST['action'] ) ) {
57
    $action = $_REQUEST['action'];
58
    $result_message = do_action( $slack, $action );
59
}
60
61
//

62
// PAGE LAYOUT

63
//

64
65
?>
66
<html>
67
    <head>
68
        <title>Slack Integration Example</title>
69
        
70
        <style>
71
            body {
72
                font-family: Helvetica, sans-serif;
73
                padding: 20px;
74
            }
75
            
76
            .notification {
77
                padding: 20px;
78
                background-color: #fafad2;
79
            }
80
81
            input {
82
                padding: 10px;
83
                font-size: 1.2em;
84
                width: 100%;
85
            }
86
        </style>
87
    </head>
88
    
89
    <body>
90
        <h1>Slack Integration Example</h1>
91
92
        <?php if ( $result_message ) : ?>
93
            <p class="notice">
94
                <?php echo $result_message; ?>
95
            </p>
96
        <?php endif; ?>
97
98
        <form action="" method="post">
99
            <input type="hidden" name="action" value="send_notification"/>
100
            <p>
101
                <input type="text" name="text" placeholder="Type your notification here and press enter to send." />
102
            </p>
103
        </form>
104
    </body>
105
</html>

Давайте посмотрим на содержимое скрипта и что там на данный момент:

  • В строках 7-13 мы сначала включаем файлы библиотеки, а затем уведомляем PHP о том, что мы будем использовать классы Slack и Slack_API_Exception из пространства имен Slack_Interface. Файлы и класс еще не существуют, но мы скоро доберемся до них.
  • Затем для вспомогательных функций есть два плейсхолдера. Первая вспомогательная функция initialize_slack_interface (строки 19-26) настроит класс Slack для текущего сеанса.
  • Вторая вспомогательная функция do_action (строки 28-45) будет использоваться для обработки других действий, кроме отображения страницы, например, отправки отправленного сообщения на ваш Slack-канал, а также получения входящих Slack команд.
  • После вспомогательных функций есть «основной» функционал нашего небольшого приложения. Во-первых, приложение инициализирует объект Slack (строка 52). Затем в строках 54-59 проверяется, было ли запрошено действие с использованием параметра action. Если да, приложение выполняет действие, используя нашу вспомогательную функцию do_action.
  • Остальная часть скрипта - это базовый HTML (и некоторый CSS, который я написал в том же файле, чтобы все было просто), который отображает форму, которую вы видели на изображении выше.

Затем добавьте некоторый контент в файлы классов, которые составляют наш интерфейс Slack.

В class-slack.php добавьте следующий код:

1
<?php
2
namespace Slack_Interface;
3
4
/**

5
 * A basic Slack interface you can use as a starting point

6
 * for your own Slack projects.

7
 */
8
class Slack {
9
10
    private static $api_root = 'https://slack.com/api/';
11
12
    public function __construct() {
13
        
14
    }
15
16
}

Класс еще не содержит функциональных возможностей, кроме конструктора-заполнителя и определения корневого URL-адреса для Slack API. В строке 2 вы также заметите, что класс помещается в пространство имен Slack_Interface.

Аналогично, в class-slack-access.php добавьте следующий код:

1
<?php
2
namespace Slack_Interface;
3
4
/**

5
 * A class for holding Slack authentication data. 

6
 */
7
class Slack_Access {
8
9
    public function __construct( $data ) {
10
11
    }
12
13
}

Наконец, добавьте следующее содержимое в class-slack-api-exception.php:

1
<?php
2
namespace Slack_Interface;
3
4
use Exception;
5
6
/**

7
 * A simple exception class for throwing Slack API errors.

8
 */
9
class Slack_API_Exception extends Exception {
10
11
}

Теперь мы создали структуру для нашего Slack-приложения и готовы приступить к добавлению некоторых функций.

Но сначала нам нужно сделать приложение доступным в Интернете, чтобы Slack мог с ним общаться.

Шаг 2: сделайте свой сервер доступным в Интернете

Прежде чем вы сможете зарегистрировать свое приложение в Slack и заставить его принимать входящие вызовы от Slack, вам сначала нужно сделать его доступным из Интернета.

Команды также требуют, чтобы приложение использовало HTTPS. Если вам не нужны команды и просто хотите, чтобы ваше приложение могло отправлять уведомления, вы можете пропустить эту часть. Однако для этого учебника, поскольку входящие команды - это большая часть того, что мы хотим сделать, нам нужно решение, которое даст нам поддержку HTTPS.

Если ваш веб-сервер уже настроен на HTTPS, это естественный путь.

Другим вариантом на этапе разработки является использование туннельного сервиса, такого как например localtunnel. Localtunnel предоставляет вашему серверу безопасный URL-адрес в Интернете, который можно указать на ваш веб-сервер, работающий на вашем локальном компьютере. Хотя это не решение для реальных приложений, при тестировании функциональности оно упрощает рабочий процесс (нет необходимости загружать файлы на сервер) и дает вам поддержку HTTPS из коробки.

Чтобы начать работу, установите localtunnel в соответствии с инструкциями на веб-сайте.

Затем запустите свой веб-сервер, отметив порт, который слушает ваш сервер.

И, наконец, как только ваш сервер запустится, запустите localtunnel в терминале, используя следующую команду. Замените your_subdomain своим предпочтительным субдоменом и your_port на порт вашего веб-сервера:

1
lt -s your_subdomain -p your_port

Если ваш запрошенный субдомен доступен, запускается localtunnel, и вы можете получить доступ к своему серверу через URL https://your_subdomain.localtunnel.me.

Tunneling startedTunneling startedTunneling started

Шаг 3: зарегистрируйте новое приложение Slack

Как только ваш сервер будет доступен из Интернета, пришло время зарегистрировать новое приложение Slack.

Чтобы создать приложение Slack, войдите в свою учетную запись Slack и перейдите на страницу «Новое приложение». Вы также можете найти ссылку на эту страницу, нажав Мои приложения в правом верхнем углу панели инструментов Slack API при входе в систему.

You will find the Add New Application link on your My Apps pageYou will find the Add New Application link on your My Apps pageYou will find the Add New Application link on your My Apps page

Страница «Новое приложение» выглядит так:

The New Application pageThe New Application pageThe New Application page

На этой странице введите информацию о своем приложении и нажмите «Создать приложение», чтобы сохранить его:

  • Имя приложения: имя для идентификации вашего приложения в списке приложений, а также в любых сообщениях, отправленных обратно в Slack. Я взял себе «Slack Tutorial».
  • Команда: команда, для которой приложение будет доступно. Когда ваше приложение будет готово, вы можете отправить его в каталог приложения. В этот момент команда Slack проверит его, и, если все будет хорошо, сделает ваше приложение доступным для всех.
  • Краткое описание: описание, которое будет показано пользователям, когда они подключают ваше приложение к своим каналам Slack. Если вы просто тестируете, вы можете оставить его пустым. То же самое касается ссылки «Ссылка на инструкции по установке и поддержка приложения».
  • Иконка: значок, который будет отображаться вашим пользователям, когда они подключат ваше приложение к своим каналам Slack, а также в каждом сообщении, отправленном вашим приложением.
  • URL-адрес перенаправления: URL-адрес, на который Slack перенаправляет ваших пользователей, когда они завершат поток аутентификации. Мы рассмотрим это более подробно на шагах 5 и 6 ниже, но теперь просто установите для поля пункт index.php?action=oauth в вашем приложении, например https://your_subdomain.localtunnel.me/slack-integration/index.php?action=oauth.

Когда определение приложения Slack было создано, вы увидите его на странице «Мои приложения». Там вы можете отредактировать информацию приложения, если это необходимо, и скопировать его учетные данные API (перечисленные в разделе, обозначенном OAuth Information) для вашей интеграции:

OAuth InformationOAuth InformationOAuth Information

Шаг 4. Сохраните учетные данные API в своем приложении.

Затем, поскольку вы будете хранить учетные данные API в своем приложении PHP, полезно подумать о том, как сделать это как можно безопаснее.

В целом, это не считается хорошей практикой для передачи такой конфиденциальной информации в систему контроля версий. Вместо этого вы можете пойти с одним из следующих вариантов:

  • Сохранение учетных данных в вашей базе данных может быть хорошей идеей, например, в плагине WordPress, где каждый пользователь будет иметь свой собственный набор учетных данных API, и вы хотите, чтобы они могли устанавливать свои учетные данные непосредственно из панели управления администратора.
  • Другой вариант (более безопасный, чем первый) заключается в определении учетных данных как констант в файле конфигурации непосредственно на сервере (опять же, если работать с WordPress, wp-config.php будет естественным выбором). Просто убедитесь, что файл конфигурации не открыт внешнему миру (или не включен в управление версиями).
  • Наконец, вы можете установить идентификатор клиента и токен как переменные среды на сервере. Таким образом, информация не сохраняется в файле, который может быть случайно прочитан вне приложения.

В нашей реализации мы рассмотрим комбинацию из двух последних методов. Чтобы интерфейс Slack знал об учетных данных API, добавьте две новые функции в класс Slack:

1
/**

2
 * Returns the Slack client ID.

3
 * 

4
 * @return string   The client ID or empty string if not configured 

5
 */
6
public function get_client_id() {
7
    // First, check if client ID is defined in a constant

8
    if ( defined( 'SLACK_CLIENT_ID' ) ) {
9
        return SLACK_CLIENT_ID;
10
    }
11
12
    // If no constant found, look for environment variable

13
    if ( getenv( 'SLACK_CLIENT_ID' ) ) {
14
        return getenv( 'SLACK_CLIENT_ID' );
15
    }
16
  	
17
    // Not configured, return empty string

18
    return '';
19
}
20
21
/**

22
 * Returns the Slack client secret.

23
 * 

24
 * @return string   The client secret or empty string if not configured

25
 */
26
private function get_client_secret() {
27
    // First, check if client secret is defined in a constant

28
    if ( defined( 'SLACK_CLIENT_SECRET' ) ) {
29
        return SLACK_CLIENT_SECRET;
30
    }
31
32
    // If no constant found, look for environment variable

33
    if ( getenv( 'SLACK_CLIENT_SECRET' ) ) {
34
        return getenv( 'SLACK_CLIENT_SECRET' );
35
    }
36
37
    // Not configured, return empty string

38
    return '';
39
}

Две функции являются почти точными копиями друг друга, поэтому давайте просто рассмотрим первую, get_client_id, чтобы получить представление о том, что они делают:

  • Во-первых, в строках 7-10 функция проверяет, был ли идентификатор клиента сохранен в константе с именем SLACK_CLIENT_ID. Если эта константа определена, функция возвращает свое значение.
  • Если константа не определена, функция продолжается, проверяя переменную среды с тем же именем (строки 12-15).
  • Наконец, если идентификатор клиента не найден, функция возвращает пустую строку.

Чтобы использовать этот подход, добавьте свои учетные данные доступа в начале index.php или, что еще лучше, отдельный PHP-файл, который вы включаете в index.php, но никогда не выполняете контроль версий:

1
// Define Slack application identifiers

2
// Even better is to put these in environment variables so you don't risk exposing

3
// them to the outer world (e.g. by committing to version control)

4
define( 'SLACK_CLIENT_ID', 'Paste your client ID here' );
5
define( 'SLACK_CLIENT_SECRET', 'Paste your client secret here' );

Шаг 5: Создание структуры данных для хранения информации авторизации

Теперь, когда мы сохранили учетные данные приложения, пришло время перейти на следующий уровень аутентификации: позволить вашим пользователям добавлять приложение на свои учетные записи Slack.

Протокол аутентификации состоит из трех этапов:

  1. Если пользователь еще не добавил приложение в Slack, в приложении отображается кнопка «Добавить в Slack».
  2. После нажатия на кнопку пользователю предлагается разрешить приложению отправлять уведомления и отвечать на команды на канале Slack.
  3. Когда пользователь разрешает приложение, ваше приложение получает временный код, который затем обменивается на набор постоянной информации проверки подлинности с использованием Slack API.

Скоро мы начнем реализацию потока, но сначала нам понадобится метод хранения и использования информации об аутентификации, как только мы получим ее от Slack.

Для этого мы будем использовать класс Slack_Access, который мы создали ранее в учебнике.

В верхней части класса сначала определите переменные для хранения данных авторизации:

1
// Slack OAuth data

2
3
private $access_token;
4
private $scope;
5
private $team_name;
6
private $team_id;
7
private $incoming_webhook;

Затем реализуйте конструктор для чтения значений этих переменных из массива, переданного в качестве параметра:

1
/**

2
 * Sets up the Slack_Access object with authentication data.

3
 *

4
 * @param array $data   The Slack OAuth authentication data. If the user

5
 *                      hasn't been authenticated, pass an empty array.

6
 */
7
public function __construct( $data ) {
8
    $this->access_token = isset( $data['access_token'] ) ? $data['access_token'] : '';
9
    $this->scope = isset( $data['scope'] ) ? $data['scope'] : array();
10
    $this->team_name = isset( $data['team_name'] ) ? $data['team_name'] : '';
11
    $this->team_id = isset( $data['team_id'] ) ? $data['team_id'] : '';
12
    $this->incoming_webhook = isset( $data['incoming_webhook'] ) ? $data['incoming_webhook'] : array();
13
}

Конструктор инициализирует переменные значениям, переданным в массиве $data, или пустым значениям, если часть информации отсутствует в массиве атрибутов.

Сразу после конструктора добавьте функцию для проверки того, был ли объект инициализирован действительными данными:

1
/**

2
 * Checks if the object has been initialized with access data.

3
 *

4
 * @return bool True if authentication data has been stored in the object. Otherwise false.

5
 */
6
public function is_configured() {
7
    return $this->access_token != '';
8
}

Затем для хранения данных аутентификации добавьте следующую функцию:

1
/**

2
 * Returns the authorization data as a JSON formatted string.

3
 *

4
 * @return string   The data in JSON format

5
 */
6
public function to_json() {
7
    $data = array(
8
        'access_token' => $this->access_token,
9
        'scope' => $this->scope,
10
        'team_name' => $this->team_name,
11
        'team_id' => $this->team_id,
12
        'incoming_webhook' => $this->incoming_webhook
13
    );
14
15
    return json_encode( $data );
16
}

Функция возвращает строку в формате JSON, содержащую данные авторизации.

В реальном приложении вы, скорее всего, захотите связать информацию авторизации с учетными записями пользователей и сохранить данные JSON вместе с информацией пользователя. Однако в нашем примере приложение - еще раз - мы пойдем с простым подходом: предположим, что только один пользователь (вы) когда-либо будет использовать приложение, и поэтому нам нужно будет только сохранить один набор учетных данных OAuth ,

Но сначала перейдем к классу Slack и используем функционал, который мы только что добавили в Slack_Access.

Внесите конструктор для создания объекта доступа для текущего экземпляра Slack:

1
/**

2
 * @var Slack_Access    Slack authorization data

3
 */
4
private $access;
5
6
/**

7
 * Sets up the Slack interface object.

8
 *

9
 * @param array $access_data An associative array containing OAuth

10
 *                           authentication information. If the user

11
 *                           is not yet authenticated, pass an empty array.

12
 */
13
public function __construct( $access_data ) {
14
    if ( $access_data ) {
15
        $this->access = new Slack_Access( $access_data );
16
    }
17
}

Сразу после конструктора добавьте функцию для проверки наличия данных авторизации в объекте Slack:

1
/**

2
 * Checks if the Slack interface was initialized with authorization data.

3
 *

4
 * @return bool True if authentication data is present. Otherwise false.

5
 */
6
public function is_authenticated() {
7
    return isset( $this->access ) && $this->access->is_configured();
8
}

Шаг 6: Показать кнопку Add to Slack

При наличии структуры данных мы можем начать использовать проверки авторизации в нашем основном приложении и показать кнопку «Добавить в Slack».

Обратите внимание, что, хотя сам класс Slack_Access может использоваться в большинстве приложений, как и есть, решение, используемое в index.php, предназначено только для демонстрации: поскольку у нас нет управления пользователями или базы данных, мы просто сохраним JSON- отформатированные учетные данные доступа от to_json в текстовом файле.

На данный момент файл еще не существует, а это означает, что приложение еще не добавлено в учетную запись Slack, а вместо текстового поля следует указать кнопку «Добавить в Slack».

Чтобы реализовать простую систему хранения, начните с изменений в index.php function initialize_slack_interface со следующим:

1
/**

2
 * Initializes the Slack handler object, loading the authentication

3
 * information from a text file. If the text file is not present,

4
 * the Slack handler is initialized in a non-authenticated state.

5
 *

6
 * @return Slack    The Slack interface object

7
 */
8
function initialize_slack_interface() {
9
    // Read the access data from a text file

10
    if ( file_exists( 'access.txt' ) ) {
11
        $access_string = file_get_contents( 'access.txt' );
12
    } else {
13
        $access_string = '{}';
14
    }
15
16
    // Decode the access data into a parameter array

17
    $access_data = json_decode( $access_string, true );
18
19
    $slack = new Slack( $access_data );
20
    
21
    return $slack;
22
}

В строках 9-14 функция считывает данные авторизации в виде строки из текстового файла access.txt, если файл существует. Если файл не существует, строка JSON инициализируется пустым хэшем.

Затем в строке 17 данные преобразуются в массив для перехода к интерфейсу Slack (строка 19).

Теперь мы готовы собрать все это вместе и чтобы наше маленькое приложение показало кнопку «Добавить в Slack", если данные авторизации не найдены.

В конце index.php замените форму следующим фрагментом кода:

1
<?php if ( $slack->is_authenticated() ) : ?>
2
    <form action="" method="post">
3
        <input type="hidden" name="action" value="send_notification"/>
4
        <p>
5
            <input type="text" name="text" placeholder="Type your notification here and press enter to send." />
6
        </p>
7
    </form>
8
<?php else : ?>
9
    <p>
10
        <a href="https://slack.com/oauth/authorize?scope=incoming-webhook,commands&client_id=<?php echo $slack->get_client_id(); ?>"><img alt="Add to Slack" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcset="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/add_to_slack@2x.png 2x"></a>
11
    </p>
12
<?php endif; ?>

В фрагменте кода в строке 1 вы заметите, что форма теперь окружена проверкой is_authenticated, чтобы пользователь не мог видеть ее до авторизации приложения.

Затем, в ветке else, на строках 8-12, код теперь отображает кнопку «Добавить в Slack».

Давайте посмотрим, что находится внутри тега кнопки:

  • Прежде всего, кнопка указывает пользователя на поток авторизации OAuth Slack (oauth/authorize).
  • Используя параметр scope, приложение может определить разрешения, которые пользователь должен предоставить: в нашем случае нам нужны входящие хуки (incoming-webhook) для отправки уведомлений и возможность добавления новых команд (commands). Полный список доступных разрешений можно найти в документации по API.
  • Наконец, ссылка должна включать публичный ключ приложения (client_id), который мы сохранили в нашем приложении ранее в учебнике.

Остальное - это просто базовый HTML-код, отображающий изображение кнопки.

Теперь, когда вы открываете приложение в своем веб-браузере, вот что вы должны увидеть:

The Add to Slack buttonThe Add to Slack buttonThe Add to Slack button

Шаг 7. Завершаем OAuth аутентификацию

Теперь кнопка «Добавить в Slack» находится на своем месте. Но что происходит, когда пользователь нажимает на нее?

Во-первых, пользователь увидит страницу аутентификации приложения Slack, которая выглядит так:

Give the Slack application access to one your Teams channelsGive the Slack application access to one your Teams channelsGive the Slack application access to one your Teams channels

Затем, если все выглядит хорошо для пользователя, он или она нажмут на кнопку Authorize, после чего выполнение вернется в ваше приложение.

Напомним, что когда мы определили приложение в Slack, мы установили URL обратного вызова (YOUR_URL/index.php?action=oauth).

Чтобы справиться с этим обратным вызовом, мы будем использовать систему действий, созданную нами ранее в учебнике. В вашем реальном приложении вам придется внедрять URL-адреса обратного вызова таким образом, который хорошо подходит для используемой платформы. Например, в WordPress вы можете создать пользовательскую константу с помощью механизма перезаписи.

Однако, хотя способ получения обратного вызова будет отличаться в зависимости от приложения, то, что мы делаем с данными, полученными от Slack, остается неизменным.

Измените до сих пор пустую функцию do_action следующим образом:

1
/**

2
 * Executes an application action (e.g. 'send_notification').

3
 *

4
 * @param Slack  $slack     The Slack interface object

5
 * @param string $action    The id of the action to execute

6
 *

7
 * @return string   A result message to show to the user

8
 */
9
function do_action( $slack, $action ) {
10
    $result_message = '';
11
12
    switch ( $action ) {
13
14
        // Handles the OAuth callback by exchanging the access code to

15
        // a valid token and saving it in a file

16
        case 'oauth':
17
            $code = $_GET['code'];
18
19
            // Exchange code to valid access token

20
            try {
21
                $access = $slack->do_oauth( $code );
22
                if ( $access ) {
23
                    file_put_contents( 'access.txt', $access->to_json() );
24
                    $result_message = 'The application was successfully added to your Slack channel';
25
                }
26
            } catch ( Slack_API_Exception $e ) {
27
                $result_message = $e->getMessage();
28
            }
29
            break;
30
31
        default:
32
            break;
33
34
    }
35
36
    return $result_message;
37
}

Когда пользователь возвращается из потока авторизации, эта функция вызывается с помощью $action, установленного в 'oauth'. Наряду с запросом приложение получает одноразовый токен, который он читает в строке 17.

Затем, в строке 21, чтобы завершить авторизацию, функция вызывает в нашем классе Slack функцию do_oauth.

Как вы помните ранее, при инициализации интерфейса Slack мы пытались загрузить данные аутентификации из текстового файла access.txt. Когда файл не был найден, приложение решило, что пользователь еще не аутентифицировал приложение и показало кнопку «Добавить в Slack».

Теперь, после того, как аутентификация OAuth была успешно завершена, в строке 23 функция сохраняет данные в этот файл.

Но прежде чем мы доберемся туда, чтобы завершить поток аутентификации, нам все равно нужно реализовать функцию do_oauth в классе Slack.

Эта функция вызовет интерфейс Slack API для обмена кодом, который был передан функции обратного вызова OAuth, с данными аутентификации, которые могут храниться постоянно и использоваться для связи со Slack до тех пор, пока пользователь не аннулирует авторизацию.

Для этого нам понадобится способ сделать HTTP-запрос на Slack-сервер. Существует много способов сделать HTTP-запросы в PHP, и то, что представлено здесь, - не единственный способ. Например, если вы разрабатываете для WordPress, вы можете использовать wp_remote_get и wp_remote_post.

Однако на этот раз, чтобы сохранить все независимым от какой-либо конкретной платформы разработки приложений, я решил воспользоваться библиотекой с красивым и чистым синтаксисом Requests.

Установите библиотеку в соответствии с инструкциями на ее веб-сайте. В исходном коде в репозитории Tuts + GitHub вы найдете готовую конфигурацию Composer для включения библиотеки в наше приложение.

После того, как вы установили «Requests» (или другой библиотеки HTTP на ваш выбор ), добавьте функцию do_oauth в класс Slack:

1
/**

2
 * Completes the OAuth authentication flow by exchanging the received

3
 * authentication code to actual authentication data.

4
 *

5
 * @param string $code  Authentication code sent to the OAuth callback function

6
 *

7
 * @return bool|Slack_Access    An access object with the authentication data in place

8
 *                              if the authentication flow was completed successfully.

9
 *                              Otherwise false.

10
 *

11
 * @throws Slack_API_Exception 

12
 */
13
public function do_oauth( $code ) {
14
    // Set up the request headers

15
    $headers = array( 'Accept' => 'application/json' );
16
		
17
    // Add the application id and secret to authenticate the request

18
    $options = array( 'auth' => array( $this->get_client_id(), $this->get_client_secret() ) );
19
20
    // Add the one-time token to request parameters 

21
    $data = array( 'code' => $code );
22
23
    $response = Requests::post( self::$api_root . 'oauth.access', $headers, $data, $options );
24
		
25
    // Handle the JSON response

26
    $json_response = json_decode( $response->body );
27
28
    if ( ! $json_response->ok ) {
29
        // There was an error in the request

30
        throw new Slack_API_Exception( $json_response->error );
31
    }
32
33
    // The action was completed successfully, store and return access data

34
    $this->access = new Slack_Access(
35
        array(
36
            'access_token' => $json_response->access_token,
37
            'scope' => explode( ',', $json_response->scope ),
38
            'team_name' => $json_response->team_name,
39
            'team_id' => $json_response->team_id,
40
            'incoming_webhook' => $json_response->incoming_webhook
41
        )
42
    );
43
44
    return $this->access;
45
}

Давайте рассмотрим функцию по строкам:

В строках 14-18 функция инициализирует параметры для HTTP-запроса. Стоит отметить, что идентификатор клиента и секретный ключ передаются в качестве параметров запроса для использования основного механизма аутентификации HTTP.

В строке 21 вы заметите, что мы отправляем одноразовый токен, полученный в функции обратного вызова, обратно в API Slack для идентификации запроса.

Запрос POST отправляется в строке 23. Затем функция выполняется путем анализа ответа и либо настройки и возврата данных авторизации (строки 33-44), если все прошло хорошо, либо выбрасывание исключения (строки 28-31), если была ошибка с запросом.

Теперь поток «Добавить в Slack» готов. Когда вы попробуете, вы должны увидеть следующее:

The authentication flow was completed successfullyThe authentication flow was completed successfullyThe authentication flow was completed successfully

Кроме того, если вы заглянете в каталог проекта, вы должны найти текстовый файл с именем access.txt с данными аутентификации, хранящимися в нем.

Теперь мы готовы к интересной части: сделать сообщение приложения на вашем Slack-канале.

2. Отправлять уведомление на канал Slack

Отправка уведомлений на канал Slack - это мощный способ постоянно обновлять команду на важных для них событиях. Интернет-магазин может отправлять уведомления о новых покупках, программное обеспечение для отслеживания ошибок может автоматически уведомлять разработчиков, и этот список можно продолжать.

В нашем примере, как вы уже видели в пользовательском интерфейсе ранее, мы отправим любое уведомление, которое пользователь отправляет, используя текстовое поле.

Но функциональность отправки любых других типов уведомлений одинакова, поэтому, как только она будет готова, вы можете использовать тот же код для отправки своих более сложных уведомлений.

Шаг 1. Создание функции отправки уведомления.

В классе Slack добавьте следующую функцию:

1
/**

2
 * Sends a notification to the Slack channel defined in the

3
 * authorization (Add to Slack) flow.

4
 *

5
 * @param string $text          The message to post to Slack

6
 * @param array $attachments    Optional list of attachments to send 

7
 *                              with the notification

8
 *

9
 * @throws Slack_API_Exception

10
 */
11
public function send_notification( $text, $attachments = array() ) {
12
    if ( ! $this->is_authenticated() ) {
13
        throw new Slack_API_Exception( 'Access token not specified' );
14
    }
15
16
    // Post to webhook stored in access object

17
    $headers = array( 'Accept' => 'application/json' );
18
19
    $url = $this->access->get_incoming_webhook();
20
    $data = json_encode(
21
        array(
22
            'text' => $text,
23
            'attachments' => $attachments,
24
            'channel' => $this->access->get_incoming_webhook_channel(),
25
        )
26
    );
27
28
    $response = Requests::post( $url, $headers, $data );
29
		
30
    if ( $response->body != 'ok' ) {
31
        throw new Slack_API_Exception( 'There was an error when posting to Slack' );
32
    }
33
}

Отправка уведомления на Slack-канал выполняется с использованием веб-хука, определенного для авторизации URL-адреса, который Slack предоставляет приложению для отправки на канал.

Мы не обращали на это внимания ранее в потоке «Добавить в Slack», но если вы снова просмотрите данные в Slack_Access, вы заметите, что Slack возвращает поле с именем incoming_webhook. Это поле представляет собой массив с двумя полями внутри него: URL-адрес, на который должны отправляться наши уведомления, и канал, выбранный пользователем для сообщений приложения.

Чтобы получить доступ к этим данным, добавьте следующие две функции в класс Slack_Access:

1
/**

2
 * Returns the webhook URL for posting notifications.

3
 * 

4
 * @return string   The incoming webhook URL

5
 */
6
public function get_incoming_webhook() {
7
    if ( is_array( $this->incoming_webhook ) && isset( $this->incoming_webhook['url'] ) ) {
8
        return $this->incoming_webhook['url'];
9
    }
10
11
    return '';
12
}
13
14
/**

15
 * Returns the channel to which the user has authorized the application

16
 * to post notifications.

17
 * 

18
 * @return string   The selected Slack channel's ID

19
 */
20
public function get_incoming_webhook_channel() {
21
    if ( is_array( $this->incoming_webhook ) && isset( $this->incoming_webhook['channel'] ) ) {
22
        return $this->incoming_webhook['channel'];
23
    }
24
25
    return '';
26
}

Теперь вернемся к функции send_notification выше и рассмотрим, как эти функции используются для отправки уведомления.

В строке 19 вы заметите, что HTTP-запрос отправляется на URL-адрес входящего веб-хука, хранящийся в данных авторизации.

И позже, в строке 24, канал передается в параметрах запроса вместе с текстом и любыми вложениями, которые мы хотим опубликовать.

Шаг 2: Используйте функцию отправки уведомлений в примере приложения

Теперь, когда мы внедрили функцию отправки уведомлений, приложим функциональность к нашему пользовательскому интерфейсу и протестируем ее.

Добавьте следующую ветку case в функцию do_action в index.php:

1
// Sends a notification to a Slack channel

2
case 'send_notification':
3
    $message = isset( $_REQUEST['text'] ) ? $_REQUEST['text'] : 'Hello!';
4
5
    try {
6
        $slack->send_notification( $message );
7
        $result_message = 'Notification sent to Slack channel.';	
8
    } catch ( Slack_API_Exception $e ) {
9
        $result_message = $e->getMessage();
10
    }
11
    break;

Этот фрагмент кода считывает сообщение из параметров запроса (строка 3) и использует функцию send_notification, которую мы только что создали, чтобы отправить ее в Slack (строка 6).

Поскольку форма была создана уже в начале учебника, теперь вы готовы отправить свое первое сообщение на ваш канал Slack. Введите что-то в текстовое поле и нажмите Enter, чтобы отправить форму.

Затем взгляните на свой канал Slack, чтобы увидеть сообщение:

The bot just sent its first messageThe bot just sent its first messageThe bot just sent its first message

Шаг 3: Используйте вложения, чтобы сделать ваши уведомления более информативными

В функции send_notification вы, вероятно, заметили параметр, называемый attachments. Я еще не упомянул об этом, так как он не подходит для примера приложения. Однако вложения - это мощный способ передать более интересную информацию о событиях вашего приложения на канал Slack, и вы, вероятно, захотите использовать их в своих приложениях.

Итак, давайте немного поэкспериментируем с вложениями, изменив вызов send_notification со второго шага. Замените вызов $slack->send_notification() следующим фрагментом кода:

1
$attachments = array(
2
    array(
3
        'fallback' => 'Jarkko just posted a new bread recipe.',
4
5
        'title' => 'Sprouted Wheat Bread',
6
        'title_link' => 'https://bread-magazine.com/sprouted-wheat-flour/',
7
8
        'text' => 'Jarkko just posted a new bread recipe. Check it out.',
9
10
        'color' => '#7CD197',
11
12
        'fields' => array(
13
            array(
14
                'title' => 'Preparation time',
15
                'value' => ':hourglass: 24 hours',
16
                'short' => true
17
            ),
18
            array(
19
                'title' => 'Difficulty',
20
                'value' => 'Medium',
21
                'short' => true
22
            ),
23
        ),
24
        'image_url' => 'https://s3.amazonaws.com/interested/wordpress/wp-content/uploads/2015/02/12093547/sprouted-bread.jpg'
25
    )
26
);
27
28
$slack->send_notification( $message, $attachments );

Вложение, указанное в приведенном выше коде, представляет собой мнимое уведомление о добавлении нового рецепта хлеба в базу данных рецептов. Это просто пример, поэтому перейдите к нему и измените его, чтобы увидеть, как изменения, внесенные вами в него, влияют на вывод на канале Slack.

  • fallback: обязательное текстовое сообщение, которое отображается, если вложение невозможно отобразить.
  • title: Заголовок для вложения, стилизованный с использованием более крупного шрифта.
  • title_link: URL-адрес, который будет открыт, когда пользователь нажмет на ссылку. В нашем примере это покажет рецепт.
  • text: текст, который будет отображаться внутри вложения.
  • color: цвет для линии на левой стороне вложения.
  • fields: список полей данных, которые будут отображаться в вложениях. В этом примере они используются для отображения некоторой информации о рецепте.
  • image_url: URL-адрес изображения, отображаемого в приложении.

Вот что вы увидите при публикации уведомления с указанным выше приложением:

A Slack notification with an attachmentA Slack notification with an attachmentA Slack notification with an attachment

Играйте с параметрами и смотрите, как их изменение влияет на сообщения, размещенные на вашем канале Slack: измените атрибуты, отправьте новое уведомление и посмотрите, что изменилось.

Для получения дополнительной информации о вложениях ознакомьтесь с документацией Slack.

3. Добавим в приложение возможность отвечать на слэш команды 

Теперь ваше приложение может общаться со Slack. Далее, мы сделаем коммуникационную работу и другим способом: добавив команды, мы можем заставить Slack работать как интерфейс для нашего приложения.

В реальном приложении это имеет много вариантов использования. Маркировка ошибки как фиксированная, маркировка заказа, как отправлен, - это лишь некоторые из примеров, которые приходят на ум.

Давайте продолжим и реализуем шуточный запрос, чтобы публиковать анекдот, когда кто-то вводит /joke на канале Slack.

Шаг 1. Определение слэш команды

Сначала перейдите на страницу настроек Slack Application, чтобы определить новую команду.

Прокрутите вниз до раздела с названием, Slash Commands и нажмите «Создать новую команду».

Slash CommandsSlash CommandsSlash Commands

На следующем экране введите необходимую информацию для указания новой команды и нажмите «Сохранить».

Create New CommandCreate New CommandCreate New Command

Ниже приведены краткие описания полей на этой странице:

  • Команда: команда, включая символ косой черты. Например, /joke.
  • URL-адрес запроса: URL-адрес вашего сервера, который должен вызываться, когда кто-то вводит эту команду на канале Slack. Именно здесь вам пригодится локальный туннель: URL-адрес должен использовать HTTPS и быть доступен для подключения из Интернета. Используйте следующий формат URL, чтобы сделать URL-адрес запроса совместимым с функциональностью, которую мы построим на шаге 2: YOUR_SERVER/index.php?action=command.
  • Краткое описание: описание, которое отображается во всплывающем окне автозаполнения, когда кто-то вводит команду.
  • Совет по использованию: Если команда принимает параметры, вы можете описать их здесь. Этот текст также отображается в диалоговом окне автозаполнения.

После сохранения команды вы найдете новую команду, показанную в разделе «Команды слэш». Вы можете использовать кнопки для редактирования или удаления.

Slash Commands now include the joke commandSlash Commands now include the joke commandSlash Commands now include the joke command

Ниже списка команд вы найдете строку с надписью Verification Token.

Вы можете использовать этот токен, чтобы убедиться, что команды действительно идут от Slack до их выполнения. Храните токен в приложении так же, как и для идентификатора клиента и секретного токена ранее в учебнике, например, добавив константу в начало index.php:

1
define( 'SLACK_COMMAND_TOKEN', 'Paste your command verification token here' );

Шаг 2. Создание системы для отслеживания слэш команд в вашем приложении

Теперь Slack идентифицирует команду, когда кто-то вводит ее в окне Slack chat (вы можете попробовать ее сейчас, чтобы просмотреть всплывающее окно автозаполнения).

Когда пользователь отправляет команду, Slack вызовет наш сервер по URL-адресу запроса, указанному на предыдущем шаге. Теперь нам нужно реализовать функциональность, чтобы наше приложение правильно реагировало на это.

Поскольку вы можете добавить несколько команд в ваше приложение Slack, полезно поддерживать переменное количество команд. Вот почему мы начнем с создания системы для отслеживания команд в приложении.

Во-первых, в классе Slack добавьте следующую переменную для хранения команд:

1
/**

2
 * @var array $slash_commands   An associative array of slash commands 

3
 *                              attached to this Slack interface

4
 */
5
private $slash_commands;

В конструкторе класса добавьте строку для инициализации массива:

1
$this->slash_commands = array();

Затем создайте функцию для добавления в массив новой команды:

1
/**

2
 * Registers a new slash command to be available through this

3
 * Slack interface.

4
 *

5
 * @param string    $command    The slash command

6
 * @param callback  $callback   The function to call to execute the command

7
 */
8
public function register_slash_command( $command, $callback ) {
9
    $this->slash_commands[$command] = $callback;
10
}

Теперь, когда у вас есть список команд, добавьте функцию для выполнения команды:

1
/**

2
 * Runs a slash command passed in the $_POST data if the

3
 * command is valid and has been registered using register_slash_command.

4
 *

5
 * The response written by the function will be read by Slack.

6
 */
7
public function do_slash_command() {
8
    // Collect request parameters

9
    $token      = isset( $_POST['token'] ) ? $_POST['token'] : '';
10
    $command    = isset( $_POST['command'] ) ? $_POST['command'] : '';
11
    $text       = isset( $_POST['text'] ) ? $_POST['text'] : '';
12
    $user_name  = isset( $_POST['user_name'] ) ? $_POST['user_name'] : '';
13
14
    // Use the command verification token to verify the request

15
    if ( ! empty( $token ) && $this->get_command_token() == $_POST['token'] ) {
16
        header( 'Content-Type: application/json' );
17
18
        if ( isset( $this->slash_commands[$command] ) ) {
19
            // This slash command exists, call the callback function to handle the command

20
            $response = call_user_func( $this->slash_commands[$command], $text, $user_name );
21
            echo json_encode( $response );
22
        } else {
23
            // Unknown slash command

24
            echo json_encode( array(
25
                'text' => "Sorry, I don't know how to respond to the command."
26
            ) );
27
        }
28
    } else {
29
        echo json_encode( array(
30
            'text' => 'Oops... Something went wrong.'
31
        ) );
32
    }
33
34
    // Don't print anything after the response

35
    exit;
36
}

Давайте рассмотрим функцию, чтобы увидеть, что она делает:

Во-первых, на строках 8-12 функция собирает данные из параметров запроса:

  • token используется для проверки того, что запрос является допустимым запросом команды Slack.
  • command содержит слэш команду, которая должна быть выполнена.
  • text - строка текста, которая была введена после команды. Его можно использовать для передачи параметров в вашу команду.
  • user_name - это имя пользователя, отправившего команду.

В строке 15 функция выполняет проверку путем сравнения маркера, который был передан в параметрах запроса с тем, который был сохранен на предыдущем шаге.

Если токен действителен, функция продолжает выполнять команду, если она была зарегистрирована в классе Slack. Выполнение команды выполняется в строке 20, где функция выполняет вызов функции обратного вызова, указанной для команды.

Затем, в строке 21, ответ кодируется в строку JSON и распечатывается. Обратите внимание, что функция заканчивается вызовом exit, чтобы убедиться, что после ответа ничего не печатается.

Чтобы завершить работу, добавьте функцию get_command_token, чтобы получить токен проверки команды для приложения:

1
/**

2
 * Returns the command verification token.

3
 *

4
 * @return string   The command verification token or empty string if not configured

5
 */
6
private function get_command_token() {
7
    // First, check if command token is defined in a constant

8
    if ( defined( 'SLACK_COMMAND_TOKEN' ) ) {
9
        return SLACK_COMMAND_TOKEN;
10
    }
11
12
    // If no constant found, look for environment variable

13
    if ( getenv( 'SLACK_COMMAND_TOKEN' ) ) {
14
        return getenv( 'SLACK_COMMAND_TOKEN' );
15
    }
16
17
    // Not configured, return empty string

18
    return '';
19
}

Теперь функция slash-команды в классе Slack завершена, и все, что осталось сделать, прежде чем мы сможем реализовать нашу первую команду, - это подключить URL-адрес обратного вызова к этому коду.

Для этого добавьте новую ветвь case в функцию do_action в index.php:

1
// Responds to a Slack slash command. Notice that commands are 

2
// registered at Slack initialization.

3
case 'command':
4
    $slack->do_slash_command();
5
    break;

Шаг 3. Регистрация и проверка слэш команды

Теперь, когда мы создали систему для обработки слэш команд в нашем приложении, давайте использовать ее для реализации функций команды /joke.

Во-первых, в конце функции initialize_slack_interface добавьте следующие строки кода, чтобы зарегистрировать команду и передать имя функции, которая будет обрабатывать команду:

1
// Register slash commands

2
$slack->register_slash_command( '/joke', 'slack_command_joke' );

Затем создайте функцию:

1
/**

2
 * A simple slash command that returns a random joke to the Slack channel.

3
 *

4
 * @return array    A data array to return to Slack

5
 */
6
function slack_command_joke() {
7
    $jokes = array(
8
        "The box said 'Requires Windows Vista or better.' So I installed LINUX.",
9
        "Bugs come in through open Windows.",
10
        "Unix is user friendly. It’s just selective about who its friends are.",
11
        "Computers are like air conditioners: they stop working when you open Windows.",
12
        "I would love to change the world, but they won’t give me the source code.",
13
        "Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning."
14
    );
15
16
    $joke_number = rand( 0, count( $jokes ) - 1 );
17
18
    return array(
19
        'response_type' => 'in_channel',
20
        'text' => $jokes[$joke_number],
21
    );
22
}

Поскольку эта функция была создана как демонстрация, она не делает много: она случайно выбирает одну из (довольно плохих) шуток и возвращает ее в формате, ожидаемом Slack.

Обратите внимание, что, хотя эта команда не принимает никаких параметров, для более сложного примера вы можете добавить два параметра: $text для доступа к любым данным, которые пользователь вводил после команды, и $user_name, чтобы получить имя пользователя, который подал команду.

Чтобы проверить команду, продолжайте и введите /joke на канале Slack.

The application tells a jokeThe application tells a jokeThe application tells a joke

Заключение и идеи на будущее

Вы завершили учебник и знаете, как интегрировать ваше приложение PHP со Slack. Во время этого учебника вы также создали инструменты для отправки уведомлений на канал Slack, а также отвечали на команды, которые пользователь вводит непосредственно в Slack.

Следующим шагом является то, чтобы эти идеи работали реально.

Подумайте о своем приложении и поищите места, где можно пообщаться со Slack и слушать команды, поступающие из него, и сделать их более полезными и приятными для ваших пользователей и реализовать их.

Эта платформа быстро развивается, а также API. Следите за тем, как это происходит, и создавайте что-то потрясающее!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.