package osi import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "time" "chis_osi/contract" ) func TestClientCallPostsSignedEnvelopeAndDecodesSuccess(t *testing.T) { var seenPath string var seenPayload map[string]any var seenHeaders http.Header server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { seenPath = r.URL.Path seenHeaders = r.Header.Clone() if err := json.NewDecoder(r.Body).Decode(&seenPayload); err != nil { t.Fatalf("decode request: %v", err) } w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"code":"01","message":"操作成功","data":{"phrId":"phr-001"}}`)) })) defer server.Close() transport, err := NewTransport(TransportConfig{Timeout: time.Second}) if err != nil { t.Fatalf("NewTransport: %v", err) } client := NewClient(ClientConfig{ BaseURL: server.URL, OrgCode: "12441625456962881G", DeviceSN: "device-001", UserName: "dyytgw", Ask: "secret-key", OperateUser: "712041", OperateUnit: "12441625456962881G", Transport: transport, NowMillis: func() string { return "1700000000123" }, }) var out struct { PHRID string `json:"phrId"` } result, err := client.Call(context.Background(), ServiceIDJKDAFind, map[string]string{"idCard": "440100199001011234"}, &out) if err != nil { t.Fatalf("Call: %v", err) } if seenPath != "/osi/api/auto/jkda/find" { t.Fatalf("path = %q", seenPath) } if seenHeaders.Get("orgCode") != "12441625456962881G" { t.Fatalf("orgCode header = %q", seenHeaders.Get("orgCode")) } if seenHeaders.Get("password") != "008aceff8247cb42d2a99b2c48d0ac88" { t.Fatalf("password header = %q", seenHeaders.Get("password")) } if _, ok := seenPayload["uploadinfo"]; !ok { t.Fatalf("payload missing uploadinfo: %#v", seenPayload) } if seenPayload["serviceId"] != ServiceIDJKDAFind { t.Fatalf("serviceId = %v", seenPayload["serviceId"]) } uploadInfo := seenPayload["uploadinfo"].(map[string]any) baseInfo := uploadInfo["baseInfo"].(map[string]any) if baseInfo["idCard"] != "440100199001011234" { t.Fatalf("baseInfo.idCard = %v", baseInfo["idCard"]) } manageInfo := uploadInfo["manageInfo"].(map[string]any) if manageInfo["DSFMC"] != "dyytgw" || manageInfo["operateUser"] != "712041" || manageInfo["operateUnit"] != "12441625456962881G" { t.Fatalf("manageInfo = %#v", manageInfo) } if !result.Success || result.Retryable { t.Fatalf("result = %#v", result) } if out.PHRID != "phr-001" { t.Fatalf("decoded phrId = %q", out.PHRID) } } func TestClientCallMarks405Retryable(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, _ = w.Write([]byte(`{"code":"405","message":"服务调用超时"}`)) })) defer server.Close() transport, err := NewTransport(TransportConfig{Timeout: time.Second}) if err != nil { t.Fatalf("NewTransport: %v", err) } client := NewClient(ClientConfig{BaseURL: server.URL, UserName: "dyytgw", Ask: "secret-key", Transport: transport}) result, err := client.Call(context.Background(), ServiceIDJKDAFind, contract.UploadInfo{}, nil) if err == nil { t.Fatal("Call returned nil error for 405") } if !result.Retryable || result.Success { t.Fatalf("result = %#v", result) } } func TestClientCallGeneratesTimestampWhenClockNotInjected(t *testing.T) { var seenTS string server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { seenTS = r.Header.Get("ts") _, _ = w.Write([]byte(`{"code":"01","message":"操作成功"}`)) })) defer server.Close() transport, err := NewTransport(TransportConfig{Timeout: time.Second}) if err != nil { t.Fatalf("NewTransport: %v", err) } client := NewClient(ClientConfig{BaseURL: server.URL, UserName: "dyytgw", Ask: "secret-key", Transport: transport}) if _, err := client.Call(context.Background(), ServiceIDJKDAFind, map[string]string{"idCard": "440100199001011234"}, nil); err != nil { t.Fatalf("Call: %v", err) } if len(seenTS) != 13 { t.Fatalf("ts header length = %d, want 13; ts=%q", len(seenTS), seenTS) } } func TestClientURLForAcceptsBaseURLWithAPIPath(t *testing.T) { client := NewClient(ClientConfig{BaseURL: "http://example.test/osi/api/"}) got := client.urlFor("/auto/jkda/find") want := "http://example.test/osi/api/auto/jkda/find" if got != want { t.Fatalf("urlFor = %q, want %q", got, want) } }