2026-09-08 · 按当前本地证书站与 FreeSign-p12 源码核对。本文为说明文档;不会修改站点、客户端或数据库。所有 .invalid 域名均为示例,请替换为实际服务地址。
适用于证书站现有的简易代销 / 贴牌签名工具配置。签名工具启动后根据自身标识读取站点配置,网页可通过 URL Scheme 唤醒打开网页或添加软件源。
示例证书站https://cert.invalid
URL Schemefreesign://
short_site。/api/signtool/index,使用当前 App 的 app_bundle_id 拉取远程配置。/api/signtool/udid 和 /api/signtool/getcertificate 两步拉取。签名工具启动时调用 Signtool.php 的配置接口,用于读取扩展菜单、默认软件源、安装域名、权限开关、公告等远程配置。
| 项目 | 说明 |
|---|---|
| 请求地址 | POST https://cert.invalid/api/signtool/index |
| Content-Type | application/x-www-form-urlencoded; charset=utf-8 |
| 参数 | app_bundle_id,签名工具当前 Bundle ID,对应 fa_signtool.app_bundle_id |
POST /api/signtool/index HTTP/1.1
Host: cert.invalid
Content-Type: application/x-www-form-urlencoded; charset=utf-8
app_bundle_id=com.vendor.signer
{
"code": 1,
"msg": "获取成功",
"data": {
"domain": "cert.invalid",
"app_bundle_id": "com.vendor.signer",
"config": {
"app_icon_url": "https://assets.invalid/icon.png",
"app_name": "演示签名",
"buy_url": "https://site.invalid/buy",
"contact_url": "https://site.invalid/contact",
"default_app_source_urls": "https://source.invalid/source.json",
"exchange": true,
"group": "https://site.invalid/group",
"import_permissions": true,
"export_permissions": true,
"notice": "公告内容",
"whitelist": true,
"tutorial_url": "https://site.invalid/help",
"plist_url": "https://cert.invalid/plist.php",
"app_source_urls_qx": true
}
}
}
{
"app_bundle_id": "com.vendor.signer",
"app_name": "演示签名",
"plist_url": "https://cert.invalid/plist.php",
"default_app_source_urls": "https://source.invalid/source.json",
"app_icon_url": "https://assets.invalid/icon.png",
"group": "https://qm.qq.com/xxx",
"contact_url": "https://site.invalid/contact",
"buy_url": "https://site.invalid/buy",
"tutorial_url": "https://site.invalid/help",
"notice": "公告内容",
"exchange": 1,
"import_permissions": 1,
"whitelist": 1,
"allow_external_source": true
}
| 字段 | 类型 | 作用 | 备注 |
|---|---|---|---|
short_site | string | 简易代销站点标识 | 关联代销站点;当前配置接口实际按 app_bundle_id 查询,且不返回 short_site。 |
sitename | string | 兼容站点名称 | 客户端收到时优先使用;当前 Signtool/index 不返回,实际回退 app_name。当前贴牌保存接口不保存此字段。 |
app_bundle_id | string | 签名工具 Bundle ID | 签名时写入 App,例:com.vendor.signer。 |
app_name | string | 桌面显示名称 | 签名时写入 CFBundleDisplayName。 |
app_icon_url | url | 桌面图标 | 建议 PNG,1024x1024;证书站签名时替换 icon.png、icon@2x.png、icon@3x.png。 |
app_launch_icon_url | url | 启动图 | 证书站签名时写入 .app/website/bg.png,签名工具启动页读取此文件。 |
plist_url | url | 安装 Plist 服务 | 用于生成 itms-services 安装链接,建议使用证书站域名的 /plist.php。 |
default_app_source_urls | url/string | 默认软件源 | 签名工具启动配置后可作为默认软件源地址。 |
group | url/string | QQ群 / 社群入口 | 签名工具菜单显示为“QQ群”。 |
contact_url | url | 联系入口 | 签名工具菜单显示为“联系我们”。 |
buy_url | url | 购买入口 | 签名工具菜单显示为“购买链接”。 |
tutorial_url | url | 教程入口 | 签名工具菜单显示为“常见问题”。 |
question_url | url | 兼容教程入口 | 客户端未取到 tutorial_url 字符串时回退;当前接口不返回,贴牌保存接口不保存。 |
notice | string | 站点公告 | 签名工具启动优先弹出该公告;设置页显示为“站点公告”。 |
bottom_html | html/string | 兼容公共内容 | 客户端兼容接收,但当前接口不返回、贴牌保存接口不保存,设置页不展示公共内容入口。 |
whitelist | boolean | 黑白名单 / 动态库注入开关 | 数据库 fa_signtool.whitelist 为 1/0;开启后校验设备资格并注入运行权限组件,关闭后新签名不注入。详见第十一节。 |
import_permissions | bool/int | 导入权限 | 当前签名工具中会和导出权限一起生效。 |
allow_export | bool/int | 导出权限 | 如果接口返回,签名工具会识别;未返回时以 import_permissions 为主。 |
export_permissions | boolean | 导出兼容字段 | 当前后台直接复制 import_permissions;客户端优先使用 import_permissions,不构成独立导出开关。 |
app_source_urls_qx | boolean | 外部软件源权限 | 当前 Signtool/index 固定返回 true,客户端映射为 allow_external_source;不是当前页面可保存的独立字段。 |
注意:
云端证书下载走 Signtool.php;已签名 App 的设备资格校验走 /api/signconfig,不依赖下载云端 P12。兼容接收字段不等于当前后台会返回或保存该字段。
签名工具需要自动拉取证书时,使用 Signtool.php 的接口。第一步按 UDID 查 profile,第二步按 profile_id 获取 p12 和 mobileprovision。
| 项目 | 说明 |
|---|---|
| 请求地址 | POST https://cert.invalid/api/signtool/udid |
| Content-Type | application/x-www-form-urlencoded; charset=utf-8 |
| 参数 | udids[],设备 UDID 数组。可提交多个,但当前服务端找到首个有效结果即返回,不是批量完整查询。 |
POST /api/signtool/udid HTTP/1.1
Host: cert.invalid
Content-Type: application/x-www-form-urlencoded; charset=utf-8
udids[]=00008030-0012345678901234
{
"code": 0,
"msg": "成功",
"data": {
"profiles": [
{
"profile_id": "123456",
"uuid": "PROFILE-UUID",
"name": "00008030-0012345678901234",
"status": "正常",
"using": true,
"devices": ["00008030-0012345678901234"],
"expiration_date": "2026-12-31T00:00:00Z",
"certificate": [
{
"name": "iOS Distribution",
"id": "CERT-ID",
"country": "US"
}
]
}
]
},
"time": 1780000000
}
| 项目 | 说明 |
|---|---|
| 请求地址 | POST https://cert.invalid/api/signtool/getcertificate |
| Content-Type | application/x-www-form-urlencoded; charset=utf-8 |
| 参数 | profile_id,来自第一步返回的 profiles[].profile_id。 |
POST /api/signtool/getcertificate HTTP/1.1
Host: cert.invalid
Content-Type: application/x-www-form-urlencoded; charset=utf-8
profile_id=123456
{
"code": 0,
"msg": "成功",
"data": {
"mobileprovision": "BASE64_MOBILEPROVISION",
"p12": "BASE64_P12",
"p12_password": "1"
}
}
签名工具内部会把第二步返回值转换成原本使用的 p12、mobileprovision、password 结构,然后继续走原来的导入和保存逻辑。
成功码不同:配置接口成功为 code=1,以上两个证书接口成功为 code=0。证书接口在无匹配、参数不满足或解析失败的部分路径可能返回空响应,不保证统一错误 JSON;不得把空响应当作明确封禁。
用于从网页或证书站页面直接打开签名工具内置浏览器。
| 格式 | freesign://web?url={目标网页URL} |
|---|---|
| 参数 | url 必填,需要 URL 编码。 |
<a href="freesign://web?url=https%3A%2F%2Fcert.invalid%2Findex%2Findex%2Fsigntool">
打开签名工具网页
</a>
示例:打开网页
用于网页按钮一键拉起签名工具并添加软件源。
| 格式 | freesign://apps?url={软件源URL} |
|---|---|
| 参数 | url 必填,需要 URL 编码。 |
| 行为 | 签名工具会请求该软件源,解析成功后写入本地软件源列表;已存在则提示重复。 |
<a href="freesign://apps?url=https%3A%2F%2Fsource.invalid%2Fsource.json">
添加软件源
</a>
<button onclick="location.href='freesign://apps?url=' + encodeURIComponent('https://source.invalid/source.json')">
添加软件源
</button>
示例:添加软件源
签名工具的软件源解析较宽松,但建议统一使用下面结构,方便缓存和展示。
{
"name": "示例软件源",
"identifier": "invalid.source",
"sourceicon": "https://assets.invalid/source-icon.png",
"message": "源公告",
"apps": [
{
"name": "示例 App",
"bundleIdentifier": "invalid.app",
"version": "1.0.0",
"iconURL": "https://assets.invalid/app-icon.png",
"downloadURL": "https://download.invalid/app.ipa",
"localizedDescription": "应用介绍"
}
]
}
签名工具安装 App 时会把 App 名、图标、Bundle ID、IPA 地址组合后交给 plist_url 生成安装描述文件。
| 字段 | 说明 |
|---|---|
plist_url | 建议填写证书站现成安装服务,例如 https://cert.invalid/plist.php。 |
appName | 安装弹窗显示名称。 |
iconURL | 安装图标地址。 |
bundleID | 待安装 App 的 Bundle ID。 |
ipaURL | 待安装 IPA 的 HTTPS 下载地址。 |
签名工具内部会按现有编码规则拼接 Plist 地址,外部对接通常只需要在贴牌设置里正确填写 plist_url。
以下为已有贴牌记录的编辑表单示例,需登录证书站且记录属于当前用户;不能用于新建记录。提交时应回填已有值,三个开关提交字符串 true/false(不要用 1/0 代替)。
<form method="post" action="/index/index/signtool">
<label>站点标识</label>
<input name="row[short_site]" value="demo" readonly>
<label>Bundle ID</label>
<input name="row[app_bundle_id]" value="com.vendor.signer" readonly>
<label>App 名称</label>
<input name="row[app_name]" value="演示签名">
<label>安装域名</label>
<input name="row[plist_url]" value="https://cert.invalid/plist.php">
<label>默认软件源</label>
<input name="row[default_app_source_urls]" value="https://source.invalid/source.json">
<label>图标 URL</label>
<input name="row[app_icon_url]" value="https://assets.invalid/icon.png">
<label>启动图 URL</label>
<input name="row[app_launch_icon_url]" value="https://assets.invalid/launch.png">
<label>QQ群</label>
<input name="row[group]" value="https://site.invalid/group">
<label>联系我们</label>
<input name="row[contact_url]" value="https://site.invalid/contact">
<label>购买链接</label>
<input name="row[buy_url]" value="https://site.invalid/buy">
<label>教程地址</label>
<input name="row[tutorial_url]" value="https://site.invalid/help">
<label>站点公告</label>
<input name="row[notice]" value="欢迎使用">
<label>黑白名单</label>
<label><input type="radio" name="row[whitelist]" value="true"> 开启</label>
<label><input type="radio" name="row[whitelist]" value="false" checked> 关闭</label>
<label>导入/导出权限</label>
<label><input type="radio" name="row[import_permissions]" value="true" checked> 开启</label>
<label><input type="radio" name="row[import_permissions]" value="false"> 关闭</label>
<button type="submit">保存设置</button>
</form>
| 检查项 | 结果要求 |
|---|---|
| 站点标识 | fa_agentsite.site 与 fa_signtool.short_site 一致。 |
| Bundle ID | 签名后的工具 Bundle ID 与贴牌设置一致。 |
| 图标 | 签名后 .app/icon.png、icon@2x.png、icon@3x.png 已替换。 |
| 启动图 | 签名后存在 .app/website/bg.png。 |
| 安装域名 | plist_url 使用 HTTPS,能返回有效 plist。 |
| 云端证书 | /api/signtool/udid 能按 UDID 返回 profile_id,/api/signtool/getcertificate 能返回 p12 与 mobileprovision。 |
| 名称与公告 | 当前接口使用 app_name 和 notice;不应期待 sitename、bottom_html 从当前接口返回。 |
| 软件源唤醒 | freesign://apps?url=... 能拉起 App 并添加软件源。 |
| 网页唤醒 | freesign://web?url=... 能拉起 App 内浏览器。 |
| 权限开关 | whitelist、import_permissions 与 App 内行为一致。 |
FreeSign-p12 使用证书站 fa_signtool.whitelist,对应 /application/index/view/index/signtool.html 中的黑白名单开关。它与 FreeSign / ioszj 签名后台的 runtime_lock_enabled 是两套协议,不可混用。
/api/signtool/index,携带签名工具的 app_bundle_id(不是被签名应用的 Bundle ID)。data.config.whitelist=false:放行,后续签名不注入;重签时清理已有权限动态库。whitelist=true:继续 GET 请求下方资格接口。只有明确有效的结果才更新权限缓存。GET /api/signconfig?udid=00008030-0012345678901234&appid=com.vendor.signer&version=1
| 参数 / 响应 | 解释 |
|---|---|
udid | 签名时写入组件配置的设备 UDID。 |
appid | 原签名工具的 Bundle ID,用于查 fa_signtool.app_bundle_id。 |
version | 当前组件传字符串 1;当前后台读取后未用于权限判断。 |
| 允许 | code 为数字 1、data.app_bundle_id 匹配且 data.config 为非空对象。 |
| 拒绝 | code 为数字 0、msg 精确为“该 UDID 不是有效使用设备”、data 为空数组。 |
| 未知 / 失败 | 网络错误、空响应、其他错误文案或结构异常不覆盖上次有效结果。 |
{"code":0,"msg":"该 UDID 不是有效使用设备","data":[]}
断网保留上次有效结果:上次允许则继续允许,上次拒绝则保持拒绝;联网后重新获取。首次没有缓存时静默等待校验,尚未取得允许结果时不开放操作;校验失败或明确拒绝后提示“设备无使用权限,请联系客服”。当前没有本地到期计时。
已注入组件的 App 也会走上述流程;关闭 whitelist 后,下次联网校验成功会放行,但不会从已安装 App 中删除动态库。未注入组件的 App 不会因后台重新开启开关自动获得校验能力,需要重新签名安装。
产物仅使用与主程序同目录的 FSRuntimeAccess.dylib,加载路径为 @executable_path/FSRuntimeAccess.dylib,配置嵌入库内,不单独生成或读取 FSRuntimeAccess.json。组件封装不是不可篡改的设备身份认证。
| 表 / 字段 | 取值 | 含义 |
|---|---|---|
fa_signtool.whitelist | 1 / 0 | 每个贴牌工具的黑白名单与注入策略开关,不是某台设备的禁用状态。 |
fa_deviceslist.zt | normal | 正常;当前资格查询只匹配这种记录。 |
fa_deviceslist.zt | disabled | 人工禁用。 |
fa_deviceslist.zt | hidden | 掉签 / 证书撤销状态。 |
fa_deviceslist.udid | 字符串 | 设备匹配键。 |
fa_deviceslist.deviceid | 标识值 | 证书接口输出为 profile_id,下载证书时按此匹配。 |
fa_deviceslist.base64p12 / base64mp | Base64 字符串 | 证书及描述文件内容,不是禁用开关。 |
当前资格接口不直接返回 zt:只要该 UDID 没有 normal 记录,就返回相同的无资格结果。因此 disabled、hidden 和不存在均可能导致拒绝,客户端不能据此准确区分人工禁用和掉签。若同一 UDID 仍存在 normal 记录,当前查询仍会允许。
下面把正常设备、无权限设备以及相关独立字段完整列在本 HTML 中。本次仅补全文档,不更改上述判定逻辑,也不需要执行数据库升级。
当前接口没有单独的 normal_device、allowed、banned 或 no_permission 字段。服务端先检查数据库 fa_deviceslist.zt,客户端再根据整个响应结构判断权限。
| 字段 | 位置 / 类型 | 必填 | 含义 |
|---|---|---|---|
udid | Query string / string | 是 | 当前设备 UDID,对应 fa_deviceslist.udid。 |
appid | Query string / string | 是 | 签名工具 Bundle ID,对应 fa_signtool.app_bundle_id;不是被签名 App 的 Bundle ID。为空时旧接口会回退固定默认值,不建议依赖。 |
version | Query string / string | 当前组件会传 | 当前传 1,服务端读取但没有参与权限判断。 |
| 独立字段 | 值 | 服务端结果 | 客户端结果 |
|---|---|---|---|
fa_signtool.whitelist | 0 | /api/signtool/index 返回 data.config.whitelist=false | 关闭设备资格校验;已有组件联网取得该配置后放行,新签名不注入组件。 |
fa_signtool.whitelist | 1 | 返回 data.config.whitelist=true | 开启设备资格校验,继续请求 /api/signconfig。 |
fa_deviceslist.zt | normal | 该 UDID 可被资格接口查到 | 在响应结构有效时判定为有权限。 |
fa_deviceslist.zt | disabled | 资格接口查不到 normal 记录 | 返回统一无资格响应,判定为无权限。 |
fa_deviceslist.zt | hidden | 资格接口查不到 normal 记录 | 返回统一无资格响应,判定为无权限;无法从响应区分为掉签。 |
fa_deviceslist.udid | 无记录 | 资格接口查不到 normal 记录 | 与 disabled、hidden 返回相同的无权限响应。 |
只有以下三个条件同时满足,当前动态库才把本次资格响应解释为“正常 / 有权限”:code 是数字 1、data.app_bundle_id 与请求的工具 Bundle ID 完全一致、data.config 是非空对象。
{
"code": 1,
"msg": "返回成功",
"data": {
"domain": "cert.invalid",
"app_bundle_id": "com.vendor.signer",
"config": {
"iid": 0,
"app_type": 2,
"app_name": "演示签名",
"app_color": "#000000",
"vip_time": "演示签名",
"default_app_source_urls": "https://source.invalid/source.json",
"app_source_urls_qx": false,
"import_app_source": 1,
"qq_url": "https://site.invalid/group",
"contact_url": "https://site.invalid/contact",
"buy_url": "https://site.invalid/buy",
"buy_app": "https://site.invalid/buy",
"jc_url": "https://site.invalid/help",
"import_permissions": true,
"export_permissions": true,
"timelock": 0,
"ver": "1.3.2",
"notice": "",
"plisturl": "cert.invalid",
"cert_search_url": "/api/certall"
}
}
}
| 响应字段 | 类型 | 是否参与动态库权限判断 | 说明 |
|---|---|---|---|
code | number | 是 | 必须为数字 1;字符串 "1" 不符合当前严格判断。 |
msg | string | 正常响应不使用 | 当前成功文案为“返回成功”。 |
data.app_bundle_id | string | 是 | 必须与组件配置中的工具 Bundle ID 完全一致。 |
data.config | object | 是 | 必须是非空对象;内部某个业务字段的真假不等同于资格结果。 |
data.domain | string | 否 | 当前请求 Host。 |
data.config.timelock | mixed | 否 | 来自 fa_signtool.timelockswitch,当前动态库权限策略不读取它。 |
data.config.vip_time | string | 否 | 当前后台实际填入 app_name,不是有效到期时间。 |
data.config.ver | string | 否 | 当前固定 1.3.2,不参与资格判断。 |
data.config.* 其他字段 | mixed | 否 | 用于工具页面、软件源、导入导出、链接等配置;仅其对象非空这一结构条件参与资格判断。 |
当没有查询到 udid 相同且 zt=normal 的记录时,当前接口返回:
{
"code": 0,
"msg": "该 UDID 不是有效使用设备",
"data": []
}
| 响应字段 | 类型 / 精确值 | 作用 |
|---|---|---|
code | number:0 | 无权限判定的第一个必要条件。 |
msg | string:该 UDID 不是有效使用设备 | 必须与当前文案精确一致;其他 code=0 错误不会被动态库直接当作新封禁。 |
data | array:[] | 必须为空数组;不是空对象 {} 或 null。 |
{
"code": 0,
"msg": "未找到相关配置",
"data": []
}
这个响应表示 appid 没有匹配 fa_signtool,不是明确的设备封禁。网络错误、HTTP 非 200、重定向、JSON 错误、Bundle ID 不匹配、空 config 或其他消息同样属于“未知 / 校验失败”。它们不会把最后一次有效的允许或拒绝改写为相反状态。
| 场景 | 数据库 / 响应 | 最终表现 |
|---|---|---|
| 黑白名单关闭 | whitelist=0 | 有效配置返回后放行;新签名不注入。 |
| 正常设备 | whitelist=1 且存在同 UDID 的 zt=normal | 有效 code=1 响应,记录“允许”。 |
| 人工禁用 | zt=disabled 且没有同 UDID 的 normal 记录 | 统一无资格响应,记录“拒绝”。 |
| 掉签 | zt=hidden 且没有同 UDID 的 normal 记录 | 统一无资格响应,记录“拒绝”;客户端无法显示为“掉签”。 |
| 未登记设备 | 没有同 UDID 的 normal 记录 | 与禁用 / 掉签相同的无资格响应。 |
| 断网 | 没有本次有效响应 | 沿用上次有效允许或拒绝;恢复联网后重新查询。 |
| 首次校验失败 | 无缓存且没有有效响应 | 不开放操作;静默等待后提示“设备无使用权限,请联系客服”。 |
本节以当前 FreeSign-p12 为准。前面第十三节的成功示例来自本地 fa_signtool 版本,并不代表所有站点的 Signconfig.php 都使用相同数据库。下面明确区分接口约定与各站点内部字段。所列适配方案尚未实施。
配置和证书流程:
工具 Bundle ID
→ POST 配置入口 /api/signtool/index(app_bundle_id)
→ 读取 data.config;data.domain 决定证书 API 基址
→ POST 证书站 /api/signtool/udid(udids[]=设备 UDID)
→ 读取 data.profiles[].profile_id
→ POST 同证书站 /api/signtool/getcertificate(profile_id)
→ 解析 P12 和描述文件 → 保存本地 / 展示证书
权限流程(取得有效 UDID 后启动,与证书下载分别执行):
→ POST 配置入口 /api/signtool/index(原工具 app_bundle_id)
→ whitelist=false:允许,后续签名不注入
→ whitelist=true:GET 证书站 /api/signconfig
(udid=设备UDID、appid=原工具BundleID、version=1)
→ 明确允许 / 明确拒绝:更新缓存
→ 无效响应 / 请求失败:保留上次有效权限
签名产物含 FSRuntimeAccess.dylib 时:
→ 组件使用签名时嵌入的接口地址、原工具 Bundle ID 和设备 UDID
→ 独立执行同一套权限流程,不依赖原签名工具保持运行
权限组件可在云端证书同步前或过程中遮住界面,因此“打不开”和“证书下载失败”需要分别检查。组件只接受 HTTPS、HTTP 200 的有效 JSON,并拒绝跳转;一个能在浏览器中跳转打开的接口,不一定能被组件使用。
| 接口 | 请求 | 成功返回 | 缺失的影响 |
|---|---|---|---|
| POST /api/signtool/index | 表单 app_bundle_id | 数字 code=1;data.app_bundle_id;data.config;跨域证书站须正确提供 data.domain | 配置失败时工具不能正常启动云端证书服务。 |
| 配置中的 whitelist | 无需额外请求 | data.config.whitelist 为 true/false;组件也接受 1/0 及字符串 "true"、"false"、"1"、"0" | 字段缺失不是关闭;组件视为未知,不会自动放行。 |
| POST /api/signtool/udid | 表单 udids[]=UDID;客户端失败时兼容尝试 JSON {"udids":["UDID"]} | 数字 code=0;data.profiles 为数组;优先使用每项 profile_id | 没有可用标识就不能进入下载。certificate[].id 仅为已有兼容候选,不能保证等同于 profile_id。 |
| POST /api/signtool/getcertificate | 表单 profile_id,按上一接口的值原样传递 | 数字 code=0;data.p12、data.mobileprovision 为 Base64 字符串;data.p12_password 为字符串 | 密码缺失时默认 "1";若真实密码不同则解析失败。缺少内容无法导入。 |
| GET /api/signconfig | udid、appid、version=1 | 数字 code=1;data.app_bundle_id 必须匹配;data.config 为非空对象 | whitelist=true 时此接口缺失或异常,无法取得新的允许结果。 |
| 资格明确拒绝 | 同上 | 数字 code=0;msg 精确为“该 UDID 不是有效使用设备”;data=[] | 当前仅此拒绝结构会记录新拒绝;其他 code=0 不自动当作禁用。 |
配置成功码是 1,证书成功码是 0,不要统一改成同一个值。当前 getcertificate 下载失败可能被逐个候选重试后转换成空列表,所以“暂无证书”也可能是下载阶段失败,不一定是设备没有证书。
| 业务含义 | 已看到的数据库实现 | 适配原则 |
|---|---|---|
| 工具身份 | Signtool 使用 fa_signtool.app_bundle_id;最新 Signconfig 使用 fa_website.bidname | App 只发送自己的 Bundle ID。站点适配层须把它映射到真实配置记录;在一个表有记录,不代表另一个表也有。 |
| 开关 | fa_signtool.whitelist;另一表还有 bidswitch、checkudidswitch、timelockswitch | 不能按名字认定等价。whitelist 当前控制是否进入资格校验和注入;bidswitch 当前用于查找启用的网站记录;其余按服务端实际代码判断。 |
| 设备状态 | 当前示例 fa_deviceslist.zt=normal/disabled/hidden | 其他站点字段可叫 status、enabled 等,App 不直接读数据库。适配层应按该站点真实含义返回统一的允许/拒绝结果。 |
| 站点到期 | 最新 Signconfig 检查 fa_website.endtime | 它额外返回“应用已过期”。当前 App 不将此响应记录为明确禁用;是否让站点到期限制设备,需先确定产品规则再增加映射。 |
| 证书标识 | deviceid 输出为 profile_id;鉴权版本可能输出临时令牌 | App 应使用返回的标识,不自行用 kid、UUID 或 Bundle ID 重造。 |
| 证书内容 | base64p12 / base64mp | 接口输出为 p12 / mobileprovision 即可;数据库无需为了 App 强行改字段名。 |
最新上传的 Signconfig(1).php 还调用 Dsign(),并要求 fa_website.bidname 匹配、bidswitch=1、endtime 未到期;这些条件是这一版服务端的要求,不是所有 Signtool 站点原本都有的要求。仅上传这个控制器不代表站点已经具备它依赖的记录和函数。
| 站点现状 | 当前 App 能力 | 需要的适配 |
|---|---|---|
| 有标准 Signtool 三接口,whitelist=false | 可走配置和证书流程,组件取得有效关闭值后不请求资格接口。 | 核对配置入口、domain、Bundle ID 和证书数据即可。 |
| 有标准 Signtool 三接口,whitelist=true,但无 Signconfig | 证书协议可匹配,但新版权限流程不完整。 | 若要设备远程禁用,需提供能区分允许/拒绝的现有接口供 App 映射,或增加站点适配接口。若业务不需要此功能,应显式配置关闭;不能把 404 自动解释为关闭。 |
| 有 Signconfig,但查另一套表 | 响应格式可能兼容,数据关联可能不兼容。 | 核对 Bundle ID 是否在该表启用、是否到期;优先映射真实业务数据,不为消除提示盲目新增正常设备。 |
| 只有 index(),没有云端证书接口 | 只能获取配置。 | 提供真实存在的证书查询/下载接口及协议,再改 App 请求;没有下载接口时无法仅靠字段实现云端证书。 |
| 字段不同、地址不同 | 当前固定证书路径不会自动识别所有接口。 | 在 App 的请求/解析层增加明确的站点协议映射,或由服务端输出标准结构。仅添加 cert_search_url、cert_content_url 字段不会让当前 App 自动使用它们。 |
| 使用 SigntoolApiSecurityService | 当前客户端未实现这份服务的 HMAC 请求签名。 | 需按实际服务定义适配鉴权头、签名串和令牌。仅收到 api_auth.algorithm=HMAC-SHA256 不足以实现签名;普通站点没有此服务则不需要它。 |
以“站点不修改”为前提,推荐在 App 中按已知协议增加适配,分别配置配置入口、证书接口和权限来源;这是后续方案,当前代码尚未实现通用多站点适配。无法从“没有证书”可靠推断“设备被禁用”,因为无证书还可能来自到期、鉴权失败、空数据或服务故障。