FreeSign-p12 简易代销参数对接文档

2026-09-08 · 按当前本地证书站与 FreeSign-p12 源码核对。本文为说明文档;不会修改站点、客户端或数据库。所有 .invalid 域名均为示例,请替换为实际服务地址。

适用于证书站现有的简易代销 / 贴牌签名工具配置。签名工具启动后根据自身标识读取站点配置,网页可通过 URL Scheme 唤醒打开网页或添加软件源。

示例证书站https://cert.invalid

URL Schemefreesign://

一、整体流程

  1. 证书站创建简易代销 / 贴牌配置,生成唯一 short_site
  2. 证书站签名工具时修改 App 名称、图标、Bundle ID,并写入启动图资源。
  3. 签名工具启动后调用 /api/signtool/index,使用当前 App 的 app_bundle_id 拉取远程配置。
  4. 签名工具按设置启用默认软件源、安装域名、菜单、黑白名单、导入导出权限等。
  5. 签名工具需要云端证书时调用 /api/signtool/udid/api/signtool/getcertificate 两步拉取。

二、签名工具配置接口

签名工具启动时调用 Signtool.php 的配置接口,用于读取扩展菜单、默认软件源、安装域名、权限开关、公告等远程配置。

项目说明
请求地址POST https://cert.invalid/api/signtool/index
Content-Typeapplication/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_sitestring简易代销站点标识关联代销站点;当前配置接口实际按 app_bundle_id 查询,且不返回 short_site。
sitenamestring兼容站点名称客户端收到时优先使用;当前 Signtool/index 不返回,实际回退 app_name。当前贴牌保存接口不保存此字段。
app_bundle_idstring签名工具 Bundle ID签名时写入 App,例:com.vendor.signer
app_namestring桌面显示名称签名时写入 CFBundleDisplayName
app_icon_urlurl桌面图标建议 PNG,1024x1024;证书站签名时替换 icon.pngicon@2x.pngicon@3x.png
app_launch_icon_urlurl启动图证书站签名时写入 .app/website/bg.png,签名工具启动页读取此文件。
plist_urlurl安装 Plist 服务用于生成 itms-services 安装链接,建议使用证书站域名的 /plist.php
default_app_source_urlsurl/string默认软件源签名工具启动配置后可作为默认软件源地址。
groupurl/stringQQ群 / 社群入口签名工具菜单显示为“QQ群”。
contact_urlurl联系入口签名工具菜单显示为“联系我们”。
buy_urlurl购买入口签名工具菜单显示为“购买链接”。
tutorial_urlurl教程入口签名工具菜单显示为“常见问题”。
question_urlurl兼容教程入口客户端未取到 tutorial_url 字符串时回退;当前接口不返回,贴牌保存接口不保存。
noticestring站点公告签名工具启动优先弹出该公告;设置页显示为“站点公告”。
bottom_htmlhtml/string兼容公共内容客户端兼容接收,但当前接口不返回、贴牌保存接口不保存,设置页不展示公共内容入口。
whitelistboolean黑白名单 / 动态库注入开关数据库 fa_signtool.whitelist 为 1/0;开启后校验设备资格并注入运行权限组件,关闭后新签名不注入。详见第十一节。
import_permissionsbool/int导入权限当前签名工具中会和导出权限一起生效。
allow_exportbool/int导出权限如果接口返回,签名工具会识别;未返回时以 import_permissions 为主。
export_permissionsboolean导出兼容字段当前后台直接复制 import_permissions;客户端优先使用 import_permissions,不构成独立导出开关。
app_source_urls_qxboolean外部软件源权限当前 Signtool/index 固定返回 true,客户端映射为 allow_external_source;不是当前页面可保存的独立字段。

注意:

云端证书下载走 Signtool.php;已签名 App 的设备资格校验走 /api/signconfig,不依赖下载云端 P12。兼容接收字段不等于当前后台会返回或保存该字段。

四、云端证书接口

签名工具需要自动拉取证书时,使用 Signtool.php 的接口。第一步按 UDID 查 profile,第二步按 profile_id 获取 p12 和 mobileprovision。

1. 查询设备可用 Profile

项目说明
请求地址POST https://cert.invalid/api/signtool/udid
Content-Typeapplication/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
}

