# Уведомления Amazon SP-API: дедупликация и сверка

Source: https://ipvolt.com/ru/guides/amazon-listing-notifications
Markdown: https://ipvolt.com/ru/guides/amazon-listing-notifications.md
Language: ru

[ipvolt — главная](https://ipvolt.com/ru.md) / [Руководства](https://ipvolt.com/ru/guides.md) / Уведомления Amazon SP-API: дедупликация и сверка

Интеграция
Проверено: 2026-09-16
Опубликовано: 2026-09-16
6 мин чтения
Автор: ipvolt

Обработка событий листингов Amazon SP-API через протестированный SQLite-инбокс: дедупликация доставок, восстановление после перезапуска и отклонение устаревших чтений.

От ipvolt · Проверено 16 сентября 2026

Сохраняйте каждое проверенное уведомление о листинге Amazon **вместе с работой, которую оно порождает, в одной транзакции**, прежде чем подтверждать доставку. Используйте уведомление для планирования чтения листинга. Если во время этого чтения приходит ещё одно принятое уведомление, оставляйте работу ожидающей и читайте снова. Это предотвращает конкретную локальную гонку: более старый, ещё выполняющийся результат сбрасывает более новый запрос на обновление.

Это руководство предназначено для разработчиков с авторизованным приложением SP-API и существующим конвейером доставки EventBridge. Для интеграции нужны ваш собственный адаптер проверенных событий и аутентифицированный адаптер чтения листингов. Загружаемая лаборатория на SQLite работает офлайн с синтетическими событиями, одним воркером сверки и стандартной библиотекой Python; она реализует проверки сохранения и завершения между этими адаптерами.

**Метод:** ipvolt запустил демо и 12 тестов 16 сентября 2026 года на CPython 3.14.7 и SQLite 3.53.4. Целевая версия исходного кода — Python 3.11+; версия 3.11 в этом записанном прогоне не проверялась. Ни аккаунт Amazon, ни API-запросы, ни реальные подтверждения очереди не тестировались.

## Запустите локальную лабораторию

Скачайте и распакуйте [полный ZIP лаборатории](https://ipvolt.com/downloads/amazon-listing-notifications/amazon-listing-notifications.zip). Откройте терминал в каталоге с `consumer.py`, затем выполните:

```sh
python3 -B demo.py
python3 -B -m unittest -v test_consumer.py
```

Устанавливать пакеты не нужно. Обе команды используют временные базы данных. Демо печатает детерминированный JSON; сравните его с [записанным выводом](https://ipvolt.com/downloads/amazon-listing-notifications/example-output.json).

[README](https://ipvolt.com/downloads/amazon-listing-notifications/README.md) документирует полный контракт. При желании изучите по отдельности [consumer.py](https://ipvolt.com/downloads/amazon-listing-notifications/consumer.py), [demo.py](https://ipvolt.com/downloads/amazon-listing-notifications/demo.py), [набор тестов](https://ipvolt.com/downloads/amazon-listing-notifications/test_consumer.py) и [синтетическую фикстуру](https://ipvolt.com/downloads/amazon-listing-notifications/fixtures/scenario.json).

## Нормализуйте доверенное событие перед сохранением

Уведомления о статусе и проблемах листинга используют **рабочий процесс EventBridge** Amazon. Очередь SQS может быть нижестоящей целью правила; это отличается от подписки через прямой рабочий процесс SP-API SQS. Следуйте [настройке EventBridge](https://developer-docs.amazon/sp-api/docs/set-up-notifications-with-amazon-eventbridge) от Amazon для назначений, подписок и разрешений на доставку.

Зафиксируйте сырой тип и версию полезной нагрузки в своём адаптере. Имена в нижнем регистре ниже принадлежат этой лаборатории:

| Документированный тип Amazon | Версия полезной нагрузки | Нормализованный тип лаборатории |
| --- | --- | --- |
| `LISTINGS_ITEM_STATUS_CHANGE` | `1.0` | `listing_status_changed` |
| `LISTINGS_ITEM_ISSUES_CHANGE` | `2023-12-13` | `listing_issues_changed` |

Amazon направляет пользователей версии `1.0` уведомлений о проблемах на миграцию к `2023-12-13`. События статуса касаются создания, удаления и возможности покупки; события о проблемах содержат сводки, которые могут стать поводом для более полного чтения. Они не описывают все возможные проблемы листинга. [Типы уведомлений Amazon](https://developer-docs.amazon/sp-api/docs/notification-type-values).

Обе сырые полезные нагрузки допускают отсутствие `MarketplaceId`. Определяйте его только через доверенную авторизованную конфигурацию; иначе задержите событие для расследования, прежде чем создавать нормализованную запись. Никогда не подставляйте молча свой маркетплейс по умолчанию. Лаборатория требует явных продавца, SKU и маркетплейса. См. зафиксированные [схему статуса](https://raw.githubusercontent.com/amzn/selling-partner-api-models/3659f96867bfc669aca7a524c2f95744ff0e4478/schemas/notifications/ListingsItemStatusChangeNotification.json) и [схему проблем](https://raw.githubusercontent.com/amzn/selling-partner-api-models/3659f96867bfc669aca7a524c2f95744ff0e4478/schemas/notifications/ListingsItemIssuesChangeNotification_2023-12-13.json).

Есть и несогласованность в именовании: в enum этой схемы статуса указано `LISTINGS_ITEM_STATUS_CHANGED`, тогда как её пример и документация говорят `LISTINGS_ITEM_STATUS_CHANGE`. Держите любое исключение в валидации узким, версионированным и покрытым тестами вашего адаптера. Нормализованная лаборатория не разбирает этот конверт и не подтверждает его соответствие схеме.

Это точная первая синтетическая запись из фикстуры:

```json
{
  "schema_version": 1,
  "source": "fixture:eventbridge:bus-A",
  "subscription": "fixture-subscription-A",
  "notification_id": "notice-001",
  "seller_id": "seller-A",
  "sku": "SKU-RED",
  "marketplace_id": "market-A",
  "notification_type": "listing_status_changed",
  "event_time": "2026-09-16T10:00:00Z",
  "payload": {"hint": "synthetic status change"}
}
```

`Store.ingest()` принимает этот объект как JSON-текст. Адаптер сначала должен проверить источник, контекст приложения/подписки, авторизацию продавца и область действия. Храните внутреннюю идентичность уведомления отдельно от внешнего ID события EventBridge и любого receipt handle очереди. [Конверт EventBridge](https://docs.aws.amazon.com/eventbridge/latest/ref/events-structure.html) и [контракт удаления SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html) описывают эти различные транспортные значения.

Лаборатория дедуплицирует по `(source, subscription, notification_id)`. Этот составной ключ — политика приложения. Не включайте в нормализованный объект счётчики попыток доставки, receipt handle и время получения: они меняются между доставками. README перечисляет строгие ограничения на поля, размер и валидацию JSON.

## Фиксируйте приём и ожидающую работу вместе

EventBridge может доставлять дубликаты и не гарантирует порядок. Нижестоящая стандартная очередь SQS также допускает дубликаты и доставку не по порядку. [Сравнение способов доставки AWS](https://docs.aws.amazon.com/decision-guides/latest/decision-guides/sns-or-sqs-or-eventbridge.html), [стандартные очереди SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/standard-queues.html).

Исполняемое ядро обрабатывает эту неопределённость в четыре шага:

1. Начните транзакцию SQLite. Для новой идентичности вставьте запись инбокса и увеличьте поколение работы для `(seller_id, sku, marketplace_id)` вместе.
2. Для существующей идентичности сравните каноническое нормализованное содержимое. Идентичное содержимое возвращает `duplicate` без увеличения работы. Различающееся содержимое вызывает `IdentityConflict` и сохраняет исходное состояние.
3. Возвращайте `may_ack=True` только после коммита. Это логическое решение для вашего транспортного адаптера; загружаемый код не делает ни одного вызова подтверждения очереди. Ошибки валидации, конфликта и хранения этого решения не порождают.
4. Сканируйте `dirty_keys()` после перезапуска и между запусками. Ключ считается «грязным», когда `generation > applied_generation`. Зафиксируйте его поколение, выполните чтение вне транзакции, затем сохраните результат, только если ключ и поколение всё ещё совпадают.

Каждая новая принятая идентичность продвигает свой ключ, включая событие с более старым `event_time`. Полезная нагрузка хранится для сравнения идентичности и никогда не применяется как текущее состояние листинга. Изученная [модель статуса](https://raw.githubusercontent.com/amzn/selling-partner-api-models/3659f96867bfc669aca7a524c2f95744ff0e4478/schemas/notifications/ListingsItemStatusChangeNotification.json) определяет `EventTime` как метку времени, а не как общую ревизию листинга. Такая конструкция не отбрасывает работу лишь потому, что её метка времени старше.

## Наблюдайте перезапуск и гонку с выполняющимся чтением

Эта компактная трассировка взята из записанного демо для `seller-A / SKU-RED / market-A`:

| Случай | Поколение | Применённое поколение | Грязный | Наблюдаемый результат |
| --- | --- | --- | --- | --- |
| Процесс завершается после коммита | 1 | 0 | true | Одна строка инбокса сохраняется |
| Повторная доставка после перезапуска | 1 | 0 | true | `duplicate`, `may_ack: true` |
| Первое синтетическое чтение | 1 | 1 | false | `read-1` сохранён |
| Приходит более старое событие | 2 | 1 | true | Требуется новое обновление |
| Ещё одно событие приходит во время чтения поколения 2 | 3 | 1 | true | `completion_applied: false` |
| Следующее чтение завершается ошибкой | 3 | 1 | true | Предыдущий снимок сохранён |
| Более позднее успешное обновление | 3 | 3 | false | `read-3` сохранён |

Результат поколения 2 не может очистить поколение 3. Его отклонённый документ `read-2` никогда не заменяет `read-1`; последующий сбой также оставляет работу ожидающей. Демо завершается с пятью строками инбокса, тремя независимыми чистыми ключами и нулём внешних подтверждений.

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

«Чистый» означает, что чтение принято относительно последнего **сохранённого локального поколения**. Это не доказывает, что ответ Amazon включает вызвавшее его изменение, что другое уведомление не задерживается или что доставка была полной. Счётчик — не ревизия Amazon и не распределённая гарантия exactly-once.

## Проверяйте чтение перед очисткой работы

Ваш адаптер чтения должен явно выбирать наборы данных `getListingsItem` и проверять HTTP-статус, содержимое ответа и предполагаемый смысл продавца/SKU/маркетплейса, прежде чем возвращать `ReadResult`. [Руководство Amazon по получению листинга](https://developer-docs.amazon/sp-api/docs/retrieve-details-about-a-listing) объясняет, какие наборы данных отвечают на какие вопросы. Теперь оно поддерживает несколько маркетплейсов одного региона для продавцов; эта лаборатория намеренно держит один маркетплейс на ключ работы.

**Ядро не проверяет реальный ответ Amazon.** Оно проверяет объявленный адаптером ключ, ограничения JSON и локальное поколение. Даже `{}` проходит его проверку формы объекта. Если обязательные данные отсутствуют, ответ относится к чему-то другому или запрос завершился ошибкой, ваш адаптер должен выбросить исключение, а не возвращать заглушку в форме успеха. Тогда `refresh_once()` оставляет работу грязной, а предыдущий снимок нетронутым.

Для отдельного решения о принятых отправках, текущих предложениях, запасах и неизвестных наблюдениях используйте [Обновления листингов Amazon: «принято» не значит «опубликовано»](/ru/blog/amazon-listing-update-reconciliation). Успешная операция сохранения не может сделать неполное наблюдение осмысленным.

## Добавьте восстановление вокруг ядра

Используйте одного воркера сверки для этого примера. Его тикеты — проверки поколения, а не аренды воркеров. База данных хранит идентичности инбокса бессрочно; их удаление меняет горизонт дедупликации. Планирование, backoff, ограничения частоты запросов, хранение и владение при нескольких воркерах требуют дополнительного проектирования.

Производственному конвейеру также нужна надёжная обработка некорректных или конфликтующих событий, восстановление после сбоев доставки и периодическая сверка авторизованной области листингов. Amazon рекомендует [резервный механизм получения](https://developer-docs.amazon/sp-api/docs/notifications-api); EventBridge прекращает повторы после исчерпания настроенной политики и поддерживает [очередь недоставленных сообщений (dead-letter queue)](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rule-retry-policy.html). Сканирующая сверка и восстановление из DLQ выходят за рамки этой лаборатории. Они покрывают сбои, которых инбокс не видит, потому что событие до него так и не дошло.

ipvolt находится в разработке. [Запишитесь в список раннего доступа](https://ipvolt.com/#waitlist-closing), чтобы получить одно письмо, когда доступ откроется. Больше ничего.

## Источники и дополнительное чтение

- [Set up notifications using the Amazon EventBridge workflow](https://developer-docs.amazon/sp-api/docs/set-up-notifications-with-amazon-eventbridge)
- [Notification Type Values](https://developer-docs.amazon/sp-api/docs/notification-type-values)
- [Listings Item Status Change Notification schema](https://raw.githubusercontent.com/amzn/selling-partner-api-models/3659f96867bfc669aca7a524c2f95744ff0e4478/schemas/notifications/ListingsItemStatusChangeNotification.json)
- [Listings Item Issues Change Notification schema2023-12-13](https://raw.githubusercontent.com/amzn/selling-partner-api-models/3659f96867bfc669aca7a524c2f95744ff0e4478/schemas/notifications/ListingsItemIssuesChangeNotification_2023-12-13.json)
- [AWS service event metadata](https://docs.aws.amazon.com/eventbridge/latest/ref/events-structure.html)
- [DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html)
- [Amazon SQS, Amazon SNS, or Amazon EventBridge?](https://docs.aws.amazon.com/decision-guides/latest/decision-guides/sns-or-sqs-or-eventbridge.html)
- [Amazon SQS standard queues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/standard-queues.html)
- [Retrieve details about a listing for single or multiple Amazon stores](https://developer-docs.amazon/sp-api/docs/retrieve-details-about-a-listing)
- [Notifications API](https://developer-docs.amazon/sp-api/docs/notifications-api)
- [How EventBridge retries delivering events](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rule-retry-policy.html)

## Связанные руководства

- [Прокси в Python Requests: словарь proxies, аутентификация, SOCKS5](https://ipvolt.com/ru/guides/python-requests-proxy.md)
- [Диагностика таймаутов прокси: по одному этапу за раз](https://ipvolt.com/ru/guides/proxy-timeout-troubleshooting.md)
- [Прокси в curl: флаг -x, переменные окружения, SOCKS5, аутентификация](https://ipvolt.com/ru/guides/curl-proxy-setup.md)

## О ipvolt

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

[Читать оригинал на английском](https://ipvolt.com/guides/amazon-listing-notifications.md)

## Узнайте, когда откроется доступ.

ipvolt · В разработке

Мы строим прокси-инфраструктуру для разработчиков и команд, работающих с данными. Оставьте email, чтобы получить уведомление, когда ipvolt будет готов.

Одно письмо, когда откроется доступ. Больше ничего.

[Получить ранний доступ](https://ipvolt.com/ru/guides/amazon-listing-notifications#waitlist-closing)

[Конфиденциальность](https://ipvolt.com/privacy)

