feat: 设备查询支持按source筛选,区分自营/第三方设备
- DeviceServiceImpl.queryPage 增加 source 筛选条件 - 自营设备 source=DIRECT(激活码激活,DB默认值) - 第三方设备 source=PARTNER(OpenAPI注册,显式设置)
This commit is contained in:
@@ -27,6 +27,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceDao, DeviceEntity> impl
|
|||||||
String status = (String) params.get("status");
|
String status = (String) params.get("status");
|
||||||
String deviceName = (String) params.get("deviceName");
|
String deviceName = (String) params.get("deviceName");
|
||||||
String mac = (String) params.get("mac");
|
String mac = (String) params.get("mac");
|
||||||
|
String source = (String) params.get("source");
|
||||||
|
|
||||||
IPage<DeviceEntity> page = this.page(
|
IPage<DeviceEntity> page = this.page(
|
||||||
new Query<DeviceEntity>().getPage(params, "created_at", false),
|
new Query<DeviceEntity>().getPage(params, "created_at", false),
|
||||||
@@ -35,6 +36,7 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceDao, DeviceEntity> impl
|
|||||||
.eq(StringUtils.isNotBlank(status), "status", status)
|
.eq(StringUtils.isNotBlank(status), "status", status)
|
||||||
.like(StringUtils.isNotBlank(deviceName), "device_name", deviceName)
|
.like(StringUtils.isNotBlank(deviceName), "device_name", deviceName)
|
||||||
.like(StringUtils.isNotBlank(mac), "mac", mac)
|
.like(StringUtils.isNotBlank(mac), "mac", mac)
|
||||||
|
.eq(StringUtils.isNotBlank(source), "source", source)
|
||||||
.eq("delete_flag", "UNDEL")
|
.eq("delete_flag", "UNDEL")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
705
橘视厅酒店版openapi文档.html
Normal file
705
橘视厅酒店版openapi文档.html
Normal file
@@ -0,0 +1,705 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: #333;
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
border-bottom: 2px solid #333;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 20px;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
margin: 15px 0;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px 12px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 12px;
|
||||||
|
overflow-x: auto;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
font-family: "SF Mono", "Menlo", "Consolas", monospace;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
padding: 2px 4px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
pre code {
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
strong {
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
border-left: 4px solid #4A90D9;
|
||||||
|
margin: 15px 0;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>天卡开放平台 第三方对接文档</h1>
|
||||||
|
<p><strong>版本</strong>: V2.0<br />
|
||||||
|
<strong>更新日期</strong>: 2026-07-23</p>
|
||||||
|
<hr />
|
||||||
|
<h2>1. 概述</h2>
|
||||||
|
<p>本文档面向第三方合作伙伴后端开发人员,描述天卡开放平台的接口规范。</p>
|
||||||
|
<h3>1.1 业务流程</h3>
|
||||||
|
<pre><code>第三方EPG 开放平台 APK
|
||||||
|
| | |
|
||||||
|
| 1. 用户在EPG界面完成支付 | |
|
||||||
|
| | |
|
||||||
|
| 2. 调用消耗接口(发卡) | |
|
||||||
|
|---POST /card/consume------->| |
|
||||||
|
|<---deviceId, expireAt-------| |
|
||||||
|
| status=ACTIVATING | |
|
||||||
|
| | 3. 异步激活(橘视厅SDK) |
|
||||||
|
| | |
|
||||||
|
| 4. EPG传参启动APK | |
|
||||||
|
|---设备标识(mac/sn等)-------> | |
|
||||||
|
| | 5. APK调init获取sign |
|
||||||
|
| |<---POST /api/jst/init-------|
|
||||||
|
| |----sign------------------->|
|
||||||
|
| | 6. APK轮询checkBenefits |
|
||||||
|
| |<---POST /checkBenefits------|
|
||||||
|
| |----thirdCardNo------------>|
|
||||||
|
| | (status=ACTIVE时返回) |
|
||||||
|
| | 7. APK用thirdCardNo播放 |
|
||||||
|
</code></pre>
|
||||||
|
<h3>1.2 服务器地址</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>环境</th>
|
||||||
|
<th>地址</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>生产环境</td>
|
||||||
|
<td>http://58.220.83.58:8084</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<hr />
|
||||||
|
<h2>2. 鉴权方式</h2>
|
||||||
|
<h3>2.1 凭证</h3>
|
||||||
|
<p>平台分配的 <code>appKey</code> 和 <code>appSecret</code>,由管理后台创建合作伙伴时自动生成。</p>
|
||||||
|
<h3>2.2 签名算法</h3>
|
||||||
|
<pre><code>sign = MD5(appKey + timestamp + nonce + appSecret).toUpperCase()
|
||||||
|
</code></pre>
|
||||||
|
<ul>
|
||||||
|
<li>拼接顺序固定:appKey + timestamp + nonce + appSecret,无分隔符</li>
|
||||||
|
<li>MD5 结果转大写</li>
|
||||||
|
</ul>
|
||||||
|
<h3>2.3 请求头</h3>
|
||||||
|
<p>每个请求必须携带以下 HTTP 请求头:</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>请求头</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>appKey</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>平台分配的应用 Key</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>timestamp</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>毫秒级时间戳,有效期 5 分钟</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>nonce</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>随机字符串,5 分钟内不可重复</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>sign</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>签名(大写 MD5)</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h3>2.4 鉴权失败响应</h3>
|
||||||
|
<p>HTTP 401:</p>
|
||||||
|
<pre><code class="language-json">{"code": 401, "msg": "签名校验失败"}
|
||||||
|
</code></pre>
|
||||||
|
<h3>2.5 统一响应格式</h3>
|
||||||
|
<pre><code class="language-json">{"code": 0, "msg": "success", "data": {}}
|
||||||
|
</code></pre>
|
||||||
|
<ul>
|
||||||
|
<li><code>code = 0</code> 表示成功,非 0 表示失败</li>
|
||||||
|
<li>业务数据在 <code>data</code> 字段内</li>
|
||||||
|
</ul>
|
||||||
|
<hr />
|
||||||
|
<h2>3. 天卡代销接口</h2>
|
||||||
|
<h3>3.1 消耗天卡</h3>
|
||||||
|
<p>用户在 EPG 完成支付后调用,从合作伙伴天卡池分配 1 张天卡绑定到设备,并异步激活。</p>
|
||||||
|
<pre><code>POST /openapi/partner/card/consume
|
||||||
|
Content-Type: application/json
|
||||||
|
</code></pre>
|
||||||
|
<p><strong>请求体</strong>:</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>参数</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>必填</th>
|
||||||
|
<th>说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>mac</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>否*</td>
|
||||||
|
<td>设备 MAC 地址</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>wifiMac</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>否*</td>
|
||||||
|
<td>WiFi MAC 地址</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>deviceUid</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>是*</td>
|
||||||
|
<td>设备唯一标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>deviceSn</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>否*</td>
|
||||||
|
<td>设备序列号</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>channelOrgId</td>
|
||||||
|
<td>Long</td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>渠道组织 ID</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>* mac / wifiMac / deviceUid / deviceSn
|
||||||
|
deviceUid必须传,mac / wifimac /deviceSn
|
||||||
|
至少传一个,需与 APK 启动时传入的设备标识一致。</p>
|
||||||
|
<p><strong>请求示例</strong>:</p>
|
||||||
|
<pre><code class="language-json">{
|
||||||
|
"mac": "AA:BB:CC:DD:EE:01",
|
||||||
|
"deviceSn": "SN-001",
|
||||||
|
"deviceUid": "UID-001"
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p><strong>响应</strong>:</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>字段</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>deviceId</td>
|
||||||
|
<td>Long</td>
|
||||||
|
<td>设备 ID</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>expireAt</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>天卡过期时间(yyyy-MM-dd HH:mm:ss),初始为 24 小时,异步激活成功后更新为真实过期时间</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>status</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>天卡状态:ACTIVATING(激活中)</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p><strong>响应示例</strong>:</p>
|
||||||
|
<pre><code class="language-json">{
|
||||||
|
"code": 0,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"deviceId": 123,
|
||||||
|
"expireAt": "2026-07-24 14:00:00",
|
||||||
|
"status": "ACTIVATING"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p><strong>幂等说明</strong>:同一设备重复调用时不会消耗新天卡,直接返回已有天卡信息。若天卡已激活成功,status 返回 <code>ACTIVE</code>。</p>
|
||||||
|
<p><strong>错误响应</strong>:</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>code</th>
|
||||||
|
<th>msg</th>
|
||||||
|
<th>说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>400</td>
|
||||||
|
<td>mac/wifiMac/deviceUid/deviceSn 至少传一个</td>
|
||||||
|
<td>缺少设备标识</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>400</td>
|
||||||
|
<td>天卡池库存不足</td>
|
||||||
|
<td>可用天卡已耗尽</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>400</td>
|
||||||
|
<td>操作太频繁,请稍后再试</td>
|
||||||
|
<td>同一设备短时间内重复请求</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>500</td>
|
||||||
|
<td>天卡分配失败,请重试</td>
|
||||||
|
<td>系统繁忙,请重试</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h3>3.2 查询天卡库存</h3>
|
||||||
|
<pre><code>GET /openapi/partner/card/stock
|
||||||
|
</code></pre>
|
||||||
|
<p><strong>响应示例</strong>:</p>
|
||||||
|
<pre><code class="language-json">{
|
||||||
|
"code": 0,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"available": 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<hr />
|
||||||
|
<h2>4. 媒资接口</h2>
|
||||||
|
<h3>4.1 查看授权范围</h3>
|
||||||
|
<pre><code>GET /openapi/partner/media/package
|
||||||
|
</code></pre>
|
||||||
|
<p><strong>响应</strong>:</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>字段</th>
|
||||||
|
<th>说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>scope</td>
|
||||||
|
<td>授权级别:CONTENT(指定内容)/ CATALOG(指定栏目)/ FULL(全量)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>catalogIds</td>
|
||||||
|
<td>授权栏目 ID(逗号分隔,CATALOG 级别有值)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>contentCount</td>
|
||||||
|
<td>授权内容数量</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h3>4.2 栏目树</h3>
|
||||||
|
<pre><code>GET /openapi/partner/media/catalog-tree
|
||||||
|
</code></pre>
|
||||||
|
<p>按授权范围过滤返回:
|
||||||
|
- CONTENT 级别返回空树
|
||||||
|
- CATALOG 级别只返回授权栏目
|
||||||
|
- FULL 级别返回完整栏目树</p>
|
||||||
|
<h3>4.3 内容列表</h3>
|
||||||
|
<pre><code>GET /openapi/partner/media/list?catalogid=472&pageindex=1&pagesize=20
|
||||||
|
</code></pre>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>参数</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>必填</th>
|
||||||
|
<th>说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>catalogid</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>FULL/CATALOG 级别必填</td>
|
||||||
|
<td>栏目 ID</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>pageindex</td>
|
||||||
|
<td>int</td>
|
||||||
|
<td>否(默认 1)</td>
|
||||||
|
<td>页码</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>pagesize</td>
|
||||||
|
<td>int</td>
|
||||||
|
<td>否(默认 20)</td>
|
||||||
|
<td>每页条数</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<ul>
|
||||||
|
<li>CONTENT 级别:返回授权内容列表,不需传 catalogid</li>
|
||||||
|
<li>CATALOG 级别:必须传授权范围内的 catalogid</li>
|
||||||
|
<li>FULL 级别:必须传 catalogid</li>
|
||||||
|
</ul>
|
||||||
|
<h3>4.4 搜索</h3>
|
||||||
|
<pre><code>GET /openapi/partner/media/search?keyword=镖人&pageindex=1&pagesize=20
|
||||||
|
</code></pre>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>参数</th>
|
||||||
|
<th>类型</th>
|
||||||
|
<th>必填</th>
|
||||||
|
<th>说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>keyword</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>搜索关键词</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>pageindex</td>
|
||||||
|
<td>int</td>
|
||||||
|
<td>否(默认 1)</td>
|
||||||
|
<td>页码</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>pagesize</td>
|
||||||
|
<td>int</td>
|
||||||
|
<td>否(默认 20)</td>
|
||||||
|
<td>每页条数</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h3>4.5 内容字段说明</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>字段</th>
|
||||||
|
<th>说明</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>contentcode</td>
|
||||||
|
<td>内容唯一编码</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>name</td>
|
||||||
|
<td>内容名称</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>posterimg</td>
|
||||||
|
<td>海报图片 URL</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>categoryname</td>
|
||||||
|
<td>分类名称</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>score</td>
|
||||||
|
<td>评分</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>isFree</td>
|
||||||
|
<td>1 = 免费,0 = 付费</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>episodecount</td>
|
||||||
|
<td>集数</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>duration</td>
|
||||||
|
<td>时长(秒)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>releaseyear</td>
|
||||||
|
<td>上映年份</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>originalcountry</td>
|
||||||
|
<td>地区</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<hr />
|
||||||
|
<h2>5. APK 侧流程说明</h2>
|
||||||
|
<p>以下接口由 APK 调用,第三方无需直接调用,但需了解流程以便 EPG 传参启动 APK。</p>
|
||||||
|
<h3>5.1 设备初始化</h3>
|
||||||
|
<p>APK 使用消耗接口传入的相同设备标识调用初始化:</p>
|
||||||
|
<pre><code>POST /api/jst/init
|
||||||
|
Content-Type: application/json
|
||||||
|
</code></pre>
|
||||||
|
<p>请求体(不传 activationCode,代销模式):</p>
|
||||||
|
<pre><code class="language-json">{
|
||||||
|
"mac": "AA:BB:CC:DD:EE:01",
|
||||||
|
"wifiMac": "...",
|
||||||
|
"deviceSn": "SN-001",
|
||||||
|
"deviceUid": "UID-001"
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<p>返回 <code>sign</code>(设备鉴权凭证,24 小时有效)。</p>
|
||||||
|
<h3>5.2 查询天卡权益</h3>
|
||||||
|
<p>APK 轮询查询激活状态,仅当 status 为 ACTIVE 时获取播放凭证:</p>
|
||||||
|
<pre><code>POST /api/jst/checkBenefits
|
||||||
|
Header: sign: <init 返回的 sign>
|
||||||
|
</code></pre>
|
||||||
|
<p><strong>响应</strong>:</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>status</th>
|
||||||
|
<th>说明</th>
|
||||||
|
<th>是否返回 thirdCardNo</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>ACTIVATING</td>
|
||||||
|
<td>异步激活中,需继续轮询</td>
|
||||||
|
<td>否</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ACTIVE</td>
|
||||||
|
<td>激活成功,可播放</td>
|
||||||
|
<td>是</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ACTIVATION_FAILED</td>
|
||||||
|
<td>激活失败</td>
|
||||||
|
<td>否</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>UNBOUND</td>
|
||||||
|
<td>无天卡绑定</td>
|
||||||
|
<td>否</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p><strong>轮询建议</strong>:间隔 2 秒,超时 5 分钟。</p>
|
||||||
|
<h3>5.3 播放</h3>
|
||||||
|
<p>APK 使用 <code>thirdCardNo</code> 作为播放凭证初始化橘视厅 SDK,获取播放地址后播放。</p>
|
||||||
|
<hr />
|
||||||
|
<h2>6. 签名示例</h2>
|
||||||
|
<h3>Java</h3>
|
||||||
|
<pre><code class="language-java">String appKey = "平台分配的appKey";
|
||||||
|
String appSecret = "平台分配的appSecret";
|
||||||
|
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||||
|
String nonce = UUID.randomUUID().toString().replace("-", "");
|
||||||
|
String sign = DigestUtils.md5Hex(appKey + timestamp + nonce + appSecret).toUpperCase();
|
||||||
|
</code></pre>
|
||||||
|
<h3>Python</h3>
|
||||||
|
<pre><code class="language-python">import hashlib, time, uuid
|
||||||
|
|
||||||
|
timestamp = str(int(time.time() * 1000))
|
||||||
|
nonce = uuid.uuid4().hex
|
||||||
|
sign = hashlib.md5((app_key + timestamp + nonce + app_secret).encode()).hexdigest().upper()
|
||||||
|
</code></pre>
|
||||||
|
<h3>Node.js</h3>
|
||||||
|
<pre><code class="language-javascript">const crypto = require('crypto');
|
||||||
|
const timestamp = Date.now().toString();
|
||||||
|
const nonce = crypto.randomBytes(16).toString('hex');
|
||||||
|
const sign = crypto.createHash('md5')
|
||||||
|
.update(appKey + timestamp + nonce + appSecret)
|
||||||
|
.digest('hex').toUpperCase();
|
||||||
|
</code></pre>
|
||||||
|
<hr />
|
||||||
|
<h2>7. 请求示例(curl)</h2>
|
||||||
|
<p>以下示例中的 <code>appKey</code>、<code>appSecret</code> 需替换为平台分配的实际值。<code>timestamp</code>、<code>nonce</code>、<code>sign</code> 需按签名算法实时生成。</p>
|
||||||
|
<h3>7.1 消耗天卡</h3>
|
||||||
|
<pre><code class="language-bash">curl -X POST "http://58.220.83.58:8084/openapi/partner/card/consume" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "appKey: 你的appKey" \
|
||||||
|
-H "timestamp: 1784809605695" \
|
||||||
|
-H "nonce: 1784809605695aaf094ef" \
|
||||||
|
-H "sign: A6EBB96858ED2FAD864CB39568E3EABB" \
|
||||||
|
-d '{"mac":"AA:BB:CC:DD:EE:01","deviceSn":"SN-001","deviceUid":"UID-001"}'
|
||||||
|
</code></pre>
|
||||||
|
<p>响应:</p>
|
||||||
|
<pre><code class="language-json">{
|
||||||
|
"code": 0,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"deviceId": 123,
|
||||||
|
"expireAt": "2026-07-24 20:26:46",
|
||||||
|
"status": "ACTIVATING"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
<h3>7.2 查询天卡库存</h3>
|
||||||
|
<pre><code class="language-bash">curl -X GET "http://58.220.83.58:8084/openapi/partner/card/stock" \
|
||||||
|
-H "appKey: 你的appKey" \
|
||||||
|
-H "timestamp: 1784809605695" \
|
||||||
|
-H "nonce: 1784809605695aaf094ef" \
|
||||||
|
-H "sign: A6EBB96858ED2FAD864CB39568E3EABB"
|
||||||
|
</code></pre>
|
||||||
|
<h3>7.3 查看授权范围</h3>
|
||||||
|
<pre><code class="language-bash">curl -X GET "http://58.220.83.58:8084/openapi/partner/media/package" \
|
||||||
|
-H "appKey: 你的appKey" \
|
||||||
|
-H "timestamp: 1784809605695" \
|
||||||
|
-H "nonce: 1784809605695aaf094ef" \
|
||||||
|
-H "sign: A6EBB96858ED2FAD864CB39568E3EABB"
|
||||||
|
</code></pre>
|
||||||
|
<h3>7.4 栏目树</h3>
|
||||||
|
<pre><code class="language-bash">curl -X GET "http://58.220.83.58:8084/openapi/partner/media/catalog-tree" \
|
||||||
|
-H "appKey: 你的appKey" \
|
||||||
|
-H "timestamp: 1784809605695" \
|
||||||
|
-H "nonce: 1784809605695aaf094ef" \
|
||||||
|
-H "sign: A6EBB96858ED2FAD864CB39568E3EABB"
|
||||||
|
</code></pre>
|
||||||
|
<h3>7.5 内容列表</h3>
|
||||||
|
<pre><code class="language-bash">curl -X GET "http://58.220.83.58:8084/openapi/partner/media/list?catalogid=472&pageindex=1&pagesize=20" \
|
||||||
|
-H "appKey: 你的appKey" \
|
||||||
|
-H "timestamp: 1784809605695" \
|
||||||
|
-H "nonce: 1784809605695aaf094ef" \
|
||||||
|
-H "sign: A6EBB96858ED2FAD864CB39568E3EABB"
|
||||||
|
</code></pre>
|
||||||
|
<h3>7.6 搜索</h3>
|
||||||
|
<pre><code class="language-bash">curl -X GET "http://58.220.83.58:8084/openapi/partner/media/search?keyword=镖人&pageindex=1&pagesize=20" \
|
||||||
|
-H "appKey: 你的appKey" \
|
||||||
|
-H "timestamp: 1784809605695" \
|
||||||
|
-H "nonce: 1784809605695aaf094ef" \
|
||||||
|
-H "sign: A6EBB96858ED2FAD864CB39568E3EABB"
|
||||||
|
</code></pre>
|
||||||
|
<h3>7.7 签名生成示例(bash)</h3>
|
||||||
|
<pre><code class="language-bash">APP_KEY="你的appKey"
|
||||||
|
APP_SECRET="你的appSecret"
|
||||||
|
TIMESTAMP=$(date +%s%3N)
|
||||||
|
NONCE="${TIMESTAMP}$(head -c 8 /dev/urandom | xxd -p)"
|
||||||
|
SIGN=$(echo -n "${APP_KEY}${TIMESTAMP}${NONCE}${APP_SECRET}" | md5sum | awk '{print toupper($0)}')
|
||||||
|
|
||||||
|
echo "appKey: $APP_KEY"
|
||||||
|
echo "timestamp: $TIMESTAMP"
|
||||||
|
echo "nonce: $NONCE"
|
||||||
|
echo "sign: $SIGN"
|
||||||
|
|
||||||
|
# 直接用变量发请求
|
||||||
|
curl -X POST "http://58.220.83.58:8084/openapi/partner/card/consume" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "appKey: $APP_KEY" \
|
||||||
|
-H "timestamp: $TIMESTAMP" \
|
||||||
|
-H "nonce: $NONCE" \
|
||||||
|
-H "sign: $SIGN" \
|
||||||
|
-d '{"mac":"AA:BB:CC:DD:EE:01","deviceSn":"SN-001"}'
|
||||||
|
</code></pre>
|
||||||
|
<hr />
|
||||||
|
<h2>8. 注意事项</h2>
|
||||||
|
<ol>
|
||||||
|
<li><strong>nonce 唯一性</strong>:每个请求的 nonce 必须唯一,5 分钟内重复提交会被拒绝。</li>
|
||||||
|
<li><strong>timestamp 有效期</strong>:与服务器时间差超过 5 分钟会过期。</li>
|
||||||
|
<li><strong>设备标识一致性</strong>:消耗接口传入的设备标识必须与 APK 启动时传入的一致,否则 APK 无法找到设备。</li>
|
||||||
|
<li><strong>异步激活</strong>:消耗接口返回后天卡异步激活(通常 2-5 秒),APK 需轮询 checkBenefits 确认激活完成。</li>
|
||||||
|
<li><strong>库存管理</strong>:消耗接口返回库存不足错误时,需联系平台采购天卡。</li>
|
||||||
|
</ol>
|
||||||
|
<hr />
|
||||||
|
<h2>附录:设备标识说明</h2>
|
||||||
|
<h3>deviceUid 生成规则</h3>
|
||||||
|
<p>APK 的 <code>deviceUid</code> 按以下优先级生成:</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>优先级</th>
|
||||||
|
<th>来源</th>
|
||||||
|
<th>格式</th>
|
||||||
|
<th>重装不变</th>
|
||||||
|
<th>工厂重置不变</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>1</td>
|
||||||
|
<td>Android ID(Settings.Secure.ANDROID_ID)</td>
|
||||||
|
<td>64 位 hex(16 字符),如 <code>f0f179fe199f7a52</code></td>
|
||||||
|
<td>是</td>
|
||||||
|
<td>否</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>2</td>
|
||||||
|
<td>UUID(兜底,存 SharedPreferences)</td>
|
||||||
|
<td>32 位无横线,如 <code>a1b2c3d4e5f6...</code></td>
|
||||||
|
<td>否</td>
|
||||||
|
<td>否</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>Android ID 为空时使用 UUID 兜底。正常情况下 deviceUid 即 Android ID。</p>
|
||||||
|
<h3>关键注意点</h3>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<p><strong>consume 与 init 的 deviceUid 必须一致</strong>:第三方调用消耗接口时传入的 <code>deviceUid</code> 必须与 APK 调用 init 时传入的 <code>deviceUid</code> 相同,否则 APK 无法找到设备。</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><strong>Android ID 按签名隔离</strong>:Android 8+ 系统中,不同签名的 App 在同一设备上获取的 Android ID 不同。因此 EPG 获取 deviceUid 的方式需与 APK 一致,建议由 APK 提供给 EPG,而非 EPG 自行获取。</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><strong>推荐传参方式</strong>:EPG 启动 APK 时通过 Intent 传递设备标识,APK 使用相同标识调 init 接口。设备标识建议优先使用 <code>mac</code>,其次 <code>deviceUid</code>。</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<h3>设备标识匹配优先级</h3>
|
||||||
|
<p>消耗接口和 init 接口均按以下优先级匹配设备:</p>
|
||||||
|
<pre><code>mac > wifiMac > deviceUid > deviceSn
|
||||||
|
</code></pre>
|
||||||
|
<p>只要有一个标识匹配即可找到设备。建议 consume 和 init 传递相同的标识组合。</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
橘视厅酒店版openapi文档.pdf
Normal file
BIN
橘视厅酒店版openapi文档.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user