NAV Navbar
cURL

Документация для вендоров

Терминология

МойСклад - SaaS-сервис управления торговлей, доступный по адресу https://online.moysklad.ru/

Маркетплейс - это набор программных компонентов в рамках сервиса МойСклад, позволяющий сторонним вендорам размещать свои приложения на витрине приложений, а пользователям МоегоСклада устанавливать (подключать) эти приложения и пользоваться ими.

Витрина приложений - отдельный экран МоегоСклада https://online.moysklad.ru/app/#apps, на котором размещаются опубликованные приложения. Витрина приложений доступна только администраторам аккаунта.

Вендор - сторонний по отношению к МоемуСкладу разработчик приложений для Маркетплейса.

Приложение - разработанный вендором программный продукт, расширяющий и дополняющий функционал МоегоСклада. Приложение размещается на витрине Маркетплейса и доступно для установки на аккаунт администратором аккаунта.

Аккаунт - пользовательский аккаунт МоегоСклада. Обычно аккаунт соответствует одной компании/бизнесу, в аккаунте несколько пользователей.

Аккаунт разработчика - привязанный к конкретному вендору пользовательский аккаунт МоегоСклада. На таком аккаунте на витрине приложений отображаются приложения вендора в статусах Черновик (Draft) и Готово, отправлено на модерацию (Ready), что позволяет выполнять проверку и отладку приложений до их публикации для всех пользователей МоегоСклада. Технически к одному вендору может быть привязано несколько аккаунтов.

Приложение на аккаунте - приложение, установленное (подключенное) на аккаунт. Альтернативный взаимозаменяемый термин - экземпляр приложения.

Пользователь МоегоСклада - конечный пользователь сервиса МойСклад, работающий с МоимСкладом в рамках определенного аккаунта.

Администратор аккаунта - пользователь МоегоСклада с правами администратора (в рамках определенного аккаунта).

Активация приложения - процесс включения приложения для конкретного аккаунта в системе вендора, выполняемый при подключении приложения пользователем (или при возобновлении платного приложения). В рамках активации происходит оповещение сервера вендора со стороны МоегоСклада.

Деактивация приложения - процесс выключения приложения для конкретного аккаунта в системе вендора, выполняемый при отключении приложения пользователем (или при приостановке платного приложения). В рамках деактивации происходит оповещение сервера вендора со стороны МоегоСклада.

Приостановка приложения - автоматический процесс выключения платного приложения при уменьшении количества "Опций платных приложений" или неоплате подписки пользователем МоегоСклада. После приостановки токен доступа приложения аннулируется. Первыми приостанавливаются последние установленные приложения на аккаунте.

Возобновление приложения - процесс включения приостановленного платного приложения при появлении на аккаунте свободных "Опций платных приложений". Возобновление может быть выполнено как автоматически (после оплаты пользователем МоегоСклада подписки или дополнительных "Опций платных приложений"), так и вручную пользователем МоегоСклада (активация экземпляра приложения по кнопке после освобождения "Опции платных приложений" путем удаления экземпляра другого платного приложения). После возобновления приложению выдается новый токен доступа. Первыми возобновляются приложения, установленные ранее прочих.

Общая информация

В данном разделе можно узнать:

Типы приложений в Маркетплейсе

Тип приложения определяет в первую очередь технический способ интеграции приложения с МоимСкладом.

Поддерживаемые на текущий момент типы приложений:

Сводная таблица поддержки функций для типов приложений

Тип приложения Количество приложений на аккаунте Iframe и доступ к контексту пользователя Активация и деактивация по Vendor API Доступ по токену к JSON API 1.2 Отладка на аккаунтах разработчика Phone API Loyalty API Блок на витрине приложений Виджеты
Телефония 1 + + Звонки
Iframe-приложения Не ограничено + + Новые
Серверные приложения Не ограничено + + + + Новые +
Системы лояльности 1 + Скидки

Серверные приложения

Серверные приложения - это приложения, основной функционал которых основан на обмене данными с МоимСкладом по JSON API. Для этого при активации приложения по Vendor API на сервер вендора передается токен доступа к JSON API 1.2 (доступ по токену поддерживается только в JSON API 1.2).

Для серверных приложений поддерживается активация и деактивация по Vendor API.

Для серверных приложений доступно получение контекста текущего пользователя МоегоСклада (через Vendor API) - то есть можно узнать, какой именно пользователь какого аккаунта открывает приложение в UI МоегоСклада.

Также серверное приложение может иметь свою вкладку среди iframe-приложений и пользовательский интерфейс. Используя данную возможность можно, например, реализовать управление настройками приложения со стороны пользователя МоегоСклада / администратора аккаунта. Поддерживается возможность расширенного iframe-окна (подробнее см. дескриптор).

Только для серверных приложений доступны виджеты.

В общем случае жесткие требования к внешнему виду / визуальному дизайну iframe-части приложений отсутствуют. Тем не менее, приветствуется визуальное соответствие дизайну МоегоСклада. Для этого мы разработали UI Kit (см. скриншот), который доступен по ссылке https://github.com/moysklad/html-marketplace-1.0-uikit.

useful image

Одновременно на аккаунте может быть подключено несколько серверных приложений.

Доступна отладка на аккаунтах разработчика.

Iframe-приложения

Iframe-приложение представляет собой веб-приложение, которое загружается по указанному вендором URL в iframe на отдельной вкладке/странице внутри UI МоегоСклада.

Iframe-приложения просты в разработке и размещении на площадке МоегоСклада, однако такие приложения тоже должны соответствовать требованиям к приложениям.

Для iframe-приложений поддерживается доступ к контексту пользователя и расширение окна iframe, однако не поддерживается активация и деактивация по Vendor API, а также доступ по токену к JSON API 1.2.

При построении пользовательского интерфейса в iframe-приложениях также желательно использовать UI Kit МоегоСклада.

Одновременно на аккаунте может быть подключено несколько iframe-приложений.

Доступна отладка на аккаунтах разработчика.

Телефония

Эти приложения представляют собой интеграцию с внешними сервисами телефонии по Phone API: https://online.moysklad.ru/api/phone/1.0/doc/index.html

Приложения телефонии на витрине приложений размещаются в блоке “Звонки”.

На текущий момент возможность получения доступа по токену к JSON API у приложений телефонии отсутствует, как и возможность активации и деактивации приложений телефонии по Vendor API (в перспективе такая возможность может появиться).

Одновременно на аккаунте может быть подключено только одно приложение телефонии.

Доступна отладка на аккаунтах разработчика.

Интеграция с системами лояльности

API для интеграции МоегоСклада с системами лояльности и внешними сервисами управления скидками: https://msloyaltyapi.docs.apiary.io

Данный тип приложений размещается на витрине в отдельном блоке “Скидки”.

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

На текущий момент для данного типа приложений недоступны возможности Маркетплейса (iframe, Vendor API, доступ по токену к JSON API, отладка на аккаунтах разработчика), так как данный тип приложений еще не заведен на механизмы Маркетплейса (но возможно ручное размещение приложений данного типа на витрине приложений).

