76 lines
2.7 KiB
Python
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",
|
||
|
|
}
|