{"value":"#### **1.基本介绍**\n\n\n什么是 Notifications API?Notifications API 是亚马逊 SP-API 中基于事件驱动,依托于 Amazon 的 SQS 服务(Simple Queue Service),基于 MQ 实现的通知 API 接口。使用 Notifications API,您可以创建接收通知、订阅通知、删除通知订阅等操作。当事件触发您订阅的通知时,您的应用程序可以直接从 Amazon 接收信息,而不再需要进行轮询,这样做可有效减少 SP-API 各个接口的轮询次数, 并拥有更高的实时性。\n截止目前,SP-API 中提供的 Notification Type (消息类型)如下:\n\n![image.png](https://dev-media.amazoncloud.cn/1b95a879acb24e8cac4216d8a625aea1_image.png)\n\n**Reference:**\n\n[https://developer-docs.amazon.com/sp-api/docs/notifications-api-v1-use-case-guide#notificationtype](https://developer-docs.amazon.com/sp-api/docs/notifications-api-v1-use-case-guide#notificationtype)\n\n\n#### **2. 使用教程详解**\n\n\n接下来,我们带给大家 Notifications API 与 SQS 结合使用的详细教程。\n\n##### **Step 1 创建 SQS**\n\n\n登录亚马逊控制台,进入 [Amazon SQS](https://aws.amazon.com/cn/sqs/?trk=cndc-detail) 服务页面\n\n###### **1.1 创建队列**\n\n![image.png](https://dev-media.amazoncloud.cn/cbed1a03ad19468c9e63daa59ec9845d_image.png)\n\n###### **1.2 设置队列的基本属性**\n\n根据需求配置队列属性\n\n![image.png](https://dev-media.amazoncloud.cn/bc9d16b51a99472d978a0daa5b5eca2e_image.png)\n\n###### **1.3 设置队列的默认访问策略**\n\n访问策略选择默认,创建结束后再修改\n\n![image.png](https://dev-media.amazoncloud.cn/781acac03a704e08ad26292d68441767_image.png)\n\n\n##### **STEP 2 配置 SQS (允许 Amazon 发送消息)**\n\n\n\n###### **2.1 编辑队列**\n\n\n在队列创建完成后,记录 arn,并点击编辑\n\n![image.png](https://dev-media.amazoncloud.cn/e0f9200b532f42ffa557cbfd4bf75af1_image.png)\n\n\n###### **2.2 修改策略**\n\n记录当前队列的 root Principal,点击策略生成器(此时,我们已经拿到了自身的 ARN,和自身的 Principal)\n\n![image.png](https://dev-media.amazoncloud.cn/aba182c9fd5e4214b3fdad852875eae0_image.png)\n\n###### **2.3 自身拥有队列的所有权限**\n\n![image.png](https://dev-media.amazoncloud.cn/e6c1a0990648438eb255727202ea443a_image.png)\n\n\n###### **2.4 Amazon 拥有 GetQueueAttributes 和 SendMessage 权限**\n\nAmazon 的为 Principal (固定的): arn:aws:iam::437568002678:root\n\n![image.png](https://dev-media.amazoncloud.cn/89b02daa19da47af86bc4c0610829fca_image.png)\n\n具体操作如下:\n\n![image.png](https://dev-media.amazoncloud.cn/c04df69d04af49ecbac8c2e170b3c596_image.png)\n\n###### **2.5 生成配置**\n\n![image.png](https://dev-media.amazoncloud.cn/d808b8d61b4c41f398cfb95d66c2521e_image.png)\n\n###### **2.6 复制配置 JSON**\n\n![image.png](https://dev-media.amazoncloud.cn/5a1b0685ff5e485aa075e067f7726f06_image.png)\n\n\n###### **2.7 替换配置 JSON**\n\n\n![image.png](https://dev-media.amazoncloud.cn/c3e714e64d984ee3a1fe2e12586d46a7_image.png)\n\n\n###### **2.8 点击保存**\n\n\n至此,我们拥有了一个队列,并且,该队列允许亚马逊发送消息,开发者账号拥有该队列所有权限。\n\n\n##### **STEP 3 监听队列**\n\n如果您是 Java 开发者,这里可以依赖 Spring boot,使用 JMS 监听队列。\n\n###### **3.1 POM 依赖**\n\n\n```\\n<dependency>\\n <groupId>org.springframework</groupId>\\n <artifactId>spring-jms</artifactId>\\n</dependency>\\n<dependency>\\n <groupId>com.amazonaws</groupId>\\n <artifactId>amazon-sqs-java-messaging-lib</artifactId>\\n <version>1.0.0</version>\\n <type>jar</type>\\n</dependency>\\n<dependency>\\n <groupId>com.amazonaws</groupId>\\n <artifactId>aws-java-sdk-sqs</artifactId>\\n <version>1.11.943</version>\\n</dependency>\\n```\n\n###### **3.2 监听代码**\n\n\n```\\n@Component\\n@Slf4j\\npublic class SqsConsumer {\\n @JmsListener(destination = \\"SQS名称\\", containerFactory = \\"listenerContainerFactory\\")\\n public void consumer(SQSTextMessage sqsTestMessage) throws Exception {\\n String text = sqsTestMessage.getText();\\n log.info(\\"接收到SQS通知:{}\\", text);\\n }\\n}\\n```\n\n###### **3.3 listenerContainerFactory**\n\n\n```\\n@Bean\\npublic SQSConnectionFactory connectionFactory() {\\n SQSConnectionFactory sqsConnectionFactory = SQSConnectionFactory.builder()\\n // amazonPropertiesConfig 为 AWSCredentialsProvider的实现类实例, 提供 AWSCredentials 即可\\n .withAWSCredentialsProvider(amazonPropertiesConfig)\\n // sqs所在地区 在endpoint中可以找到,如: us-west-1\\n .withRegionName(amazonPropertiesConfig.getSqsRegion())\\n // sqs地址 配置页中的地址 https://sqs.us-west-1.amazonaws.com/xxxxxxxx/TEST\\n .withEndpoint(amazonPropertiesConfig.getSqsEndpoint())\\n .build();\\n return sqsConnectionFactory;\\n}\\n@Bean\\npublic DefaultJmsListenerContainerFactory listenerContainerFactory(SQSConnectionFactory connectionFactory) {\\n DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();\\n factory.setConnectionFactory(connectionFactory);\\n factory.setDestinationResolver(new DynamicDestinationResolver());\\n //开启多少线程\\n factory.setConcurrency(\\"10-20\\"); \\n //开启自动确认\\n factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE); \\n return factory;\\n}\\n```\n\n\n##### **STEP 4 订阅消息**\n\n\n###### **4.1 创建 createDestination**\n\n\n注意:\n在请求参数中: resourceSpecification 下的 SQS 和 EventBridge 只能二选一,并且必须选一个,在 SQS 中,我们填写 SQS 即可。\ncreateDesition 是一种[无授权操作](https://developer-docs.amazon.com/sp-api/docs/grantless-operations),与卖家身份无关,调用 createDestination 时,可以不用显式地获得 Selling Partner 的授权。由于 Destination 是开发者的内容,与卖家没有关系,因此,在 Client 对象的创建上,不用 refresh token 的方式,而是使用 scope 模式,scope = “sellingpartnerapi::notifications”\n\n```\\nLWAClientScopes lwaClientScopes = new LWAClientScopes(new HashSet<>());\\n lwaClientScopes.getScopes().add(\\"sellingpartnerapi::notifications\\");\\n LWAAuthorizationCredentials lwaAuthorizationCredentials = LWAAuthorizationCredentials.builder()\\n .clientId(clientId())\\n .clientSecret(clientSecret())\\n .scopes(lwaClientScopes)\\n .endpoint(authUrl())\\n .build();\\n```\n\ncreateDestination 示例代码:\n\n\n```\\npublic CreateDestinationResponse createDestination(String marketplaceId, CreateDestinationDTO createDestinationDTO) throws ApiException {\\n NotificationsApi notificationsApi = getNotificationsApi(marketplaceId);\\n DestinationResourceSpecification destinationResourceSpecification = new DestinationResourceSpecification();\\n SqsResource sqsResource = new SqsResource();\\n sqsResource.setArn(createDestinationDTO.getArn());\\n destinationResourceSpecification.setSqs(sqsResource);\\n CreateDestinationRequest body = new CreateDestinationRequest();\\n body.setResourceSpecification(destinationResourceSpecification);\\n body.setName(createDestinationDTO.getDestinationName());\\n return notificationsApi.createDestination(body);\\n}\\n@Data\\npublic class CreateDestinationDTO {\\n //sqs详情页中可以找到改值\\n private String arn; \\n private String destinationName;\\n //sqs详情页中可以找到改值\\n private String sqsName; \\n}\\n```\n\n请求体参数示例:\n\n\n```\\n{\\n \\"resourceSpecification\\": {\\n \\"sqs\\": {\\n \\"arn\\": \\"arn:aws:sqs:us-west-1:xxxxxxxx:TEST\\"\\n }\\n },\\n \\"name\\": \\"testDestination\\"\\n}\\n返回值示例:\\n{\\n \\"payload\\": {\\n \\"name\\": \\"testDestination\\",\\n \\"destinationId\\": \\"2d6eee67-23e9-40fe-destinationId\\",\\n \\"resource\\": {\\n \\"sqs\\": {\\n \\"arn\\": \\"arn:aws:sqs:us-west-1:xxxxxxxx:TEST\\"\\n }\\n }\\n }\\n}\\n```\n\n需要记录下返回结果中的: destinationId\n\n\n###### **4.2 根据 Destination 创建订阅**\n\n\n注意:\n一个卖家的一种消息类型,只能订阅一个 Destination\n在 SP-API 的权限设计中此时,操作与卖家有关,需要使用卖家的授权进行访问。\n\n```\\nLWAAuthorizationCredentials lwaAuthorizationCredentials = LWAAuthorizationCredentials.builder()\\n .clientId(clientId)\\n .clientSecret(clientSecret)\\n .refreshToken(spAuthToken)\\n .endpoint(authUrl)\\n .build();\\n```\n\ncreateSubscription 示例代码:\n\n\n```\\npublic CreateSubscriptionResponse createSubscription(String destinationId, NotificationTypeEnum notificationType,String spAuthToken) throws ApiException {\\n NotificationsApi notificationsApi = getNotificationsApi(spAuthToken);\\n CreateSubscriptionRequest request = new CreateSubscriptionRequest();\\n request.setDestinationId(destinationId);\\n request.setPayloadVersion(\\"1.0\\");\\n return notificationsApi.createSubscription(request, notificationType.name());\\n}\\n```\n\n请求参数示例:\n\n```\\nurl:\\n /notifications/v1/subscriptions/REPORT_PROCESSING_FINISHED\\nbody:\\n{\\n \\"payloadVersion\\": \\"1.0\\",\\n \\"destinationId\\": \\"2d6eee67-23e9-40fe-destinationId\\"\\n}\\n```\n\n\n返回值示例:\n\n```\\n{\\n \\"payload\\": {\\n \\"subscriptionId\\":\\"7ca3572b-2130-41eb-subscriptionId\\",\\n \\"payloadVersion\\":\\"1.0\\",\\n \\"destinationId\\": \\"2d6eee67-23e9-40fe-destinationId\\",\\n }\\n}\\n```\n\n至此,已经完成了所有准备工作,耐心等待 Amazon 触发相关类型的消息即可。\n\n##### **STEP 5 监听消息**\n\n###### **5.1 接收通知数据**\n\nSP-API 的返回通知数据结构采用 JSON 格式。每个通知都包含一个 Payload 对象,其中包含通知的可操作数据。Notification Type 与 PayloadVersion 一起确定 Payload 对象的结构。\nREPORT_PROCESSING_FINISHED notification 示例:\n\n```\\n{\\n \\"notificationVersion\\": \\"2020-09-04\\",\\n \\"notificationType\\": \\"REPORT_PROCESSING_FINISHED\\",\\n \\"payloadVersion\\": \\"1.0\\",\\n \\"eventTime\\": \\"2022-02-10T03:05:00.197Z\\",\\n \\"payload\\": {\\n \\"reportProcessingFinishedNotification\\": {\\n \\"sellerId\\": \\"A2BAZU3******\\",\\n \\"reportId\\": \\"34997*********\\",\\n \\"reportType\\": \\"GET_FLAT_FILE_VAT_INVOICE_DATA_REPORT\\",\\n \\"processingStatus\\": \\"DONE\\",\\n \\"reportDocumentId\\": \\"amzn1.tortuga.********************************************\\"\\n }\\n },\\n \\"notificationMetadata\\": {\\n \\"applicationId\\": \\"amzn1.sellerapps.app.********************\\",\\n \\"subscriptionId\\": \\"36df6577-33c7-********************\\",\\n \\"publishTime\\": \\"2022-02-18T03:05:00.230Z\\",\\n \\"notificationId\\": \\"0cbae32d-222f-********************\\"\\n }\\n}\\n```\n\nFEED_PROCESSING_FINISHED notification 示例:\n\n```\\n{\\n \\"notificationVersion\\": \\"2020-09-04\\",\\n \\"notificationType\\": \\"FEED_PROCESSING_FINISHED\\",\\n \\"payloadVersion\\": \\"1.0\\",\\n \\"eventTime\\": \\"2022-02-11T08:46:38.498Z\\",\\n \\"payload\\": {\\n \\"feedProcessingFinishedNotification\\": {\\n \\"sellerId\\": \\"A2EW6******\\",\\n \\"feedId\\": \\"625004******\\",\\n \\"feedType\\": \\"POST_ORDER_FULFILLMENT_DATA\\",\\n \\"processingStatus\\": \\"DONE\\",\\n \\"resultFeedDocumentId\\": \\"amzn1.tortuga.********************************************\\"\\n }\\n },\\n \\"notificationMetadata\\": {\\n \\"applicationId\\": \\"amzn1.sellerapps.app.**************************\\",\\n \\"subscriptionId\\": \\"4d5b53b4-66ad-4ee0-***************\\",\\n \\"publishTime\\": \\"2022-02-18T08:46:39.950Z\\",\\n \\"notificationId\\": \\"188fea65-74da-4fce-***************\\"\\n }\\n}\\n```\n\nORDER_STATUS_CHANGE notification 示例:\n\n\n```\\n{\\n \\"NotificationVersion\\": \\"1.0\\",\\n \\"NotificationType\\": \\"ORDER_STATUS_CHANGE\\",\\n \\"PayloadVersion\\": \\"1.0\\",\\n \\"EventTime\\": \\"2022-01-13T19:42:04.284Z\\",\\n \\"Payload\\":\\n {\\n \\"OrderNotification\\":\\n {\\n \\"SellerId\\": \\"A2EW6******\\",\\n \\"AmazonOrderId\\": \\"333-7777777-7777777\\",\\n \\"PurchaseDate\\": 1595882000633,\\n \\"OrderStatus\\": \\"PROCESSED\\",\\n \\"DestinationPostalCode\\": \\"48110\\",\\n \\"SupplySourceId\\": \\"SSID39485\\",\\n \\"OrderItemId\\": \\"OIID34853450\\",\\n \\"SellerSKU\\": \\"SellerSKUID1\\",\\n \\"Quantity\\": 45\\n }\\n },\\n \\"NotificationMetadata\\":\\n {\\n \\"ApplicationId\\": \\"app-id-d0e9e693-c3ad-4373-979f-ed4ec98dd746\\",\\n \\"SubscriptionId\\": \\"subscription-id-d0e9e693-c3ad-4373-979f-ed4ec98dd746\\",\\n \\"PublishTime\\": \\"2022-01-13T19:42:04.284Z\\",\\n \\"NotificationId\\": \\"d0e9e693-c3ad-4373-979f-ed4ec98dd746\\"\\n }\\n}\\n```\n\n其他通知类型的数据接口请参考 reference:\n\n[https://developer-docs.amazon.com/sp-api/docs/notifications-api-v1-use-case-guide#notification-structure](https://developer-docs.amazon.com/sp-api/docs/notifications-api-v1-use-case-guide#notification-structure)\n\n###### **5.2 处理队列中的消息**\n\n为了正确处理通知,您需要了解 [Amazon SQS](https://aws.amazon.com/cn/sqs/?trk=cndc-detail) 队列的几个重要属性:\n\n- SP-API 不支持分发到 FIFO 队列。您必须使用 [Amazon SQS](https://aws.amazon.com/cn/sqs/?trk=cndc-detail) 标准队列来接收通知。\n- SP-API 标准队列不保证将按照发送顺序接收通知。标准队列提供尽力而为的排序,这意味着通知通常以与发送时相同的顺序传递。但是,有时多份通知的副本可能会乱序传送。因此,您需要将您的应用程序设计为以任何顺序接受通知。\n- [Amazon SQS](https://aws.amazon.com/cn/sqs/?trk=cndc-detail) 标准队列通知可能会发送多次。[Amazon SQS](https://aws.amazon.com/cn/sqs/?trk=cndc-detail) 将通知副本存储在多台服务器上,以实现冗余和高可用性。在极少数情况下,当您收到或删除通知时,其中一个存储通知副本的服务器可能不可用。如果发生这种情况,通知副本不会在该不可用服务器上删除,并且您可能会在收到通知时再次获得该通知副本。因此,您需要将您的应用程序设计为接受任何给定通知的多个副本。\n您可以通过查看通知的属性来确定通知是否与您已收到的通知重复。您可以在通知的对象中找到该属性例如:notificationId,NotificationMetaData。\n\n\n#### **本系列文章**\n\n[如何对接亚马逊电商 Selling Partner API](https://aws.amazon.com/cn/blogs/china/how-to-connect-with-amazon-e-commerce-selling-partner-api/)\n\n[创建 SP-API 第三方登录应用并完成 API Call](https://aws.amazon.com/cn/blogs/china/create-sp-api-third-party-login-application-and-complete-api-call/)\n\n[SP-API 中 Notifications API 结合 Amazon EventBridge 使用的详细教程\\n](https://aws.amazon.com/cn/blogs/china/detailed-tutorial-on-the-use-of-notifications-api-with-amazon-eventbridge-in-sp-api/)\n\n\n#### **本篇作者**\n\n![image.png](https://dev-media.amazoncloud.cn/bf27c4f42a1d4620bcaaa4b044a6db78_image.png)\n\n#### **Lei Wang**\n\n亚马逊 SP-API 中国区负责人。Amazon 解决方案架构师。专注亚马逊电商平台合作伙伴及第三方服务商 ISV 的 SP-API 对接咨询及推广。为中国区开发者提供基于 SP-API 的解决方案。\n\n![image.png](https://dev-media.amazoncloud.cn/f0b93a9a47f7484b9c185baf0115c426_image.png)\n\n#### **Aonan Guan**\n\n亚马逊云科技解决方案架构师,负责基于 Amazon 云计算方案架构的咨询和设计,曾任算法工程师和部署平台全栈软件开发工程师。","render":"<h4><a id=\\"1_0\\"></a><strong>1.基本介绍</strong></h4>\\n<p>什么是 Notifications API?Notifications API 是亚马逊 SP-API 中基于事件驱动,依托于 Amazon 的 SQS 服务(Simple Queue Service),基于 MQ 实现的通知 API 接口。使用 Notifications API,您可以创建接收通知、订阅通知、删除通知订阅等操作。当事件触发您订阅的通知时,您的应用程序可以直接从 Amazon 接收信息,而不再需要进行轮询,这样做可有效减少 SP-API 各个接口的轮询次数, 并拥有更高的实时性。<br />\\n截止目前,SP-API 中提供的 Notification Type (消息类型)如下:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/1b95a879acb24e8cac4216d8a625aea1_image.png\\" alt=\\"image.png\\" /></p>\n<p><strong>Reference:</strong></p>\\n<p><a href=\\"https://developer-docs.amazon.com/sp-api/docs/notifications-api-v1-use-case-guide#notificationtype\\" target=\\"_blank\\">https://developer-docs.amazon.com/sp-api/docs/notifications-api-v1-use-case-guide#notificationtype</a></p>\\n<h4><a id=\\"2__13\\"></a><strong>2. 使用教程详解</strong></h4>\\n<p>接下来,我们带给大家 Notifications API 与 SQS 结合使用的详细教程。</p>\n<h5><a id=\\"Step_1__SQS_18\\"></a><strong>Step 1 创建 SQS</strong></h5>\\n<p>登录亚马逊控制台,进入 Amazon SQS 服务页面</p>\n<h6><a id=\\"11__23\\"></a><strong>1.1 创建队列</strong></h6>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/cbed1a03ad19468c9e63daa59ec9845d_image.png\\" alt=\\"image.png\\" /></p>\n<h6><a id=\\"12__27\\"></a><strong>1.2 设置队列的基本属性</strong></h6>\\n<p>根据需求配置队列属性</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/bc9d16b51a99472d978a0daa5b5eca2e_image.png\\" alt=\\"image.png\\" /></p>\n<h6><a id=\\"13__33\\"></a><strong>1.3 设置队列的默认访问策略</strong></h6>\\n<p>访问策略选择默认,创建结束后再修改</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/781acac03a704e08ad26292d68441767_image.png\\" alt=\\"image.png\\" /></p>\n<h5><a id=\\"STEP_2__SQS__Amazon__40\\"></a><strong>STEP 2 配置 SQS (允许 Amazon 发送消息)</strong></h5>\\n<h6><a id=\\"21__44\\"></a><strong>2.1 编辑队列</strong></h6>\\n<p>在队列创建完成后,记录 arn,并点击编辑</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/e0f9200b532f42ffa557cbfd4bf75af1_image.png\\" alt=\\"image.png\\" /></p>\n<h6><a id=\\"22__52\\"></a><strong>2.2 修改策略</strong></h6>\\n<p>记录当前队列的 root Principal,点击策略生成器(此时,我们已经拿到了自身的 ARN,和自身的 Principal)</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/aba182c9fd5e4214b3fdad852875eae0_image.png\\" alt=\\"image.png\\" /></p>\n<h6><a id=\\"23__58\\"></a><strong>2.3 自身拥有队列的所有权限</strong></h6>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/e6c1a0990648438eb255727202ea443a_image.png\\" alt=\\"image.png\\" /></p>\n<h6><a id=\\"24_Amazon__GetQueueAttributes__SendMessage__63\\"></a><strong>2.4 Amazon 拥有 GetQueueAttributes 和 SendMessage 权限</strong></h6>\\n<p>Amazon 的为 Principal (固定的): arn:aws:iam::437568002678:root</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/89b02daa19da47af86bc4c0610829fca_image.png\\" alt=\\"image.png\\" /></p>\n<p>具体操作如下:</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/c04df69d04af49ecbac8c2e170b3c596_image.png\\" alt=\\"image.png\\" /></p>\n<h6><a id=\\"25__73\\"></a><strong>2.5 生成配置</strong></h6>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/d808b8d61b4c41f398cfb95d66c2521e_image.png\\" alt=\\"image.png\\" /></p>\n<h6><a id=\\"26__JSON_77\\"></a><strong>2.6 复制配置 JSON</strong></h6>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/5a1b0685ff5e485aa075e067f7726f06_image.png\\" alt=\\"image.png\\" /></p>\n<h6><a id=\\"27__JSON_82\\"></a><strong>2.7 替换配置 JSON</strong></h6>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/c3e714e64d984ee3a1fe2e12586d46a7_image.png\\" alt=\\"image.png\\" /></p>\n<h6><a id=\\"28__88\\"></a><strong>2.8 点击保存</strong></h6>\\n<p>至此,我们拥有了一个队列,并且,该队列允许亚马逊发送消息,开发者账号拥有该队列所有权限。</p>\n<h5><a id=\\"STEP_3__94\\"></a><strong>STEP 3 监听队列</strong></h5>\\n<p>如果您是 Java 开发者,这里可以依赖 Spring boot,使用 JMS 监听队列。</p>\n<h6><a id=\\"31_POM__98\\"></a><strong>3.1 POM 依赖</strong></h6>\\n<pre><code class=\\"lang-\\"><dependency>\\n <groupId>org.springframework</groupId>\\n <artifactId>spring-jms</artifactId>\\n</dependency>\\n<dependency>\\n <groupId>com.amazonaws</groupId>\\n <artifactId>amazon-sqs-java-messaging-lib</artifactId>\\n <version>1.0.0</version>\\n <type>jar</type>\\n</dependency>\\n<dependency>\\n <groupId>com.amazonaws</groupId>\\n <artifactId>aws-java-sdk-sqs</artifactId>\\n <version>1.11.943</version>\\n</dependency>\\n</code></pre>\\n<h6><a id=\\"32__119\\"></a><strong>3.2 监听代码</strong></h6>\\n<pre><code class=\\"lang-\\">@Component\\n@Slf4j\\npublic class SqsConsumer {\\n @JmsListener(destination = "SQS名称", containerFactory = "listenerContainerFactory")\\n public void consumer(SQSTextMessage sqsTestMessage) throws Exception {\\n String text = sqsTestMessage.getText();\\n log.info("接收到SQS通知:{}", text);\\n }\\n}\\n</code></pre>\\n<h6><a id=\\"33_listenerContainerFactory_134\\"></a><strong>3.3 listenerContainerFactory</strong></h6>\\n<pre><code class=\\"lang-\\">@Bean\\npublic SQSConnectionFactory connectionFactory() {\\n SQSConnectionFactory sqsConnectionFactory = SQSConnectionFactory.builder()\\n // amazonPropertiesConfig 为 AWSCredentialsProvider的实现类实例, 提供 AWSCredentials 即可\\n .withAWSCredentialsProvider(amazonPropertiesConfig)\\n // sqs所在地区 在endpoint中可以找到,如: us-west-1\\n .withRegionName(amazonPropertiesConfig.getSqsRegion())\\n // sqs地址 配置页中的地址 https://sqs.us-west-1.amazonaws.com/xxxxxxxx/TEST\\n .withEndpoint(amazonPropertiesConfig.getSqsEndpoint())\\n .build();\\n return sqsConnectionFactory;\\n}\\n@Bean\\npublic DefaultJmsListenerContainerFactory listenerContainerFactory(SQSConnectionFactory connectionFactory) {\\n DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();\\n factory.setConnectionFactory(connectionFactory);\\n factory.setDestinationResolver(new DynamicDestinationResolver());\\n //开启多少线程\\n factory.setConcurrency("10-20"); \\n //开启自动确认\\n factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE); \\n return factory;\\n}\\n</code></pre>\\n<h5><a id=\\"STEP_4__164\\"></a><strong>STEP 4 订阅消息</strong></h5>\\n<h6><a id=\\"41__createDestination_167\\"></a><strong>4.1 创建 createDestination</strong></h6>\\n<p>注意:<br />\\n在请求参数中: resourceSpecification 下的 SQS 和 EventBridge 只能二选一,并且必须选一个,在 SQS 中,我们填写 SQS 即可。<br />\\ncreateDesition 是一种<a href=\\"https://developer-docs.amazon.com/sp-api/docs/grantless-operations\\" target=\\"_blank\\">无授权操作</a>,与卖家身份无关,调用 createDestination 时,可以不用显式地获得 Selling Partner 的授权。由于 Destination 是开发者的内容,与卖家没有关系,因此,在 Client 对象的创建上,不用 refresh token 的方式,而是使用 scope 模式,scope = “sellingpartnerapi::notifications”</p>\\n<pre><code class=\\"lang-\\">LWAClientScopes lwaClientScopes = new LWAClientScopes(new HashSet<>());\\n lwaClientScopes.getScopes().add("sellingpartnerapi::notifications");\\n LWAAuthorizationCredentials lwaAuthorizationCredentials = LWAAuthorizationCredentials.builder()\\n .clientId(clientId())\\n .clientSecret(clientSecret())\\n .scopes(lwaClientScopes)\\n .endpoint(authUrl())\\n .build();\\n</code></pre>\\n<p>createDestination 示例代码:</p>\n<pre><code class=\\"lang-\\">public CreateDestinationResponse createDestination(String marketplaceId, CreateDestinationDTO createDestinationDTO) throws ApiException {\\n NotificationsApi notificationsApi = getNotificationsApi(marketplaceId);\\n DestinationResourceSpecification destinationResourceSpecification = new DestinationResourceSpecification();\\n SqsResource sqsResource = new SqsResource();\\n sqsResource.setArn(createDestinationDTO.getArn());\\n destinationResourceSpecification.setSqs(sqsResource);\\n CreateDestinationRequest body = new CreateDestinationRequest();\\n body.setResourceSpecification(destinationResourceSpecification);\\n body.setName(createDestinationDTO.getDestinationName());\\n return notificationsApi.createDestination(body);\\n}\\n@Data\\npublic class CreateDestinationDTO {\\n //sqs详情页中可以找到改值\\n private String arn; \\n private String destinationName;\\n //sqs详情页中可以找到改值\\n private String sqsName; \\n}\\n</code></pre>\\n<p>请求体参数示例:</p>\n<pre><code class=\\"lang-\\">{\\n "resourceSpecification": {\\n "sqs": {\\n "arn": "arn:aws:sqs:us-west-1:xxxxxxxx:TEST"\\n }\\n },\\n "name": "testDestination"\\n}\\n返回值示例:\\n{\\n "payload": {\\n "name": "testDestination",\\n "destinationId": "2d6eee67-23e9-40fe-destinationId",\\n "resource": {\\n "sqs": {\\n "arn": "arn:aws:sqs:us-west-1:xxxxxxxx:TEST"\\n }\\n }\\n }\\n}\\n</code></pre>\\n<p>需要记录下返回结果中的: destinationId</p>\n<h6><a id=\\"42__Destination__239\\"></a><strong>4.2 根据 Destination 创建订阅</strong></h6>\\n<p>注意:<br />\\n一个卖家的一种消息类型,只能订阅一个 Destination<br />\\n在 SP-API 的权限设计中此时,操作与卖家有关,需要使用卖家的授权进行访问。</p>\n<pre><code class=\\"lang-\\">LWAAuthorizationCredentials lwaAuthorizationCredentials = LWAAuthorizationCredentials.builder()\\n .clientId(clientId)\\n .clientSecret(clientSecret)\\n .refreshToken(spAuthToken)\\n .endpoint(authUrl)\\n .build();\\n</code></pre>\\n<p>createSubscription 示例代码:</p>\n<pre><code class=\\"lang-\\">public CreateSubscriptionResponse createSubscription(String destinationId, NotificationTypeEnum notificationType,String spAuthToken) throws ApiException {\\n NotificationsApi notificationsApi = getNotificationsApi(spAuthToken);\\n CreateSubscriptionRequest request = new CreateSubscriptionRequest();\\n request.setDestinationId(destinationId);\\n request.setPayloadVersion("1.0");\\n return notificationsApi.createSubscription(request, notificationType.name());\\n}\\n</code></pre>\\n<p>请求参数示例:</p>\n<pre><code class=\\"lang-\\">url:\\n /notifications/v1/subscriptions/REPORT_PROCESSING_FINISHED\\nbody:\\n{\\n "payloadVersion": "1.0",\\n "destinationId": "2d6eee67-23e9-40fe-destinationId"\\n}\\n</code></pre>\\n<p>返回值示例:</p>\n<pre><code class=\\"lang-\\">{\\n "payload": {\\n "subscriptionId":"7ca3572b-2130-41eb-subscriptionId",\\n "payloadVersion":"1.0",\\n "destinationId": "2d6eee67-23e9-40fe-destinationId",\\n }\\n}\\n</code></pre>\\n<p>至此,已经完成了所有准备工作,耐心等待 Amazon 触发相关类型的消息即可。</p>\n<h5><a id=\\"STEP_5__295\\"></a><strong>STEP 5 监听消息</strong></h5>\\n<h6><a id=\\"51__297\\"></a><strong>5.1 接收通知数据</strong></h6>\\n<p>SP-API 的返回通知数据结构采用 JSON 格式。每个通知都包含一个 Payload 对象,其中包含通知的可操作数据。Notification Type 与 PayloadVersion 一起确定 Payload 对象的结构。<br />\\nREPORT_PROCESSING_FINISHED notification 示例:</p>\n<pre><code class=\\"lang-\\">{\\n "notificationVersion": "2020-09-04",\\n "notificationType": "REPORT_PROCESSING_FINISHED",\\n "payloadVersion": "1.0",\\n "eventTime": "2022-02-10T03:05:00.197Z",\\n "payload": {\\n "reportProcessingFinishedNotification": {\\n "sellerId": "A2BAZU3******",\\n "reportId": "34997*********",\\n "reportType": "GET_FLAT_FILE_VAT_INVOICE_DATA_REPORT",\\n "processingStatus": "DONE",\\n "reportDocumentId": "amzn1.tortuga.********************************************"\\n }\\n },\\n "notificationMetadata": {\\n "applicationId": "amzn1.sellerapps.app.********************",\\n "subscriptionId": "36df6577-33c7-********************",\\n "publishTime": "2022-02-18T03:05:00.230Z",\\n "notificationId": "0cbae32d-222f-********************"\\n }\\n}\\n</code></pre>\\n<p>FEED_PROCESSING_FINISHED notification 示例:</p>\n<pre><code class=\\"lang-\\">{\\n "notificationVersion": "2020-09-04",\\n "notificationType": "FEED_PROCESSING_FINISHED",\\n "payloadVersion": "1.0",\\n "eventTime": "2022-02-11T08:46:38.498Z",\\n "payload": {\\n "feedProcessingFinishedNotification": {\\n "sellerId": "A2EW6******",\\n "feedId": "625004******",\\n "feedType": "POST_ORDER_FULFILLMENT_DATA",\\n "processingStatus": "DONE",\\n "resultFeedDocumentId": "amzn1.tortuga.********************************************"\\n }\\n },\\n "notificationMetadata": {\\n "applicationId": "amzn1.sellerapps.app.**************************",\\n "subscriptionId": "4d5b53b4-66ad-4ee0-***************",\\n "publishTime": "2022-02-18T08:46:39.950Z",\\n "notificationId": "188fea65-74da-4fce-***************"\\n }\\n}\\n</code></pre>\\n<p>ORDER_STATUS_CHANGE notification 示例:</p>\n<pre><code class=\\"lang-\\">{\\n "NotificationVersion": "1.0",\\n "NotificationType": "ORDER_STATUS_CHANGE",\\n "PayloadVersion": "1.0",\\n "EventTime": "2022-01-13T19:42:04.284Z",\\n "Payload":\\n {\\n "OrderNotification":\\n {\\n "SellerId": "A2EW6******",\\n "AmazonOrderId": "333-7777777-7777777",\\n "PurchaseDate": 1595882000633,\\n "OrderStatus": "PROCESSED",\\n "DestinationPostalCode": "48110",\\n "SupplySourceId": "SSID39485",\\n "OrderItemId": "OIID34853450",\\n "SellerSKU": "SellerSKUID1",\\n "Quantity": 45\\n }\\n },\\n "NotificationMetadata":\\n {\\n "ApplicationId": "app-id-d0e9e693-c3ad-4373-979f-ed4ec98dd746",\\n "SubscriptionId": "subscription-id-d0e9e693-c3ad-4373-979f-ed4ec98dd746",\\n "PublishTime": "2022-01-13T19:42:04.284Z",\\n "NotificationId": "d0e9e693-c3ad-4373-979f-ed4ec98dd746"\\n }\\n}\\n</code></pre>\\n<p>其他通知类型的数据接口请参考 reference:</p>\n<p><a href=\\"https://developer-docs.amazon.com/sp-api/docs/notifications-api-v1-use-case-guide#notification-structure\\" target=\\"_blank\\">https://developer-docs.amazon.com/sp-api/docs/notifications-api-v1-use-case-guide#notification-structure</a></p>\\n<h6><a id=\\"52__390\\"></a><strong>5.2 处理队列中的消息</strong></h6>\\n<p>为了正确处理通知,您需要了解 Amazon SQS 队列的几个重要属性:</p>\n<ul>\\n<li>SP-API 不支持分发到 FIFO 队列。您必须使用 Amazon SQS 标准队列来接收通知。</li>\n<li>SP-API 标准队列不保证将按照发送顺序接收通知。标准队列提供尽力而为的排序,这意味着通知通常以与发送时相同的顺序传递。但是,有时多份通知的副本可能会乱序传送。因此,您需要将您的应用程序设计为以任何顺序接受通知。</li>\n<li>Amazon SQS 标准队列通知可能会发送多次。Amazon SQS 将通知副本存储在多台服务器上,以实现冗余和高可用性。在极少数情况下,当您收到或删除通知时,其中一个存储通知副本的服务器可能不可用。如果发生这种情况,通知副本不会在该不可用服务器上删除,并且您可能会在收到通知时再次获得该通知副本。因此,您需要将您的应用程序设计为接受任何给定通知的多个副本。<br />\\n您可以通过查看通知的属性来确定通知是否与您已收到的通知重复。您可以在通知的对象中找到该属性例如:notificationId,NotificationMetaData。</li>\n</ul>\\n<h4><a id=\\"_400\\"></a><strong>本系列文章</strong></h4>\\n<p><a href=\\"https://aws.amazon.com/cn/blogs/china/how-to-connect-with-amazon-e-commerce-selling-partner-api/\\" target=\\"_blank\\">如何对接亚马逊电商 Selling Partner API</a></p>\\n<p><a href=\\"https://aws.amazon.com/cn/blogs/china/create-sp-api-third-party-login-application-and-complete-api-call/\\" target=\\"_blank\\">创建 SP-API 第三方登录应用并完成 API Call</a></p>\\n<p><a href=\\"https://aws.amazon.com/cn/blogs/china/detailed-tutorial-on-the-use-of-notifications-api-with-amazon-eventbridge-in-sp-api/\\" target=\\"_blank\\">SP-API 中 Notifications API 结合 Amazon EventBridge 使用的详细教程<br />\\n</a></p>\\n<h4><a id=\\"_410\\"></a><strong>本篇作者</strong></h4>\\n<p><img src=\\"https://dev-media.amazoncloud.cn/bf27c4f42a1d4620bcaaa4b044a6db78_image.png\\" alt=\\"image.png\\" /></p>\n<h4><a id=\\"Lei_Wang_414\\"></a><strong>Lei Wang</strong></h4>\\n<p>亚马逊 SP-API 中国区负责人。Amazon 解决方案架构师。专注亚马逊电商平台合作伙伴及第三方服务商 ISV 的 SP-API 对接咨询及推广。为中国区开发者提供基于 SP-API 的解决方案。</p>\n<p><img src=\\"https://dev-media.amazoncloud.cn/f0b93a9a47f7484b9c185baf0115c426_image.png\\" alt=\\"image.png\\" /></p>\n<h4><a id=\\"Aonan_Guan_420\\"></a><strong>Aonan Guan</strong></h4>\\n<p>亚马逊云科技解决方案架构师,负责基于 Amazon 云计算方案架构的咨询和设计,曾任算法工程师和部署平台全栈软件开发工程师。</p>\n"}