Платные и бесплатные приложения

На текущий момент в Маркетплейсе поддерживаются как бесплатные, так и платные приложения.

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

Для платных приложений в системе МойСклад на данный момент доступен любой вариант стоимости, кратный 500 рублям в месяц. Эта оплата взимается с пользователей в виде платной опции в рамках их подписки на МойСклад — "Опции платных приложений", поэтому здесь так же, как на подписку, для пользователей применяются скидки за оплату на 3, 6 и 12 месяцев.

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

Вендор получает 75% от стоимости своих приложений без учета скидок и комиссий. Например, если приложение стоимостью 500 руб было оплачено на 3 месяца, вендор будет получать 500 * 0,75 = 375 рублей ежемесячно.

В дальнейшем возможно изменение доли вендора в ту или иную сторону.

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

Пробный период платных приложений

В Маркетплейсе МоегоСклада есть возможность дать пользователям поработать с платным приложением бесплатно некоторое время - пробный период.

Что важно знать о пробном периоде:

Приложение с пробным периодом можно создать через Личный кабинет вендора.

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

Жизненный цикл приложения

На текущий момент для приложения Маркетплейса предусмотрены следующие статусы жизненного цикла:

Жизненный цикл приложения выглядит следующим образом:

  1. Приложение создается в Личном кабинете вендора со статусом Draft. Вендор проверяет и отлаживает работу приложения на аккаунте разработчика. По готовности приложения вендор передает его на публикацию, статус приложения меняется на Ready.
  2. Сотрудники МоегоСклада проверяют приложение и, в случае отсутствия замечаний, публикуют приложение на витрине, статус приложения меняется на Published. Приложение становится доступно для установки пользователями МоегоСклада.
  3. Пользователи МоегоСклада подключают/устанавливают приложение на свой аккаунт, выполняют его настройку (если таковая опция имеется в приложении), пользуются приложением и, если оно становится ненужным, отключают/удаляют приложение с аккаунта.
  4. Если по каким-то причинам приложение требуется убрать с витрины приложений, то оно переводится в статус Hidden. Установленные до этого момента экземпляры приложений на аккаунтах продолжают работать и отображаться на UI МоегоСклада до момента удаления приложения самим пользователем. Для прочих аккаунтов, а также для аккаунтов, удаливших приложение, оно скрывается и установка становится невозможна. Подобный вариант скрытия сейчас реализован только для бесплатных приложений.

Требования к приложениям

Ниже перечислены требования, которым должно соответствовать приложение для успешного прохождения модерации:

Требования к иконкам приложений

При разработке иконки, которая будет отображаться на витрине приложений, нужно ориентироваться на следующие требования:

  1. Отчетливая крупная форма отчетливого цвета. Иконка будет на белом фоне и может теряться если в ней будут мелкие детали на белом фоне. К тому же один крупный знак будет просто и понятно восприниматься.
  2. Не делайте иконку без фона, если только она не заполняет выделенное пространство плотно, иначе она будет «исчезать» на фоне других иконок.
  3. Не ставьте скриншоты и фотографии и элементы интерфейса. Фотографии и экраны приложений могут включать много ненужных и плохо различичмых деталей. Детали интерфейса могут быть обманчивыми и путающими человека.
  4. По возможности не используйте слова. Используйте знак вашего логотипа, если у вас есть отдельный. Если используете какую-то букву из вашего логотипа как знак, то можно использовать его. Если вы так не делаете, то можно поставить полное название, учитывая все остальные пункты.
  5. Не ставьте логотип МоегоСклада или его имитации. Указать наш логотип значит сказать, что мы как-то учавствовали в разработке приложения, что будет неправдой.
  6. Размер иконки 90x90. Можно использовать все это пространство и не оставлять внутренних белых рамок.

useful image

Разработка и публикация приложений

Краткая инструкция по разработке, отладке и публикации приложений на примере iframe- и серверных приложений.

Разработка серверных приложений

При разработке серверного приложения следует определиться по следующим вопросам:

Также заметим, что для серверных приложений является обязательным реализация эндпоинта /api/moysklad/vendor/1.0/apps (см. Vendor API) на стороне вендора, и предполагается, что серверное приложение будет взаимодействовать с МоимСкладом по JSON API 1.2 с авторизацией по токену (передаваемому приложению по Vendor API при активации).

Разработка iframe-приложений

При разработке iframe-приложения вендору следует определиться по следующим вопросам:

Личный кабинет вендора

Для упрощения и автоматизации работы над приложениями Маркетплейса был создан Личный кабинет вендора (ЛКВ). Это сервис, который позволяет вендорам самостоятельно создавать приложения в статусе Draft (Черновик), отлаживать и тестировать их на витрине приложений, вносить необходимые изменения (в том числе самостоятельно получать и изменять SecretKey) и, по окончании разработки, отправлять на модерацию в МойСклад.

Что можно делать в личном кабинете:

Получение доступа к личному кабинету Вендору

Для получения доступа в Личный кабинет следует заполнить анкету или, если вы уже являетесь Вендором, обратиться к сотруднику МоегоСклада.

Создание черновика приложения

Форма создания черновика приложения открывается по кнопке Создать приложение.

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

В личном кабинете Вендора можно завести три типа приложений:

Создание Серверных и Iframe-приложений:

При создании Серверного или Iframe приложения можно указать платным или бесплатным будет ваше приложение: за это отвечает чекбокс Платное.

Для платных приложений нужно определить их стоимость, кратную 500 рублям. Максимальная стоимость приложения, которую можно задать через ЛКВ, 10000 рублей, минимальная, соответственно, 500 рублей. Если необходимо указать большую стоимость, вендор может обратиться к сотруднику МоегоСклада.

Для платных приложений открывается возможность добавить Пробный период. После установки отметки в чекбоксе Платное станет доступен селектор, в котором можно выбрать длительность Пробного периода (до 14 дней) или его отсутствие.

При создании Серверного или Iframe-приложения дескриптор обязателен для заполнения. Ознакомиться с правилами его заполнения можно в разделе Дескриптор приложения.

Создание Телефонии:

При создании приложения с типом Телефония нельзя проставить признак Платности, выбрать Пробный период и не нужно заполнять Дескриптор. Телефония оплачивается пользователем отдельно - через опцию CRM.

Редактирование черновика приложения

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

Что следует знать:

Редактирование информации о вендоре

Для редактирования информации о вендоре (разработчике) приложения потребуется перейти на вкладку Вендор в верхнем меню Личного кабинета.

Функция доступна, пока на аккаунте отсутствуют приложения или есть только Черновики. В остальных случаях данные доступны только для просмотра, а для изменения следует обратиться к модератору МоегоСклада.

Привязка аккаунта к вендору

Отладка приложений для Маркетплейса производится на аккаунтах разработчика. Для того, чтобы аккаунт в МоемСкладе стал аккаунтом разработчика, его нужно привязать к вендору, и это тоже можно сделать в Личном кабинете вендора.

Инициировать привязку можно по кнопке Привязать, расположенной в верхнем меню Личного кабинета.

