diff --git a/app/integrations/ehr.py b/app/integrations/ehr.py index 369ecac..b0f81fe 100644 --- a/app/integrations/ehr.py +++ b/app/integrations/ehr.py @@ -53,6 +53,17 @@ class EhrClient(BaseClient): self._token_type: str | None = None self._token_expires_at: float | None = None + @staticmethod + def _normalize_token_type(token_type: str | None) -> str: + # 北森文档示例返回 token_type=bearer(小写),但鉴权头要求 "Bearer "。 + # 这里统一规范为首字母大写,避免服务端大小写敏感导致 401。 + raw = str(token_type or "").strip() + if not raw: + return "Bearer" + if raw.lower() == "bearer": + return "Bearer" + return raw + def authenticate(self) -> str: body: dict[str, Any] = { "grant_type": self.grant_type, @@ -67,7 +78,7 @@ class EhrClient(BaseClient): ) data = resp.json() if resp.content else {} access_token = str(data.get("access_token", "") or "") - token_type = str(data.get("token_type", "") or "Bearer") + token_type = self._normalize_token_type(data.get("token_type")) expires_in = int(data.get("expires_in", 0) or 0) if not access_token: raise RuntimeError("EHR authenticate failed (access_token missing)") @@ -88,7 +99,7 @@ class EhrClient(BaseClient): def request(self, method: str, path: str, **kwargs: Any) -> httpx.Response: # type: ignore[override] token = self._get_access_token() - token_type = self._token_type or "Bearer" + token_type = self._normalize_token_type(self._token_type) headers = dict(kwargs.pop("headers", {}) or {}) headers["Authorization"] = f"{token_type} {token}" @@ -106,7 +117,7 @@ class EhrClient(BaseClient): self._token_expires_at = None token2 = self._get_access_token() - token_type2 = self._token_type or "Bearer" + token_type2 = self._normalize_token_type(self._token_type) headers["Authorization"] = f"{token_type2} {token2}" return super().request(method, path, headers=headers, **kwargs)