# 权益平台 SDK v2 商户接入说明


## 价格体系与调价规则

中国道一卡通采用三层价格治理：

1. **上游成本价**：平台向权益供应商采购/结算的底价，仅平台内部可见。
2. **平台基准结算价**：平台给商户的默认结算价，必须大于等于上游成本价，是平台毛利底线。
3. **商户零售价**：商户展示给用户并向用户收款的价格，必须大于等于商户结算价。

### 安全底线

- 平台基准结算价 >= 上游成本价。
- 商户结算价 >= 平台基准结算价。
- 用户支付价/商户零售价 >= 商户结算价。
- 出现空价格、倒挂价格、过期报价时，平台将拒单或回退到安全建议价。

### 价格模式

| 模式 | 适用场景 | 下单要求 |
| --- | --- | --- |
| fixed 固定价 | 话费、会员、洗车、洁牙、标准权益券等 | 前端只展示，后端按授权价格重算 |
| quote 动态锁价 | 餐饮、商超、酒店、景区、电影、票务等 | 先生成 quoteId，再用 quoteId 下单 |
| h5 实时/H5价 | 打车、外跳H5、展码付、第三方收银等 | 按实时页面和订单快照核验 |

商户可在平台授权范围内调整零售价、建议价、最低价、最高价；低于结算价的零售价不允许保存。动态价产品不允许商户自行填写最终履约价，必须使用 quoteId 或平台实时价格快照。

## 定位

这是面向合作商户的权益商城 SDK。终端用户看到的是商户自己的平台名称、主题和收银台；SDK 只负责权益展示、锁价、创建待支付订单和跳转商户收银台。

## 用户路径

1. 用户进入商户页面
2. SDK 自动识别城市并加载可用权益
3. 用户选择权益并确认
4. 后端锁定价格，生成 quoteId
5. 创建待支付订单
6. 跳转商户收银台
7. 商户服务端支付成功后回调权益平台
8. 权益平台完成履约与订单状态同步

## 页面接入示例

```html
<div id="merchant-benefit-sdk"></div>
<link rel="stylesheet" href="/sdk/commercial-v2/commercial-v2.css">
<script src="/sdk/commercial-v2/commercial-v2-sdk.js"></script>
<script>
ChinaDaoCommercialV2.init({
  merchantId: '1',
  container: '#merchant-benefit-sdk',
  merchantName: '商户权益商城',
  apiBase: '/prod-api/openapi/v1',
  sandboxMode: true
});
</script>
```

## 关键配置

| 配置项 | 说明 |
|---|---|
| merchantId | 商户编号 |
| merchantName | 用户侧展示的商户平台名称 |
| container | SDK 挂载容器 |
| apiBase | API 网关地址 |
| sandboxMode | 沙箱模式，仅用于联调；正式商用应关闭 |
| cashierUrl | 商户收银台跳转地址，由平台后台配置；订单创建后返回的实际 URL 仅包含短期 token，不暴露订单号/金额/签名 |
| notifyUrl | 商户服务端支付成功回调地址，由后台配置 |
| domainWhitelist | 商户页面域名白名单 |

## 订单与支付边界

- SDK 不直接收款。
- SDK 不信任前端金额。
- 创建订单前必须先走后端锁价 quote。
- 支付页面必须由商户自己的收银台承接。
- 支付成功必须由商户服务端回调，不能由浏览器前端直接确认。

## cashierUrl、token 查询与支付确认安全说明

订单创建成功后，平台返回的 `cashierUrl` 是短期 token 化跳转地址，例如：

```text
/sdk/commercial-v2/merchant-cashier.html?token=cst_xxx
```

浏览器 URL 只包含 `token=cst_xxx`，不暴露 `merchantId/orderNo/quoteId/amount/timestamp/nonce/sign`。

### 收银台 token 查询接口

商户收银台或平台收银台页面展示订单信息时，使用 token 查询：

```http
GET /prod-api/openapi/v1/sdk/cashier-token?token=cst_xxx
```

用途：仅用于收银台展示待支付订单和当前状态，不代表支付成功，不用于服务端履约确认。

鉴权：不需要 AppSecret/HMAC；token 是一次性短期令牌，格式 `cst_...`，有效期约 10 分钟。过期后需要重新创建订单或重新发起支付流程。

返回示例：

```json
{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "merchantId": 11,
    "orderNo": "SDK202605201812405703",
    "quoteId": "quote_xxx",
    "amount": "43.20",
    "status": "WAIT_PAY",
    "testMode": true,
    "expiresIn": 600
  }
}
```

错误示例：

```json
{"code":500,"msg":"收银台令牌已过期，请重新下单","data":null}
```

### 支付确认边界

支付成功仍必须由商户服务端调用 `/prod-api/openapi/v1/sdk/payment/notify` 或兼容接口 `/prod-api/openapi/v1/sdk/order-pay-notify`，携带 `merchantId/orderNo/quoteId/amount/timestamp/nonce/sign` 完成服务端验签确认。浏览器前端不能直接确认支付成功。

