# 简介 #

WooCommerce 2.1 版本引入的 REST API 允许使用 JSON 格式对 WooCommerce 数据进行创建、读取、更新和删除操作。

## 要求 ##

您必须使用 WooCommerce 2.1 或更高版本，并且需要在 `WooCommerce > 设置` 下启用 REST API。同时，您必须在 `设置 > 固定链接` 中启用美观的固定链接（默认的固定链接将无法工作）。

<aside class="notice">
	端点在每个 WooCommerce 版本中可能会得到改进，因此我们始终建议保持 WooCommerce 为最新版本，以符合本文档的描述。
</aside>

## 版本 ##

当前 API 版本为 `v3`，它在端点中占据首要位置。下表展示了每个主要 WooCommerce 版本中存在的 API 版本：

| API 版本   |          WooCommerce          |
| ---------- | ----------------------------- |
| `v1`       | 2.1.x, 2.2.x, 2.3.x 和 2.4.x |
| `v2`       | 2.2.x, 2.3.x 和 2.4.x        |
| `v3`       | 2.4.x, 2.5.x                  |

`v1` 和 `v2` API 将在未来版本中被移除。

### v3 版本有哪些变化？ ###

* v3 实现了完整的 HTTP 基本认证（[符合基本认证规范](http://tools.ietf.org/html/rfc2617)）。
* v3 修复了 OAuth 实现，以符合 [OAuth 1.0a 规范](http://tools.ietf.org/html/rfc5849)。
* v3 新增了一个用于[获取所有产品订单](#view-list-of-product-orders)的端点。
* v3 为批量创建和更新[产品](#create-update-multiple-products)、[订单](#create-update-multiple-orders)、[客户](#create-update-multiple-customers)和[优惠券](#create-update-multiple-coupons)提供了新的端点。
* v3 引入了新的[产品属性端点](#product-attributes)（`GET`、`POST`、`PUT` 和 `DELETE`）。
* v3 弃用了 product/sku/&lt;id&gt; 端点（因为 SKU 可以用任何字符生成，并且有一个过滤器 `filter[sku]` 可以满足此用例）。
* v3 在请求 `product/categories` 时包含分类缩略图。
* v3 在启用“自动生成客户密码”选项时，可以为新客户自动生成密码。

### v1 与 v2 版本差异 ###

* v1 支持 XML 响应格式，v2 仅支持 JSON。
* v1 不支持创建或更新任何资源（订单状态除外），v2 支持所有端点的完整创建/读取/更新/删除操作。
* v1 不包含订单项元数据，v2 包含完整的订单项元数据（可通过可选 `filter` 参数包含受保护的订单项元数据）。
* v1 不包含列出客户可用下载的端点，v2 包含 `GET /customer/{id}/downloads` 端点。
* v1 包含列出订单备注的端点，v2 包含完整的创建/读取/更新/删除端点。
* v1 不包含列出产品分类的端点，v2 包含两个产品分类端点（`GET /products/categories` 和 `GET /products/categories/{id}`）。
* v1 不包含获取有效订单状态的端点，v2 包含列出有效订单状态的端点（`GET /orders/statuses`）。
* v2 支持 WooCommerce 2.2 新增的核心功能，主要是订单退款（通过 `/orders/refunds` 端点）和 Webhooks（通过 `/webhooks` 端点）。

### 历史版本 API 文档 ###

* [WooCommerce REST API v1 文档](source/includes/v3/v1.html)
* [WooCommerce REST API v2 文档](source/includes/v3/v2.html)

## 架构 ##

可通过以下端点访问此 API：

`https://www.your-store.com/wc-api/v3`

*必须启用固定链接*。您可以通过 HTTP 或 HTTPS 访问 API。*在可能的情况下，建议使用 HTTPS*，因为身份验证更简单。API 索引将声明站点是否支持 SSL。

## 请求/响应 ##

默认响应格式为 JSON。包含消息体的请求使用纯 JSON 来设置或更新资源属性。成功的请求将返回 `200 OK` HTTP 状态码。

关于响应的一些通用信息：

* 日期以 [RFC3339](http://www.ietf.org/rfc/rfc3339.txt) 格式返回，使用 UTC 时区：`YYYY-MM-DDTHH:MM:SSZ`

* 资源 ID 以整数形式返回。

* 任何十进制货币金额，例如价格或总计，将以保留两位小数的字符串形式返回。小数分隔符（通常是 `.` 或 `,`）由站点控制，并包含在 API 索引中。这是有意设计的，以便客户端更容易本地化 API 数据。如果您需要对返回的数据进行计算（例如，在执行计算前将带逗号的字符串金额转换为小数），则可能需要在实现中考虑这一点。

* 其他数量，例如项目计数，以整数形式返回。

* 空白字段通常包含为 `null`，而不是作为空字符串返回或被省略。

## 认证 ##

根据网站是否支持 SSL，有两种 API 认证方式。请记住，Index 端点会指示网站是否支持 SSL。

### 通过 HTTPS ###

您可以使用 [HTTP 基本认证](http://en.wikipedia.org/wiki/Basic_access_authentication)，将 API 消费者密钥作为用户名，API 消费者密钥作为密码。

> HTTP 基本认证示例

```shell
curl https://www.example.com/wc-api/v3/orders \
    -u consumer_key:consumer_secret
```

有时某些服务器可能无法正确解析 Authorization 标头（如果在 SSL 认证时看到“Consumer key is missing”错误，则说明您的服务器有问题）。在这种情况下，您可以将消费者密钥/密钥作为查询字符串参数提供。

> 针对无法正确解析 Authorization 标头的服务器的示例：

```shell
curl https://www.example.com/wc-api/v3/orders?consumer_key=123&consumer_secret=abc
```

### 通过 HTTP 访问 ###

您必须使用 [OAuth 1.0a "单腿式" 认证](http://tools.ietf.org/html/rfc5849) 来确保 API 凭据不被截获。通常，您可以使用所选语言中的任何标准 OAuth 1.0a 库来处理认证，或按照以下说明生成必要的参数。

#### 生成 OAuth 签名 ####

1) 设置请求的 HTTP 方法：

`GET`

2) 设置你的基础请求 URI —— 这是不包含查询字符串参数的完整请求 URI —— 并根据 RFC 3986 进行 URL 编码：

`http://www.example.com/wc-api/v1/orders`

编码后：

`http%3A%2F%2Fwww.example.com%2Fwc-api%2Fv1%2Forders`

3) 收集并规范化你的查询字符串参数。这包括除签名外的所有 `oauth_*` 参数。参数应根据 RFC 3986（PHP 中的 `rawurlencode`）进行 URL 编码，并且百分号（`%`）字符应进行双重编码（例如，`%` 变为 `%25`）。

4) 按字节顺序对参数进行排序（PHP 中使用 `uksort( $params, 'strcmp' )`）

5) 用编码后的等号（`%3D`）连接每个参数：

`oauth_signature_method%3DHMAC-SHA1`

6) 用编码后的与符号（`%26`）连接每个参数的键/值对：

`oauth_consumer_key%3Dabc123%26oauth_signature_method%3DHMAC-SHA1`

7) 通过用未编码的与符号（&）连接 HTTP 方法、编码后的基础请求 URI 和编码后的参数字符串，形成待签名字符串：

`GET&http%3A%2F%2Fwww.example.com%2Fwc-api%2Fv1%2Forders&oauth_consumer_key%3Dabc123%26oauth_signature_method%3DHMAC-SHA1`

8) 使用待签名字符串和你的消费者密钥生成签名