Важно: Для привязки необходимо иметь доступ к email ответственного сотрудника, назначенного в аккаунте МоегоСклада на странице Подписка. По умолчанию им является администратор, зарегистрировавший аккаунт, однако впоследствии этого пользователя можно изменить.

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

Ручная приостановка приложения

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

Для тестирования приостановки необходимо:

  1. Привязать аккаунт в МоемСкладе к аккаунту Вендора в ЛКВ (создать аккаунт разработчика)
  2. Завести платное приложение в ЛКВ
  3. Установить приложение на аккаунте разработчика
  4. Выбрать приложение в списке и нажать кнопку Приостановить на аккаунте
  5. Готово! Приложение приостановлено.
  6. Для отладки возобновления можно воспользоваться кнопкой Активировать в карточке приложения на витрине МоегоСклада.

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

Отправка на модерацию

Перед публикацией на витрине МоегоСклада новое приложение должно сначала пройти модерацию.

Для отправки на модерацию следует выбрать нужное приложение в статусе Черновик из списка и нажать кнопку Отправить на модерацию.

Важно: для получения оперативных оповещений о ходе модерации необходимо заполнить Email для уведомлений в разделе Вендор

Карточка вендора

Карточка вендора - это Google Sheets таблицы, через которые происходил обмен информацией между вендором и МоимСкладом до создания Личного кабинета.

На данный момент карточка не используется.

Отладка приложений на аккаунтах разработчика

Отладка неопубликованных приложений выполняется вендором на специальном аккаунте(ах), привязанных к вендору.

На таких аккаунтах неопубликованные приложения вендора появляются в специальном блоке на витрине приложений "ПРИЛОЖЕНИЯ В РАЗРАБОТКЕ". Для остальных пользователей приложения-черновики не будут видны.

Неопубликованные приложения можно подключать и отключать так же, как и обычные опубликованные приложения.

Привязка аккаунтов к вендору осуществляется через Личный кабинет вендора.

Общая схема процесса размещения приложения в Маркетплейсе

После готовности приложения на стороне вендора в общем случае вендору нужно выполнить следующие шаги по размещению приложения в Маркетплейсе:

  1. Создать Черновик приложения в Личном кабинете вендора.
  2. После создания Черновика на странице редактирования приложения будет доступен Секретный ключ (Secret Key).
  3. Создать аккаунт разработчика, привязав аккаунт МоегоСклада к аккаунту в Личном кабинете вендора.
  4. Протестировать и отладить приложение на аккаунте разработчика.
  5. Отправить приложение на модерацию через Личный кабинет вендора.

Далее сотрудник МоегоСклада смотрит на приложение и, при отсутствии замечаний, публикует его на витрине приложений.

Демо-приложение

Для демонстрации взаимодействия приложений с Маркетплейсом МоегоСклада было создано демо-приложение на PHP.

В демо-приложении реализованы следующие функции:

Более подробную информацию и исходный код приложения можно получить по ссылке: https://github.com/moysklad/php-dummyapp-marketplace-1.0

Виджеты

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

FAQ по виджетам

Куда сейчас можно встраивать виджеты?

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

Во всех точках расширения виджеты имеют одинаковый функционал.

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

Список доступных для модернизации страниц (точек расширения) будет активно дополняться.

Хочу встроить виджет в точку МоегоСклада, которой нет в списке - что делать?

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

Какими могут быть виджеты:

Сейчас можно создать только виджеты с

Планируется реализация поддержки двух режимов отображения виджетов:

Жизненный цикл виджета

Виджет начинает отображаться на странице только после перехода приложения в статус Activated. Если приложение предполагает настройку и статус SettingsRequired - виджет отобразится после настройки приложения.

При первом открытии страницы с виджетом (в рамках одной вкладки браузера) cистема МоегоСклада загружает виджет по HTTP GET-запросом по URL'у, указанному в теге sourceUrl. При этом система генерирует и передает GET-параметром одноразовый contextKey, по которому виджет получает текущий контекст пользователя через Vendor API.

Прочие данные передаются при помощи postMessage в первом и последующих открытиях виджета.

В частности, при каждом открытии виджета система МоегоСклада отображает ранее загруженный iframe виджета (без повторной загрузки с сервера вендора) и через postMessage передает в iframe этого виджета сообщение Open.

Без дополнительных настроек виджет отображает содержимое сразу, как только получает сообщение Open, даже если еще не успел обновить отображаемую информацию.

В случае, если виджет использует протокол open-feedback, система не отображает содержимое виджета сразу, а ждет ответного сообщения от виджета о готовности. До этого момента внутри виджета отображается заглушка. Когда виджет готов, он отправляет сообщение OpenFeedback, после чего система полностью открывает виджет пользователю.

Использование виджетом протокола open-feedback необходимо указать в дескрипторе приложения.

Как работают виджеты

Описание конфигурации виджетов приложения в дескрипторе

Виджеты доступны для серверных приложений с дескриптором версии v2.

Пример дескриптора приложения с виджетом в карточке контрагента расположен в правой части экрана.

Дескриптор приложения с виджетом в карточке контрагента

   <ServerApplication xmlns="https://online.moysklad.ru/xml/ns/appstore/app/v2"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="https://online.moysklad.ru/xml/ns/appstore/app/v2
         https://online.moysklad.ru/xml/ns/appstore/app/v2/application-v2.xsd">
       <iframe>...</iframe>
       <vendorApi>...</vendorApi>
       <access>...</access>
       <widgets>
           <entity.counterparty.view>
               <sourceUrl>https://b2b.moysklad.ru/widget/counter-party</sourceUrl>
               <height>
                   <fixed>28px</fixed>
               </height>
               <supports>
                   <open-feedback/>
               </supports>
           </entity.counterparty.view>
       </widgets>
   </ServerApplication>

Подробнее со структурой дескриптора для приложения с виджетом можно ознакомиться в разделе Дескриптор приложений.

В результате после установки и настройки приложения пользователем виджет отображается на карточке контрагента:

useful image

Загрузка виджета на странице

Виджет на странице загружается в iframe по URL, указанному в теге <sourceUrl>...</sourceUrl> виджета в дескрипторе приложения.

Ширина содержимого виджета одинакова для виджетов всех приложений и равна 384px, а высота содержимого виджета статически указывается разработчиком в дескрипторе приложения (в данном примере 28px).

useful image

Так же, как и для основного iframe-приложения, виджету GET-параметром передается contextKey, по которому через Vendor API можно получить информацию о текущем пользователе.

Пока происходит загрузка виджета - отображается ненавязчивый лоадер.

Кэширование виджетов

Система виджетов в МоемСкладе реализована таким образом, чтобы, по-возможности, загрузить виджет только один раз при первом открытии страницы с виджетом (в рамках одной вкладки браузера) и далее кэшировать iframe c загруженном в него виджетом, переиспользуя его во всех последующих (в рамках одной вкладки браузера) открытиях страницы с виджетом.

Несмотря на стремление к идеальному кэшированию - оно не гарантировано. То есть хост-окно может:

Открытие виджета

