feat(osi): 实现 MD5 头签名与请求头组装(T-002)
password=md5("ts=<ts>&ask=<ask>") 32 位小写;ask 仅参与签名不进 headers
测试向量与本地 Python 联调脚本对齐
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package osi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HeaderInput struct {
|
||||||
|
OrgCode string
|
||||||
|
DeviceSN string
|
||||||
|
UserName string
|
||||||
|
Ask string
|
||||||
|
TS string
|
||||||
|
}
|
||||||
|
|
||||||
|
func SignPassword(ts, ask string) string {
|
||||||
|
sum := md5.Sum([]byte("ts=" + ts + "&ask=" + ask))
|
||||||
|
return hex.EncodeToString(sum[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildHeaders(input HeaderInput) map[string]string {
|
||||||
|
return map[string]string{
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"orgCode": input.OrgCode,
|
||||||
|
"deviceSN": input.DeviceSN,
|
||||||
|
"ts": input.TS,
|
||||||
|
"userName": input.UserName,
|
||||||
|
"password": SignPassword(input.TS, input.Ask),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package osi
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestSignPasswordMatchesPythonScriptVector(t *testing.T) {
|
||||||
|
got := SignPassword("1700000000123", "secret-key")
|
||||||
|
want := "008aceff8247cb42d2a99b2c48d0ac88"
|
||||||
|
if got != want {
|
||||||
|
t.Fatalf("SignPassword() = %q, want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildHeadersIncludesSignatureFields(t *testing.T) {
|
||||||
|
headers := BuildHeaders(HeaderInput{
|
||||||
|
OrgCode: "12441625456962881G",
|
||||||
|
DeviceSN: "device-001",
|
||||||
|
UserName: "dyytgw",
|
||||||
|
Ask: "secret-key",
|
||||||
|
TS: "1700000000123",
|
||||||
|
})
|
||||||
|
|
||||||
|
if headers["Content-Type"] != "application/json" {
|
||||||
|
t.Fatalf("Content-Type = %q", headers["Content-Type"])
|
||||||
|
}
|
||||||
|
if headers["orgCode"] != "12441625456962881G" {
|
||||||
|
t.Fatalf("orgCode = %q", headers["orgCode"])
|
||||||
|
}
|
||||||
|
if headers["deviceSN"] != "device-001" {
|
||||||
|
t.Fatalf("deviceSN = %q", headers["deviceSN"])
|
||||||
|
}
|
||||||
|
if headers["ts"] != "1700000000123" {
|
||||||
|
t.Fatalf("ts = %q", headers["ts"])
|
||||||
|
}
|
||||||
|
if headers["userName"] != "dyytgw" {
|
||||||
|
t.Fatalf("userName = %q", headers["userName"])
|
||||||
|
}
|
||||||
|
if headers["password"] != "008aceff8247cb42d2a99b2c48d0ac88" {
|
||||||
|
t.Fatalf("password = %q", headers["password"])
|
||||||
|
}
|
||||||
|
if _, ok := headers["ask"]; ok {
|
||||||
|
t.Fatal("headers must not include ask")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user