## 服务端调用来源头（必填）

商户服务器端调用 `/prod-api/openapi/v1/sdk/*` 接口时，除 `timestamp/nonce/sign` 等签名参数外，还必须携带已在商户 SDK 白名单授权的来源头。浏览器会自动带 `Origin/Referer`，服务端请求不会自动带，若缺失会返回：

```json
{"code":403,"msg":"无法验证请求来源，请通过授权域名发起请求","data":null}
```

请求头示例：

```http
Origin: https://商户授权域名
Referer: https://商户授权域名/

# 示例：商户 11 从 115.29.237.207 服务端调用
Origin: http://115.29.237.207
Referer: http://115.29.237.207/
```

正式接口地址统一使用：`https://lukeydao.com/prod-api/openapi/v1/`。不要使用服务器 IP 直连，也不要省略 `/prod-api` 前缀。

商户接入要求：

1. 商户前端直接跳转 `cashierUrl`。
2. 不要从 URL 中解析订单号、金额、签名；这些敏感字段不会再出现在浏览器地址栏。
3. 不要自行拼接 `merchantId/orderNo/quoteId/amount/timestamp/nonce/sign` 到收银台 URL。
4. token 只用于收银台读取展示信息，默认短期有效；过期后应重新创建订单或重新发起支付流程。
5. 正式支付成功后，仍必须由商户服务端调用 `/prod-api/openapi/v1/sdk/payment/notify` 或 `/prod-api/openapi/v1/sdk/order-pay-notify`，携带 `merchantId/orderNo/quoteId/amount/timestamp/nonce/sign` 做服务端验签确认。

这样可以避免订单号、金额和签名出现在浏览器历史、日志、Referer 或第三方监控中。

## 商用验收标准

- 用户侧不出现平台方内部品牌、内部接口、调试信息。
- 商户已配置品牌名、域名白名单、收银台地址、支付回调地址。
- 订单创建返回后端生成的 cashierUrl。
- cashierUrl 只包含短期 `token=cst_xxx`，不在 URL 暴露 `timestamp/nonce/sign`、订单号或金额。
- 支付成功回调具备验签、防重放、幂等处理。
- 正式模式关闭 sandboxMode。
- 试点品类已完成真实履约和售后补偿验证。

## 产品开放清单与准入规则

SDK 用户端只开放经过正式接口准入的权益。产品状态以 `product-admission.json` 为准，展示口径如下：

| 状态 | 用户端表现 | 开放条件 |
|---|---|---|
| 可购买 | 进入正式购买/预约/领取流程 | 已验证后端 query/quote/order-create 链路，金额以后端锁价快照为准 |
| 可查资源，暂不开放支付 | 可查看接入说明或资源状态，不进入支付 | 已有正式接口字段或资源查询，但上游授权、价格日历、订单履约或回调未完成 |
| 即将开放 | 仅展示能力规划，不进入购买弹窗 | 产品规划中，未进入正式联调 |
| 暂不可接入 | 展示不可接入原因，不提供临时跳转 | 缺少正式开放文档、签名/回调说明或属于非用户购买型能力 |

### 当前可购买产品

点餐外卖+到店、微信立减金、话费充值、移动充值、话费小额充值、影音会员、虚拟会员(无票版)、洗车、干洗、家政、洁牙、跑腿、途虎养车、快递、问诊、京东家政、蛋糕外卖、蛋糕、鲜花、大润发、叮咚买菜、京东、永辉超市、盒马、山姆会员商店、自营商超、自营商城2期、1688采购批发、天猫API、怡亚通、短剧、药品、积分焕彩、支付宝红包、景区门票、电影、酒店、银联支付、国际机票、团油加油。

### 当前可查/联调但暂不开放支付的产品

点餐、打车、打车V2、饿了么H5、图书、点餐(无票)、电影(无票)、电影V3、演出、丽呈酒店、锦江酒店、国际酒店、飞机票、InternationalAirTicket、火车票、TrainTicket、火车票标准版、汽车票、贵宾厅、柴油加油、永辉彩食鲜、ChargingStationOfficial、油站(中石油中石化)、油站V2、加油站、充电站、充电桩V2、充电桩API版、团油充电。

这些产品不得进入真实支付，原因包括上游未授权、沙箱可联调、选座/出票/履约链路待验收、价格日历或订单回调未完成。

### 即将开放产品

水电燃气、LifePayment、ShopMall、DiscountMall、MedicalCare。

### 暂不可接入产品

海底捞、美团外卖H5、美团团购H5、沃尔玛展码付、三方支付、实名、锅圈展码付、饿了么(开票版)、山姆展码付、中石化中石油展码付、夏商展码付、支付宝企业码、核销、大润发到店、小象超市H5。

这些产品缺少正式开放文档或不属于用户购买型权益，用户端不使用非正式地址、临时参数或前端伪跳转。