如果你在生成正确签名时遇到问题，应检查待签名字符串是否存在编码错误。[认证源代码](https://github.com/woocommerce/woocommerce/blob/master/includes/class-wc-rest-authentication.php#L185)也有助于理解如何正确生成签名。

#### OAuth 使用技巧 ####

* OAuth 参数可作为查询字符串参数添加，也可包含在 Authorization 头信息中。
* 请注意，在 WordPress 中没有可靠的跨平台方法来获取原始请求头信息，因此在某些情况下使用查询字符串可能更可靠。
* 必需的参数包括：`oauth_consumer_key`、`oauth_timestamp`、`oauth_nonce`、`oauth_signature` 和 `oauth_signature_method`。`oauth_version` 不是必需的，应省略。
* OAuth nonce 可以是任何随机生成的 32 字符（推荐）字符串，且对每个 consumer key 唯一。
* OAuth timestamp 应为请求时的 Unix 时间戳。REST API 将拒绝包含时间戳超出 15 分钟窗口的请求，以防止重放攻击。
* 在构建用于签名的 base string 时，必须使用索引提供的商店 URL，因为服务器将使用此 URL。（例如，如果商店 URL 包含 `www` 子域名，则应在请求中使用它）
* 请注意，根据 OAuth 规范，请求体*不*参与签名。
* 如果在请求中包含参数，按字母顺序排列参数可以避免很多麻烦。
* 从 WooCommerce 3.0 开始支持 Authorization 头信息。

## 参数 ##

所有端点都接受可选参数，可通过 HTTP 查询字符串参数传递，例如 `GET /orders?status=completed`。参数分为通用参数和端点特定参数，这些参数会随相应端点一同记录。

### 筛选参数 ###

所有端点都接受一个 `filter` 参数，该参数使用方括号来限定单个筛选条件，例如日期筛选：

`GET /orders?filter[created_at_min]=2013-11-01`

可以包含多个 `filter` 参数，并与其他参数混合使用：

`GET /orders?status=completed&filter[created_at_min]=2013-11-01&filter[created_at_max]=2013-11-30`

请注意，以下筛选条件适用于除 `reports` 端点外的所有端点，该端点有自己的一套筛选条件，这些条件与该端点一同记录。

#### 可用过滤器 ####

|       Filter       |                                                                                                                                         Description                                                                                                                                          |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `created_at_min`   | given a date, only resources *created after the provided date* will be returned                                                                                                                                                                                                              |
| `created_at_max`   | given a date, only resources *created before the provided date* will be returned                                                                                                                                                                                                             |
| `updated_at_min`   | given a date, only resources *updated after the provided date* will be returned                                                                                                                                                                                                              |
| `updated_at_max`   | given a date, only resources *updated before the provided date* will be returned                                                                                                                                                                                                             |
| `q`                | performs a keyword search and returns resources that match, e.g. `GET /products?filter[q]=search-keyword`. Note that search terms should be URL-encoded as they will be decoded internally with [`urldecode`](http://us3.php.net/manual/en/function.urldecode.php)                           |
| `order`            | controls the ordering of the resources returned, accepted values are `ASC` (default) or `DESC`                                                                                                                                                                                               |
| `orderby`          | controls the field that is used for ordering the resources returned. Accepts the same arguments as [`WP_Query`](http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters). Defaults to `date`. You can order by `meta_value` but you must provide `orderby_meta_key` |
| `orderby_meta_key` | the meta key to order returned resources by when using `orderby=meta_value`. For example, you could order products by price using `GET /products?filter[orderby]=meta_value_num&filter[orderby_meta_key]=_price`                                                                             |
| `post_status`      | limits resources to only those with the specified post status. Most useful for returning unpublished products, e.g. `GET /products?filter[post_status]=draft`                                                                                                                                |
| `meta`             | resource meta is excluded by default, but it can be included by setting `meta=true`, e.g. `GET /orders?filter[meta]=true`. Protected meta (meta whose key is prefixed with an underscore) is not included in the response                                                                    |
| `pagination`       | explained below                                                                                                                                                                                                                                                                              |

请注意，日期应以 [RFC3339](http://www.ietf.org/rfc/rfc3339.txt) 格式在 UTC 时区提供：`YYYY-MM-DDTHH:MM:SSZ`。如果需要，可以省略时间和时区。

### 字段参数 ###

您可以使用 `fields` 参数来限制响应中返回的字段：

`GET /orders?fields=id`

要包含多个字段，请用逗号分隔它们：

`GET /orders?fields=id,status`

您可以使用点符号指定子字段：

`GET /orders?fields=id,status,payment_details.method_title`

对于具有多个结构体的资源（例如订单的行项目），子字段无法被限制。例如，以下请求将只返回行项目，但每个行项目将包含完整的信息集，而不仅仅是产品ID：

`GET /orders?fields=line_items.product_id`

## 分页 ##

返回多个项目的请求默认会分页为每页 10 个项目。站点管理员可以通过更改 `posts_per_page` 选项来修改此默认值。或者，也可以使用 `?filter[limit]` 参数指定每页的项目数：

`GET /orders?filter[limit]=15`

您可以使用 `?page` 参数指定后续页面：

`GET /orders?page=2`

您还可以使用 `?filter[offset]` 参数指定从第一个资源开始的偏移量：

`GET /orders?filter[offset]=5`

页码从 1 开始计数，省略 `?page` 参数将返回第一页。

资源总数和总页数始终包含在 `X-WC-Total` 和 `X-WC-TotalPages` HTTP 头中。

## 链接头部 ##

分页信息包含在[链接头部](http://tools.ietf.org/html/rfc5988)中。建议您尽可能遵循这些值，而不是自行构建 URL。

```
Link: <https://www.example.com/wc-api/v1/products?page=2>; rel="next",
<https://www.example.com/wc-api/v1/products?page=3>; rel="last"`
```

*为便于阅读，已包含换行*

可能的 `rel` 值有：

|  值     |                       描述                       |
|---------|---------------------------------------------------------|
| `next`  | 显示下一页结果的 URL     |
| `last`  | 显示最后一页结果的 URL               |
| `first` | 显示第一页结果的 URL              |
| `prev`  | 显示上一页结果的 URL |

## 错误处理 ##

访问 API 时，您偶尔可能会遇到错误。主要有以下四种类型：

* 无效请求，例如使用了不支持的 HTTP 方法，将导致 `400 Bad Request`。
* 身份验证或权限错误，例如 API 密钥不正确，将导致 `401 Unauthorized`。
* 请求不存在的资源或缺少必需参数，将导致 `404 Not Found`。
* 由于服务器错误导致请求无法处理，将导致 `500 Internal Server Error`。

> `400 Bad Request` 示例：

```json
{
  "errors" : [
    {
      "code" : "woocommerce_api_unsupported_method",
      "message" : "Unsupported request method"
    }
  ]
}
```

> `401 Unauthorized` 示例：

```json
{
  "errors" : [
    {
      "code" : "woocommerce_api_authentication_error",
      "message" : "Consumer Key is invalid"
    }
  ]
}
```

> `404 Not Found` 示例：

```json
{
  "errors" : [
    {
      "code" : "woocommerce_api_invalid_order",
      "message" : "Invalid order"
    }
  ]
}
```

> `500 Internal Server Error` 示例：

```json
{
  "errors" : [
    {
      "code" : "woocommerce_api_invalid_handler",
      "message" : "The handler for the route is invalid"
    }
  ]
}
```

错误会返回相应的 HTTP 状态码和一个响应对象，该对象包含 `code` 和 `message` 属性。如果某个端点有任何自定义错误，将在该端点的文档中进行说明。

## HTTP Verbs ##

The API uses the appropriate HTTP verb for each action:

|  Verb    |                               Description                               |
|----------|-------------------------------------------------------------------------|
| `HEAD`   | Can be used for any endpoint to return just the HTTP header information |
| `GET`    | Used for retrieving resources                                           |
| `PUT`    | Used for updating resources                                             |
| `POST`   | Used for creating resources                                             |
| `DELETE` | Used for deleting resources                                             |

## JSONP Support ##

The API supports JSONP by default. JSONP responses use the `application/javascript` content-type. You can specify the callback using the `?_jsonp` parameter for `GET` requests to have the response wrapped in a JSON function:

<div class="api-endpoint">
	<div class="endpoint-data">
		<i class="label label-get">GET</i>
		<h6>/wc-api/v3/orders/count?_jsonp=ordersCount</h6>
	</div>
</div>

```shell
curl https://example.com/wc-api/v3/orders/count?_jsonp=ordersCount \
	-u consumer_key:consumer_secret
```

> Response:

```
\**\ordersCount({"count":8})
```

> If the site administrator has chosen to disable it, you will receive a `400 Bad Request` error:

```json
{
  "errors": [
    {
      "code": "woocommerce_api_jsonp_disabled",
      "message": "JSONP support is disabled on this site"
    }
  ]
}
```

> If your callback contains invalid characters, you will receive a `400 Bad Request` error:


```json
{
  "errors": [
    {
      "code": "woocommerce_api_jsonp_callback_invalid",
      "message": "The JSONP callback function is invalid"
    }
  ]
}
```

## Webhooks ##

Webhooks 可通过 WooCommerce 设置界面或使用 REST API 端点进行管理。`WC_Webhook` 类负责管理自定义文章类型的所有数据存储与检索，以及将 webhook 操作加入队列、处理/发送/记录 webhook。在 `woocommerce_init` 时，会加载活跃的 webhooks 并添加其关联的钩子。

每个 webhook 包含：

* 状态：活跃（发送有效载荷）、暂停（管理员暂停发送）、禁用（因失败暂停发送）
* 主题：决定 webhook 针对哪些资源事件触发
* 发送 URL：接收有效载荷的 URL，必须是 HTTP 或 HTTPS 协议
* 密钥：可选的密钥，用于生成请求正文的 HMAC-SHA256 哈希值，以便接收方验证 webhook 的真实性
* 钩子：为处理 webhook 而添加并绑定的一系列钩子名称数组

### 主题 ###

主题是资源（例如订单）和事件（例如创建）的组合，并映射到一个或多个钩子名称（例如 `woocommerce_checkout_order_processed`）。可以使用主题名称创建 Webhook，相应的钩子会自动添加。

核心主题包括：

* `coupon.created, coupon.updated, coupon.deleted`
* `customer.created, customer.updated, customer.deleted`
* `order.created, order.updated, order.deleted`
* `product.created, product.updated, product.deleted`

也可以使用自定义主题，它们映射到单个钩子名称。例如，您可以添加一个主题为 `action.woocommerce_add_to_cart` 的 Webhook，该 Webhook 将在该事件触发时执行。自定义主题会将第一个钩子参数传递给有效载荷，因此在此示例中，`cart_item_key` 将包含在有效载荷中。

### 交付/负载 ###

交付默认使用 `wp_remote_post()`（HTTP POST）完成，并通过 wp-cron 在后台处理。请求中添加了几个自定义标头，以帮助接收方处理 webhook：

* `X-WC-Webhook-Topic` - 例如 `order.updated`
* `X-WC-Webhook-Resource` - 例如 `order`
* `X-WC-Webhook-Event` - 例如 `updated`
* `X-WC-Webhook-Signature` - 负载的 base64 编码 HMAC-SHA256 哈希值
* `X-WC-Webhook-ID` - webhook 的文章 ID
* `X-WC-Delivery-ID` - 交付日志 ID（一条评论）

负载采用 JSON 编码，对于 API 资源（优惠券、客户、订单、产品），其响应与通过 REST API 请求时完全相同。

### 日志记录 ###

请求/响应以评论形式记录在 webhook 自定义文章类型中。每条投递日志包含：

* 请求时长
* 请求 URL、方法、头部和正文
* 响应代码、消息、头部和正文

为减少评论表膨胀，仅保留最近的 25 条投递日志。

连续 5 次投递失败（定义为非 HTTP 2xx 响应代码）后，webhook 将被禁用，必须通过 REST API 编辑以重新启用。

可通过 REST API 端点或使用 `WC_Webhook::get_delivery_logs()` 代码获取投递日志。

### 端点 ###

[请参阅 Webhook 资源部分](#webhooks7)。

### 可视化界面 ###

您可以通过访问“WooCommerce” > “设置” > “API” > “Webhooks”找到 Webhooks 界面，更多详情请参阅我们的[可视化 Webhooks 文档](https://docs.woocommerce.com/document/webhooks/)。

## 故障排除 ##

* Nginx - 旧版 Nginx 配置可能导致 API 问题，详情参见[此问题](https://github.com/woocommerce/woocommerce/issues/5616#issuecomment-47338737)
* ModSecurity - 启用时可能阻止 `POST`、`PUT` 和 `DELETE` 请求，通常显示 `501 Method Not Implemented` 错误，详情参见[此问题](https://github.com/woocommerce/woocommerce/issues/9838)

## Official Libraries ##

- [Node.js](https://www.npmjs.com/package/woocommerce-api)
- [PHP](https://packagist.org/packages/automattic/woocommerce)
- [Python](https://pypi.python.org/pypi/WooCommerce)
- [Ruby](https://rubygems.org/gems/woocommerce_api)

```javascript
// Install:
// npm install --save woocommerce-api

// Setup:
var WooCommerceAPI = require('woocommerce-api');

var WooCommerce = new WooCommerceAPI({
  url: 'http://example.com', // Your store URL
  consumerKey: 'consumer_key', // Your consumer key
  consumerSecret: 'consumer_secret', // Your consumer secret
  version: 'v3' // WooCommerce API version
});
```

```php
<?php 
// Install:
// composer require automattic/woocommerce

// Setup:
require __DIR__ . '/vendor/autoload.php';

use Automattic\WooCommerce\Client;

$woocommerce = new Client(
    'http://example.com', // Your store URL
    'consumer_key', // Your consumer key
    'consumer_secret', // Your consumer secret
    [
        'version' => 'v3' // WooCommerce API version
    ]
);
?>
```

```python
# Install:
# pip install woocommerce

# Setup:
from woocommerce import API

wcapi = API(
    url="http://example.com", # Your store URL
    consumer_key="consumer_key", # Your consumer key
    consumer_secret="consumer_secret", # Your consumer secret
    version="v3" # WooCommerce API version
)
```

```ruby
# Install:
# gem install woocommerce_api

# Setup:
require "woocommerce_api"

woocommerce = WooCommerce::API.new(
  "http://example.com", # Your store URL
  "consumer_key", # Your consumer key
  "consumer_secret", # Your consumer secret
  {
    version: "v3" # WooCommerce API version
  }
)
```

<aside class="notice">
	Use the tabs in the top-right corner of this page to see how to install and use each library.
</aside>

## 工具 ##

* [CocoaRestClient](http://mmattozzi.github.io/cocoa-rest-client/) - 一款免费、易用的 Mac OS X GUI 客户端，用于与 API 交互，当您的测试商店启用 SSL 时最为实用。
* [Paw HTTP Client](https://itunes.apple.com/us/app/paw-http-client/id584653203?mt=12) - 另一款优秀的 Mac OS X HTTP 客户端。
* [RESTClient, a debugger for RESTful web services](https://addons.mozilla.org/en-US/firefox/addon/restclient/) - 免费的 Firefox 扩展。
* [Advanced REST client](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo) - 免费的 Google Chrome 扩展。