> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orriven.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Headless 购买流

> 在你自己的网站上卖票:后端下单、把买家送到 Stripe 支付页,再用 API 搭出买家的用户中心。

购买流端点让你完全自建的活动网站卖出与 Orriven 活动页完全相同的东西——票、加购、捆绑、兑换码,免费与付费——底层仍由平台完成它一直在做的事:容量占位、webhook 结算、履约成报名与权益。

<Warning>
  形态永远是**买家 → 你的前端 → 你的后端(持 API 密钥)→ Orriven**。密钥可读写整个业务单元,绝不能下发到浏览器——并且你的后端有责任只把**本人**的订单、报名、签到码返回给登录买家。买家账号体系(邮箱 OTP、会话)由你自建;Orriven 以邮箱识别买家。
</Warning>

## 完整流程

<Steps>
  <Step title="展示在售内容">
    用 `GET …/ticket-types`(票名、价格、售卖窗口、状态)、`…/availability`(实时剩余数字)、`…/addons`、`…/bundles`、`…/venues`、`…/sessions`(议程)、`…/speakers`(讲者)渲染你的活动页。买家输入兑换码时,先用 `GET …/redemption-codes/lookup?code=` 预览——解锁的票(隐藏票也在内)、附带的权益、折后价,在下单之前就能展示。购物车是你前端自己的状态——Orriven 在结算那一刻才第一次听说它。
  </Step>

  <Step title="下单">
    ```bash theme={null}
    curl -s -X POST "$BASE/v1/events/$EVENT/orders" \
      -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
      -d '{
        "email": "ada@example.com",
        "name": "Ada",
        "items": [
          { "itemType": "registration_type", "itemId": "…", "quantity": 1 },
          { "itemType": "addon",             "itemId": "…", "quantity": 2 }
        ],
        "redemptionCode": "VIP2026"
      }'
    ```

    `201` 返回待确认订单——它会**占位 15 分钟**。已在该活动报过名的买家得到 `200` 和 `alreadyRegistered: true`:被确认,绝不重复占位。票已满则 `412`。
  </Step>

  <Step title="确认——免费当场结清,付费拿 Stripe 支付页">
    ```bash theme={null}
    curl -s -X POST "$BASE/v1/events/$EVENT/orders/$ORDER_NUMBER/confirm" \
      -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
      -d '{
        "successUrl": "https://tickets.your-site.com/thanks?order='"$ORDER_NUMBER"'",
        "cancelUrl":  "https://tickets.your-site.com/checkout?order='"$ORDER_NUMBER"'"
      }'
    ```

    * **免费订单**(总额 0)当场结清:`{"status":"paid", "registration":{…}, "created":true}` ——完成,全程不碰 Stripe。
    * **付费订单**返回 `{"status":"awaiting_payment", "paymentUrl":"https://checkout.stripe.com/…"}`。把买家重定向过去;`successUrl`/`cancelUrl` 是 Stripe 把买家送回**你的**网站的地址(付费单必填,仅限 https——本地开发允许 [http://localhost)。](http://localhost\)。)
  </Step>

  <Step title="等待结算">
    付款经平台的 Stripe webhook 结算,而不是经你这次调用。买家回到你的 `successUrl` 后,轮询 `GET …/orders/{orderId}` 直到 `status` 变为 `paid` 且 `registrationId` 已填——那一刻,座位、权益、签到码都已存在。
  </Step>

  <Step title="搭建买家的用户中心">
    「我的票」页面需要的一切,你的后端都能按登录买家的邮箱过滤读取:

    * **报名**(`GET …/registrations`)——状态、票种、以及渲染成入场二维码的 **`checkinCode`**;
    * **权益**(`GET …/registrations/{id}/perks`)——票种 ∪ 兑换码 ∪ 个人授予的生效并集;
    * **签到记录**(`GET …/checkins?registrationId=`)——使用历史;
    * **订单**——购买历史。
  </Step>
</Steps>

## 会咬人的规则

* **一单一座。** 报名模型是一人一活动一报名,一张订单最多承载一个票座(超出 `412`)——替朋友买票 = 每人一单、各用各的邮箱。加购项数量不受此限。
* **订单号就是订单的凭证** ——在你的服务端像对待该买家的会话令牌一样保管它。
* **待确认订单占位 15 分钟**;付费单确认后占位拉长到 35 分钟。用 `POST …/orders/{orderNumber}/cancel` 提前释放;重复取消只被确认。
* **付费单确认必须带 `successUrl`/`cancelUrl`** ——缺了会在任何事发生之前收到 `400`。
* **业务单元未配置收款**(未完成 Stripe 入驻)时,付费下单返回 `412`;免费路径不受影响。
* **自动化与平台自己的结账完全同源** ——下单/过期/取消与报名类触发器行为一致。

## 相关页面

<CardGroup cols={2}>
  <Card title="端点参考" icon="book" href="/zh/developers/api-reference">
    place、confirm、cancel 的精确结构。
  </Card>

  <Card title="订单(控制台视角)" icon="receipt" href="/zh/ticketing/orders">
    同一批订单在主办方眼中的样子。
  </Card>
</CardGroup>