При открытии пользователем страницы с виджетом хост-окно отображает iframe виджета (только что загруженный или ранее закэшированный) и передает в этот iframe виджета сообщение Open через postMessage.

Пример сообщения Open cм. в правой части экрана.

Сообщение Open

    {
      "name": "Open",
      "messageId": 12345,
      "extensionPoint": "entity.counterparty.view",
      "objectId": "8e9512f3-111b-11ea-0a80-02a2000a3c9c",
      "displayMode": "expanded"
    }

Здесь objectId - это в данном случае идентификатор контрагента, так как точка расширения entity.counterparty.view.

Виджет при получении сообщения Open может, например, обратиться на сервер за данными для указанного объекта objectId и отобразить их пользователю.

Протокол обратной связи при открытии виджета

По умолчанию при открытии закэшированного виджета его содержимое отображается сразу.

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

Протокол обратной связи позволяет виджету явно сообщить хост-окну в какой именно момент отобразить содержимое виджета. До этого содержимое виджета будет закрыто ненавязчивым лоадером:

useful image

Тег дополнительных протоколов supports с протоколом open-feedback

    <supports>
        <open-feedback/>
    </supports>

Для переключения хост-окна на использование протокола обратной связи при открытии виджета в дескрипторе для виджета надо явно указать поддержку дополнительного протокола open-feedback. Пример тега дополнительных протоколов supports с указанным в нем протоколом open-feedback см. в правой части экрана.

Виджет передает сообщение OpenFeedback хост-окну в качестве сигнала готовности содержимого виджета для отображения пользователю. Пример сообщения OpenFeedback - в правой части экрана.

Cообщение OpenFeedback

{
  "name": "OpenFeedback",
  "correlationId": 12345
}

Здесь correlationId содержит значение messageId ранее полученного сообщения Open.

Хост-окно, получив сообщение OpenFeedback, отображает содержимое виджета пользователю (убирает ненавязчивый лоадер).

Дескриптор приложения

Дескриптор приложения представляет собой XML-структуру, которая описывает технические параметры встраивания/интеграции приложения вендора в МойСклад.

Содержимое дескриптора должно соответствовать версии XSD-схемы. Актуальной версией считается v2.

История версий XSD-схемы дескриптора

Версия Описание Разрешенное содержимое дескриптора Поддерживаемые типы приложений
1.0.0 Серверные и простые iFrame-приложения vendorApi, access, iframe iFrame, Серверные
1.1.0 Расширение iFrame (тег expand) vendorApi, access, iframe(c expand) iFrame, Серверные
2.0.0 Виджеты в карточке контрагента. Прекращена поддержка приложений с типом iFrame vendorApi, access, iframe(c expand), widgets Серверные
2.1.0 Виджеты в Заказе покупателя и Отгрузке vendorApi, access, iframe(c expand), widgets Серверные

Основные отличия дескриптора v2 от дескрипторов версий 1.x.x:

Дескрипторы версий 1.x.x некоторое время будут продолжать поддерживаться.

Содержимое дескриптора приложения

Рассмотрим дескриптор приложения на примерах.

<ServerApplication  xmlns="https://online.moysklad.ru/xml/ns/appstore/app/v2"             
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"             
                    xsi:schemaLocation="https://online.moysklad.ru/xml/ns/appstore/app/v2      
                    https://online.moysklad.ru/xml/ns/appstore/app/v2/application-v2.xsd">
    <iframe>
        <sourceUrl>https://example.com/iframe.html</sourceUrl>
        <expand>true</expand>
    </iframe>
    <vendorApi>
        <endpointBase>https://example.com/dummy-app</endpointBase>
    </vendorApi>
    <access>
        <resource>https://online.moysklad.ru/api/remap/1.2</resource>
        <scope>admin</scope>
    </access>
    <widgets>        
        <entity.counterparty.view>            
            <sourceUrl>https://example.com/widget.php</sourceUrl>            
            <height>                
                <fixed>150px</fixed>            
            </height>                  
        </entity.counterparty.view>    
    </widgets>
</ServerApplication>

На текущий момент в актуальной версии дескриптора приложения есть четыре блока: iframe, vendorApi, access, widgets. Порядок расположения этих блоков относительно друг друга в дескрипторе может быть произвольным.

Блок Назначение Доступно для типов приложений Требует наличия других блоков
iframe Описывает iframe-часть приложения. iframe-приложения, серверные приложения Не требует
vendorApi Описывает взаимодействие по Vendor API. серверные приложения Не требует
access Описывает требуемый доступ приложения к ресурсам пользовательского аккаунта. серверные приложения vendorApi
widgets Описывает виджеты. серверные приложения Не требует

Блок iframe

В теге iframe/sourceUrl указывается URL, по которому будет загружаться содержимое iframe внутри UI МоегоСклада. В URL допускается использование только протокола HTTPS.

В случае отсутствия блока iframe в дескрипторе считается, что у приложения отсутствует iframe-часть.

В теге iframe/expand указывается boolean значение, которое отвечает, будет ли iframe расширяться в основном приложении МоегоСклада. Под расширением подразумевается автоматическое масштабирование iframe элемента в зависимости от контента. Данный элемент является опциональным со значением false по умолчанию. Чтобы расширение iframe работало верно, на странице, которая указана в sourceUrl, должен работать скрипт, оповещающий страницу МоегоСклада об изменении высоты его контента, то есть:

Для удобства можно добавить следующий js скрипт на свою страницу. Пример:

<!doctype html>
<html>

<head>
...
</head>

<body>
...
<script type="text/javascript" src="https://online.moysklad.ru/js/ns/appstore/app/v1/moysklad-iframe-expand-2.js"></script>
</body>

</html>

Блок vendorApi

В теге vendorApi/endpointBase указывается базовый URL эндпоинта на стороне вендора, к которому будет обращаться МойСклад. В URL допускается использование только протокола HTTPS.

Для получения полного адреса конкретного эндпоинта Vendor API на стороне вендора к базовому URL’у добавляется суффикс /api/moysklad/vendor/1.0 и путь эндпоинта. То есть шаблон формирования полного URL ресурса в общем случае такой:

{endpointBase}/api/moysklad/vendor/1.0/{endpointPath}/…

Для эндпоинта активации/деактивации приложений на аккаунте шаблон следующий (endpointPath = apps):

{endpointBase}/api/moysklad/vendor/1.0/apps/{appId}/{accountId}

Например, если:

то полный URL ресурса на стороне вендора, к которому будет выполнять запросы МойСклад при активации (и деактивации) приложения на аккаунте, будет следующим:

https://example.com/dummy-app/api/moysklad/vendor/1.0/apps/5f3c5489-6a17-48b7-9fe5-b2000eb807fe/f088b0a7-9490-4a57-b804-393163e7680f

В случае отсутствия блока vendorApi в дескрипторе не выполняется активация и деактивация приложения на серверах вендора.

Блок access

В тегах access/resource (в перспективе их может быть несколько) указываются ресурсы, к которым приложению нужен доступ.

