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

  • Все запросы к API должны приходить только по защищенному протоколу HTTPS
  • Каждый запрос должен содержать подпись в заголовке X-lemurSIGN
  • Параметры передаются в теле POST запроса в формате JSON (content-type: application/json)
  • Структура запросов и ответов при работе с API имеет строгую типизацию
  • Обязательные к заполнению поля (chatid, user.name и на выбор message или attachments)

Условия формирования подписи

Для формирования X-lemurSIGN подписи используется метод HMAC с шифрованием SHA256 всего тела сообщения по ключу (полученному в админ-панели) и приведенному к HEX формату.

Примеры реализаций на разных языках программирования:

1
2
3
4
5
6
<?php
$key = 'the shared secret key here';
$message = 'the message to hash here';

// to lowercase hexits
hash_hmac('sha256', $message, $key);
1
2
3
4
5
6
7
8
9
var crypto = require('crypto');

var key = 'the shared secret key here';
var message = 'the message to hash here';

var hash = crypto.createHmac('sha256', key).update(message);

// to lowercase hexits
hash.digest('hex');
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
const key = 'the shared secret key here';
const message = 'the message to hash here';

const getUtf8Bytes = str =>
  new Uint8Array(
    [...unescape(encodeURIComponent(str))].map(c => c.charCodeAt(0))
  );

const keyBytes = getUtf8Bytes(key);
const messageBytes = getUtf8Bytes(message);

const cryptoKey = await crypto.subtle.importKey(
  'raw', keyBytes, { name: 'HMAC', hash: 'SHA-256' },
  true, ['sign']
);
const sig = await crypto.subtle.sign('HMAC', cryptoKey, messageBytes);

// to lowercase hexits
[...new Uint8Array(sig)].map(b => b.toString(16).padStart(2, '0')).join('');
1
2
3
4
5
6
7
require 'openssl'

key = 'the shared secret key here'
message = 'the message to hash here'

# to lowercase hexits
OpenSSL::HMAC.hexdigest('sha256', key, message)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
)

func main() {
	secret := []byte("the shared secret key here")
	message := []byte("the message to hash here")
	
	hash := hmac.New(sha256.New, secret)
	hash.Write(message)
	
	// to lowercase hexits
	hex.EncodeToString(hash.Sum(nil))
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import hashlib
import hmac

message = bytes('the message to hash here').encode('utf-8')
secret = bytes('the shared secret key here').encode('utf-8')

hash = hmac.new(secret, message, hashlib.sha256)

# to lowercase hexits
hash.hexdigest()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import hashlib
import hmac

message = bytes('the message to hash here', 'utf-8')
secret = bytes('the shared secret key here', 'utf-8')

hash = hmac.new(secret, message, hashlib.sha256)

# to lowercase hexits
hash.hexdigest()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
using System;
using System.Security.Cryptography;
using System.Text;

class MainClass {
  public static void Main (string[] args) {
    string key = "the shared secret key here";
    string message = "the message to hash here";
    
    byte[] keyByte = new ASCIIEncoding().GetBytes(key);
    byte[] messageBytes = new ASCIIEncoding().GetBytes(message);
    
    byte[] hashmessage = new HMACSHA256(keyByte).ComputeHash(messageBytes);
    
    // to lowercase hexits
    String.Concat(Array.ConvertAll(hashmessage, x => x.ToString("x2")));
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import javax.xml.bind.DatatypeConverter;

class Main {
  public static void main(String[] args) {
  	try {
	    String key = "the shared secret key here";
	    String message = "the message to hash here";
	    
	    Mac hasher = Mac.getInstance("HmacSHA256");
	    hasher.init(new SecretKeySpec(key.getBytes(), "HmacSHA256"));
	    
	    byte[] hash = hasher.doFinal(message.getBytes());
	    
	    // to lowercase hexits
	    DatatypeConverter.printHexBinary(hash);
	    
  	}
  	catch (NoSuchAlgorithmException e) {}
  	catch (InvalidKeyException e) {}
  }
}

Принцип обмена сообщениями

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

Тестирование и Примеры

Отправка сообщений из окна чата:

Для начала необходимо установить на вашей странице виджет с чатом!

Теперь для проверки сообщений отправленных из окна чата можно воспользоваться сервисом Webhook.site. Полученную уникальную ссылку необходимо прописать в настройках chatAPI админ-панели в поле Адрес для передачи сообщений секции Получатель.

Закончив с настроками можно пробовать отправлять сообщения в окне чата, а на странице Webhook.site получать их.

Получение сообщений в чат:

Чтобы отправить сообщение в окно чата можно воспользоваться виджетом Swagger.

Заполните правильно поля соблюдая очередность:

  • ID - идентификатор сайта (можно найти в настройках chatAPI админ-панели)

  • Тело сообщения

    • chatid - идентификатор чата (генерируется в момент подключения чата к серверу)

    • message - текст сообщения (при необходимости поправьте)

    • name - имя пользователя (при необходимости поправьте)

  • X-lemurSIGN - подпись (описание смотрите выше)