Command Palette

Search for a command to run...

Основные концепции

В этой главе вы узнаете о Модуле интеграций и о том, как его использовать.

Где можно применять Модуль интеграций

Модуль интеграций можно применять в самых разных сценариях. Он не зависит от типа провайдера, и ему всё равно, для чего нужны параметры.

  • Любой тип провайдера: Платежи, доставка, уведомления, аналитика, авторизация и другие.
  • Плагины: Добавляйте плагину настраиваемые параметры, не разрабатывая UI и слой данных.
  • Кастомные модули и расширения: Любой модуль Medusa, которому нужны настраиваемые параметры в Admin, например API-ключи, режимы или feature-флаги.

Если администратор магазина должен уметь управлять настройкой, её можно сделать через Модуль интеграций.

Провайдеры и потребители

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

  • Провайдер интеграции: Объявляет интеграцию. Описывает параметры, их группировку и валидацию, а также необязательную проверку соединения. Провайдером интеграции может быть любой плагин, провайдер или собственный модуль, и всё это он объявляет в одном дескрипторе.
  • Администратор магазина: Настраивает в Admin эти параметры, например учётные данные, режимы или вебхуки.
  • Потребитель: Читает параметры инстанса интеграции во время выполнения.

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

Дескриптор

Дескриптор представляет собой единое объявление метаданных интеграции, её параметров, секций настроек, валидации и необязательной проверки соединения. Создаётся он через .

Вот дескриптор платёжного провайдера с двумя параметрами и одной секцией:

providers/integration-my/services/my-integration.ts
1import { defineIntegration, AbstractIntegrationProvider } from "@gorgo/medusa-integration"
2
3const descriptor = defineIntegration({
4 category: "payment",
5 displayName: "my.name",
6 options: {
7 apiKey: {
8 type: "string",
9 control: "secret",
10 secret: true,
11 required: true,
12 label: "my.apiKey"
13 },
14 sandbox: {
15 type: "boolean",
16 control: "switch",
17 default: false,
18 label: "my.sandbox"
19 },
20 },
21 sections: [
22 {
23 id: "credentials",
24 title: "my.credentials",
25 options: ["apiKey", "sandbox"]
26 },
27 ],
28})
29
30export class MyIntegration extends AbstractIntegrationProvider {
31 static identifier = "my"
32
33 get descriptor() {
34 return descriptor
35 }
36}

Дескриптор служит единым источником истины для интеграции: в этом примере он объявляет и , сгруппированные в одну секцию . По нему модуль генерирует CRUD API, валидирует запись, отрисовывает UI настроек и определяет, что потребители получают во время выполнения. Вам не нужно писать ни модели данных, ни API-роуты, ни UI-формы.

Инстансы и их идентификаторы

Инстанс представляет собой отдельную регистрацию провайдера интеграции с собственной конфигурацией. Один и тот же провайдер можно зарегистрировать несколько раз, и каждая регистрация даёт самостоятельный инстанс со своими настройками в Admin.

Каждый инстанс интеграции адресуется по вида:

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

У каждой интеграции есть стабильный идентификатор, например , заданный как в провайдере:

providers/integration-my/services/my-integration.ts
1import { defineIntegration, AbstractIntegrationProvider } from "@gorgo/medusa-integration"
2
3// ...
4
5export class MyIntegration extends AbstractIntegrationProvider {
6 static identifier = "my"
7
8 // ...
9}

Все инстансы провайдера используют общий . Он всегда . Различает инстансы только в .

Один инстанс

Это вариант по умолчанию. У него нет ID инстанса (), поэтому его выглядит, например, как .

Зарегистрируйте его без :

medusa-config.ts
1module.exports = defineConfig({
2 // ...
3 plugins: [
4 {
5 resolve: "@gorgo/medusa-integration",
6 options: {
7 // ...
8 providers: [
9 {
10 resolve: "@gorgo/medusa-payment-my/providers/integration-my",
11 options: {},
12 },
13 ],
14 },
15 },
16 ],
17})

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

Несколько инстансов

Зарегистрируйте один и тот же провайдер несколько раз, каждый со своим . Каждый инстанс настраивается независимо, например для поддержки нескольких аккаунтов интегрируемого сервиса.

Например, две независимые регистрации одного и того же провайдера:

