Package Exports
- amocrm-connector
- amocrm-connector/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (amocrm-connector) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Node.js AmoCRM api connector
Изначально библиотека создавалась для внутреннего использования. Периодически, с внесением изменений в amocrm api, в интеграции появляются ошибки. Цель данного проекта помочь создать надежный, протестированный инструмент для работы с amocrm. 👌 Поддерживать его актуальным с помощью автотестов и сообщества. Автоматические тесты запускаются каждый день с использованием github actions.
Описание
Основные возможности:
- OAuth авторизация
- Запросы к api
- Частичное покрытие методов api
- Работа с api чатов
Основные отличия версии 0.3.x от 0.2.x
- Переход на TypeScript
- Убраны механизмы контроля частоты запросов и автоматического обновления токена
- Убрана поддержка стора
- Добавлены подсистемы и описаны типы некоторых dto
- Добавлена поддержка chat api
Начало работы
Установка
yarn add amocrm-connector
Пример использования
import {AmoCRM, AmoCRMToken} from 'amocrm-connector'
import rawToken from './token.json'
const {accessUntil, ...rest} = rawToken
const token = {
accessUntil: new Date(accessUntil),
...rest
}
;(async () => {
const amocrm = new AmoCRM({
credential: {
domain: 'your_domain',
integrationId: 'integration-id',
secretKey: 'secret-key',
redirectUri: 'redirect-uri'
},
token
})
const {amojoId} = await amocrm.account.get(AccountWith.amojoId)
if (!amojoId) return
const scopeId = await amocrm.chat.connectChannel(amojoId, 'Название канала')
const result = await amocrm.chat.addMessage(
scopeId,
{
date: new Date(),
// id беседы из вашей системы
conversationId: 'conversation-id',
sender: {
id: 'sender-id',
name: 'Имя клиента',
profile: {
phone: '71234567890'
}
},
id: 'message-id',
message: {
type: MessageType.Text,
text: 'Тест сообщения'
}
}
)
})()
Другие примеры смотрите в папке examples
Документация
Создание объекта AmoCRM
Методы AmoCRM
- amocrm.on(event, eventListener)
- amocrm.addListener(event, eventListener)
- amocrm.removeListener(event, eventListener)
- amocrm.tokenIsActual()
- amocrm.getToken(options)
- amocrm.getOAuthLink(state, mode)
- amocrm.request(config)
- amocrm.get(config)
- amocrm.post(config)
- amocrm.patch(config)
- amocrm.delete(config)
Подсистемы
Аккаунт
Чаты
- amocrm.chat.request(config)
- amocrm.chat.get(config)
- amocrm.chat.post(config)
- amocrm.chat.checkSignature(body, signature)
- amocrm.chat.connectChannel(amojoId, title)
- amocrm.chat.addMessage(scopeId, payload)
- amocrm.chat.deliveryStatus(scopeId, messageId, data)
- amocrm.chat.typing(scopeId, data)
Прочее
AmoCRM
const amocrm = new AmoCRM({
credential: {
// Домен вашего аккаунта. Ссылка на ваш аккаунт выглядит как https://[domain].amocrm.ru
domain: string,
// ID интеграции из "ключи и доступы" вашей интеграции
integrationId: string,
// Секретный ключ из "ключи и доступы" вашей интеграции
secretKey: string,
// url из настроек вашей интеграции
redirectUri: string,
// Секретный ключ канала чатов (secret_key)
chatSecret?: string,
// id зарегистрированного канала чатов
chatId?: string
},
// необязательный параметр, объект токена полученный ранее
token: AmoCRMToken
})
Методы
amocrm.on(event, eventListener)
Алиас для amocrm.addListener(event, eventListener)
amocrm.addListener(event, eventListener)
amocrm.addListener(event: 'token', eventListener: (token: AmoCRMToken) => void): void
События
token
- при получении нового токена
amocrm.removeListener(event, eventListener)
amocrm.addListener(event: 'token', eventListener: (token: AmoCRMToken) => void): void
amocrm.tokenIsActual()
amocrm.tokenIsActual(): boolean
amocrm.getToken(options)
Запрашивает новый токен по коду авторизации или токену обновления
async amocrm.getToken(options: { code?: string, refreshToken?: string })): Promise<void>
amocrm.getOAuthLink(state, mode)
amocrm.getOAuthLink(state: string = '', mode: 'post_message' | 'popup' = 'post_message'): string
amocrm.request(config)
HTTP запрос к amocrm. Основано на библиотеке axios.
async amocrm.request<T = unknown, D = unknown>(config: AmoCRMRequestConfig<D>): Promise<AxiosResponse<T, D>>
type AmoCRMRequestConfig<D = undefined> = AxiosRequestConfig<D> & {
useToken?: boolean,
ifModifiedSince?: Date
}
// Описание некоторых полей AmoCRMRequestConfig
{
// Добавлять ли заголовок Authorization
useToken: boolean = true,
// Добавляет заголовок If-Modified-Since
ifModifiedSince?: Date,
// Тело запроса
data?: D,
// Заголовки запроса
headers: Record<string, string | number | boolean> = {},
// Метод запроса
method: 'GET' | 'POST' | 'PATCH' | 'DELETE' = 'GET',
// URL относительно BaseURL
url: string,
baseURL: string = `https://${this.credential.domain}.amocrm.ru`
}
amocrm.get(config)
amocrm.request({method: 'GET', ...config})
amocrm.post(config)
amocrm.request({method: 'POST', ...config})
amocrm.patch(config)
amocrm.request({method: 'PATCH', ...config})
amocrm.delete(config)
amocrm.request({method: 'DELETE', ...config})
amocrm.account.get(withParams)
Запрос параметров аккаунта
async amocrm.account.get(withParams ? : AccountWith | AccountWith[]): Promise<AccountInfo>
amocrm.chat.request(config)
HTTP запрос к api чатов Автоматически добавляет заголовки для авторизации запроса
async amocrm.chat.request<T = unknown, D = unknown>(config: AmoCRMRequestConfig<D>): Promise<AxiosResponse<T, D>>
amocrm.chat.get(config)
amocrm.chat.request({method: 'GET', ...config})
amocrm.chat.post(config)
amocrm.chat.request({method: 'POST', ...config})
amocrm.chat.checkSignature(body, signature)
Проверяет подпись для входящих запросов (вебхуков)
amocrm.chat.checkSignature(body: unknown, signature?: string | string[]): boolean
amocrm.chat.connectChannel(amojoId, title)
Подключение канала чата в аккаунте
async amocrm.chat.connectChannel(amojoId: string, title: string): Promise<string>
Возвращаемое значение - scopeId
amojoId может быть получен следующим образом
const {amojoId} = await amocrm.account.get(AccountWith.amojoId)
amocrm.chat.addMessage(scopeId, payload)
async amocrm.chat.addMessage(scopeId: string, addMessagePayload: AmoLike<AddMessagePayload>): Promise<AddMessageResponse>
AddMessagePayload AddMessageResponse
amocrm.chat.deliveryStatus(scopeId, messageId, data)
Обновление статуса доставки сообщения
async amocrm.chat.deliveryStatus(scopeId: string, messageId: string, deliveryStatusRequest: AmoLike<DeliveryStatusRequest>): Promise<void>
amocrm.chat.typing(scopeId, data)
Передача информации о печатании
async amocrm.chat.typing(scopeId: string, typingRequest: AmoLike<TypingRequest>)
AmoDTO
Цель данного класса - описать объекты передачи данных AmoCRM API. Какие задачи решает данный класс
- Преобразование названий свойств camelCase <-> snake_case
- Валидация объекта [нереализовано]
- Типизация объекта
- Сериализация/десериализация
AmoEntity
AmoEntity - некая сущность обладающая уникальным идентификатором. Свойства содержащие ссылки (идентификаторы) на объекты такого типа при десериализации автоматически заменяются на объекты этого тип, и наоборот.
AmoLike
AmoDTO и AmoEntity - классы, и для передачи значений в методы api необходимо создать каждый объект, создать вложенные объекты и т.п. Это создает много лишнего кода. Для возможности более лаконичного описания передаваемого аргумента используется AmoLike.
type AmoLike<T extends AmoDTO = AmoDTO> = T | DeepPartial<T>
Таким образом мы можем передавать в качестве аргумента как сам объект AmoDTO, так и плоский объект.
Пример
// Плоский объект
const result = await amocrm.chat.addMessage(
scopeId,
{
date: new Date(),
// id беседы из вашей системы
conversationId: 'conversation-id',
sender: {
id: 'sender-id',
name: 'Имя клиента',
profile: {
phone: '71234567890'
}
},
id: 'message-id',
message: {
type: MessageType.Text,
text: 'Тест сообщения'
}
}
)
//AmoDTO
const result = await amocrm.chat.addMessage(
scopeId,
new AddMessagePayload({
date: new Date(),
// id беседы из вашей системы
conversationId: 'conversation-id',
sender: new MessageParticipant({
id: 'sender-id',
name: 'Имя клиента',
profile: new MessageParticipantProfile({
phone: '71234567890'
})
}),
id: 'message-id',
message: new AddMessageContent({
type: MessageType.Text,
text: 'Тест сообщения'
})
})
)
Авторизация
Подробно про AmoCRM реализацию OAuth2 авторизации в официальной документации Также можете посмотреть видео от создателей другой библиотеки https://github.com/UsefulWeb/AmoCRM.
Коротко, шаги:
- Регистрация вашей интеграции
- Переход пользователя по ссылке выдачи доступа пользователем вашему приложению. Ссылку получить можно
методом
amocrm.getOAuthLink
- Обработка запроса на redirect uri, здесь должен быть запущен ваш сервер. В виде гет параметра amocrm передаст код
авторизации. Его необходимо обменять на токен с помощью метода
amocrm.getToken
. Пример реализации смотрите в файлеtesting/server.js
Ошибки и пожелания
Если в процессе использования вы обнаружили ошибку, расскажите о ней, откройте issue с подробным описанием. Спасибо за помощь в тестировании! 👍 Если у вас есть пожелания, также открывайте issue! 👀
Планы
- Покрыть все методы api
- Реализовать унифицированный механизм работы с сущностями (Leads, Contacts, Pipelines, Companies, Catalogs, ...)
- create(data: AmoEntity | AmoEntity[])
- find(type: typeof AmoEntity, findOptions)
- findOne(type: typeof AmoEntity, findOptionsOrId)
- update(data: AmoEntity | AmoEntity[])
- delete(data: AmoEntity | AmoEntity[])
- Валидация AmoDTO
Разработка
Команды
yarn build
сборка проектаyarn serve
запуск сервера для обработки запросов от amocrm. Необходима настройка окружения.yarn tunnel
создает туннель с использованием утилиты localtunnel. Необходима настройка окружения.yarn cypress
запуск cypress тестов, используется для проверки работы OAuth и автоматического получения токена. Необходимо:- Настроить окружение. Токен сохраняется в testing/token.json. Про настройку окружения ниже.
- Запустить сервер для обработки запросов от amocrm.
- Создать туннель с публичного адреса на ваш локальный сервер.
yarn cypress:open
запуск cypress тестов в интерактивном режиме. Необходима настройка окружения.yarn jest
запуск jest тестов. Для работы необходимо настроить окружение, а также токен в testing/token.json. Поэтому полезно сначала запустить cypress тест. [Пока тестов нет]yarn test
запуск cypress и jest тестов
Настройка окружения
Необходимо создать файл .evn.test
с переменными окружения в корне проекта. Для удобства можно воспользоваться
шаблоном .env.test.example
(здесь также описано для чего нужны переменные)
cp .env.test.example .env.test
Если у вас есть вопросы касательно разработки - пишите мне в телеграм @lybrus. 👈
Любая помощь в разработке и тестировании данного проекта приветствуется! 👍