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

Недавно я реализовал функцию чата в более крупном приложении моей команды с помощью относительно нового сервиса под названием Stitch. Stitch — это продукт для обмена IP-сообщениями от Nexmo, поставщика API для сети Vonage, который состоит из SDK для iOS, Android, поддержки JavaScript и API. Поскольку он все еще находится в предварительной версии для разработчиков, документация для него еще не полностью конкретизирована, поэтому вот несколько советов о том, как его использовать. В частности, я использовал API на сервере Node/Express и JavaScript SDK для внешнего интерфейса, встроенного в React.

  • Сгенерируйте ключ и секрет API на сайте Nexmo.
  • Установите интерфейс командной строки.
$ npm install -g nexmo-cli@beta
  • Настройте его с помощью своего ключа API и секрета.
$ nexmo setup api_key api_secret
  • Убедившись, что вы находитесь в каталоге, в котором хотите работать, создайте приложение.
$ nexmo app:create "My Stitch App" https://example.com/answer https://example.com/event --type=rtc --keyfile=private.key

Это создаст файл конфигурации с идентификатором вашего приложения и файлом private.key с вашим закрытым ключом. Вы можете хранить свои переменные среды в файле .env и ссылаться на закрытый ключ как private.key

  • Например:
NEXMO_APP_ID=aaaaaaaa-bbbb-cccc-dddd-0123456789ab
NEXMO_API_KEY=01a23b45
NEXMO_API_SECRET=A1bCd2efgHIJ34KL
NEXMO_PRIVATE_KEY=private.key
  • Установите обёртку API Nexmo — убедитесь, что это именно эта версия, так как на момент создания этого блога это версия с поддержкой Stitch. Вы можете прочитать их документацию по нему здесь. Вам нужно перейти в раздел под названием Разговор.
$ npm install --save [email protected]
  • Настройте логику на стороне сервера.
const Nexmo = require('nexmo');
const nexmo = new Nexmo({
  apiKey: process.env.NEXMO_API_KEY,
  apiSecret: process.env.NEXMO_API_SECRET,
  applicationId: process.env.NEXMO_APP_ID,
  privateKey: process.env.NEXMO_PRIVATE_KEY,
});

Оболочка Nexmo API предоставляет несколько полезных удобных функций для работы с их сервисами. Что касается Stitch, наиболее важными, на мой взгляд, являются создание нового пользователя и генерация веб-токена JSON для этого пользователя — остальное, по большей части, может быть обработано их SDK на внешнем интерфейсе.

  • Создание пользователя
nexmo.users.create(params, callback);
// params are shaped like this
{
  name: string, // required
  display_name: string, // optional
  image_url: string, // optional
  channels: string, // optional
}
  • Генерация JWT — правильное создание JWT для вашего пользователя имеет решающее значение, поскольку без него они не могут получить доступ к функциям приложения.
const jwt = Nexmo.generateJwt(process.env.NEXMO_PRIVATE_KEY, {
  application_id: process.env.NEXMO_APP_ID,
  sub: userNexmoName,
  exp: new Date().getTime() + 86400,
  acl: adminAcl,
}

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

Теперь о клиентской стороне!

  • Установите SDK — он тоже по-прежнему называется «Разговор», но это то же самое, что и Stitch.
$ npm install --save nexmo-conversation
  • Включите его как тег скрипта в свой HTML-файл.
<script src="node_modules/nexmo-conversation/dist/conversationClient.js"></script>

Stitch SDK построен на нескольких основных конструкторах, которые имеют свои собственные методы. Сегодня нас будут интересовать в первую очередь ConversationClient, Application и Conversation.

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

new ConversationClient()
  .login(jwt);

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

new ConversationClient()
  .login(jwt)
  .then((app) => {
    this.setState({ chatApp: app });
    app.on('member:invited', (member, event) => {
      console.log('*** invitation received:', event);
    });
    return app.getConversations();
  })
  .then((conversations) => {
     console.log('*** Retrieved conversations', conversations);
     this.setState({ allUserChats: conversations });
  })
  .catch(error => console.error('error logging into nexmo', error));

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

startNewChat(userNexmoId, userNameFirst, userNameLast) {
  const { chatApp } = this.state;
  
  chatApp.newConversationAndJoin({
    display_name: `${userNameFirst} ${userNameLast}`,
  })
  .then((conversation) => {
    conversation
      .invite({ id: userNexmoId })
      .then(user => console.log('invited', user))
      .catch(error => console.error('error inviting user to chat',
         error));
  })
  .catch(error => console.error('error creating new chat', error));
}

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

Наконец, отправка нового сообщения — это простой метод объекта Conversation.

sendMessage() {
  const { newMessage } = this.state;
  conversation
    .sendText(newMessage)
    .then(() => this.setState({ newMessage: '' }))
    .catch(error => console.error('error sending message', error));
}

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

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