Feeds API v2020-09-04 用例指南

亚马逊SPAPI

# 什么是Feeds API?

通过Selling Partner API for Feeds (Feeds API),您可以构建应用程序,使卖家能够向亚马逊上传信息,帮助他们管理销售业务.有各种使用案例的feeds,如创建列表、管理库存和价格、确认订单等.参见feedType values (opens new window),查看可用的feed类型列表.

# 提交feed的工作流程

以下是提交飼料的高層次-步驟

1.调用createFeedDocument (opens new window)操作,指定你要提交的feed的内容类型.

亚马逊返回一个**feedDocumentId**值,加密细节,以及一个用于上传feed内容的URL.
  1. 加密并上传你的feed文件内容到上一步的URL.

3.调用createFeed (opens new window)操作.使用inputFeedDocumentId参数来传递步骤1中的feedDocumentId值.指定你想要应用feed的市场和任何相关的feed选项.

亚马逊返回一个**feedId**值.

4.定期调用getFeed (opens new window)操作,指定步骤3中的feedId值,直到feed进入以下终端状态之一DONE, CANCELLED, or FATAL. 当feed进入DONE状态时,继续进行步骤5.

当feed进入DONE状态时,Amazon返回resultFeedDocumentId值.

5.调用getFeedDocument (opens new window)操作.使用feedDocumentId参数来传入上一步的resultFeedDocumentId值.

亚马逊返回**feedDocumentId**值,一个用于下载feed处理报告的URL,以及加密的细节.
  1. 下载并解密feeds处理报告.

  2. 检查进料处理报告中在进料处理过程中产生的错误. 如果有错误,纠正它们并提交更正后的进料,从步骤1开始. 如果没有错误,你的进料提交成功了.

关于提交feed的更多细节,请看TutorialSubmit a feed.

# Terminology

  1. 密码区块链.密码区块链是一种使用区块密码来提供保密性或真实性等信息安全的算法.这种算法使用一个初始化向量和一个密钥来加密数据.

  2. S3预签名的URL.一个AWS S3桶的URL,你可以在没有AWS安全凭证或权限的情况下上传一个对象.你在步骤1得到一个S3预签名的URL.创建一个feed documentStep 5. Get information for retrieving the feed processing report.

# Tutorial: 提交一个feeds

本教程告诉你如何提交feeds,检查feeds处理的状态,并验证你的feeds提交是否成功. 本教程包含Java代码样本,可以帮助你完成诸如加密和上传feeds以及下载和解密feeds处理报告等任务. 你可以使用这些代码样本中演示的原理来指导你使用其他编程语言来完成这些任务.

先决条件

要完成本教程,你将需要

1.一个要提交的feed.参见feedType values (opens new window),以获得可用的feed类型列表.

1.来自你为之打电话的卖家的授权.参见Selling Partner API Developer Guide (opens new window)了解更多信息.

1.一个工作的Java开发工具包(JDK)安装,包括javax.crypto库.

  1. The Selling Partner API Documents Helper (opens new window).

1.对使用密码块链(CBC).的客户端-侧加密的理解,定义见术语 (opens new window).

# 步骤1.创建一个feed文档

调用createFeedDocument操作来创建一个feed文档.

  1. Call the createFeedDocument (opens new window) operation, passing the following parameter:

主体参数

Name Description Required
contentType

feeds的内容类型.亚马逊推荐UTF-8字符编码.

重要的是.Step 2.加密和上传feed数据.否则你的feed数据上传将失败.

Type: string

是的

请求示例