В тегах access/scope (в перспективе их тоже может быть несколько) указываются требуемые разрешения/требуемый уровень доступа. При наличии блока access должны присутствовать как минимум по одному тегу resource и scope.

Наличие блока access требует наличия блока vendorApi для передачи токена(ов) к ресурсам аккаунта при активации приложения по Vendor API.

В случае отсутствия этого блока в дескрипторе приложения при установке на аккаунт приложению не выдаются никакие доступы к ресурсам аккаунта.

На текущий момент для access/resource возможно только одно значение: https://online.moysklad.ru/api/remap/1.2

Для access/scope на текущий момент доступно тоже только одно значение: admin

Другими словами, на текущий момент блок access может иметь только такой вид:

<access>
    <resource>https://online.moysklad.ru/api/remap/1.2</resource>
    <scope>admin</scope>
</access>

Блок widgets

Сначала необходимо определить в блоке widgets точку расширения - указать страницу, где будет расположен виджет.

Сейчас доступны следующие точки расширения:

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

Тем не менее, в итоге на одной странице может оказаться несколько виджетов (от разных приложений).

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

Тег sourceUrl - обязательный. Содержит URL, по которому загружается код виджета в iframe. В URL допускается использование только протокола HTTPS.

Тег height - обязательный. В теге height/fixed задается фиксированная высота виджета в пикселях, в формате 150px.

Тег supports - опциональный. Предназначен для дополнительных протоколов, поддерживаемых виджетом. На данный момент в нем можно указать только протокол supports/open-feedback. При открытии экрана обеспечивает скрытие содержимого виджета до явного уведомления от виджета о готовности. Подробнее про протокол open-feedback можно прочитать в разделе Жизненный цикл виджета. Параметры у протокола отсутствуют.

Пример заполненного блока widgets:

Блок widgets с точками расширения в контрагенте и заказе покупателя

    <widgets>
        <entity.counterparty.view>
            <sourceUrl>https://example.com/widget-counterparty.php</sourceUrl>
            <height>
                <fixed>200px</fixed>
            </height>
            <supports><open-feedback/></supports>
        </entity.counterparty.view>

        <document.customerorder.edit>
            <sourceUrl>https://example.com/widget-customerorder.php</sourceUrl>
            <height>
                <fixed>50px</fixed>
            </height>
        </document.customerorder.edit>

    </widgets>

Примеры дескрипторов

Для серверных приложений (актуальная версия схемы дескриптора v2)

Дескриптор для серверных приложений с iframe-частью и расширением окна (expand)

<ServerApplication  xmlns="https://online.moysklad.ru/xml/ns/appstore/app/v2"             
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"             
                    xsi:schemaLocation="https://online.moysklad.ru/xml/ns/appstore/app/v2      
                    https://online.moysklad.ru/xml/ns/appstore/app/v2/application-v2.xsd">
    <iframe>
        <sourceUrl>https://example.com/iframe.html</sourceUrl>
        <expand>true</expand>
    </iframe>
    <vendorApi>
        <endpointBase>https://example.com/dummy-app</endpointBase>
    </vendorApi>
    <access>
        <resource>https://online.moysklad.ru/api/remap/1.2</resource>
        <scope>admin</scope>
    </access>
</ServerApplication>

Дескриптор для серверных приложений с виджетом в карточке контрагента

<ServerApplication  xmlns="https://online.moysklad.ru/xml/ns/appstore/app/v2"             
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"             
                    xsi:schemaLocation="https://online.moysklad.ru/xml/ns/appstore/app/v2      
                    https://online.moysklad.ru/xml/ns/appstore/app/v2/application-v2.xsd">
    <iframe>
        <sourceUrl>https://example.com/iframe.html</sourceUrl>
    </iframe>
    <vendorApi>
        <endpointBase>https://example.com/dummy-app</endpointBase>
    </vendorApi>
    <access>
        <resource>https://online.moysklad.ru/api/remap/1.2</resource>
        <scope>admin</scope>
    </access>
    <widgets>        
        <entity.counterparty.view>            
            <sourceUrl>https://example.com/widget.php</sourceUrl>            
            <height>                
                <fixed>150px</fixed>            
            </height>                  
        </entity.counterparty.view>    
    </widgets>
</ServerApplication>

Дескриптор для серверных приложений с виджетом в карточке контрагента, заказе покупателя и отгрузке и протоколом openfeedback

<ServerApplication  xmlns="https://online.moysklad.ru/xml/ns/appstore/app/v2"             
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"             
                    xsi:schemaLocation="https://online.moysklad.ru/xml/ns/appstore/app/v2      
                    https://online.moysklad.ru/xml/ns/appstore/app/v2/application-v2.xsd">
    <iframe>
        <sourceUrl>https://example.com/iframe.html</sourceUrl>
    </iframe>
    <vendorApi>
        <endpointBase>https://example.com/dummy-app</endpointBase>
    </vendorApi>
    <access>
        <resource>https://online.moysklad.ru/api/remap/1.2</resource>
        <scope>admin</scope>
    </access>
    <widgets>        
        <entity.counterparty.view>            
            <sourceUrl>https://example.com/widget.php</sourceUrl>            
            <height>                
                <fixed>150px</fixed>            
            </height>            
            <supports><open-feedback/></supports>        
        </entity.counterparty.view>    

        <document.customerorder.edit>
            <sourceUrl>https://example.com/widget-customerorder.php</sourceUrl>
            <height>
                <fixed>50px</fixed>
            </height>
            <supports><open-feedback/></supports>  
        </document.customerorder.edit>

        <document.demand.edit>
            <sourceUrl>https://example.com/widget-demand.php</sourceUrl>
            <height>
                <fixed>50px</fixed>
            </height>
            <supports><open-feedback/></supports>  
        </document.demand.edit>

    </widgets>
</ServerApplication>

Для серверных приложений (устаревшие версии схемы дескриптора 1.x.x)

Минимальный дескриптор для серверных приложений (без возможности настройки параметров приложения пользователем МоегоСклада, так как у приложения отсутствует iframe-часть)

<application xmlns="https://online.moysklad.ru/xml/ns/appstore/app/v1"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                                  
      xsi:schemaLocation="https://online.moysklad.ru/xml/ns/appstore/app/v1 
      https://online.moysklad.ru/xml/ns/appstore/app/v1/application-1.1.0.xsd">
    <vendorApi>
        <endpointBase>https://example.com/dummy-app</endpointBase>
    </vendorApi>
    <access>
        <resource>https://online.moysklad.ru/api/remap/1.2</resource>
        <scope>admin</scope>
    </access>
</application>

Дескриптор для серверных приложений с iframe-частью

<application xmlns="https://online.moysklad.ru/xml/ns/appstore/app/v1"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"                                  
      xsi:schemaLocation="https://online.moysklad.ru/xml/ns/appstore/app/v1 
      https://online.moysklad.ru/xml/ns/appstore/app/v1/application-1.1.0.xsd">
    <iframe>
        <sourceUrl>https://example.com/iframe.html</sourceUrl>
    </iframe>
    <vendorApi>
        <endpointBase>https://example.com/dummy-app</endpointBase>
    </vendorApi>
    <access>
        <resource>https://online.moysklad.ru/api/remap/1.2</resource>
        <scope>admin</scope>
    </access>