2. 下载证书内容

项目说明
请求地址POST https://cert.invalid/api/signtool/getcertificate
Content-Typeapplication/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"
  }
}

签名工具内部会把第二步返回值转换成原本使用的 p12mobileprovisionpassword 结构,然后继续走原来的导入和保存逻辑。

成功码不同:配置接口成功为 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>
示例:添加软件源

七、软件源 JSON 建议格式

签名工具的软件源解析较宽松,但建议统一使用下面结构,方便缓存和展示。

{
  "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": "应用介绍"
    }
  ]
}

八、安装链接 / Plist 服务

签名工具安装 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

九、HTML 表单示例

以下为已有贴牌记录的编辑表单示例,需登录证书站且记录属于当前用户;不能用于新建记录。提交时应回填已有值,三个开关提交字符串 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.sitefa_signtool.short_site 一致。
Bundle ID签名后的工具 Bundle ID 与贴牌设置一致。
图标签名后 .app/icon.pngicon@2x.pngicon@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 内浏览器。
权限开关whitelistimport_permissions 与 App 内行为一致。

十一、黑白名单、动态库注入与已签名 App

FreeSign-p12 使用证书站 fa_signtool.whitelist,对应 /application/index/view/index/signtool.html 中的黑白名单开关。它与 FreeSign / ioszj 签名后台的 runtime_lock_enabled 是两套协议,不可混用。

  1. 组件 POST 请求 /api/signtool/index,携带签名工具的 app_bundle_id(不是被签名应用的 Bundle ID)。
  2. 有效响应中 data.config.whitelist=false:放行,后续签名不注入;重签时清理已有权限动态库。
  3. 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.whitelist1 / 0每个贴牌工具的黑白名单与注入策略开关,不是某台设备的禁用状态。
fa_deviceslist.ztnormal正常;当前资格查询只匹配这种记录。
fa_deviceslist.ztdisabled人工禁用。
fa_deviceslist.zthidden掉签 / 证书撤销状态。
fa_deviceslist.udid字符串设备匹配键。
fa_deviceslist.deviceid标识值证书接口输出为 profile_id,下载证书时按此匹配。
fa_deviceslist.base64p12 / base64mpBase64 字符串证书及描述文件内容,不是禁用开关。

当前资格接口不直接返回 zt:只要该 UDID 没有 normal 记录,就返回相同的无资格结果。因此 disabled、hidden 和不存在均可能导致拒绝,客户端不能据此准确区分人工禁用和掉签。若同一 UDID 仍存在 normal 记录,当前查询仍会允许。

下面把正常设备、无权限设备以及相关独立字段完整列在本 HTML 中。本次仅补全文档,不更改上述判定逻辑,也不需要执行数据库升级。

十三、正常设备与无权限设备字段

当前接口没有单独的 normal_deviceallowedbannedno_permission 字段。服务端先检查数据库 fa_deviceslist.zt,客户端再根据整个响应结构判断权限。

1. 请求字段

字段位置 / 类型必填含义
udidQuery string / string当前设备 UDID,对应 fa_deviceslist.udid
appidQuery string / string签名工具 Bundle ID,对应 fa_signtool.app_bundle_id;不是被签名 App 的 Bundle ID。为空时旧接口会回退固定默认值,不建议依赖。
versionQuery string / string当前组件会传当前传 1,服务端读取但没有参与权限判断。

2. 数据库权限字段

独立字段服务端结果客户端结果
fa_signtool.whitelist0/api/signtool/index 返回 data.config.whitelist=false关闭设备资格校验;已有组件联网取得该配置后放行,新签名不注入组件。
fa_signtool.whitelist1返回 data.config.whitelist=true开启设备资格校验,继续请求 /api/signconfig
fa_deviceslist.ztnormal该 UDID 可被资格接口查到在响应结构有效时判定为有权限。
fa_deviceslist.ztdisabled资格接口查不到 normal 记录返回统一无资格响应,判定为无权限。
fa_deviceslist.zthidden资格接口查不到 normal 记录返回统一无资格响应,判定为无权限;无法从响应区分为掉签。
fa_deviceslist.udid无记录资格接口查不到 normal 记录与 disabled、hidden 返回相同的无权限响应。

