# Hủy đơn

## Endpoint

| Môi trường | URL |
| --- | --- |
| Production | `https://online-gateway.ghn.vn/shiip/public-api/v2/switch-status/cancel` |
| Staging | `https://dev-online-gateway.ghn.vn/shiip/public-api/v2/switch-status/cancel` |

**Method**: `POST`

## Headers

| Header | Bắt buộc | Mô tả |
| --- | --- | --- |
| `Content-Type` | Có | `application/json` |
| `Token` | Có | Token của shop (do GHN cấp) — [lấy token](https://developer.ghn.vn/vi/docs/token/get-token.md) |
| `ShopId` | Có | Shop ID (số nguyên) |

## Tham số

- **order_codes** (String[]): Danh sách mã vận đơn GHN cần hủy, gửi theo lô. **Tất-cả-hoặc-không**: nếu có bất kỳ mã nào không tồn tại hoặc không thuộc tài khoản của bạn thì toàn bộ yêu cầu bị từ chối và không đơn nào bị hủy (xem phần Response)
- **reason_code** (String): Lý do hủy, áp dụng cho mọi đơn trong lô. Một trong các giá trị:<br>`GHN-CO001`: thời gian lấy hàng quá lâu<br>`GHN-CO002`: hết hàng, chưa có hàng để gửi<br>`GHN-CO003`: người nhận không còn nhu cầu nữa<br>`GHN-CANCEL-OTHER`: lý do khác
- **reason** (String): Ghi chú lý do hủy dạng văn bản tự do, áp dụng cho mọi đơn trong lô. Dùng để bổ sung chi tiết, ví dụ đi kèm `GHN-CANCEL-OTHER`. Mặc định: không có

## Ví dụ Request

```bash
curl -X POST https://dev-online-gateway.ghn.vn/shiip/public-api/v2/switch-status/cancel \
  -H "Token: 5c1d8a9e-2f4b-11ed-..." \
  -H "ShopId: 92837" \
  -H "Content-Type: application/json" \
  -d '{
    "order_codes": ["LADTC8", "LADFYR"],
    "reason_code": "GHN-CO001",
    "reason": "Khách đổi ý, không gửi nữa"
  }'
```

## Response

### Thành công (HTTP 200)

_Lấy từ một lần gọi thật trên môi trường Staging._

```json
{
  "code": 200,
  "message": "Success",
  "data": [
    {
      "order_code": "LADTC8",
      "result": true,
      "message": "OK"
    }
  ]
}
```

### Các trường Response

| Trường | Kiểu | Mô tả |
| --- | --- | --- |
| `code` | Int | Mã HTTP (`200` nếu thành công) |
| `message` | String | Thông báo kết quả (`Success`) |
| `data` | Object[] | Mỗi phần tử tương ứng một mã đơn trong request |
| `data[].order_code` | String | Mã đơn của phần tử này |
| `data[].result` | Bool | `true` nếu đơn đã được hủy; `false` nếu GHN từ chối (ví dụ đơn đã ở trạng thái không thể hủy) |
| `data[].message` | String | Thông báo kết quả cho từng đơn (ví dụ `OK`) |

### Lỗi — đơn không tồn tại / không thuộc về bạn (HTTP 400)

_Lấy từ một lần gọi thật trên môi trường Staging (mã đơn không tồn tại)._ Vì lô là tất-cả-hoặc-không, chỉ cần một mã sai là toàn bộ yêu cầu bị hủy bỏ với `data: null` — không đơn nào trong lô được hủy.

```json
{
  "code": 400,
  "message": "Lỗi gọi API: corev2_tenant_order_detail - Đơn hàng không tồn tại",
  "data": null
}
```

> **NOTE**
> Phần có ý nghĩa của `message` là đoạn sau dấu `-` cuối cùng (ở đây là `Đơn hàng không tồn tại`). Phần đầu là tham chiếu nội bộ.

## Bảng mã lỗi

| Điều kiện | HTTP | Ý nghĩa |
| --- | --- | --- |
| Đơn không tồn tại (`Đơn hàng không tồn tại`) | 400 | Một trong các mã đơn không tồn tại hoặc không thuộc tài khoản của bạn. Toàn bộ lô bị hủy bỏ; không đơn nào được hủy |
| `result: false` trong `data` | 200 | Mã đơn hợp lệ nhưng trạng thái hiện tại không còn cho phép hủy |
| `CLIENT_NOT_OWNER_OF_SHOP` | 400 | Token không sở hữu shop |
| `SERVER_ERROR_COMMON` | 500 | Lỗi hệ thống |
