AccessToken,再以 Bearer Token 方式访问业务接口。API Key、时间戳和签名换取 AccessToken。Authorization: Bearer <AccessToken> 携带访问令牌。POST /cmd/GetAccessToken HTTP/1.1Host: <FHIR_SERVICE_HOST>Content-Type: application/json
<FHIR_SERVICE_HOST> 为鉴权服务访问域名,请以腾讯健康数据服务控制台实例接入信息或部署方提供的服务访问地址为准。<FHIR_SERVICE_HOST> 仅为占位符,调用时需替换为实际可访问域名,不要直接使用占位符发起请求。{"header": {"version": "v0.1","flag": 0},"body": {"seq": 0,"cmd": "","token": "","traceid": "","client": {"platform": 0,"env": "","isTourist": 0,"product": 0},"payload": {"timestamp": 1730000000000,"apiKey": "<API_KEY>","signature": "<SIGNATURE>","scopes": [],"context": {}}}}
timestamp 为毫秒级 Unix 时间戳。signature 为基于 API Secret 计算得到的签名值。scopes 和 context 为扩展字段,可按实际授权场景传入。POST:创建资源,或提交 Bundle 事务/批处理请求。GET:读取资源、读取历史版本、执行搜索。PUT:更新完整资源内容。PATCH:更新局部字段。DELETE:删除指定资源。GET /INSTANCE_ID/fhir/Patient/199963 HTTP/1.1Host: HOSTNAMEAuthorization: Bearer <AccessToken>Accept: application/fhir+json
[baseUrl]/[resourceType] 或 [baseUrl]/[resourceType]/[id][baseUrl]/[resourceType]/[id]/_history/[versionId][baseUrl]/[resourceType]?[searchParams][baseUrl]/Patient/[id]/$everything[baseUrl]参数名称 | 类型 | 是否必填 | 说明 |
header.version | String | 是 | 请求协议版本,示例为 v0.1 |
header.flag | Integer | 是 | 请求标记,示例为 0 |
body.seq | Integer | 是 | 请求序号,示例为 0 |
body.cmd | String | 否 | 预留命令字段 |
body.token | String | 否 | 预留令牌字段,获取 AccessToken 时通常为空 |
body.traceid | String | 否 | 请求链路追踪标识 |
body.client.platform | Integer | 否 | 客户端平台标识 |
body.client.env | String | 否 | 调用环境标识 |
body.client.isTourist | Integer | 否 | 游客标识 |
body.client.product | Integer | 否 | 产品标识 |
body.payload.timestamp | Integer | 是 | 毫秒级时间戳。服务端允许的时间窗口为请求到达服务端时间前后3600000毫秒(1小时),超出窗口会被拒绝 |
body.payload.apiKey | String | 是 | API 密钥 |
body.payload.signature | String | 是 | 签名值 |
body.payload.scopes | Array | 条件必填 | 申请的权限范围。开启知情同意访问控制时必填,且至少含1个 actor/<资源类型>/<ID>(如 "actor/Practitioner/P001"),否则访问 FHIR 接口返回401(Claims 中缺少 scope 字段)。未开启时可留空([]) |
body.payload.context | Object | 否 | 上下文扩展参数 |
参数名称 | 类型 | 是否必填 | 说明 |
Host | String | 是 | |
Authorization | String | 是 | 访问令牌,格式为 Bearer <AccessToken> |
Content-Type | String | 否 | 请求体类型,写入类请求通常为 application/fhir+json;Patch 请求通常为 application/json-patch+json |
Accept | String | 否 | 响应格式,建议使用 application/fhir+json |
resourceType | String | 视接口而定 | FHIR 资源类型,如 Patient、Observation、Encounter |
id | String | 视接口而定 | 资源唯一标识 |
searchParams | Query String | 否 | 搜索参数,用于筛选结果集 |
versionId | String | 否 | 历史版本号,用于 vRead 等场景 |
API Key、API Secret 和签名机制的令牌鉴权方式。调用方需先向鉴权服务申请 AccessToken,再携带该令牌访问 FHIR 接口。API Key 和 API Secret。timestamp。signature。apiKey、timestamp、signature 提交至鉴权接口。AccessToken。Authorization 请求头携带该令牌。AccessToken。message = apiKey + timestamp
signature = HMAC-SHA256(apiSecret, message)
message 使用 UTF-8 编码。timestamp 为毫秒级时间戳。3600000 毫秒(1 小时):timestamp > 服务端当前时间 + 3600000,请求将被拒绝。timestamp < 服务端当前时间 - 3600000,请求将被拒绝。signTime is timed outsignature is invalidAccessToken 后,调用方需在访问 FHIR 接口时将其放入 HTTP Header:Authorization: Bearer <AccessToken>
AuthorizationBearer <空格><AccessToken>import hashlibimport hmacimport timefrom typing import Optionalimport requestsdef sign(api_key: str, api_secret: str, sign_time: int) -> str:"""签名Args:api_key: API密钥api_secret: API密钥对应的秘密sign_time: 签名时间(毫秒)Returns:签名字符串(大写十六进制)"""message = f"{api_key}{sign_time}".encode("utf-8")h = hmac.new(api_secret.encode("utf-8"), message, hashlib.sha256)return h.hexdigest().upper()# 校验签名逻辑(本地自测用)def check_signature(api_key: str, api_secret: str, signature: str, sign_time: int, timeout: int) -> Optional[str]:"""校验签名Args:api_key: API密钥api_secret: API密钥对应的秘密signature: 签名字符串sign_time: 签名时间(毫秒)timeout: 超时时间(毫秒)Returns:None表示校验通过,否则返回错误信息"""now_time = int(time.time() * 1000) # 当前时间(毫秒)if sign_time > now_time + timeout or sign_time < now_time - timeout:return "signTime is timed out"calculated_sign = sign(api_key, api_secret, sign_time)if signature.upper() != calculated_sign.upper():return "signature is invalid"return Nonedef request_auth_server(api_key: str, api_secret: str) -> Optional[str]:sign_time = int(time.time() * 1000)signature = sign(api_key, api_secret, sign_time)rsp = requests.post(# 将 <FHIR_SERVICE_HOST> 替换为实际鉴权服务访问域名url="https://<FHIR_SERVICE_HOST>/cmd/GetAccessToken",json={"header": {"version": "v0.1","flag": 0,},"body": {"seq": 0,"cmd": "","token": "","traceid": "","client": {"platform": 0,"env": "","isTourist": 0,"product": 0,},"payload": {"timestamp": sign_time,"apiKey": api_key,"signature": signature,"scopes": [],"context": {},},},},timeout=10,)if rsp.status_code != 200:return Nonedata = rsp.json()if data.get("retcode", 0) != 0:return Nonepayload = data.get("payload") or {}return payload.get("accessToken")if __name__ == "__main__":key = "<KEY>"secret = "<SECRET>"token = request_auth_server(key, secret)print(token)
accessToken,调用方应妥善保存并在后续 FHIR 请求中使用。返回结果示例如下:{"payload": {"accessToken": "<ACCESS_TOKEN>"}}
200。accessToken。Bundle。OperationOutcome 或状态结果。Bundle。参数名称 | 说明 |
Status Code | HTTP 状态码,用于标识请求处理结果 |
ETag | 资源版本标识 |
Location / Content-Location | 资源或历史版本访问地址 |
Status Code、ETag 和 Location 判断是否写入成功。Bundle.entry、Bundle.total 和 Bundle.link。OperationOutcome 或错误响应体定位具体原因。文档反馈