package lakala import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "strings" "testing" ) func TestVerifyNotifyDetail(t *testing.T) { key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { t.Fatalf("generate key: %v", err) } privatePEM, certPEM := testKeyPairPEM(t, key) client := NewClient(Config{ GatewayURL: "https://example.com", AppID: "app-1", SerialNo: "serial-1", MerchantID: "merchant-1", PrivateKey: privatePEM, NotifyCert: certPEM, }) body := `{"req_data":{"out_order_no":"NO1","total_amount":100,"trade_state":"SUCCESS"}}` message := "1710000000\nabc123\n" + body + "\n" signature, err := signRSA(key, []byte(message)) if err != nil { t.Fatalf("signRSA: %v", err) } authorization := `LKLAPI-SHA256withRSA timestamp="1710000000",nonce_str="abc123",signature="` + signature + `"` result := client.VerifyNotifyDetail(body, authorization) if !result.OK { t.Fatalf("VerifyNotifyDetail().OK = false, got=%s expected=%v base=%v", result.Got, result.Expected, result.BaseString) } tampered := client.VerifyNotifyDetail(strings.Replace(body, "100", "101", 1), authorization) if tampered.OK { t.Fatal("VerifyNotifyDetail() = true after body changed, want false") } } func TestParsePayloadNormalizesAliases(t *testing.T) { params, err := ParsePayload([]byte(`{ "req_data": { "out_order_no": "ORDER1", "pay_order_no": "PAY1", "total_amount": 88, "trade_state": "SUCCESS", "trade_time": "20240521101010" } }`)) if err != nil { t.Fatalf("ParsePayload error = %v", err) } if params["third_order_id"] != "ORDER1" { t.Fatalf("third_order_id = %q, want ORDER1", params["third_order_id"]) } if params["provider_order_id"] != "PAY1" { t.Fatalf("provider_order_id = %q, want PAY1", params["provider_order_id"]) } if params["amount"] != "88" { t.Fatalf("amount = %q, want 88", params["amount"]) } if params["status"] != "paid" { t.Fatalf("status = %q, want paid", params["status"]) } } func testKeyPairPEM(t *testing.T, key *rsa.PrivateKey) (string, string) { t.Helper() privateDER := x509.MarshalPKCS1PrivateKey(key) privatePEM := string(pem.EncodeToMemory(&pem.Block{ Type: "RSA PRIVATE KEY", Bytes: privateDER, })) template := &x509.Certificate{} certDER, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key) if err != nil { t.Fatalf("create certificate: %v", err) } certPEM := string(pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: certDER, })) return privatePEM, certPEM }