</application>

Для телефонии

Для приложений телефонии дескриптор на текущий момент не требуется (не поддерживается).

Для систем лояльности

Для интеграций с системами лояльности дескриптор на текущий момент не требуется (не поддерживается).

Доступ по токену к JSON API

Токен для доступа к JSON API 1.2 передается вендору при активации приложения через Vendor API в момент установки или возобновления приложения. Время жизни токена не ограничено.

Токен аннулируется при удалении и приостановке приложения. На момент деактивации приложения через Vendor API токен уже нерабочий (аннулирован).

Токен при доступе к JSON API 1.2 следует передавать как Bearer-токен, а именно в виде заголовка HTTP-запроса:

Authorization: Bearer <access_token>

Пример:

Authorization: Bearer 6ab89be1ae6ff147755625ee8da948e42612233b

Диаграмма последовательности предоставления доступа при подключении приложения

useful image

Диаграмма последовательности отзыва доступа при отключении приложения

useful image

Работа с вебхуками

Если ваше приложение может создать вебхук(-и) на аккаунте пользователя, то нужно иметь в виду следующее поведение:

Подробную информацию о работе с вебхуками можно получить по ссылке https://dev.moysklad.ru/doc/api/remap/1.2/dictionaries/#suschnosti-veb-huki

Особенности доступа к некоторым функциям JSON API 1.2

На данный момент для приложений существует ряд ограничений в работе со следующими сущностями JSON API 1.2:

Vendor API 1.0

Vendor API предназначено для взаимодействия Маркетплейса с системами вендоров касательно процессов, происходящих в рамках функционирования Маркетплейса.

На текущий момент Vendor API включает в себя следующие функции:

В данном разделе описаны спецификации REST-эндпоинтов на стороне МоегоСклада и вендора приложений.

Процесс активации приложения на аккаунте

В общем виде процесс активации приложения выглядит так:

  1. Пользователь МоегоСклада нажимает кнопку “Установить” приложение.
    • Для платных приложений возможно возобновление в случаях:
      • Пользователь, на аккаунте которого есть приостановленные приложения, оплачивает подписку с "Опцией платных приложений"
      • Пользователь удаляет работающее платное приложение, после чего нажимает кнопку "Активировать" у приостановленного приложения.
  2. Маркетплейс делает HTTP PUT запрос на сервер вендора, в том числе передавая причину активации и токен доступа к JSON API (если в дескрипторе приложения таковой доступ запрашивается). При этом доступ по переданному токену уже работает.
  3. Сервер вендора, в рамках допустимого тайм-аута, отвечает на запрос одним из статусов в теле ответа:
    • Activating - этот статус предназначен для асинхронной активации на стороне вендора (то есть если в рамках допустимого тайм-аута обработки HTTP PUT запроса не получается активировать приложение - например, для активации приложения требуется несколько минут). Далее вендор должен оповестить МойСклад через эндпоинт “Обратного вызова изменения статуса приложения на аккаунте” о завершении активации приложения статусом Activated или о том, что приложению требуется настройка статусом SettingsRequired.
    • SettingsRequired - таким статусом вендор сообщает МоемуСкладу, что приложению требуется настройка пользователем (через iframe-часть приложения). После того, как пользователь настроит приложение, вендор должен оповестить МойСклад через эндпоинт “Обратного вызова изменения статуса приложения на аккаунте” об активации приложения, передав статус Activated.
    • Activated - этот статус означает, что приложение сразу полностью активировано и уже заработало.

Диаграмма деятельности активации приложения:

useful image

Процесс деактивации приложения на аккаунте

Процесс деактивации приложения существенно проще процесса активации:

  1. Пользователь МоегоСклада нажимает кнопку “Удалить” в карточке приложения.
    • Для платных приложений возможна приостановка в случаях:
      • У пользователя, на аккаунте которого есть установленные платные приложения, кончается подписка.
      • Пользователь, на аккаунте которого есть установленные платные приложения, оплачивает подписку с количеством "Опций платных приложений" меньше, чем требуется для оплаты установленных платных приложений.
  2. Маркетплейс аннулирует доступ по токену (если таковой был выдан) и выполняет HTTP DELETE запрос с причиной деактивации к серверу вендора. То есть на момент получения вендором оповещения по деактивации доступ по токену уже не работает.

Диаграмма деятельности деактивации приложения:

useful image

Аутентификация взаимодействия по Vendor API

Все запросы от МоегоСклада к серверу вендора и в обратную сторону от сервера вендора к МоемуСкладу должны быть подписаны с использованием JWT (JSON Web Token) описанным ниже образом.

Секретный ключ secretKey

Если приложение предполагает взаимодействие по Vendor API (оповещение по активации и деактивации, получение контекста пользователя для iframe), то ему понадобится Секретный ключ.

Секретный ключ (secretKey) используется для построения/вычисления сигнатуры JWT.

Секретный ключ генерируется на стороне МоегоСклада и выдается вендору. На текущий момент процесс выглядит так:

  1. Вендор заводит Черновик приложения в Личном кабинете вендора.
  2. После этого будет доступна страница редактирования, на которой, в числе прочих read-only полей, доступен Секретный ключ.
  3. Пока приложение находится в статусе Черновик, вендор может перегенерировать Секретный ключ самостоятельно.
  4. После передачи приложения на модерацию и далее Секретный ключ доступен только для просмотра и копирования.
  5. Если по какой-то причине вендор хочет перегенерировать secretKey для приложения не в статусе Черновик, то он это делает через взаимодействие с сотрудником МоегоСклада.

Исходящие запросы МойСклад → Вендор

МойСклад подписывает свои запросы к REST-эндпоинтам вендора, передавая JWT-токен в заголовке HTTP-запроса следующим образом:

Authorization: Bearer <token>

Описание полей JWT-payload:

Поле Описание Предполагаемое использование вендором
iat Время генерации токена в секундах от 1970-01-01T00:00:00Z UTC На усмотрение вендора
exp Время жизни/“протухания“ токена в секундах от 1970-01-01T00:00:00Z UTC - позволяет ограничить срок валидности токена (после указанного момента времени токен считается невалидным) При получении JWT после времени, указанного в exp, следует отклонять запрос с ошибкой аутентификации
jti Уникальный идентификатор токена - позволяет отслеживать одноразовость применения токена При получении JWT с jti, который был уже получен ранее, следует отклонять запрос с ошибкой аутентификации
JWT-header всегда такой:
{
  "alg": "HS256",
  "typ": "JWT"
}
JWT-payload включает в себя следующие поля:
{
  "iat": 1516239022,
  "exp": 1516239322,
  "jti": "6S3BQLsaSRNdEnhPCoW9lplY2LozRUOq"
}

Входящие запросы Вендор → МойСклад

Вендор при выполнении REST запросов к МоемуСкладу по Vendor API также должен подписывать их токеном JWT, который также следует передавать в заголовке HTTP-запроса:

