# Order Sync API (Server -> Central)

## Authentication

Each server must be registered in `bot_servers` with:

- `server_id`
- `api_token`
- `instance_id` (bot instance id, used to link voucher check requests to the correct server)
- `status = active`

The API validates both values.

You can send credentials using either:
- query params: `server_id` + `token`
- headers: `X-Server-ID` + `X-Server-Token`
- bearer token: `Authorization: Bearer <token>` (with `server_id` still provided)

## Fetch new orders

`GET /wt_webhook/index.php?api=orders&server_id=SERVER_ID&token=API_TOKEN&limit=50`

Response:

```json
{
  "status": "success",
  "server_id": "server-1",
  "match_mode": "target_server_id",
  "orders": [
    {
      "order_no": "ORD-20260303-ABC123",
      "created_at": "2026-03-03 10:00:00",
      "payload": {
        "chat_id": "9705xxxxxxx"
      }
    }
  ]
}
```

## Mark orders as synced

`POST /wt_webhook/index.php?api=orders&server_id=SERVER_ID&token=API_TOKEN`

Body:

```json
{
  "order_nos": ["ORD-20260303-ABC123"]
}
```

Response:

```json
{
  "status": "success",
  "updated": 1
}
```

If credentials fail, the API now returns a `reason` field (e.g. `server_id_not_found`, `token_mismatch`, `server_inactive`) to simplify troubleshooting.

## Order flow

1. Bot stores each new order in MySQL table `bot_server_orders`.
2. Target server fetches its rows by `server_id`.
3. Target server saves locally then acknowledges with `order_nos`.


`match_mode` values:
- `target_server_id`: standard path (orders assigned to this server).
- `source_server_id_fallback`: fallback path when rows were inserted with a different target id but same source server id.

## Order desicon callback (Backend -> Bot)

`POST /wt_webhook/index.php?api=order_desicon_callback`

Headers:
- `Content-Type: application/json`

### Request body

Minimum fields:

```json
{
  "order_no": "ORD-20260303-ABC123",
  "customer_name": "John",
  "desicon": "accept"
}
```

Accept with vouchers + password for each voucher:

```json
{
  "order_no": "ORD-20260303-ABC123",
  "customer_name": "John",
  "desicon": "accept",
  "vouchers": [
    {
      "code": "VC-111",
      "password": "P@ss-111"
    },
    {
      "code": "VC-222",
      "password": "P@ss-222"
    }
  ]
}
```

Reject example:

```json
{
  "order_no": "ORD-20260303-ABC123",
  "customer_name": "John",
  "desicon": "reject",
  "reject_reason": "البيانات غير مكتملة"
}
```

### Vouchers format support

`vouchers` accepts multiple formats for backward compatibility:

1. Array of strings:

```json
"vouchers": ["VC-111", "VC-222"]
```

2. Array of objects (recommended):

```json
"vouchers": [
  { "code": "VC-111", "password": "P@ss-111" },
  { "code": "VC-222", "password": "P@ss-222" }
]
```

Supported voucher object keys:
- code: `code`, `voucher`, `name`, `value`
- password: `password`, `voucher_password`, `pass`

Stored in `bot_order_desicon.vouchers_json` as:

```json
[
  { "code": "VC-111", "password": "P@ss-111" },
  { "code": "VC-222", "password": "P@ss-222" }
]
```

Validation rules:

1. `order_no`, `customer_name`, `desicon` are required.
2. `desicon` must be `accept` or `reject`.
3. if `desicon` is `reject`, `reject_reason` is required.
4. order must exist in `bot_orders` (fallback to `bot_server_orders` for legacy rows).
5. order `sync_status` must be `synced`.

Behavior:

- Records the callback in table `bot_order_desicon`.
- Sends WhatsApp reply to the same chat as the original order.
- `reject`: Arabic multiline message (name + emoji, reject text, reject reason, and `0️⃣` return line).
- `accept`: Arabic multiline greeting + order number + accept line + vouchers pointer (`👇`) + each voucher in separate message (includes voucher password when provided) + closing wish + `0️⃣` return line.

### Response example

```json
{
  "status": "success",
  "order_no": "ORD-20260303-ABC123",
  "desicon": "accept",
  "chat_id": "9705xxxxxxx",
  "messages_sent": 5
}
```

## Voucher check callback (Backend -> Bot)

`POST /wt_webhook/index.php?api=voucher_check_callback`

Headers:
- `Content-Type: application/json`

The bot stores each check request in table `bot_voucher_check_requests` when the user submits:
1) card number, then
2) card password.

### Request body

Minimum:

```json
{
  "request_no": "VCR-20260307-ABC123",
  "status": "completed"
}
```

Full example:

```json
{
  "request_no": "VCR-20260307-ABC123",
  "status": "completed",
  "card_number": "1234567890",
  "card_password": "9988",
  "message": "البطاقة فعّالة حتى 2026-12-31",
  "voucher": {
    "state": "active",
    "expires_at": "2026-12-31"
  }
}
```

Validation rules:

1. `request_no` is required and must exist in `bot_voucher_check_requests`.
2. `status` must be one of: `pending`, `submitted`, `completed`, `failed`.

Behavior:

- Updates `bot_voucher_check_requests` row (`request_status`, `result_json`, `api_result_json`).
- Keeps linkage fields from request row: `source_server_id` + `bot_instance_id`.
- Sends WhatsApp reply back to the same user chat with:
  - request number
  - card number
  - password (if present)
  - final status and message

### Response example

```json
{
  "status": "success",
  "request_no": "VCR-20260307-ABC123",
  "chat_id": "9705xxxxxxx",
  "request_status": "completed"
}
```
