package lewan import ( "testing" "time" ) func TestOfficialVectors(t *testing.T) { // 固定密钥与时间戳 accessKey := "ak_test_fixed_20260905" secretKey := "sk_test_fixed_20260905" timestamp := "1788566400" _ = accessKey // Vector 1: GET 查询 t.Run("Vector1_GET_Query", func(t *testing.T) { method := "GET" path := "/openapi/v1/products" rawQuery := "pageSize=20&page=1" nonce := "nonce_get_20260905_fixed" bodySHA256 := EmptyBodySHA256 expectedSig := "54ea478585e61230be670d664745c81ffb4907b87c8592bf082c9cc894232adf" signingStr := BuildSigningString(method, path, rawQuery, bodySHA256, timestamp, nonce) expectedSigningStr := "GET\n/openapi/v1/products\npage=1&pageSize=20\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n1788566400\nnonce_get_20260905_fixed" if signingStr != expectedSigningStr { t.Fatalf("signing string mismatch:\ngot:\n%s\nwant:\n%s", signingStr, expectedSigningStr) } sig := SignRequest(secretKey, signingStr) if sig != expectedSig { t.Fatalf("signature mismatch:\ngot: %s\nwant: %s", sig, expectedSig) } }) // Vector 2: POST JSON t.Run("Vector2_POST_JSON", func(t *testing.T) { method := "POST" path := "/openapi/v1/orders" rawQuery := "" body := []byte(`{"callerOrderId":"DOC-20260905-001","roleId":"1148711973","items":[{"productId":"00000000-0000-4000-8000-000000000101","quantity":2}]}`) nonce := "nonce_post_20260905_fixed" expectedBodySHA := "146e687459b70c7fdf2781f72593306a8041aa0d5212207459dc71cd76e59032" expectedSig := "1e1d3df46b885e76b1e992585215e488c29315e7207e62df4aa26b0124d04968" bodySHA := SHA256Hex(body) if bodySHA != expectedBodySHA { t.Fatalf("body SHA256 mismatch:\ngot: %s\nwant: %s", bodySHA, expectedBodySHA) } signingStr := BuildSigningString(method, path, rawQuery, bodySHA, timestamp, nonce) expectedSigningStr := "POST\n/openapi/v1/orders\n\n146e687459b70c7fdf2781f72593306a8041aa0d5212207459dc71cd76e59032\n1788566400\nnonce_post_20260905_fixed" if signingStr != expectedSigningStr { t.Fatalf("signing string mismatch:\ngot:\n%s\nwant:\n%s", signingStr, expectedSigningStr) } sig := SignRequest(secretKey, signingStr) if sig != expectedSig { t.Fatalf("signature mismatch:\ngot: %s\nwant: %s", sig, expectedSig) } }) // Vector 3: 重复查询参数 t.Run("Vector3_Duplicate_Query", func(t *testing.T) { method := "GET" path := "/openapi/v1/orders" rawQuery := "status=SUCCEEDED&keyword=%E4%BA%91%20%E8%A7%A6%E8%A7%92&status=FAILED" nonce := "nonce_repeat_20260905_fixed" expectedSig := "c1c2be18372e3ac89e8042f3477fff8287126e31777a18a593c0cce7028626d8" normQuery := NormalizeQuery(rawQuery) expectedNormQuery := "keyword=%E4%BA%91%20%E8%A7%A6%E8%A7%92&status=FAILED&status=SUCCEEDED" if normQuery != expectedNormQuery { t.Fatalf("normalized query mismatch:\ngot: %s\nwant: %s", normQuery, expectedNormQuery) } signingStr := BuildSigningString(method, path, rawQuery, EmptyBodySHA256, timestamp, nonce) sig := SignRequest(secretKey, signingStr) if sig != expectedSig { t.Fatalf("signature mismatch:\ngot: %s\nwant: %s", sig, expectedSig) } }) // Vector 4: POST 空请求体 t.Run("Vector4_POST_Empty_Body", func(t *testing.T) { method := "POST" path := "/openapi/v1/orders/00000000-0000-4000-8000-000000000201/account/release" rawQuery := "" nonce := "nonce_empty_20260905_fixed" expectedSig := "167f6d7c116fc7e51b0d2418e65a0705f08076940025f2c013adbd8f27648908" signingStr := BuildSigningString(method, path, rawQuery, EmptyBodySHA256, timestamp, nonce) sig := SignRequest(secretKey, signingStr) if sig != expectedSig { t.Fatalf("signature mismatch:\ngot: %s\nwant: %s", sig, expectedSig) } }) // Vector 5: Webhook 固定向量 t.Run("Vector5_Webhook", func(t *testing.T) { webhookSecret := "whsec_test_fixed_20260905" eventID := "00000000-0000-4000-8000-000000000302" rawBody := []byte(`{"applicationId":"00000000-0000-4000-8000-000000000301","data":{"callerOrderId":"DOC-20260905-001","failedQuantity":1,"failureCodes":["SUPPLIER_REJECTED"],"orderId":"00000000-0000-4000-8000-000000000303","pendingQuantity":0,"releasedQuantity":0,"status":"PARTIAL_SUCCESS","succeededQuantity":1},"eventId":"00000000-0000-4000-8000-000000000302","occurredAt":"2026-09-05T00:00:00.000Z","orderVersion":7,"schemaVersion":"1.0","type":"ORDER_COMPLETED"}`) expectedSig := "v1=ee3968ef467a4f9c19c0a33e7af1bb3118fab8d02c5ebf9cbd8001cc34ebe6be" sig := SignWebhook(webhookSecret, timestamp, eventID, rawBody) if sig != expectedSig { t.Fatalf("webhook signature mismatch:\ngot: %s\nwant: %s", sig, expectedSig) } // 测试验证函数(不限时限) if !VerifyWebhook(webhookSecret, sig, timestamp, eventID, rawBody, 0) { t.Fatalf("VerifyWebhook should succeed") } // 测试错误 secret if VerifyWebhook("wrong_secret", sig, timestamp, eventID, rawBody, 0) { t.Fatalf("VerifyWebhook should fail with wrong secret") } // 测试时间窗口超限 if VerifyWebhook(webhookSecret, sig, timestamp, eventID, rawBody, 5*time.Minute) { t.Fatalf("VerifyWebhook should fail for expired timestamp") } }) }