I am currently working on implementing a SOAP API in Go. I used the Hooklift's GoWSDL (http://ift.tt/1uKMe1t) to compile the WSDL file (http://ift.tt/1vifnHb) into Go, then changed it over to GAE Go. However, I'm having problem with the code still. I call the API through:
req:=new(OKPay.GetDateTime)
api:=OKPay.NewI_OkPayAPI("https://api.okpay.com", true)
resp, err:=api.GetDateTime(c, req)
c.Debugf("resp, err - %v, %v", resp, err)
And the response I get is essentially the HTML code from http://ift.tt/1uKMfT1 , rather than an envelope response. I suspect I might be using a wrong URL to initialize the API, but I'm not sure.
Here is the rest of the relevant code:
OKPay.go:
package OKPay
import (
"encoding/xml"
"time"
"appengine"
gowsdl "http://ift.tt/1vifpP7"
)
var _ time.Time
var _ xml.Name
type GetDateTime struct {
XMLName xml.Name `xml:"https://api.okpay.com Get_Date_Time"`
}
type GetDateTimeResponse struct {
XMLName xml.Name `xml:"https://api.okpay.com Get_Date_TimeResponse"`
GetDateTimeResult string `xml:"Get_Date_TimeResult,omitempty"`
}
type I_OkPayAPI struct {
client *gowsdl.SoapClient
}
func NewI_OkPayAPI(url string, tls bool) *I_OkPayAPI {
if url == "" {
url = ""
}
client := gowsdl.NewSoapClient(url, tls)
return &I_OkPayAPI{
client: client,
}
}
func (service *I_OkPayAPI) GetDateTime(c appengine.Context, request *GetDateTime) (*GetDateTimeResponse, error) {
response := &GetDateTimeResponse{}
err := service.client.Call(c, "http://ift.tt/1uKMe1w", request, response)
if err != nil {
return nil, err
}
return response, nil
}
GAESoap.go:
package GAESoap
import (
"appengine"
"appengine/urlfetch"
"bytes"
//"crypto/tls"
"encoding/xml"
"io/ioutil"
"net/http"
"time"
"net"
)
var timeout = time.Duration(30 * time.Second)
func dialTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
}
type SoapEnvelope struct {
XMLName xml.Name `xml:"http://ift.tt/sVJIaE Envelope"`
//Header SoapHeader `xml:"http://ift.tt/sVJIaE Header,omitempty"`
Body SoapBody `xml:"http://ift.tt/sVJIaE Body"`
}
type SoapHeader struct {
Header interface{}
}
type SoapBody struct {
Fault *SoapFault `xml:"http://ift.tt/sVJIaE Fault,omitempty"`
Content string `xml:",innerxml"`
}
type SoapFault struct {
Faultcode string `xml:"faultcode,omitempty"`
Faultstring string `xml:"faultstring,omitempty"`
Faultactor string `xml:"faultactor,omitempty"`
Detail string `xml:"detail,omitempty"`
}
type SoapClient struct {
url string
tls bool
}
func (f *SoapFault) Error() string {
return f.Faultstring
}
func NewSoapClient(url string, tls bool) *SoapClient {
return &SoapClient{
url: url,
tls: tls,
}
}
func (s *SoapClient) Call(c appengine.Context, soapAction string, request, response interface{}) error {
envelope := SoapEnvelope{
//Header: SoapHeader{},
}
if request != nil {
reqXml, err := xml.Marshal(request)
if err != nil {
c.Errorf("Call - %v", err)
return err
}
envelope.Body.Content = string(reqXml)
}
buffer := &bytes.Buffer{}
encoder := xml.NewEncoder(buffer)
//encoder.Indent(" ", " ")
err := encoder.Encode(envelope)
if err == nil {
err = encoder.Flush()
}
if err != nil {
c.Errorf("Call - %v", err)
return err
}
req, err := http.NewRequest("POST", s.url, buffer)
req.Header.Add("Content-Type", "text/xml; charset=\"utf-8\"")
if soapAction != "" {
req.Header.Add("SOAPAction", soapAction)
}
req.Header.Set("User-Agent", "gowsdl/0.1")
tr := urlfetch.Transport{
/*TLSClientConfig: &tls.Config{
InsecureSkipVerify: s.tls,
},
Dial: dialTimeout,*/
Context: c,
}
client := &http.Client{Transport: &tr}
res, err := client.Do(req)
if err != nil {
c.Errorf("Call - %v", err)
return err
}
defer res.Body.Close()
c.Debugf("res - %v", res)
rawbody, err := ioutil.ReadAll(res.Body)
if len(rawbody) == 0 {
c.Warningf("empty response")
return nil
}
respEnvelope := &SoapEnvelope{}
err = xml.Unmarshal(rawbody, respEnvelope)
if err != nil {
c.Errorf("Call - %v", err)
c.Debugf("rawbody - %x", rawbody)
c.Debugf("respEnvelope - %x", respEnvelope)
return err
}
body := respEnvelope.Body.Content
fault := respEnvelope.Body.Fault
if body == "" {
c.Warningf("empty response body", "envelope", respEnvelope, "body", body)
return nil
}
c.Debugf("response", "envelope", respEnvelope, "body", body)
if fault != nil {
c.Errorf("Call - %v", fault)
return fault
}
err = xml.Unmarshal([]byte(body), response)
if err != nil {
c.Errorf("Call - %v", err)
return err
}
return nil
}
What would be the proper way to call the SOAP API? Is it the problem with the URL I use to initialize the API, or is it something else?
No comments:
Post a Comment