Files
wecom_it_smart_desk/backend/app/utils/itsm_signer.py
T
Simon bea288e414 feat: 2026-07-11 全量更新 - 代办集成+会议室预定+知识迭代修复+UI统一+Bug修复
== 已部署上线 (9项) ==
- 代办事项真实数据源集成 (企微审批API 8bug修复链)
- H5/坐席端 Logo样式统一+绿色背景
- 视频引导页修复 (localStorage key v2)
- 坐席端 v9 Vue版本修复 (ElMessage._context)
- 截图按钮 v10 修复 (getDisplayMedia user gesture)
- 扫码样式恢复+H5扫码登录跳转修复
- H5截图快捷键提示

== 代码完成待部署 (3项) ==
- 知识迭代3Bug修复 (#8 POST端点/#7 MERGE幂等/#6 过期检查)
- 会议室预定-小鱼易联终端 (40文件, 40/40测试通过)
- IT资产升级审批推送 (asset_service.py)

== 需求文档 (2项) ==
- 坐席端AI辅助消息框-PRD (4项新功能确认)
- 坐席端布局优化建议 v2.0 (7天计划)

== 新增文档 ==
- 日报-2026-07-11.md
- 知识迭代Bug修复报告-20260711.md
- 会议室预定-部署指南.md
- CHANGELOG.md 更新

== 测试 ==
- test_todo_integration.py: 40/40
- test_meetingroom.py: 40/40
- test_bugfix_ki_suggestions.py: 21/21
2026-07-11 23:13:10 +08:00

76 lines
2.7 KiB
Python

# =============================================================================
# 企微IT智能服务台 — ITSM OpenAPI 签名工具
# =============================================================================
# 说明:ITSM 一站式运维平台 OpenAPI 采用 SHA1 签名认证。
# 每次请求需在 header 中携带 appId、timestamp、sign 三个字段。
# sign 的计算方式由 ITSM API 文档定义,此模块封装为静态工具类。
# =============================================================================
import hashlib
import json
import time
from urllib.parse import quote_plus
class ITSMSigner:
"""ITSM OpenAPI 签名工具 — SHA1 签名认证。
签名算法(来自 ITSM API 文档):
1. 组装 sign_params = {appId, timestamp, appSecret, bizData=json.dumps(body)}
2. 按 key 升序排列
3. 拼接所有 value 为一个字符串
4. quote_plus 编码
5. SHA1 哈希
6. 转大写 hex
设计为纯静态工具类,无需实例化,线程安全。
"""
@staticmethod
def compute_signature(app_id: str, timestamp: str, app_secret: str, biz_data: dict) -> str:
"""计算 ITSM API 签名。
Args:
app_id: ITSM OpenAPI app_id
timestamp: 毫秒级时间戳字符串
app_secret: ITSM OpenAPI app_secret
biz_data: 请求体(业务数据),将被 json 序列化后参与签名
Returns:
str: 大写 hex 格式的 SHA1 签名
"""
sign_params = {
"appSecret": app_secret,
"appId": app_id,
"timestamp": timestamp,
"bizData": json.dumps(biz_data, ensure_ascii=False),
}
# 按 key 升序排列后拼接所有 value
sorted_params = sorted(sign_params.items(), key=lambda x: x[0])
canonicalized = "".join(str(v) for _, v in sorted_params)
# URL 编码
quoted = quote_plus(canonicalized)
# SHA1 哈希转大写
return hashlib.sha1(quoted.encode("utf-8")).hexdigest().upper()
@staticmethod
def get_headers(app_id: str, app_secret: str, biz_data: dict) -> dict:
"""生成带签名的请求头。
Args:
app_id: ITSM OpenAPI app_id
app_secret: ITSM OpenAPI app_secret
biz_data: 请求体(业务数据),用于计算签名
Returns:
dict: 包含 appId、timestamp、sign、Content-Type 的请求头
"""
timestamp = str(int(time.time() * 1000))
sign = ITSMSigner.compute_signature(app_id, timestamp, app_secret, biz_data)
return {
"appId": app_id,
"timestamp": timestamp,
"sign": sign,
"Content-Type": "application/json",
}