Golang中SOAP请求的实现与问题解决

Golang中SOAP请求的实现与问题解决 响应类似: 我们找不到您的 wsUserName

httpClient := &http.Client{
				Timeout: 5000 * time.Millisecond,
			}

			soap, err := gosoap.SoapClient("http://webservices.yurticikargo.com:8080/KOPSWebServices/ShippingOrderDispatcherServices?wsdl", httpClient)
			if err != nil {
				log.Fatalf("SoapClient error: %s", err)
			}

			params := gosoap.Params{
				"wsUserName":        customerInfo.Username,
				"wsPassword":        customerInfo.Password,
				"wsLanguage":        "TR",
				"keys":              customerInfo.CargoKey,
				"keyType":           0,
				"addHistoricalData": false,
				"onlyTracking":      false}
			res, _ := soap.Call("queryShipment", params)
			res.Unmarshal(&r)
			result := ShippingDeliveryVO{}
			err = xml.Unmarshal([]byte(r.ShippingDeliveryVO), &result)
			if err != nil {
				log.Fatalf("xml.Unmarshal error: %s", err)
			}

		log.Println("Country: ", result.outFlag)
		log.Println("State: ", result.outResult)

当我使用 soapui 时,我可以得到返回。

www


更多关于Golang中SOAP请求的实现与问题解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中SOAP请求的实现与问题解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


从你的代码和错误信息来看,问题很可能出在SOAP请求的格式或参数传递上。gosoap库在处理某些WSDL时可能存在格式兼容性问题。以下是更可靠的实现方案:

package main

import (
    "bytes"
    "encoding/xml"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

type Envelope struct {
    XMLName xml.Name `xml:"soap:Envelope"`
    Soap    string   `xml:"xmlns:soap,attr"`
    Xsi     string   `xml:"xmlns:xsi,attr"`
    Xsd     string   `xml:"xmlns:xsd,attr"`
    Body    Body
}

type Body struct {
    XMLName xml.Name `xml:"soap:Body"`
    Query   QueryShipment
}

type QueryShipment struct {
    XMLName         xml.Name `xml:"queryShipment"`
    Xmlns           string   `xml:"xmlns,attr"`
    WsUserName      string   `xml:"wsUserName"`
    WsPassword      string   `xml:"wsPassword"`
    WsLanguage      string   `xml:"wsLanguage"`
    Keys            string   `xml:"keys"`
    KeyType         int      `xml:"keyType"`
    AddHistoricalData bool   `xml:"addHistoricalData"`
    OnlyTracking    bool     `xml:"onlyTracking"`
}

type Response struct {
    XMLName xml.Name `xml:"Envelope"`
    Body    struct {
        QueryShipmentResponse struct {
            Result string `xml:"result"`
        } `xml:"queryShipmentResponse"`
    } `xml:"Body"`
}

func main() {
    // 构建SOAP请求
    request := Envelope{
        Soap: "http://schemas.xmlsoap.org/soap/envelope/",
        Xsi:  "http://www.w3.org/2001/XMLSchema-instance",
        Xsd:  "http://www.w3.org/2001/XMLSchema",
        Body: Body{
            Query: QueryShipment{
                Xmlns:           "http://yurticikargo.com.tr/ShippingOrderDispatcherServices",
                WsUserName:      "your_username",
                WsPassword:      "your_password",
                WsLanguage:      "TR",
                Keys:            "cargo_key",
                KeyType:         0,
                AddHistoricalData: false,
                OnlyTracking:    false,
            },
        },
    }

    // 序列化XML
    xmlData, err := xml.MarshalIndent(request, "", "  ")
    if err != nil {
        fmt.Printf("XML Marshal error: %v\n", err)
        return
    }

    // 添加SOAP头部
    soapRequest := []byte(xml.Header + string(xmlData))

    // 创建HTTP客户端
    client := &http.Client{
        Timeout: 5 * time.Second,
    }

    // 发送请求
    req, err := http.NewRequest("POST", 
        "http://webservices.yurticikargo.com:8080/KOPSWebServices/ShippingOrderDispatcherServices",
        bytes.NewBuffer(soapRequest))
    if err != nil {
        fmt.Printf("Request creation error: %v\n", err)
        return
    }

    // 设置必要的HTTP头
    req.Header.Set("Content-Type", "text/xml; charset=utf-8")
    req.Header.Set("SOAPAction", "queryShipment")

    // 执行请求
    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("HTTP request error: %v\n", err)
        return
    }
    defer resp.Body.Close()

    // 读取响应
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Read response error: %v\n", err)
        return
    }

    fmt.Printf("Response Status: %s\n", resp.Status)
    fmt.Printf("Response Body:\n%s\n", string(body))

    // 解析响应
    var response Response
    err = xml.Unmarshal(body, &response)
    if err != nil {
        fmt.Printf("XML Unmarshal error: %v\n", err)
        return
    }

    fmt.Printf("Query Result: %s\n", response.Body.QueryShipmentResponse.Result)
}

如果需要处理更复杂的响应结构,可以这样定义:

type ShippingDeliveryVO struct {
    OutFlag   string `xml:"outFlag"`
    OutResult string `xml:"outResult"`
    // 添加其他字段
}

type DetailedResponse struct {
    XMLName xml.Name `xml:"Envelope"`
    Body    struct {
        QueryShipmentResponse struct {
            ShippingDeliveryVO ShippingDeliveryVO `xml:"ShippingDeliveryVO"`
        } `xml:"queryShipmentResponse"`
    } `xml:"Body"`
}

func parseDetailedResponse(body []byte) {
    var resp DetailedResponse
    err := xml.Unmarshal(body, &resp)
    if err != nil {
        fmt.Printf("Detailed parse error: %v\n", err)
        return
    }
    
    fmt.Printf("Country: %s\n", resp.Body.QueryShipmentResponse.ShippingDeliveryVO.OutFlag)
    fmt.Printf("State: %s\n", resp.Body.QueryShipmentResponse.ShippingDeliveryVO.OutResult)
}

这个实现直接使用标准库的encoding/xml包,确保SOAP请求格式正确,特别是:

  1. 正确的XML命名空间声明
  2. 正确的SOAPAction头部
  3. 符合目标服务期望的XML结构

注意替换代码中的用户名、密码和货物密钥为实际值。如果仍有问题,建议使用Wireshark或tcpdump捕获网络包,对比SOAP UI和Go程序发送的原始请求差异。

回到顶部