medusa-config.ts
1module.exports = defineConfig({
2 // ...
3 plugins: [
4 {
5 resolve: "@gorgo/medusa-integration",
6 options: {
7 // ...
8 providers: [
9 {
10 resolve: "@gorgo/medusa-payment-my/providers/integration-my",
11 id: "eu",
12 options: {},
13 },
14 {
15 resolve: "@gorgo/medusa-payment-my/providers/integration-my",
16 id: "us",
17 options: {},
18 },
19 ],
20 },
21 },
22 ],
23})

Это даст и соответственно. задаётся на верхнем уровне записи. Если случайно поместить его внутрь , провайдер зарегистрируется под инстансом по умолчанию (безымянным) без предупреждения.

Потребитель получает параметры по идентификатору и инстансу, поэтому один и тот же код может обращаться к нужному.

Параметры интеграции

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

Поля параметра

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

Loading...

Дополнительные поля по типу параметра

У некоторых типов есть свои поля сверх общих:

  • : , ,
  • :
  • : , , , , ,
  • : ,
Loading...

Сгенерированный CRUD и валидация

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

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

providers/integration-my/services/my-integration.ts
1const descriptor = defineIntegration({
2 // ...
3 validate: (full, { addIssue }) => {
4 if (full.mode === "webhook" && !full.webhookSecret) {
5 addIssue({ path: ["webhookSecret"], message: "Required when mode is \"webhook\"" })
6 }
7 },
8})

В отличие от или конкретного параметра, это правило запускается только при полной валидации (проверке готовности интеграции к включению), а не при сохранении отдельной секции.

Включена и заполнена

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

Секреты и шифрование

Параметры с пометкой шифруются при хранении алгоритмом AES-256-GCM и никогда не попадают в браузер. CRUD API маскирует их и сообщает лишь, задано значение или нет. Сохранение секрета пустым оставляет прежнее хранимое значение, а не стирает его.

Для шифрования модулю нужен ключ. Задайте его как при регистрации модуля в :

medusa-config.ts
1module.exports = defineConfig({
2 // ...
3 plugins: [
4 {
5 resolve: "@gorgo/medusa-integration",
6 options: {
7 encryptionKey: process.env.INTEGRATION_ENCRYPTION_KEY,
8 providers: [
9 // ...
10 ],
11 },
12 },
13 ],
14})

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

.env
INTEGRATION_ENCRYPTION_KEY=supersecret

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

Проверка соединения

Дескриптор может объявить необязательную проверку соединения, которая сверяет учётные данные со сторонним сервисом. Администраторы запускают её по требованию, а запланированная задача ежедневно перепроверяет настроенные интеграции.

Добавьте в дескриптор. Он получает уже итоговые (расшифрованные) параметры и возвращает статус:

providers/integration-my/services/my-integration.ts
1const descriptor = defineIntegration({
2 // ...
3 testConnection: async ({ options }) => {
4 const res = await fetch("https://api.my.com/ping", {
5 headers: { Authorization: `Bearer ${options.apiKey}` },
6 })
7
8 if (!res.ok) {
9 return { status: "failed", message: `My responded with ${res.status}` }
10 }
11
12 return { status: "passed" }
13 },
14})

принимает одно из значений: , или ; необязательное отображается в Admin рядом с результатом проверки.

Получение параметров во время выполнения

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

Генерация UI

Модуль генерирует UI интеграции из её дескриптора, поэтому строить страницы не нужно.

Секции

Параметры группируются в секции настроек и рендерятся через LayoutComposer Medusa в виде карточек с изменяемым порядком, в одну или две колонки.

Собственные секции

Когда сгенерированного UI недостаточно, вы можете построить для своих параметров любой интерфейс на собственных admin-виджетах. Это обычные admin-виджеты Medusa на том же механизме и зон внедрения, что вы уже используете в других местах, так что учить ничего нового не придётся. Модуль предоставляет зоны внедрения на странице каждой интеграции (например, ), и виджет, нацеленный на такую зону, получает готовый и напрямую читает и пишет параметры интеграции.

Локализация

Метки, подсказки и заголовки в дескрипторе задаются как i18n-ключи. Поставляйте переводы вместе со своей интеграцией, и UI настроек локализуется автоматически.

Всё это построено на стандартном i18n Medusa, так что учить ничего нового не нужно. Регистрируйте переводы привычным способом, и ключи подставляются по активному языку Admin с откатом на английский, если ключ отсутствует. Собственные виджеты локализуются так же, используя тот же каталог сообщений, что и сгенерированная форма.

Дальнейшие шаги

Изменено 12 августа 2026 г.·Редактировать страницу