SP-API 中 Notifications API 结合 Amazon SQS 使用的详细教程

0
0
{"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 服务页面\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 队列的几个重要属性:\n\n- SP-API 不支持分发到 FIFO 队列。您必须使用 Amazon SQS 标准队列来接收通知。\n- SP-API 标准队列不保证将按照发送顺序接收通知。标准队列提供尽力而为的排序,这意味着通知通常以与发送时相同的顺序传递。但是,有时多份通知的副本可能会乱序传送。因此,您需要将您的应用程序设计为以任何顺序接受通知。\n- Amazon SQS 标准队列通知可能会发送多次。Amazon SQS 将通知副本存储在多台服务器上,以实现冗余和高可用性。在极少数情况下,当您收到或删除通知时,其中一个存储通知副本的服务器可能不可用。如果发生这种情况,通知副本不会在该不可用服务器上删除,并且您可能会在收到通知时再次获得该通知副本。因此,您需要将您的应用程序设计为接受任何给定通知的多个副本。\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-\">&lt;dependency&gt;\n &lt;groupId&gt;org.springframework&lt;/groupId&gt;\n &lt;artifactId&gt;spring-jms&lt;/artifactId&gt;\n&lt;/dependency&gt;\n&lt;dependency&gt;\n &lt;groupId&gt;com.amazonaws&lt;/groupId&gt;\n &lt;artifactId&gt;amazon-sqs-java-messaging-lib&lt;/artifactId&gt;\n &lt;version&gt;1.0.0&lt;/version&gt;\n &lt;type&gt;jar&lt;/type&gt;\n&lt;/dependency&gt;\n&lt;dependency&gt;\n &lt;groupId&gt;com.amazonaws&lt;/groupId&gt;\n &lt;artifactId&gt;aws-java-sdk-sqs&lt;/artifactId&gt;\n &lt;version&gt;1.11.943&lt;/version&gt;\n&lt;/dependency&gt;\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 = &quot;SQS名称&quot;, containerFactory = &quot;listenerContainerFactory&quot;)\n public void consumer(SQSTextMessage sqsTestMessage) throws Exception {\n String text = sqsTestMessage.getText();\n log.info(&quot;接收到SQS通知:{}&quot;, 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(&quot;10-20&quot;); \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&lt;&gt;());\n lwaClientScopes.getScopes().add(&quot;sellingpartnerapi::notifications&quot;);\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 &quot;resourceSpecification&quot;: {\n &quot;sqs&quot;: {\n &quot;arn&quot;: &quot;arn:aws:sqs:us-west-1:xxxxxxxx:TEST&quot;\n }\n },\n &quot;name&quot;: &quot;testDestination&quot;\n}\n返回值示例:\n{\n &quot;payload&quot;: {\n &quot;name&quot;: &quot;testDestination&quot;,\n &quot;destinationId&quot;: &quot;2d6eee67-23e9-40fe-destinationId&quot;,\n &quot;resource&quot;: {\n &quot;sqs&quot;: {\n &quot;arn&quot;: &quot;arn:aws:sqs:us-west-1:xxxxxxxx:TEST&quot;\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(&quot;1.0&quot;);\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 &quot;payloadVersion&quot;: &quot;1.0&quot;,\n &quot;destinationId&quot;: &quot;2d6eee67-23e9-40fe-destinationId&quot;\n}\n</code></pre>\n<p>返回值示例:</p>\n<pre><code class=\"lang-\">{\n &quot;payload&quot;: {\n &quot;subscriptionId&quot;:&quot;7ca3572b-2130-41eb-subscriptionId&quot;,\n &quot;payloadVersion&quot;:&quot;1.0&quot;,\n &quot;destinationId&quot;: &quot;2d6eee67-23e9-40fe-destinationId&quot;,\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 &quot;notificationVersion&quot;: &quot;2020-09-04&quot;,\n &quot;notificationType&quot;: &quot;REPORT_PROCESSING_FINISHED&quot;,\n &quot;payloadVersion&quot;: &quot;1.0&quot;,\n &quot;eventTime&quot;: &quot;2022-02-10T03:05:00.197Z&quot;,\n &quot;payload&quot;: {\n &quot;reportProcessingFinishedNotification&quot;: {\n &quot;sellerId&quot;: &quot;A2BAZU3******&quot;,\n &quot;reportId&quot;: &quot;34997*********&quot;,\n &quot;reportType&quot;: &quot;GET_FLAT_FILE_VAT_INVOICE_DATA_REPORT&quot;,\n &quot;processingStatus&quot;: &quot;DONE&quot;,\n &quot;reportDocumentId&quot;: &quot;amzn1.tortuga.********************************************&quot;\n }\n },\n &quot;notificationMetadata&quot;: {\n &quot;applicationId&quot;: &quot;amzn1.sellerapps.app.********************&quot;,\n &quot;subscriptionId&quot;: &quot;36df6577-33c7-********************&quot;,\n &quot;publishTime&quot;: &quot;2022-02-18T03:05:00.230Z&quot;,\n &quot;notificationId&quot;: &quot;0cbae32d-222f-********************&quot;\n }\n}\n</code></pre>\n<p>FEED_PROCESSING_FINISHED notification 示例:</p>\n<pre><code class=\"lang-\">{\n &quot;notificationVersion&quot;: &quot;2020-09-04&quot;,\n &quot;notificationType&quot;: &quot;FEED_PROCESSING_FINISHED&quot;,\n &quot;payloadVersion&quot;: &quot;1.0&quot;,\n &quot;eventTime&quot;: &quot;2022-02-11T08:46:38.498Z&quot;,\n &quot;payload&quot;: {\n &quot;feedProcessingFinishedNotification&quot;: {\n &quot;sellerId&quot;: &quot;A2EW6******&quot;,\n &quot;feedId&quot;: &quot;625004******&quot;,\n &quot;feedType&quot;: &quot;POST_ORDER_FULFILLMENT_DATA&quot;,\n &quot;processingStatus&quot;: &quot;DONE&quot;,\n &quot;resultFeedDocumentId&quot;: &quot;amzn1.tortuga.********************************************&quot;\n }\n },\n &quot;notificationMetadata&quot;: {\n &quot;applicationId&quot;: &quot;amzn1.sellerapps.app.**************************&quot;,\n &quot;subscriptionId&quot;: &quot;4d5b53b4-66ad-4ee0-***************&quot;,\n &quot;publishTime&quot;: &quot;2022-02-18T08:46:39.950Z&quot;,\n &quot;notificationId&quot;: &quot;188fea65-74da-4fce-***************&quot;\n }\n}\n</code></pre>\n<p>ORDER_STATUS_CHANGE notification 示例:</p>\n<pre><code class=\"lang-\">{\n &quot;NotificationVersion&quot;: &quot;1.0&quot;,\n &quot;NotificationType&quot;: &quot;ORDER_STATUS_CHANGE&quot;,\n &quot;PayloadVersion&quot;: &quot;1.0&quot;,\n &quot;EventTime&quot;: &quot;2022-01-13T19:42:04.284Z&quot;,\n &quot;Payload&quot;:\n {\n &quot;OrderNotification&quot;:\n {\n &quot;SellerId&quot;: &quot;A2EW6******&quot;,\n &quot;AmazonOrderId&quot;: &quot;333-7777777-7777777&quot;,\n &quot;PurchaseDate&quot;: 1595882000633,\n &quot;OrderStatus&quot;: &quot;PROCESSED&quot;,\n &quot;DestinationPostalCode&quot;: &quot;48110&quot;,\n &quot;SupplySourceId&quot;: &quot;SSID39485&quot;,\n &quot;OrderItemId&quot;: &quot;OIID34853450&quot;,\n &quot;SellerSKU&quot;: &quot;SellerSKUID1&quot;,\n &quot;Quantity&quot;: 45\n }\n },\n &quot;NotificationMetadata&quot;:\n {\n &quot;ApplicationId&quot;: &quot;app-id-d0e9e693-c3ad-4373-979f-ed4ec98dd746&quot;,\n &quot;SubscriptionId&quot;: &quot;subscription-id-d0e9e693-c3ad-4373-979f-ed4ec98dd746&quot;,\n &quot;PublishTime&quot;: &quot;2022-01-13T19:42:04.284Z&quot;,\n &quot;NotificationId&quot;: &quot;d0e9e693-c3ad-4373-979f-ed4ec98dd746&quot;\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"}
目录
亚马逊云科技解决方案 基于行业客户应用场景及技术领域的解决方案
联系亚马逊云科技专家
亚马逊云科技解决方案
基于行业客户应用场景及技术领域的解决方案
联系专家
0
目录
关闭
contact-us