---
title: "Create Order"
method: POST
path: "/auth/order"
---

# Create Order

`POST /auth/order`

## Request

- Base URL: `https://api.twtapi.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.twtapi.com/auth/order`
- Auth: none declared

创建订单（下单入口），只落 pending 单，不涉及任何实际收款。

已登录则关联 user_id，未登录（匿名）也能下单，此时 user_id 为空。
Price comes from the plans table.

价格与计费方式一律以后端 plans 表为准，前端传来的 plan_type/plan_name 只用来定位套餐，
杜绝篡改价格。

主流程：
  1. 按 plan_type + plan_name 查启用中的套餐，查不到即拒（40007）；
  2. 解析套餐 features（展示用快照）；
  3. 决定计费方式与成交价：订阅单且订阅价 > 0 用 subscription_price，否则用 price；
  4. 0 元单一律降级成一次性（不得成为订阅）；
  5. api 类型的免费套餐不允许下单（注册时已赠送，兼容旧前端）；
  6. 登录用户领 0 元试用：先过风控 deny_free_trial，再加行锁做重复领取检查；
  7. 登录用户买付费订阅：加行锁做重复下单检查；
  8. 落一张 pending 单，expires_at = 现在 + ORDER_PENDING_TIMEOUT_MINUTES。

返回：success(data={order_id, order_no, status})；各类重复/非法下单返回带 sub_code 的 error。
副作用：写库（orders、风控事件/画像）；锁行会占用数据库连接直到事务结束。

并发说明：查询与插入之间不是原子的，靠 _for_update 锁住 users 行把同一用户的
下单流程串行化；匿名（user_id 为空）路径拿不到任何锁，因此不享受这层保护。

## Query parameters

- `lang` string

## Request body

- CreateOrderRequest: 创建订单。 安全提示：price 由客户端提交，服务端必须与 Plan 表的值比对后 再落库，不能直接采信。
  - `plan_type` string, required
  - `plan_name` string, required
  - `price` number, required
  - `currency` string
  - `features` string[]
  - `payment_method` string, nullable
  - `billing_mode` string, nullable

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/twtapi/apis/twtapi-backend.md) · [All operations](https://skmtc.dev/twtapi/apis/twtapi-backend/llms.txt) · [OpenAPI document](https://skmtc.dev/twtapi/apis/twtapi-backend/revisions/5295976febaf?raw)
