# Cập nhật đơn

> Cập nhật một đơn đã tồn tại. Đây là **cập nhật một phần** — chỉ những trường bạn gửi trong body mới bị thay đổi; các trường còn lại giữ nguyên. Mọi trường của [Tạo đơn](https://developer.ghn.vn/vi/docs/order/create.md#tham-so) đều được chấp nhận ở đây; bảng dưới đây liệt kê các trường có hành vi riêng khi cập nhật.

Shares the request contract with [order/create](https://developer.ghn.vn/vi/docs/order/create.md)

## Endpoint

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

**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ố

Gửi `order_code` cùng với chỉ những trường bạn muốn thay đổi. **Mọi trường của [Tạo đơn](https://developer.ghn.vn/vi/docs/order/create.md#tham-so) đều được chấp nhận với cùng ý nghĩa** — gửi để thay đổi, bỏ qua để giữ nguyên. Chỉ các trường dưới đây là riêng của Cập nhật; các trường còn lại xem ở Tạo đơn.

- **order_code** (String): Mã vận đơn GHN của đơn cần cập nhật. Phải thuộc tài khoản của bạn
- **cod_amount** (Int): Số tiền COD mới (VND). Chỉ áp dụng khi khác giá trị hiện tại. **Thay đổi giá trị này cần `otp`** (xem bên dưới)
- **otp** (String): Mã dùng một lần, **chỉ bắt buộc khi thay đổi `cod_amount`**. GHN gửi mã về SĐT đã đăng ký của tài khoản. Mã sai/thiếu sẽ lỗi `OTP_NOT_VALID`

## Trường nào được cập nhật theo trạng thái

Một trường chỉ được thay đổi nếu trạng thái hiện tại của đơn cho phép. `ready_to_pick` cho phép tất cả; tập trường thu hẹp dần khi đơn đi qua mạng lưới; các trạng thái kết thúc như đã giao / đã hoàn / đã hủy không cho phép thay đổi gì. Viết tắt: **thông tin người gửi** gồm `from_*`, **thông tin người nhận** gồm `to_*` (tên/SĐT/địa chỉ), **thông tin hoàn** gồm `return_*`, **dịch vụ** gồm `service_id` / `service_type_id`.

| Trạng thái đơn | Trường được cập nhật |
| --- | --- |
| `ready_to_pick` | Tất cả các trường |
| `picking` | Mọi trường trừ thông tin người gửi, `pick_shift`, `pickup_time`, `pick_station_id` |
| `money_collect_picking` | `order_value`, `to_name`/`to_phone`, `weight`, `content`, `required_note`, `note`, `cod_amount`, `cod_failed_amount`, thông tin hoàn, `coupon`, `items` |
| `picked` | dịch vụ, thông tin người nhận, `weight`, `content`, `required_note`, `note`, `cod_amount`, `cod_failed_amount`, thông tin hoàn, `coupon`, `items`, `document_return`, `double_check` |
| `storing`, `transporting`, `sorting` | dịch vụ, thông tin người nhận, `content`, `required_note`, `note`, `cod_amount`, `cod_failed_amount`, thông tin hoàn, `coupon`, `document_return`, `double_check` |
| `delivering` | dịch vụ, thông tin người nhận, `required_note`, `note`, `cod_amount`, `cod_failed_amount`, thông tin hoàn, `document_return`, `double_check` |
| `delivery_fail` | dịch vụ, thông tin người nhận, `content`, `required_note`, `note`, `cod_amount`, thông tin hoàn, `document_return`, `double_check` |
| `waiting_to_return` | dịch vụ, thông tin người nhận, `content`, `required_note`, `note`, `cod_amount`, `cod_failed_amount`, thông tin hoàn, `document_return`, `double_check` |
| `return`, `return_transporting`, `return_sorting` | chỉ liên hệ hoàn (`return_name`, `return_phone`) |
| `return_fail` | thông tin hoàn (`return_name`, `return_phone`, `return_address`) |
| `delivered`, `money_collect_delivering`, `returning`, `returned`, `cancel`, `exception`, `lost`, `damage` | Không — đơn không thể chỉnh sửa nữa |

## Ví dụ Request

```bash
curl -X POST https://dev-online-gateway.ghn.vn/shiip/public-api/v2/shipping-order/update \
  -H "Token: 5c1d8a9e-2f4b-11ed-..." \
  -H "ShopId: 92837" \
  -H "Content-Type: application/json" \
  -d '{
    "order_code": "LADAK9",
    "note": "Giao trong giờ hành chính",
    "weight": 700
  }'
```

```bash
curl -X POST https://dev-online-gateway.ghn.vn/shiip/public-api/v2/shipping-order/update \
  -H "Token: 5c1d8a9e-2f4b-11ed-..." \
  -H "ShopId: 92837" \
  -H "Content-Type: application/json" \
  -d '{
    "order_code": "LADAK9",
    "cod_amount": 300000,
    "otp": "123456"
  }'
```

## 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": null
}
```

### 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` | null | Luôn `null` với API này |

### Lỗi — thay đổi COD mà không có OTP hợp lệ (HTTP 400)

_Lấy từ một lần gọi thật trên môi trường Staging (`cod_amount` thay đổi, không có `otp`)._

```json
{
  "code": 400,
  "message": "Check OTP fail: Lỗi gọi API: notify_check_sms_otp - Key: 'myRequest.OTP' Error:Field validation for 'OTP' failed on the 'required' tag",
  "data": null,
  "code_message": "OTP_NOT_VALID",
  "code_message_value": "Mã OTP đã hết hạn hoặc không đúng."
}
```

## Bảng mã lỗi

| code_message | HTTP | Khi nào |
| --- | --- | --- |
| `USER_ERR_COMMON` | 400 | Thiếu `order_code` hoặc dữ liệu không hợp lệ |
| `OTP_NOT_VALID` | 400 | Thay đổi `cod_amount` với `otp` thiếu/sai/hết hạn |
| `PERMISSION_DENIED_EDIT_COD` | 400 | Tài khoản nhân viên không có quyền "Sửa COD" cố thay đổi COD |
| `PHONE_INVALID` | 400 | SĐT người gửi/nhận/trả sai định dạng |
| `PICKUP_TIME_ERROR` | 400 | Thời gian lấy hàng yêu cầu nằm trong quá khứ |
| `CLIENT_NOT_OWNER_OF_SHOP` | 400 | Đơn không thuộc tài khoản của bạn |
| `SERVER_ERROR_COMMON` | 500 | Lỗi hệ thống |
