front/scripts/verify-aop-signature.py
zzh 5a26ae0048 feat: 小红书模块迁移、登录重构与 xhs-agent-desktop 桌面 Agent
- 新增小红书前端模块(启动服务、内容分析、爆款创作、发布记录、技能卡片、拟人设置、AI 助手)

- 新增 xhs-agent-desktop 独立桌面 Agent,对接 OMS 任务调度

- 登录页重构,整合微信登录与 OMS JWT 认证

- 订单、渠道、用户中心等页面与 API 增强

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 16:13:13 +08:00

85 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""Verify Alibaba AOP signatureWithParamsAndUrlPath against a known-good URL."""
import hashlib
import hmac
from urllib.parse import unquote
EXPECTED = "c950e08db859f1d3899d88a30dc2b8b46e5b3394"
URL_PATH = "param2/1/ali.intl.onetouch/logistics.order.notifyBizEvent/842172"
# Exact notifyBizEventDTO value from the working URL (query-decoded once)
DTO_FROM_URL = unquote(
"%7B%22aliOrderNo%22%3A%22ALS01691955122%22%2C%22apiMessageCode%22%3A31%2C"
"%22eventCode%22%3A%22WAREHOUSE_INBOUND%22%2C%22eventTime%22%3A%222026-06-06T09%3A24%3A50%2B0800%22%2C"
"%22extInfo%22%3A%22%22%2C%22location%22%3A%22CHINA+SHENZHEN%22%2C%22reason%22%3A%22%22%2C%22status%22%3A%22SUCCESS%22%7D"
)
# C# JsonConvert.SerializeObject often uses space after colon/comma
DTO_CSHARP_LIKE = (
'{"aliOrderNo":"ALS01691955122","apiMessageCode":31,"eventCode":"WAREHOUSE_INBOUND",'
'"eventTime":"2026-06-06T09:24:50+0800","extInfo":"","location":"CHINA SHENZHEN",'
'"reason":"","status":"SUCCESS"}'
)
# location with + instead of space (as in URL before decode)
DTO_LOCATION_PLUS = DTO_FROM_URL.replace("CHINA SHENZHEN", "CHINA+SHENZHEN")
def hmac_sha1_hex_lower(secret: str, data: str) -> str:
return hmac.new(secret.encode("utf-8"), data.encode("utf-8"), hashlib.sha1).hexdigest()
def hmac_sha1_hex_upper(secret: str, data: str) -> str:
return hmac_sha1_hex_lower(secret, data).upper()
def sign_url_path_params(secret: str, url_path: str, params: dict[str, str]) -> str:
"""1688 CommonUtil.signatureWithParamsAndUrlPath style."""
parts = [url_path]
for key in sorted(params.keys()):
parts.append(key + params[key])
sign_str = "".join(parts)
return hmac_sha1_hex_lower(secret, sign_str), sign_str
def sign_py_style(secret: str, url_path: str, dto: str) -> tuple[str, str, str]:
"""Match E:/py脚本/平台exe/al_tax_core.py sign()."""
param_list = ["notifyBizEventDTO" + dto]
param_list.sort()
sign_str = url_path + "".join(param_list)
digest = hmac.new(secret.encode("utf-8"), sign_str.encode("utf-8"), hashlib.sha1).hexdigest()
return digest, digest.upper(), sign_str
def main() -> None:
import sys
secret = sys.argv[1] if len(sys.argv) > 1 else "5VGqKYWs4UOA"
candidates = {
"dto_from_url": DTO_FROM_URL,
"dto_csharp_like": DTO_CSHARP_LIKE,
"dto_location_plus": DTO_LOCATION_PLUS,
}
print("Expected:", EXPECTED)
print("Secret:", secret[:4] + "***")
for label, dto in candidates.items():
lower_sorted, sign_str = sign_url_path_params(
secret, URL_PATH, {"notifyBizEventDTO": dto}
)
py_lower, py_upper, py_str = sign_py_style(secret, URL_PATH, dto)
match_lower = lower_sorted == EXPECTED
match_py_lower = py_lower == EXPECTED
match_py_upper = py_upper.lower() == EXPECTED
print(f"\n[{label}]")
print(" sorted-dict lower:", lower_sorted, "MATCH" if match_lower else "")
print(" py-style lower:", py_lower, "MATCH" if match_py_lower else "")
print(" py-style upper:", py_upper, "MATCH" if py_upper == EXPECTED else "")
print(" sign_str len:", len(py_str))
if py_str != sign_str:
print(" NOTE: sign_str differs between implementations")
if __name__ == "__main__":
main()