Интеграция с Max мессенджером

Начальные действия по регистрации бота для Max

Чтобы сделать бота для Max, необходимо зерегистрироваться на портале Max для партнеров https://business.max.ru/

Необходимо подтвердить свой аккаунт через Тбанк, Госуслуги, Сбер или др способ. Физические лица и самозанятые не могут там зарегистрироваться.

Создаем чат бота в кабинете и получаем его логин и токен.

После модерации находим в Max созданного бота. 

Подключение по API к боту Max

Подробная документация от Max - https://dev.max.ru/docs

Описание объектов и методов API - https://dev.max.ru/docs-api

Первый запрос к боту это me - получение информации о боте. 

В /asapi создаем тест GET запрос https://platform-api.max.ru/me  с http header Token={token}. 

В ответ получаем информацию о боте. Убеждаемся, что API в целом работает. 

Получение сообщений, которые пишут боту

Чтобы Max понимал какой наш веб хук вызывать используется методы subscriptions.

Описание - https://dev.max.ru/docs-api/methods/POST/subscriptions

Get метод дает понимание какие у нас есть вебхуки на бот. 

Post метод обновляет информацию о веб хуке. 

Реализуем через тест запросы (т.е. не нужно делать постоянный метод API у себя для этого)

Примечание: secret параметр используется для того, чтобы проверять в вебхуке наличие этого secret через Http заголовок (убедиться, что это Max делает отправку запроса). 

Через GET запрос subscriptions проверяем, что появилась подписка с нашим адресом.

Далее реализуем входящий API для этого веб хука. 

В нем мы проверяем secret параметр и передаем на обработку дальше данные от Max. Пример процедуры для входящего API метода: 

CREATE PROCEDURE [dbo].[api_max_webhook]
@parameters ExtendedDictionaryParameter READONLY,
@username nvarchar(256)
as
begin
	declare @s  nvarchar(max) = '' 
    select @s = @s + isnull([key], '') + '='+ isnull(value2, '') + '
' from @parameters 
    execute as_print @s

	declare @maxSecret nvarchar(128) = dbo.as_setting('max-secret', 'XXXXXXX')

	declare @secret nvarchar(max) = (select value2 from @parameters where [key]='X-Max-Bot-Api-Secret')
  
  	if(@secret<> @maxSecret) begin 
    	select 0 Result, 'Wrong key' Msg
        return 
    end 

	-- SELECT 1 - вывод метаданных о результате операции метода API 
	select 'OK' Msg, 1 Result, 0 errorCode
    -- SELECT 2
	select 1
	-- SELECT 3 - процедура может выдать внешнее действие (на отправку сообщения)
	exec [dbo].[max_bot_action]
		@parameters = @parameters  

end
	
  1. Через execute as_print @s мы смотрим формат, что нам пришло в @parameters (основные данные придут в key=InputStream).
  2. Делается проверка secret - если пришло что-то не то, то дальше не пускаем
  3. В конце мы запускаем процедуhe max_bot_action, которая может выдать некое внешнее действие (SELECT). Например, вызов метода отправки сообщения (apirequest).

Процедура обработки max_bot_action

Процедура определяет что пришло на вход и выдает некий фидбек в виде вызова внешнего действия на отправку сообщения обратно в Max. 

CREATE PROCEDURE [dbo].[max_bot_action]
	@parameters ExtendedDictionaryParameter READONLY  -- входящие параметры для внутренней обработки

AS
BEGIN

	declare @userIP nvarchar(max) = (select value2 from @parameters where [key]='userIP')
    declare @json nvarchar(max) = (select value2 from @parameters where [key]='InputStream')

declare @s  nvarchar(max) = '' 
    select @s = @s + isnull([key], '') + '='+ isnull(value2, '') + '
' from @parameters 
  -- execute as_print @json
 -- execute as_print @s


	declare @updateType nvarchar(max) = ''
    declare @timestamp datetime = ''
    declare @chatID bigint = ''
    declare @messageID nvarchar(max) = ''
    declare @text nvarchar(max) = ''
    declare @senderUserID bigint = ''
   declare @senderIsBot bit = ''
   declare @senderName nvarchar(max) = ''
   declare @senderFirstName nvarchar(max) = ''
   declare @senderLastName nvarchar(max) = ''
   declare @senderLastActivity datetime = ''

select
 @updateType= updateType,
    @timestamp = DATEADD(S, CONVERT(int,LEFT([timestamp], 10)), '1970-01-01')  ,
    @chatID  = chatID,
    @messageID = messageID,
    @text = text,
    @senderUserID = senderUserID,
   @senderIsBot = senderIsBot, 
   @senderName  = senderName,
   @senderFirstName = senderFirstName,
    @senderLastName = senderLastName,
    @senderLastActivity  = DATEADD(S, CONVERT(int,LEFT(senderLastActivity, 10)), '1970-01-01') 
