# 顾客

Customer API 用于在前台 JavaScript 中注册顾客、让顾客登录和登出，以及读取和修改已登录顾客的资料、地址和营销邮件订阅状态。

所有 Ajax API 请求应使用[多语言 URL](/zh-CN/docs/theme/references/ajax-api/#locale-aware-urls)，以便为访客提供一致的体验。

## 身份要求

**顾客登录态。** 注册、登录、发送密码重置邮件、重置密码、发送登录验证码、订阅营销邮件、读取登录配置这几个 endpoint 匿名访客可以调用，本页其余 endpoint 都需要顾客已登录。登录态保存在 cookie 里，`sign_up` 或 `sign_in` 成功后浏览器会自动带上。没有登录态时请求返回 `401`：

```json
{
  "errors": [
    "Sign in to continue store operations."
  ]
}
```

**CSRF token。** 除 `GET` 以外的请求都要带 `X-CSRF-Token` 请求头，值取 cookie `CSRF-TOKEN`。该 cookie 可以在 JavaScript 中读取，下面的示例都用这个函数取值：

```javascript
function getCsrfToken() {
  const entry = document.cookie.split('; ').find((item) => item.startsWith('CSRF-TOKEN='));
  return entry ? decodeURIComponent(entry.slice('CSRF-TOKEN='.length)) : '';
}
```

缺少该请求头时，请求返回 `406`，响应体为 `{"errors":["CSRF token verify fails"]}`。

**人机校验。** 注册、登录、发送密码重置邮件、重置密码这四个 endpoint 受店铺的人机校验保护。服务端需要校验时返回 `400`，响应体为 `{"errors":["{\"errors\":[\"empty token\"]}"]}`。此时把人机校验令牌放进 `token` 字段、`version` 传 `v3`，重新提交请求。在 Shoplazza 主题中，`spz-privacy-token` 组件会自动填好这两个字段；自己发请求时，从店铺配置的人机校验服务（Google reCAPTCHA v3）获取令牌。

**请求格式。** 本页需要提交数据的 endpoint 都使用 `application/x-www-form-urlencoded` 请求体，下面的示例用 `URLSearchParams` 构造。

## 注册顾客账号

```text
POST /{locale}/api/customers/sign_up
```

注册顾客账号。请求成功后会同时建立顾客登录态，顾客即为已登录状态。

### 请求示例

**请求示例**

```javascript
const body = new URLSearchParams({
  email: 'jane@example.com',
  password: 'your-password',
  first_name: 'Jane',
  last_name: 'Doe',
  newsletter: 'true'
});

fetch(window.SHOPLAZZA.routes.root + '/api/customers/sign_up', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  },
  body: body
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `email` string

  账号的邮箱地址。
- `password` string

  账号的密码。
- `first_name` string

  顾客的名。
- `last_name` string

  顾客的姓。
- `newsletter` boolean

  顾客是否订阅营销邮件。
- `token` string

  人机校验令牌。店铺的人机校验要求校验时必填。
- `version` string

  人机校验版本，取值 `v3`。与 `token` 一起填。

### 响应

**数据结构 | 示例**

- `customer` object

  - `id` string

    顾客的 ID。
  - `email` string

    顾客的邮箱地址。
  - `first_name` string

    顾客或收件人的名。
  - `last_name` string

    顾客或收件人的姓。
  - `phone` string

    顾客的电话号码。
  - `tags` undefined[]

    对象上的标签。
  - `name` string

    顾客的全名。
  - `note` string

    对象上的备注。
  - `contact` string

    顾客的联系方式，邮箱或电话号码。
  - `contact_type` string

    联系方式类型，邮箱或电话。
  - `created_by` string
  - `location_id` string
  - `registered_at` string

    顾客完成注册的时间。
  - `noted_at` string
  - `created_at` string

    创建时间（ISO-8601 格式）。
  - `source` string

    顾客数据的来源。
  - `free_tax` boolean

    顾客是否享有税收豁免。
  - `subscribed` boolean

    顾客是否订阅了营销信息。
  - `registered` boolean

    顾客是否已注册账号。
  - `customer_extra_info` object

    顾客的附加统计信息。

    - `finished_order_count` number

      顾客已完成的订单数。
    - `finished_order_total` string

      顾客已完成订单的总金额。
    - `country` string
    - `country_code` string
    - `province` string

      地址所在省或州。
    - `province_code` string

      省或州的代码。
    - `currency_code` string

      订单的货币代码，例如 `USD`。
    - `purchase_product_count` number

      顾客已购买的商品件数。
    - `store_customer_id` string
    - `customer_role` string
    - `ext` string
    - `first_order_at` string

      顾客首次下单时间。
    - `last_order_at` string

      顾客最后一次下单时间。

```json
{
  "customer": {
    "id": "04f268c8-fea5-4386-abd7-c4fade761257",
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "phone": null,
    "tags": [],
    "name": "Jane Doe",
    "note": null,
    "contact": "jane@example.com",
    "contact_type": "email",
    "created_by": "default",
    "location_id": "",
    "registered_at": "2026-09-03T02:48:07Z",
    "noted_at": null,
    "created_at": "2026-09-03T02:48:08Z",
    "source": "sign_up",
    "free_tax": false,
    "subscribed": true,
    "registered": true,
    "customer_extra_info": {
      "finished_order_count": 0,
      "finished_order_total": "0.0",
      "country": null,
      "country_code": null,
      "province": null,
      "province_code": null,
      "currency_code": "USD",
      "purchase_product_count": 0,
      "store_customer_id": "",
      "customer_role": null,
      "ext": null,
      "first_order_at": null,
      "last_order_at": null
    }
  }
}
```

## 顾客登录

```text
POST /{locale}/api/customers/sign_in
```

用邮箱和密码登录顾客账号，并建立顾客登录态。

### 请求示例

**请求示例**

```javascript
const body = new URLSearchParams({
  email: 'jane@example.com',
  password: 'your-password'
});

fetch(window.SHOPLAZZA.routes.root + '/api/customers/sign_in', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  },
  body: body
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `email` string

  账号的邮箱地址。
- `password` string

  账号的密码。
- `token` string

  人机校验令牌。店铺的人机校验要求校验时必填。
- `version` string

  人机校验版本，取值 `v3`。与 `token` 一起填。

### 响应

**数据结构 | 示例**

- `customer` object

  - `id` string

    顾客的 ID。
  - `email` string

    顾客的邮箱地址。
  - `first_name` string

    顾客或收件人的名。
  - `last_name` string

    顾客或收件人的姓。
  - `phone` string

    顾客的电话号码。
  - `tags` undefined[]

    对象上的标签。
  - `name` string

    顾客的全名。
  - `note` string

    对象上的备注。
  - `contact` string

    顾客的联系方式，邮箱或电话号码。
  - `contact_type` string

    联系方式类型，邮箱或电话。
  - `created_by` string
  - `location_id` string
  - `registered_at` string

    顾客完成注册的时间。
  - `noted_at` string
  - `created_at` string

    创建时间（ISO-8601 格式）。
  - `source` string

    顾客数据的来源。
  - `free_tax` string

    顾客是否享有税收豁免。
  - `subscribed` boolean

    顾客是否订阅了营销信息。
  - `registered` boolean

    顾客是否已注册账号。
  - `customer_extra_info` object

    顾客的附加统计信息。

    - `finished_order_count` number

      顾客已完成的订单数。
    - `finished_order_total` string

      顾客已完成订单的总金额。
    - `country` string
    - `country_code` string
    - `province` string

      地址所在省或州。
    - `province_code` string

      省或州的代码。
    - `currency_code` string

      订单的货币代码，例如 `USD`。
    - `purchase_product_count` number

      顾客已购买的商品件数。
    - `store_customer_id` string
    - `customer_role` string
    - `ext` string
    - `first_order_at` string

      顾客首次下单时间。
    - `last_order_at` string

      顾客最后一次下单时间。

```json
{
  "customer": {
    "id": "9fe44049-abab-4fed-ab3d-1bf4ffee8ef5",
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "phone": "+1 555-0100",
    "tags": [],
    "name": "Jane Doe",
    "note": null,
    "contact": "jane@example.com",
    "contact_type": "email",
    "created_by": "default",
    "location_id": "",
    "registered_at": "2026-09-03T01:03:32Z",
    "noted_at": null,
    "created_at": "2026-09-02T14:13:31Z",
    "source": "order_create_c",
    "free_tax": null,
    "subscribed": false,
    "registered": true,
    "customer_extra_info": {
      "finished_order_count": 2,
      "finished_order_total": "33.0",
      "country": "United States",
      "country_code": "US",
      "province": "California",
      "province_code": "US-CA",
      "currency_code": "USD",
      "purchase_product_count": 4,
      "store_customer_id": "",
      "customer_role": null,
      "ext": null,
      "first_order_at": "2026-09-03T02:19:44Z",
      "last_order_at": "2026-09-03T02:32:31Z"
    }
  }
}
```

## 顾客登出

```text
POST /{locale}/api/customers/sign_out
```

结束当前顾客登录态。需要顾客登录态，没有参数。

### 请求示例

**请求示例**

```javascript
fetch(window.SHOPLAZZA.routes.root + '/api/customers/sign_out', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  }
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 响应

**数据结构 | 示例**

- `` object

```json
{}
```

## 发送密码重置邮件

```text
POST /{locale}/api/customers/password_reset_email
```

向顾客发送密码重置邮件。邮件里带的验证码用于 `PATCH /{locale}/api/customers/password_reset`。

### 请求示例

**请求示例**

```javascript
const body = new URLSearchParams({ email: 'jane@example.com' });

fetch(window.SHOPLAZZA.routes.root + '/api/customers/password_reset_email', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  },
  body: body
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `email` string

  账号的邮箱地址。

### 响应

**数据结构 | 示例**

- `` object

```json
{}
```

## 重置顾客密码

```text
PATCH /{locale}/api/customers/password_reset
```

用密码重置邮件里的验证码为顾客设置新密码。

### 请求示例

**请求示例**

```javascript
const body = new URLSearchParams({
  email: 'jane@example.com',
  code: '123456',
  password: 'your-new-password',
  confirm_password: 'your-new-password'
});

fetch(window.SHOPLAZZA.routes.root + '/api/customers/password_reset', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  },
  body: body
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `email` string

  账号的邮箱地址。
- `code` string

  密码重置邮件里的验证码。
- `password` string

  新密码。
- `confirm_password` string

  再次输入的新密码，必须与 `password` 一致。
- `token` string

  人机校验令牌。店铺的人机校验要求校验时必填。
- `version` string

  人机校验版本，取值 `v3`。与 `token` 一起填。

### 响应

**数据结构 | 示例**

- `` object

```json
{}
```

## 发送登录验证码

```text
POST /{locale}/api/customers/login_email
```

向顾客邮箱发送登录验证码，用于让顾客用验证码代替密码登录的场景。

### 请求示例

**请求示例**

```javascript
const body = new URLSearchParams({ email: 'jane@example.com' });

fetch(window.SHOPLAZZA.routes.root + '/api/customers/login_email', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  },
  body: body
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `email` string

  接收验证码的邮箱地址。

### 响应

**数据结构 | 示例**

- `` object

```json
{}
```

## 获取店铺社交登录方式

```text
GET /{locale}/api/customers/login_settings
```

获取店铺登录页提供的社交登录方式。无参数。店铺未开启任何社交登录时，`login_setting` 为 `null`。

### 请求示例

**请求示例**

```javascript
fetch(window.SHOPLAZZA.routes.root + '/api/customers/login_settings')
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 响应

**数据结构 | 示例**

- `login_setting` object

  - `google` boolean

    是否开启 Google 登录。
  - `apple` boolean

    是否开启 Apple 登录。
  - `facebook` boolean

    是否开启 Facebook 登录。

```json
{
  "login_setting": {
    "google": true,
    "apple": true,
    "facebook": true
  }
}
```

## 获取当前顾客资料

```text
GET /{locale}/api/customers/show
```

获取当前已登录顾客的资料。需要顾客登录态，没有参数。

### 请求示例

**请求示例**

```javascript
fetch(window.SHOPLAZZA.routes.root + '/api/customers/show')
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 响应

**数据结构 | 示例**

- `customer` object

  - `id` string

    顾客的 ID。
  - `email` string

    顾客的邮箱地址。
  - `first_name` string

    顾客或收件人的名。
  - `last_name` string

    顾客或收件人的姓。
  - `phone` string

    顾客的电话号码。
  - `tags` undefined[]

    对象上的标签。
  - `name` string

    顾客的全名。
  - `note` string

    对象上的备注。
  - `contact` string

    顾客的联系方式，邮箱或电话号码。
  - `contact_type` string

    联系方式类型，邮箱或电话。
  - `created_by` string
  - `location_id` string
  - `registered_at` string

    顾客完成注册的时间。
  - `noted_at` string
  - `created_at` string

    创建时间（ISO-8601 格式）。
  - `source` string

    顾客数据的来源。
  - `free_tax` string

    顾客是否享有税收豁免。
  - `subscribed` boolean

    顾客是否订阅了营销信息。
  - `registered` boolean

    顾客是否已注册账号。
  - `customer_extra_info` object

    顾客的附加统计信息。

    - `finished_order_count` number

      顾客已完成的订单数。
    - `finished_order_total` string

      顾客已完成订单的总金额。
    - `country` string
    - `country_code` string
    - `province` string

      地址所在省或州。
    - `province_code` string

      省或州的代码。
    - `currency_code` string

      订单的货币代码，例如 `USD`。
    - `purchase_product_count` number

      顾客已购买的商品件数。
    - `store_customer_id` string
    - `customer_role` string
    - `ext` string
    - `first_order_at` string

      顾客首次下单时间。
    - `last_order_at` string

      顾客最后一次下单时间。

```json
{
  "customer": {
    "id": "9fe44049-abab-4fed-ab3d-1bf4ffee8ef5",
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "phone": "+1 555-0100",
    "tags": [],
    "name": "Jane Doe",
    "note": null,
    "contact": "jane@example.com",
    "contact_type": "email",
    "created_by": "default",
    "location_id": "",
    "registered_at": "2026-09-03T01:03:32Z",
    "noted_at": null,
    "created_at": "2026-09-02T14:13:31Z",
    "source": "newsletter",
    "free_tax": null,
    "subscribed": true,
    "registered": true,
    "customer_extra_info": {
      "finished_order_count": 0,
      "finished_order_total": "0.0",
      "country": null,
      "country_code": null,
      "province": null,
      "province_code": null,
      "currency_code": "USD",
      "purchase_product_count": 0,
      "store_customer_id": "",
      "customer_role": null,
      "ext": null,
      "first_order_at": null,
      "last_order_at": null
    }
  }
}
```

## 修改当前顾客资料

```text
PATCH /{locale}/api/customers/update
```

修改当前已登录顾客的姓名和邮箱地址。需要顾客登录态。`email` 要与姓名字段一起提交。

### 请求示例

**请求示例**

```javascript
const body = new URLSearchParams({
  email: 'jane@example.com',
  first_name: 'Jane',
  last_name: 'Doe'
});

fetch(window.SHOPLAZZA.routes.root + '/api/customers/update', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  },
  body: body
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `email` string

  账号的邮箱地址。
- `first_name` string

  顾客的名。
- `last_name` string

  顾客的姓。

### 响应

**数据结构 | 示例**

- `customer` object

  - `email` string

    顾客的邮箱地址。
  - `first_name` string

    顾客或收件人的名。
  - `last_name` string

    顾客或收件人的姓。
  - `phone` string

    顾客的电话号码。
  - `id` string

    顾客的 ID。
  - `contact_type` string

    联系方式类型，邮箱或电话。
  - `contact` string

    顾客的联系方式，邮箱或电话号码。
  - `name` string

    顾客的全名。
  - `tags` undefined[]

    对象上的标签。
  - `note` string

    对象上的备注。
  - `created_by` string
  - `location_id` string
  - `registered_at` string

    顾客完成注册的时间。
  - `noted_at` string
  - `created_at` string

    创建时间（ISO-8601 格式）。
  - `source` string

    顾客数据的来源。
  - `free_tax` string

    顾客是否享有税收豁免。
  - `subscribed` boolean

    顾客是否订阅了营销信息。
  - `registered` boolean

    顾客是否已注册账号。
  - `customer_extra_info` object

    顾客的附加统计信息。

    - `finished_order_count` number

      顾客已完成的订单数。
    - `finished_order_total` string

      顾客已完成订单的总金额。
    - `country` string
    - `country_code` string
    - `province` string

      地址所在省或州。
    - `province_code` string

      省或州的代码。
    - `currency_code` string

      订单的货币代码，例如 `USD`。
    - `purchase_product_count` number

      顾客已购买的商品件数。
    - `store_customer_id` string
    - `customer_role` string
    - `ext` string
    - `first_order_at` string

      顾客首次下单时间。
    - `last_order_at` string

      顾客最后一次下单时间。

```json
{
  "customer": {
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "phone": "+1 555-0100",
    "id": "9fe44049-abab-4fed-ab3d-1bf4ffee8ef5",
    "contact_type": "email",
    "contact": "jane@example.com",
    "name": "Jane Doe",
    "tags": [],
    "note": null,
    "created_by": "default",
    "location_id": "",
    "registered_at": "2026-09-03T01:03:32Z",
    "noted_at": null,
    "created_at": "2026-09-02T14:13:31Z",
    "source": "newsletter",
    "free_tax": null,
    "subscribed": true,
    "registered": true,
    "customer_extra_info": {
      "finished_order_count": 0,
      "finished_order_total": "0.0",
      "country": null,
      "country_code": null,
      "province": null,
      "province_code": null,
      "currency_code": "USD",
      "purchase_product_count": 0,
      "store_customer_id": "",
      "customer_role": null,
      "ext": null,
      "first_order_at": null,
      "last_order_at": null
    }
  }
}
```

## 订阅营销邮件

```text
POST /{locale}/api/customers/newsletters
```

让一个邮箱地址订阅店铺的营销邮件。匿名访客可以调用。

### 请求示例

**请求示例**

```javascript
const body = new URLSearchParams({ email: 'jane@example.com' });

fetch(window.SHOPLAZZA.routes.root + '/api/customers/newsletters', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  },
  body: body
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `email` string

  要订阅的邮箱地址。

### 响应

**数据结构 | 示例**

- `id` string

  完成订阅的顾客 ID。

```json
{
  "id": "9fe44049-abab-4fed-ab3d-1bf4ffee8ef5"
}
```

## 获取顾客地址列表

```text
GET /{locale}/api/customers/addresses
```

获取当前已登录顾客的地址列表。需要顾客登录态。

### 请求示例

**请求示例**

```javascript
fetch(window.SHOPLAZZA.routes.root + '/api/customers/addresses?per_page=40')
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `per_page` number

  返回的地址条数。

### 响应

**数据结构 | 示例**

- `count` number

  返回的地址数量。
- `addresses` object[]

  顾客的地址列表。

  *   Array \[

  - `id` string

    地址的 ID。
  - `first_name` string

    顾客或收件人的名。
  - `last_name` string

    顾客或收件人的姓。
  - `phone` string

    与该地址关联的电话号码。
  - `email` string

    与该地址关联的邮箱。
  - `country` string

    地址所在国家的名称。
  - `country_code` string

    地址所在国家的 ISO 代码。
  - `province` string

    地址所在省或州。
  - `province_code` string

    省或州的代码。
  - `area` string

    地址所在区域。
  - `city` string

    地址所在城市。
  - `company` string

    地址的公司名称。
  - `zip` string

    邮政编码。
  - `gender` string

    收件人的性别。
  - `phone_area_code` string

    电话号码的区号。
  - `address` string

    收件人的详细地址。
  - `address1` string

    详细地址第一行。
  - `is_default` boolean

    是否为顾客的默认地址。
  - `created_at` string

    创建时间（ISO-8601 格式）。
  *   \]

```json
{
  "count": 1,
  "addresses": [
    {
      "id": "f4892e84-0d09-4370-8144-37a21a01f2f6",
      "first_name": "Jane",
      "last_name": "Doe",
      "phone": null,
      "email": "jane@example.com",
      "country": "United States",
      "country_code": "US",
      "province": "California",
      "province_code": "US-CA",
      "area": null,
      "city": "Los Angeles",
      "company": null,
      "zip": "90001",
      "gender": null,
      "phone_area_code": null,
      "address": "123 Main St",
      "address1": "123 Main St",
      "is_default": true,
      "created_at": "2026-09-03T01:07:23Z"
    }
  ]
}
```

## 创建地址

```text
POST /{locale}/api/customers/addresses
```

为当前已登录顾客新增一个地址。需要顾客登录态。`country` 与 `country_code` 要一起提交。

### 请求示例

**请求示例**

```javascript
const body = new URLSearchParams({
  first_name: 'Jane',
  last_name: 'Doe',
  address: '123 Main St',
  address1: 'Apt 4',
  city: 'Los Angeles',
  province: 'California',
  province_code: 'CA',
  country: 'United States',
  country_code: 'US',
  zip: '90001',
  email: 'jane@example.com',
  is_default: '1'
});

fetch(window.SHOPLAZZA.routes.root + '/api/customers/addresses', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  },
  body: body
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `first_name` string

  收件人的名。
- `last_name` string

  收件人的姓。
- `address` string

  街道地址第一行。
- `address1` string

  街道地址第二行，例如门牌号。
- `city` string

  城市。
- `province` string

  省/州名称。
- `province_code` string

  省/州代码，例如 `CA`。
- `country` string

  国家/地区名称，例如 `United States`。
- `country_code` string

  国家/地区两位代码，例如 `US`。
- `zip` string

  邮政编码。
- `email` string

  收件人的邮箱地址。
- `is_default` number

  是否设为默认地址，取值 `1` 或 `0`。

### 响应

**数据结构 | 示例**

- `address` object

  - `id` string

    地址的 ID。
  - `first_name` string

    顾客或收件人的名。
  - `last_name` string

    顾客或收件人的姓。
  - `phone` string

    与该地址关联的电话号码。
  - `email` string

    与该地址关联的邮箱。
  - `country` string

    地址所在国家的名称。
  - `country_code` string

    地址所在国家的 ISO 代码。
  - `province` string

    地址所在省或州。
  - `province_code` string

    省或州的代码。
  - `area` string

    地址所在区域。
  - `city` string

    地址所在城市。
  - `company` string

    地址的公司名称。
  - `zip` string

    邮政编码。
  - `gender` string

    收件人的性别。
  - `phone_area_code` string

    电话号码的区号。
  - `address` string

    收件人的详细地址。
  - `address1` string

    详细地址第一行。
  - `is_default` boolean

    是否为顾客的默认地址。
  - `created_at` string

    创建时间（ISO-8601 格式）。

```json
{
  "address": {
    "id": "f4892e84-0d09-4370-8144-37a21a01f2f6",
    "first_name": "Jane",
    "last_name": "Doe",
    "phone": null,
    "email": "jane@example.com",
    "country": "United States",
    "country_code": "US",
    "province": "California",
    "province_code": "US-CA",
    "area": null,
    "city": "Los Angeles",
    "company": null,
    "zip": "90001",
    "gender": null,
    "phone_area_code": null,
    "address": "123 Main St",
    "address1": "123 Main St",
    "is_default": true,
    "created_at": "2026-09-03T01:07:23Z"
  }
}
```

## 查询地址详情

```text
GET /{locale}/api/customers/addresses/{address_id}
```

获取当前已登录顾客的某一个地址。需要顾客登录态。

### 请求示例

**请求示例**

```javascript
fetch(window.SHOPLAZZA.routes.root + '/api/customers/addresses/f4892e84-0d09-4370-8144-37a21a01f2f6')
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `address_id` string

  地址的 id。

### 响应

**数据结构 | 示例**

- `address` object

  - `id` string

    地址的 ID。
  - `first_name` string

    顾客或收件人的名。
  - `last_name` string

    顾客或收件人的姓。
  - `phone` string

    与该地址关联的电话号码。
  - `email` string

    与该地址关联的邮箱。
  - `country` string

    地址所在国家的名称。
  - `country_code` string

    地址所在国家的 ISO 代码。
  - `province` string

    地址所在省或州。
  - `province_code` string

    省或州的代码。
  - `area` string

    地址所在区域。
  - `city` string

    地址所在城市。
  - `company` string

    地址的公司名称。
  - `zip` string

    邮政编码。
  - `gender` string

    收件人的性别。
  - `phone_area_code` string

    电话号码的区号。
  - `address` string

    收件人的详细地址。
  - `address1` string

    详细地址第一行。
  - `is_default` boolean

    是否为顾客的默认地址。
  - `created_at` string

    创建时间（ISO-8601 格式）。

```json
{
  "address": {
    "id": "f4892e84-0d09-4370-8144-37a21a01f2f6",
    "first_name": "Jane",
    "last_name": "Doe",
    "phone": null,
    "email": "jane@example.com",
    "country": "United States",
    "country_code": "US",
    "province": "California",
    "province_code": "US-CA",
    "area": null,
    "city": "Los Angeles",
    "company": null,
    "zip": "90001",
    "gender": null,
    "phone_area_code": null,
    "address": "123 Main St",
    "address1": "123 Main St",
    "is_default": true,
    "created_at": "2026-09-03T01:07:23Z"
  }
}
```

## 修改地址

```text
PATCH /{locale}/api/customers/addresses/{address_id}
```

修改当前已登录顾客的某一个地址。需要顾客登录态。`country` 与 `country_code` 要一起提交。

### 请求示例

**请求示例**

```javascript
const body = new URLSearchParams({
  first_name: 'Jane',
  last_name: 'Doe',
  address: '456 Oak Ave',
  city: 'Los Angeles',
  province: 'California',
  province_code: 'CA',
  country: 'United States',
  country_code: 'US',
  zip: '90002'
});

fetch(window.SHOPLAZZA.routes.root + '/api/customers/addresses/f4892e84-0d09-4370-8144-37a21a01f2f6', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'X-CSRF-Token': getCsrfToken()
  },
  body: body
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `address_id` string

  地址的 id。
- `first_name` string

  收件人的名。
- `last_name` string

  收件人的姓。
- `address` string

  街道地址第一行。
- `city` string

  城市。
- `province` string

  省/州名称。
- `province_code` string

  省/州代码，例如 `CA`。
- `country` string

  国家/地区名称，例如 `United States`。
- `country_code` string

  国家/地区两位代码，例如 `US`。
- `zip` string

  邮政编码。

### 响应

**数据结构 | 示例**

- `address` object

  - `id` string

    地址的 ID。
  - `first_name` string

    顾客或收件人的名。
  - `last_name` string

    顾客或收件人的姓。
  - `country` string

    地址所在国家的名称。
  - `country_code` string

    地址所在国家的 ISO 代码。
  - `province` string

    地址所在省或州。
  - `province_code` string

    省或州的代码。
  - `city` string

    地址所在城市。
  - `zip` string

    邮政编码。
  - `email` string

    与该地址关联的邮箱。
  - `gender` string

    收件人的性别。
  - `phone` string

    与该地址关联的电话号码。
  - `area` string

    地址所在区域。
  - `company` string

    地址的公司名称。
  - `phone_area_code` string

    电话号码的区号。
  - `address` string

    收件人的详细地址。
  - `address1` string

    详细地址第一行。
  - `is_default` boolean

    是否为顾客的默认地址。
  - `created_at` string

    创建时间（ISO-8601 格式）。

```json
{
  "address": {
    "id": "f4892e84-0d09-4370-8144-37a21a01f2f6",
    "first_name": "Jane",
    "last_name": "Doe",
    "country": "United States",
    "country_code": "US",
    "province": "California",
    "province_code": "US-CA",
    "city": "Los Angeles",
    "zip": "90001",
    "email": "jane@example.com",
    "gender": null,
    "phone": null,
    "area": null,
    "company": null,
    "phone_area_code": null,
    "address": "123 Main St",
    "address1": "123 Main St",
    "is_default": true,
    "created_at": "2026-09-03T01:07:23Z"
  }
}
```

## 删除地址

```text
DELETE /{locale}/api/customers/addresses/{address_id}
```

删除当前已登录顾客的某一个地址。需要顾客登录态。

### 请求示例

**请求示例**

```javascript
fetch(window.SHOPLAZZA.routes.root + '/api/customers/addresses/f4892e84-0d09-4370-8144-37a21a01f2f6', {
  method: 'DELETE',
  headers: {
    'X-CSRF-Token': getCsrfToken()
  }
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `address_id` string

  地址的 id。

### 响应

**数据结构 | 示例**

- `` object

```json
{}
```

## 设置默认地址

```text
POST /{locale}/api/customers/addresses/{address_id}/default
```

把某一个地址设为当前已登录顾客的默认地址。需要顾客登录态。

### 请求示例

**请求示例**

```javascript
fetch(window.SHOPLAZZA.routes.root + '/api/customers/addresses/f4892e84-0d09-4370-8144-37a21a01f2f6/default', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': getCsrfToken()
  }
})
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 请求参数