Authorization: Bearer <token>

Поле alg в JWT-заголовке всегда должно иметь значение HS256. Соответственно, JWT-сигнатура всегда должна генерироваться по алгоритму HMAC SHA-256 с использованием секретного ключа secretKey.

Описание полей JWT-payload:

Поле Обязательное Описание Обработка на стороне МоегоСклада
sub да appUid приложения Используется для идентификации и авторизации приложения
iat да Время генерации токена в секундах от 1970-01-01T00:00:00Z UTC Используется для ограничения допустимого времени жизни токена
exp нет Время жизни/“протухания“ токена в секундах от 1970-01-01T00:00:00Z UTC (после какого момента токен считается невалидным) Если данное поле присутствует, то оно также используется для проверки валидности токена по времени
jti да Уникальный идентификатор токена Используется для проверки одноразовости использования токена

В системе МоегоСклада есть ограничение на максимальное время жизни для JWT-токена (порядка нескольких минут) - назовем его maxTokenLifetime. При проверке/валидации на стороне МоегоСклада значение exp ограничивается максимальным временем жизни: если (exp - iat) превышает maxTokenLifetime или поле exp отсутствует, то в качестве exp используется iat + maxTokenLifetime, то есть:

effectiveExp = exp ? min(exp, iat + maxTokenLifetime) : iat + maxTokenLifetime

JWT-header может быть как с указанием поля typ:
{
  "alg": "HS256",
  "typ": "JWT"
}
так и без поля typ:
{
  "alg": "HS256"
}
JWT-payload должен содержать следующие поля (все поля являются обязательными за исключением exp - это поле опциональное):
{
  "sub": "dummyapp.example-vendor",
  "iat": 1516239022,
  "exp": 1516239322,
  "jti": "6S3BQLsaSRNdEnhPCoW9lplY2LozRUOq"
}

Ошибки аутентификации и авторизации

Обработка ошибок аутентификации и авторизации на стороне МоегоСклада осуществляется аналогично тому как это сделано в JSON API 1.2:

https://dev.moysklad.ru/doc/api/remap/1.2/

То есть при возникновении ошибок возвращается аналогичный объект error и заголовки HTTP-ответа X-Lognex-Auth и X-Lognex-Auth-Message.

REST-эндпоинты на стороне вендора приложений

Если вендору требуется

то в этом случае вендору со своей стороны требуется реализовать REST-endpoint с доступом по HTTPS и поддерживающий HTTP-методы PUT, GET, DELETE:

https://<VENDOR-SERVER-ENDPOINT>/api/moysklad/vendor/1.0/apps/{appId}/{accountId}

где VENDOR-SERVER-ENDPOINT - тот URL, который указан в дескрипторе приложения.

Здесь

Активация приложения на аккаунте

Запрос должен обрабатываться сервером идемпотентно. Маркетплейс может повторять/дублировать запросы в соответствии со своей внутренней логикой (например, при работе механизма Retry).

HTTP-метод: PUT

Content-Type: application/json

В теле запроса передаем:

В теле ответа ожидаем получить следующую структуру:

Статус Описание Дальнейшие действия вендора Отображаемый пользователю статус приложения на витрине приложений
Activating приложение в процессе активации вендор оповестит Маркетплейс по эндпоинту обратного вызова об изменении статуса приложения (на SettingsRequired или Activated) приложение подключается
SettingsRequired требуется настройка приложения пользователем вендор оповестит Маркетплейс об изменении статуса (на Activated), когда пользователь выполнит настройку приложения (через iframe) приложение требует настройки
Activated приложение на аккаунте полностью активировано (и начало свою работу) действий вендора не требуется приложение подключено

HTTP status codes:

Пример активации бесплатного приложения:

Request:

PUT https://example.com/baseurl/api/moysklad/vendor/1.0/apps/5f3c5489-6a17-48b7-9fe5-b2000eb807fe/f088b0a7-9490-4a57-b804-393163e7680f

Body

{
  "appUid": "example-app.example-vendor",
  "accountName": "dummyaccount",
  "cause": "Install",
  "access": [
    {
      "resource": "https://online.moysklad.ru/api/remap/1.2",
      "scope": ["admin"],
      "access_token": "6ab89be1ae6ff147755625ee8da948e42612233b"
    }
  ]
}

Response:

Response 200

Content-Type: application/json

Body:

{
  "status": "SettingsRequired"
}


Пример активации платного приложения:

Request:

PUT https://example.com/baseurl/api/moysklad/vendor/1.0/apps/5f3c5489-6a17-48b7-9fe5-b2000eb807fe/f088b0a7-9490-4a57-b804-393163e7680f

Body

{
  "appUid": "example-app.example-vendor",
  "accountName": "dummyaccount",
  "cause": "Resume",
  "access": [
    {
      "resource": "https://online.moysklad.ru/api/remap/1.2",
      "scope": ["admin"],
      "access_token": "6ab89be1ae6ff147755625ee8da948e42612233b"
    }
  ]
}

Response:

Response 200

Content-Type: application/json

Body:

{
  "status": "Activated"
}

Деактивация приложения на аккаунте

HTTP-метод: DELETE

Тело запроса:

Тело ответа: пустое

HTTP status codes:

Пример деактивации бесплатного приложения:

Request:

DELETE https://example.com/baseurl/api/moysklad/vendor/1.0/apps/5f3c5489-6a17-48b7-9fe5-b2000eb807fe/f088b0a7-9490-4a57-b804-393163e7680f

Body

{
  "cause": "Uninstall"
}

Response:

Response 200

Content-Type: application/json



Пример деактивации платного приложения:

Request:

DELETE https://example.com/baseurl/api/moysklad/vendor/1.0/apps/5f3c5489-6a17-48b7-9fe5-b2000eb807fe/f088b0a7-9490-4a57-b804-393163e7680f

Body

{
  "cause": "Suspend"
}

Response:

Response 200

Content-Type: application/json

Проверка статуса активации приложения в системе вендора

HTTP-метод: GET

Тело запроса: пустое

Тело ответа:

HTTP status codes:

Пример

Request:

GET https://example.com/api/moysklad/vendor/1.0/apps/5f3c5489-6a17-48b7-9fe5-b2000eb807fe/f088b0a7-9490-4a57-b804-393163e7680f


Response:

Response 200

Content-Type: application/json

Response body

{
  "status": "SettingsRequired"
}

REST-эндпоинты на стороне МоегоСклада

Rest-эндпоинты на стороне МоегоСклада позволяют Вендору ограниченно управлять состоянием установки приложения для конкретного аккаунта, а также позволяют узнать информацию о пользователе, который загружает iframe-приложение в UI МоегоСклада.

Базовый URL REST-эндпоинтов со стороны МоегоСклада (далее будем называть его MARKETPLACE-ENDPOINT):

На текущий момент со стороны МоегоСклада есть следующие эндпоинты:

Обратный вызов изменения статуса приложения на аккаунте