POST https://sellingpartnerapi-na.amazon.com/feeds/2020-09-04/documents
{
  "contentType":"text/tab-separated-values; charset=UTF-8"

1
2
3
4

响应

一个成功的响应包括以下内容

feeds的标识符.

类型: string

Name Description Required
feedDocumentId

进给文件的标识符.

Type: string

Yes
url

用于上传feeds内容的预设URL.此URL在5分钟后过期.

Type: string

是的
encryptionDetails

要求的客户端-文件内容的加密细节.

类型FeedDocumentEncryptionDetails

是的

响应实例

{
  "payload":
  {
    "feedDocumentId":"amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM",
    "url":"https://tortuga-prod-na.s3.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Date=20200919T035824Z&amp;X-Amz-SignedHeaders=<headers>&amp;X-Amz-Expires=300&amp;X-Amz-Credential=<credential>&amp;X-Amz-Signature=<signature>",
    "encryptionDetails":
    {
      "标准": "AES"
      "initializationVector": "kF3bZt0FSv6JQEimfEJD8g=="
      "key": "5EZo/P06OGF0UAy8QuOnMIaQbkAvYBru6EGsFvK8wJ2="
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
  1. 保存以下数值

# 步骤2.加密和上传feed数据

你可以使用上一步返回的信息来加密和上传feed数据. 下面的示例代码,以及Selling Partner API (SP-API)Documents Helper (opens new window)中提供的类,可以帮助你. 你也可以使用示例代码和SP-API Documents Helper中展示的原则来指导你在其他编程语言中构建应用程序.

示例代码中有一些方法用于从一个字符串创建一个输入流和创建一个管道输入流.

从一个字符串创建一个输入流

-使用以下内容作为示例代码的输入

  - 你的输入数据被输入到``ByteArrayInputStream``类.

  - 上一步的**key**、**initializationVector**和**url**值是``key``、``initializationVector``和``url``类的``encryptAndUpload_fromString```方法的参数.

创建一个管道输入流

  • 使用以下内容作为样本代码的输入

    • 你的feed数据通过与PipedOutputStream```连接的方式输入到PipedInputStream```..

    • 上一步的key, initializationVector, 和url值是key, `initializationVector, 和url参数的参数,在UploadExample类的encryptAndUpload_fromPipedInputStream``方法中.

# 加密和上传示例代码(Java)

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.charset.StandardCharsets;

import com.amazon.spapi.documents.UploadHelper;
import com.amazon.spapi.documents.UploadSpecification;
import com.amazon.spapi.documents.exception.CryptoException;
import com.amazon.spapi.documents.exception.HttpResponseException;
import com.amazon.spapi.documents.impl.AESCryptoStreamFactory;

/* 我们要保持静态加密,所以不要把未加密的数据写到磁盘上. 这是不好的
InputStream source = new FileInputStream(new File("/path/to/myFeed.xml"))

相反,如果你的数据可以放在内存中,你可以从一个字符串中创建一个InputStream (see encryptAndUpload_fromString().
否则,你可以使用管道流将数据引入InputStream (see encryptAndUpload_fromPipedInputStream().
 */
public class UploadExample {
  private final UploadHelper uploadHelper = new UploadHelper.Builder().build();

  // key, initializationVector, and url是由createFeedDocument操作返回的.
  public void encryptAndUpload_fromString(String key, String initializationVector, String url) {
    AESCryptoStreamFactory aesCryptoStreamFactory =
      new AESCryptoStreamFactory.Builder(key, initializationVector)
      .build();

    // 这个contentType必须是提供给createFeedDocument.的同一个值
    String contentType = String.format("text/plain; charset=%s", StandardCharsets.UTF_8);

    // 字符集必须与contentType.中指定的字符集相同
    试试
      (InputStream source = new ByteArrayInputStream("my feed data".getBytes(StandardCharsets.UTF_8))_ {
        UploadSpecification uploadSpec =
          new UploadSpecification.Builder(contentType, aesCryptoStreamFactory, source, url)
          .build();

        uploadHelper.upload(uploadSpec);
      }
    catch (CryptoException | HttpResponseException | IOException e) {
      //处理异常.
    }
  }

  //从createFeedDocument.返回key、initializationVector和url
  public void encryptAndUpload_fromPipedInputStream(String key, String initializationVector, String url) {
    AESCryptoStreamFactory aesCryptoStreamFactory =
      new AESCryptoStreamFactory.Builder(key, initializationVector)
      .build();

    // 这个contentType必须是提供给createFeedDocument.的同一个值
    String contentType = String.format("text/plain; charset=%s", StandardCharsets.UTF_8);

    试试
      (PipedInputStream source = new PipedInputStream()) {
        新的线程(
          新的Runnable() {
          public void run() {
            试试
              (PipedOutputStream feedContents = new PipedOutputStream(source)) {
                //字符集必须与contentType.中指定的字符集相同
                feedContents.write("my feed data\n".getBytes(StandardCharsets.UTF_8));
                feedContents.write("more feed data".getBytes(StandardCharsets.UTF_8));
              }
            catch (IOException e) {
              //处理异常.
            }
          }
        }).start();

        uploadSpecification uploadSpec =
          new UploadSpecification.Builder(contentType, aesCryptoStreamFactory, source, url)
          .build();

        uploadHelper.upload(uploadSpec);
      }
    catch (CryptoException | HttpResponseException | IOException e) {
      //处理异常.
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

# 第3步.创建一个feed

调用createFeed操作,指定feed文档标识符、feed类型、你希望feed应用到的市场,以及任何你想要的可选参数.

  1. 调用createFeed (opens new window)操作,传递以下参数

主体参数

Name 描述Required
feedType

您要提交的feed的类型.更多信息,请参见feedType values.

Type: string

是的
marketplaceIds

您希望feeds被应用到的市场的标识符列表.

类型: &lt; string &gt; array

是的
inputFeedDocumentId

Step 1. Create a feed document.

中由createFeedDocument操作返回的文档标识

Type: string

是的
feedOptions

控制喂食的额外选项.这些因喂食类型而异.

Type: string

没有

请求示例

POST https://sellingpartnerapi-na.amazon.com/feeds/2020-09-04/feeds
{
  "feedType": "POST_PRODUCT_DATA",
  "marketplaceIds":[
    "atvpdkikx0der",
    "a2euq1wtgctbg2"
  ],
  "inputFeedDocumentId":"amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM"
}
1
2
3
4
5
6
7
8
9

易发货订单的请求示例

POST https://sellingpartnerapi-na.amazon.com/feeds/2020-09-04/feeds
{
  "feedType": "POST_EASYSHIP_DOCUMENTS",
  "marketplaceIds":["A21TJRUUN4KGV"],
  "feedOptions":
  {
    "AmazonOrderId":"902-3159896-1390916",
    "DocumentType": "航运标签"
  },
  "inputFeedDocumentId":"amzn1.tortuga.3.06438a22-2b6f-4138-a120-362c096d5e04.TKXDFQFUMYD86"
}
1
2
3
4
5
6
7
8
9
10
11

响应

一个成功的响应包括以下元素

Name Description Required
feedId

feed的标识符.这个标识符只有在与卖家ID.

结合时才是唯一的

Type: string

是的

响应的例子

{
  "payload":
  {
    "feedId": "23492394"
  }
}
1
2
3
4
5
6

2.保存feedId值.在步骤4.确认feed处理的getFeed操作中传递这个值.

# 步骤4.确认进料处理

通过定期调用getFeed操作确认进料处理,直到进料进入以下终端状态之一DONE, CANCELLED, or FATAL.当进料进入DONE状态时,进入步骤5.获取信息以检索进料处理报告.

1.调用getFeed (opens new window)操作,传递以下参数

路径参数

Name Description Required
feedId

feed的标识符.从Step 3. Create a feed.中调用createFeed操作的结果中获得这个标识符

Type: string

是的

请求示例

GET https://sellingpartnerapi-na.amazon.com/feeds/2020-09-04/feeds/23492394
1

响应

一个成功的响应包括以下内容

feeds是什么? feeds处理开始于ISO 8601日期时间格式 feeds处理完成的日期是ISO 8601日期时间格式.

类型: string (date-time)

Name Description Required
feedId

进货文件的标识符.这个标识符只有在与卖家ID.

结合时才是唯一的

Type: string

是的
feedType

feeds类型.

Type: string

是的
marketplaceIds

一个适用于该feeds的市场的标识符列表.

类型< string > array

No
createdTime

创建feeds的日期和时间,格式为ISO 8601日期时间.

类型: string (date-time)

processingStatus

feeds的处理状态.

类型ProcessingStatus

是的
processingStartTime

feeds加工开始的日期和时间,格式为ISO 8601日期时间.

类型: string (date-time)

processingEndTime

feeds加工完成的日期和时间,格式为ISO 8601日期时间.

类型: string (date-time)

resultFeedDocumentId

进料文件的标识符.该标识符只有在与卖家ID.

结合时才是唯一的

Type: string

没有

响应实例

{
  "payload":
  {
    "processingEndTime":"2020-08-10T16:56:55+00:00",
    "processingStatus": "DONE",
    "marketplaceIds":[
      "atvpdkikx0der"
    ],
    "feedId": "23492394"
    "feedType": "POST_PRODUCT_DATA",
    "createdTime":"2020-08-10T16:55:32+00:00",
    "processingStartTime":"2020-08-10T16:55:40+00:00",
    "resultFeedDocumentId":"amzn1.tortuga.3.ed4cd0d8-447b-4c22-96b5-52da8ace1207.T3YUVYPGKE9BMY"
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

2.检查processingStatus属性的值.

- 如果**processingStatus**是IN_QUEUE或IN_PROGRESS,则feeds处理尚未完成. 重试getFeed操作,直到**processingStatus**达到以下终端状态之一DONE, CANCELLED, 或 FATAL.

-如果**processingStatus**是DONE,则feeds处理完成.转到[步骤5.获取检索feeds处理报告的信息](#步骤-5_获取-信息-用于-检索-feeds-处理-报告).

-如果**processingStatus**是CANCELLED,说明该feed在开始处理之前就被取消了.如果你想再次提交feed,请从[步骤1.创建一个feed文档](#步骤-1-创建-a-feed-文档).开始

-如果**处理状态**为FATAL,则表示由于致命的错误而中止了feed.feed中的一些、没有或所有的操作都可能成功完成.在某些(但不是所有)情况下,亚马逊会生成一份feed处理报告.如果亚马逊生成一份报告它的格式可能与成功完成的feeds处理报告不同.进入[步骤5.获取检索feeds处理报告的信息](#步骤-5-获取-信息-用于-检索-feeds-处理-报告_) 试图检索一个feeds处理报告.在极少数情况下,亚马逊可能会因为与feeds无关的原因而中止一个feeds.如果你在feeds中找不到错误需要纠正尝试再次提交feeds.

注意getFeed操作只为过去90天内创建的feed请求提供信息.

# 步骤5.获取检索进料处理报告的信息

feeds处理报告表明你提交的feeds中哪些记录是成功的,哪些记录产生了错误.在这个步骤中,你得到一个预设的URL,用于下载feeds处理报告,以及解密文件内容所需的信息.

  1. Call the getFeedDocument (opens new window) operation, passing the following parameter:

路径参数

Name Description Required
feedDocumentId

feeds文件的标识符.使用resultFeedDocumentId中返回的Step 4.确认feeds处理.

的值

Type: string

是的

请求示例

GET https://sellingpartnerapi-na.amazon.com/feeds/2020-09-04/documents/amzn1.tortuga.3.ed4cd0d8-447b-4c22-96b5-52da8ace1207.T3YUVYPGKE9BMY
1

响应

一个成功的响应包括以下内容

Name Description Required
feedDocumentId

进货文件的标识符.该标识符只有在与卖方ID.

结合时才是唯一的

Type: string

是的
url

一个预设的feeds文件的URL.这个URL在5分钟后失效.

Type: string

是的
encryptionDetails

要求的客户端-文件内容解密的加密细节.

类型FeedDocumentEncryptionDetails

是的
compressionAlgorithm

如果存在,则使用指定的算法对进给文件内容进行压缩.

类型CompressionAlgorithm

没有

响应实例

{
  "payload":
  {
    "feedDocumentId":"amzn1.tortuga.3.ed4cd0d8-447b-4c22-96b5-52da8ace1207.T3YUVYPGKE9BMY",
    "url":"https://tortuga-prod-na.s3.amazonaws.com/%2FNinetyDays/amzn1.tortuga.3.920614b0-fc4c-4393-b0d9-fff175300000.T29XK4YL08B2VM?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Date=20200919T035824Z&amp;X-Amz-SignedHeaders=<headers>&amp;X-Amz-Expires=300&amp;X-Amz-Credential=<credential>&amp;X-Amz-Signature=<signature>",
    "encryptionDetails":
    {
      "标准": "AES"
      "initializationVector": "kF3bZt0FSv6JQEimfEJD8g=="
      "key": "5EZo/P06OGF0UAy8QuOnMIaQbkAvYBru6EGsFvK8wJ2="
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12

2.保存initializationVectorkeyurl值,以便在Step 6.下载和解密feeds处理报告.中传递

# 步骤6.下载并解密feeds处理报告

你可以使用上一步返回的信息下载和解密feeds处理报告. 下面的Java示例代码以及Selling Partner API (SP-API)Documents Helper (opens new window)中提供的类可以帮助你. 你也可以使用Java示例代码和SP-API Documents Helper中展示的原则来指导你用其他编程语言构建应用程序.

1.使用以下内容作为样本代码的输入

- 上一步的**key**, **initializationVector**, **url**, 和可选的**compressionAlgorithm**值是``key``, ``initializationVector``, ``url``, 和``compressionAlgorithm``类的``downloadAndDecrypt```方法的参数.

注意始终保持静态加密是开发者的责任.未加密的feeds处理报告内容绝不应存储在磁盘上,即使是临时的,因为feeds处理报告可能包含敏感信息.我们提供的示例代码演示了这一原则.

# 下载和解密示例代码(Java)

// DownloadExample.java
import java.io.BufferedReader;
import java.io.IOException;
 
import com.amazon.spapi.documents.CompressionAlgorithm;
import com.amazon.spapi.documents.DownloadBundle;
import com.amazon.spapi.documents.DownloadHelper;
import com.amazon.spapi.documents.DownloadSpecification;
import com.amazon.spapi.documents.exception.CryptoException;
import com.amazon.spapi.documents.exception.HttpResponseException;
import com.amazon.spapi.documents.exception.MissingCharsetException;
import com.amazon.spapi.documents.impl.AESCryptoStreamFactory;
 
public class DownloadExample {
  final DownloadHelper downloadHelper = new DownloadHelper.Builder().build();
 
  // key, initializationVector, url, and compressionAlgorithm是由getFeedDocument操作返回的.
  public void downloadAndDecrypt(String key, String initializationVector, String url, String compressionAlgorithm) {
    AESCryptoStreamFactory aesCryptoStreamFactory =
      new AESCryptoStreamFactory.Builder(key, initializationVector).build();
 
    DownloadSpecification downloadSpec = new DownloadSpecification.Builder(aesCryptoStreamFactory, url)
      .withCompressionAlgorithm(CompressionAlgorithm.fromEquivalent(compressionAlgorithm))
      .build();
 
    try (DownloadBundle downloadBundle = downloadHelper.download(downloadSpec)) {
      // 这个例子假设下载的文件在内容类型上有一个charset,e.g.
      // text/plain; charset=UTF-8
      try (BufferedReader reader = downloadBundle.newBufferedReader()) {
        字符串行
        do {
          line = reader.readLine();
          // 处理已解密的行.
        } while (line != null);
      }
    } 
    catch (CryptoException | HttpResponseException | IOException | MissingCharsetException e) {
        //处理异常.
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 步骤7.检查feeds处理报告中是否有错误

检查feeds处理报告中在处理过程中产生的错误.如果没有错误,你的feeds提交就完成了.如果有错误,纠正它们并提交更正后的feeds,从步骤1.创建一个feeds文件.重复该过程直到feeds处理报告中没有错误.

# 最佳实践

关于使用Feeds API的最佳做法,请参阅Feeds API最佳做法 (opens new window).