3. 正常设备响应

只有以下三个条件同时满足,当前动态库才把本次资格响应解释为“正常 / 有权限”:code 是数字 1data.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"
    }
  }
}
响应字段类型是否参与动态库权限判断说明
codenumber必须为数字 1;字符串 "1" 不符合当前严格判断。
msgstring正常响应不使用当前成功文案为“返回成功”。
data.app_bundle_idstring必须与组件配置中的工具 Bundle ID 完全一致。
data.configobject必须是非空对象;内部某个业务字段的真假不等同于资格结果。
data.domainstring当前请求 Host。
data.config.timelockmixed来自 fa_signtool.timelockswitch,当前动态库权限策略不读取它。
data.config.vip_timestring当前后台实际填入 app_name,不是有效到期时间。
data.config.verstring当前固定 1.3.2,不参与资格判断。
data.config.* 其他字段mixed用于工具页面、软件源、导入导出、链接等配置;仅其对象非空这一结构条件参与资格判断。

4. 无权限设备响应

当没有查询到 udid 相同且 zt=normal 的记录时,当前接口返回:

{
  "code": 0,
  "msg": "该 UDID 不是有效使用设备",
  "data": []
}
响应字段类型 / 精确值作用
codenumber:0无权限判定的第一个必要条件。
msgstring:该 UDID 不是有效使用设备必须与当前文案精确一致;其他 code=0 错误不会被动态库直接当作新封禁。
dataarray:[]必须为空数组;不是空对象 {} 或 null。

5. 其他失败响应

{
  "code": 0,
  "msg": "未找到相关配置",
  "data": []
}

这个响应表示 appid 没有匹配 fa_signtool,不是明确的设备封禁。网络错误、HTTP 非 200、重定向、JSON 错误、Bundle ID 不匹配、空 config 或其他消息同样属于“未知 / 校验失败”。它们不会把最后一次有效的允许或拒绝改写为相反状态。

6. 状态判断速查

场景数据库 / 响应最终表现
黑白名单关闭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 都使用相同数据库。下面明确区分接口约定与各站点内部字段。所列适配方案尚未实施。

1. 实际调用流程

配置和证书流程:
工具 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,并拒绝跳转;一个能在浏览器中跳转打开的接口,不一定能被组件使用。

2. App 真正需要的接口字段

接口请求成功返回缺失的影响
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/signconfigudid、appid、version=1数字 code=1;data.app_bundle_id 必须匹配;data.config 为非空对象whitelist=true 时此接口缺失或异常,无法取得新的允许结果。
资格明确拒绝同上数字 code=0;msg 精确为“该 UDID 不是有效使用设备”;data=[]当前仅此拒绝结构会记录新拒绝;其他 code=0 不自动当作禁用。

配置成功码是 1,证书成功码是 0,不要统一改成同一个值。当前 getcertificate 下载失败可能被逐个候选重试后转换成空列表,所以“暂无证书”也可能是下载阶段失败,不一定是设备没有证书。

3. 数据库字段不同,如何适配

业务含义已看到的数据库实现适配原则
工具身份Signtool 使用 fa_signtool.app_bundle_id;最新 Signconfig 使用 fa_website.bidnameApp 只发送自己的 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 站点原本都有的要求。仅上传这个控制器不代表站点已经具备它依赖的记录和函数。

4. 各种站点的适配选择

站点现状当前 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 中按已知协议增加适配,分别配置配置入口、证书接口和权限来源;这是后续方案,当前代码尚未实现通用多站点适配。无法从“没有证书”可靠推断“设备被禁用”,因为无证书还可能来自到期、鉴权失败、空数据或服务故障。

5. 适配前提供哪些信息

  1. 工具实际 Bundle ID、配置入口,以及配置响应中的 domain。
  2. 配置响应、UDID 查询响应和证书下载响应的 code、msg、字段结构;P12、描述文件和密码用占位符替换,不提供私钥内容。
  3. 正常、人工禁用、掉签三种设备各自的权限响应,或对应服务端判断代码。
  4. 是否存在 Signconfig;如果没有,哪个现有接口能够明确返回设备禁用状态。
  5. 若接口有鉴权,提供鉴权实现或协议说明,不在公开文档中填写实际密钥。