С помощью этого эндпоинта вендор может изменить статус устанавливающегося приложения пользователя. При активации приложения со стороны вендора, вендор может ответить одним из статусов Activated, Activating, Settings. Если вендор перевел в статусы Activating и Settings, то МойСклад ожидает, что вендор с помощью обратного вызова оповестит МойСклад о том, что активация на его стороне завершена.

Resource: MARKETPLACE-ENDPOINT/apps/{appId}/{accountId}/status

Здесь

HTTP-метод: PUT

Тело запроса:

МойСклад при обработке данного запроса проверяет возможность перехода приложения на аккаунте в требуемое состояние в соответствии с жизненным циклом приложения на аккаунте. При отсутствии перехода по жизненному циклу - ошибка. Если приложение на аккаунте уже находится в целевом состоянии - то ошибки нет.

Тело ответа: пустое (за исключением ошибок)

HTTP status codes:

Пример

Request:

PUT https://online.moyslad.ru/api/vendor/1.0/apps/5f3c5489-6a17-48b7-9fe5-b2000eb807fe/f088b0a7-9490-4a57-b804-393163e7680f

Body

{
  "status": "Activating"
}

Response:

Response 200

Content-Type: application/json

Получение контекста пользователя для приложений с iframe-частью

Через этот эндпоинт можно получить информацию по пользователю, который загружает приложение c iframe-частью в UI МоегоСклада. В URL, по которому загружается iframe-часть приложения, добавляется GET-параметр contextKey. Пример того, что будет загружаться в Iframe, при условии, что в дескрипторе приложения Iframe имеет значение https://yoursite.ru/moysklad: https://yoursite.ru/moysklad?contextKey=1c14e98cd272239c03bf3d9697f167699743292c. contextKey - это одноразовый ключ, который может быть использован не более одного раза для получения контекста пользователя через данный эндпоинт. В случае повторного использования contextKey - эндпоинт вернет ошибку.

Resource: MARKETPLACE-ENDPOINT/context/{contextKey}

Здесь

HTTP-метод: POST

Тело запроса: пустое

Тело ответа:

В случае успешного ответа возвращается такое же по структуре содержимое как в https://online.moysklad.ru/api/remap/1.2/context/employee

В случае ошибок - JSON-объект с ошибкой. Подробнее см. Обработка ошибок МоегоСклада.

HTTP status codes:

Пример

Request:

POST https://online.moysklad.ru/api/vendor/1.0/context/6S3BQLsaSRNdEnhPCoW9lplY2LozRUOq6S3BQLsaSRNdEnh


Response 200 (application/json). Успешный запрос.

{
  "meta": {
    "href": "https://online.moysklad.ru/api/remap/1.2/entity/employee/b0a02321-13e3-11e9-912f-f3d4002516e3?expand=cashier.retailStore",
    "metadataHref": "https://online.moysklad.ru/api/remap/1.2/entity/employee/metadata",
    "type": "employee",
    "mediaType": "application/json",
    "uuidHref": "https://online.moysklad.ru/app/#employee/edit?id=b0a02321-13e3-11e9-912f-f3d4002516e3"
  },
  "id": "b0a02321-13e3-11e9-912f-f3d4002516e3",
  "accountId": "b0b309ee-13e3-11e9-9109-f8fc0001f188",
  "owner": {
    "meta": {
      "href": "https://online.moysklad.ru/api/remap/1.2/entity/employee/b0a02321-13e3-11e9-912f-f3d4002516e3",
      "metadataHref": "https://online.moysklad.ru/api/remap/1.2/entity/employee/metadata",
      "type": "employee",
      "mediaType": "application/json",
      "uuidHref": "https://online.moysklad.ru/app/#employee/edit?id=b0a02321-13e3-11e9-912f-f3d4002516e3"
    }
  },
  "shared": true,
  "group": {
    "meta": {
      "href": "https://online.moysklad.ru/api/remap/1.2/entity/group/b0b3c289-13e3-11e9-9109-f8fc0001f189",
      "metadataHref": "https://online.moysklad.ru/api/remap/1.2/entity/group/metadata",
      "type": "group",
      "mediaType": "application/json"
    }
  },
  "updated": "2019-12-10 18:37:25.786",
  "name": "Кожевников",
  "externalCode": "Exh56G1wiRTPHpYBc-nx12",
  "archived": false,
  "created": "2019-01-09 10:53:45.202",
  "uid": "admin@bkozhevnikov",
  "email": "bkozhevnikov@moysklad.ru",
  "lastName": "Кожевников",
  "fullName": "Кожевников",
  "shortFio": "Кожевников",
  "cashiers": [
    {
      "meta": {
        "href": "https://online.moysklad.ru/api/remap/1.2/entity/retailstore/b0b7cd8d-13e3-11e9-912f-f3d400251724/cashiers/b0b7d387-13e3-11e9-912f-f3d400251725",
        "type": "cashier",
        "mediaType": "application/json"
      }
    }
  ],
  "permissions": {
    "currency": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "uom": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "productfolder": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "product": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "bundle": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "service": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "consignment": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "variant": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "store": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "counterparty": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "organization": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "employee": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "contract": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "project": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "country": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "customentity": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "demand": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "customerorder": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "internalorder": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "invoiceout": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "invoicein": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "paymentin": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "paymentout": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "cashin": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "cashout": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "supply": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "salesreturn": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "purchasereturn": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "retailstore": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "receipttemplate": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "retailshift": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "retaildemand": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "retailsalesreturn": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "retaildrawercashin": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "retaildrawercashout": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "prepayment": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "prepaymentreturn": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "purchaseorder": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "move": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "enter": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "loss": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "facturein": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "factureout": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "commissionreportin": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "commissionreportout": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "pricelist": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "processingplanfolder": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "processingplan": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "processing": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "processingorder": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "assortment": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "inventory": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "print": "ALL"
    },
    "bonustransaction": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "crptorder": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "approve": "ALL",
      "print": "ALL"
    },
    "webhook": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL"
    },
    "task": {
      "view": "ALL",
      "create": "ALL",
      "update": "ALL",
      "delete": "ALL",
      "done": "ALL"
    },
    "dashboard": {
      "view": "ALL"
    },
    "stock": {
      "view": "ALL"
    },
    "customAttributes": {
      "view": "ALL"
    },
    "pnl": {
      "view": "ALL"
    },
    "company_crm": {
      "view": "ALL"
    },
    "tariff_crm": {
      "view": "ALL"
    },
    "audit_dashboard": {
      "view": "ALL"
    },
    "admin": {
      "view": "ALL"
    },
    "dashboardMoney": {
      "view": "ALL"
    }
  }
}

Обработка ошибок на стороне МоегоСклада

Обработка ошибок на стороне МоегоСклада (при взаимодействии Вендор → МойСклад) выполняется аналогично тому, как это сделано в JSON API 1.2 https://dev.moysklad.ru/doc/api/remap/1.2/ - в тело ответа включается JSON объект с описанием ошибки и также проставляются (если нужно) соответствующие HTTP-заголовки в ответе.

Механизм Retry

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

Если израсходованы все количества повторений, то Retry завершается с ошибкой. Что система делает далее - зависит от контекста (какую операцию мы пытались выполнить).