FROM OPENJSON(@json, N'$')
WITH (
    [timestamp] bigint    N'$.timestamp',
    updateType        nvarchar(max)        N'$.update_type', 
    chatID bigint    N'$.message.recipient.chat_id', 
    messageID        nvarchar(max)        N'$.message.body.mid',
    text        nvarchar(max)        N'$.message.body.text',
   senderUserID bigint   N'$.message.sender.user_id',
   senderIsBot bit  N'$.message.sender.is_bot',
   senderName nvarchar(max) N'$.message.sender.name',
   senderFirstName nvarchar(max) N'$.message.sender.first_name',
   senderLastName nvarchar(max) N'$.message.sender.last_name',
   senderLastActivity bigint  N'$.message.sender.last_activity_time'    
)
    
  /*
 {
  "timestamp": 1765714796034,
  "message": {
    "recipient": {
      "chat_id": 175054076,
      "chat_type": "dialog",
      "user_id": 139389187
    },
    "timestamp": 1765714796034,
    "body": {
      "mid": "mid.000000000a6f1cfc019b1ccd9e0224fc",
      "seq": 115717884872893692,
      "text": "11"
    },
    "sender": {
      "user_id": 35780095,
      "first_name": "Руслан",
      "last_name": "falconspace",
      "is_bot": false,
      "last_activity_time": 1765714794000,
      "name": "Руслан falconspace"
    }
  },
  "user_locale": "ru",
  "update_type": "message_created"
}  */	  
	
	select 'apirequest' type, 'maxSendMessage' code,
 		'options' p1_name,
 	 	(select @chatID chatID,	
     		@senderUserID userID,
			@text + '...' text,
        	'html' format,
         	@messageID replyMessageID 
     for JSON PATH,WITHOUT_ARRAY_WRAPPER) p1_value
 

В процедуре пример отклика в JSON, который мы разбираем на параметры. 

В конце процедуры формируется ответ в виде вызова apirequest. 

Реализуем исходящий метод API maxSendMessage

Исходящий API POST метод. 

Код reqponse процедуры: 

CREATE PROCEDURE [dbo].[api_maxSendMessage_request]
	@parameters ExtendedDictionaryParameter READONLY,  -- входящие параметры для внутренней обработки (используйте Key, Value2)
	@username nvarchar(32)  -- текущий пользователь.
AS
BEGIN
	declare @json nvarchar(max) = (select value2 from @parameters where [key]='options')
	declare @userID nvarchar(max), @chatID nvarchar(max), @text nvarchar(max), 
    	@format nvarchar(max), @forwardMessageID nvarchar(max), @replyMessageID nvarchar(max)
    select
        @chatID  = chatID,
        @userID = userID,
        @text = text,
        @format = format,
       	@forwardMessageID = forwardMessageID, 
       	@replyMessageID  = replyMessageID
    FROM OPENJSON(@json, N'$')
    WITH (
        chatID nvarchar(max)   N'$.chatID',
        userID  nvarchar(max)   N'$.userID',
        text nvarchar(max)   N'$.text',
        format nvarchar(max)   N'$.format',
        forwardMessageID nvarchar(max)   N'$.forwardMessageID',
        replyMessageID nvarchar(max)   N'$.replyMessageID'
    )
    
    declare @body nvarchar(max) = (
      select @format format,	
		@text text,       
		iif(@forwardMessageID<>'', 
            'forward',
             iif(@replyMessageID<>'', 'reply', NULL) 
        ) 'link.type',
        iif(@forwardMessageID<>'', 
            @forwardMessageID,
             iif(@replyMessageID<>'', @replyMessageID, NULL) 
        ) 'link.mid'       
	  	for JSON PATH,WITHOUT_ARRAY_WRAPPER
    )
    execute as_print @body
	-- SELECT 1  Msg, Result, Url (адрес, куда будет идти запрос)
	select '' Msg, 1 Result, 'https://platform-api.max.ru/messages chat_id='+ @chatID + iif(@userID<>'', '&userID='+ @userID, '') Url 

	-- SELECT 2 PARAMETERS - параметры, которые будут передаваться во внешний источник
	select 'json' name, @body value, 'json' [type]
    union 
    select 'Authorization' name, dbo.as_setting('maxToken', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX') value, 'header' [type]
    
END

На входе у нас JSON параметр options - разбираем его и формируем JSON body для запроса.  Параметры chat_id и user_id (необязательный) передаются в URL. 

Заключение

Таким образом работает схема бота: 

  1. пишем боту что-то
  2. по subscriptions бот находит наш вебхук и отправляем нам сообщенеи
  3. в вебхуке мы проверяем secret и вызываем процедуру max_bot_action
  4. процедура определяет что пришло и вызывает исходящий API метод на отправку сообщения в Max 
  5. идет отправка через метод maxSendMessage.
Страница-источник на сайте falconspace.ru