- `address_id` string

  地址的 id。

### 响应

**数据结构 | 示例**

- `` object

```json
{}
```

## 获取店铺地址表单配置

```text
GET /{locale}/api/customers/address_settings
```

获取店铺地址表单的配置：姓名字段如何排布、哪些可选字段展示或隐藏、哪些联系方式字段必填。需要顾客登录态，没有参数。

### 请求示例

**请求示例**

```javascript
fetch(window.SHOPLAZZA.routes.root + '/api/customers/address_settings')
  .then((response) => response.json())
  .then((data) => {
    // do something...
  });
```

### 响应

**数据结构 | 示例**

- `email` string

  地址表单中邮箱字段的展示设置。
- `name` string

  地址表单中姓名字段的排布方式。
- `phone` string

  地址表单中电话字段的展示设置。
- `company` string

  地址表单中公司字段的展示设置，例如 `hidden`。
- `address1` string

  地址表单中详细地址字段的展示设置。
- `name_requirement` string

  姓名字段中哪一项必填，例如 `last_name`。
- `contact_details` string

  地址表单收集联系方式的方式。

```json
{
  "email": "jane@example.com",
  "name": "separate",
  "phone": "+1 555-0100",
  "company": "hidden",
  "address1": "123 Main St",
  "name_requirement": "last_name",
  "contact_details": "multiple"
}
```
