Je suis nouveau sur golang et j'essaye de faire un appel savon avec gowsdl .
J'ai généré le code wsdl et l'ai installé sous forme de package. J'ai cependant du mal à comprendre la syntaxe pour appeler la méthode à partir d'elle.
Lorsque j'examine le paquet, voici ce que je veux dans le corps du savon:
type AccountUser struct {
XMLName xml.Name `xml:"http://exacttarget.com/wsdl/partnerAPI AccountUser"`
*APIObject
AccountUserID int32 `xml:"AccountUserID,omitempty"`
UserID string `xml:"UserID,omitempty"`
Password string `xml:"Password,omitempty"`
Name string `xml:"Name,omitempty"`
Email string `xml:"Email,omitempty"`
MustChangePassword bool `xml:"MustChangePassword,omitempty"`
ActiveFlag bool `xml:"ActiveFlag,omitempty"`
ChallengePhrase string `xml:"ChallengePhrase,omitempty"`
ChallengeAnswer string `xml:"ChallengeAnswer,omitempty"`
UserPermissions []*UserAccess `xml:"UserPermissions,omitempty"`
Delete int32 `xml:"Delete,omitempty"`
LastSuccessfulLogin time.Time `xml:"LastSuccessfulLogin,omitempty"`
IsAPIUser bool `xml:"IsAPIUser,omitempty"`
NotificationEmailAddress string `xml:"NotificationEmailAddress,omitempty"`
IsLocked bool `xml:"IsLocked,omitempty"`
Unlock bool `xml:"Unlock,omitempty"`
BusinessUnit int32 `xml:"BusinessUnit,omitempty"`
DefaultBusinessUnit int32 `xml:"DefaultBusinessUnit,omitempty"`
DefaultApplication string `xml:"DefaultApplication,omitempty"`
Locale *Locale `xml:"Locale,omitempty"`
TimeZone *TimeZone `xml:"TimeZone,omitempty"`
DefaultBusinessUnitObject *BusinessUnit `xml:"DefaultBusinessUnitObject,omitempty"`
AssociatedBusinessUnits struct {
BusinessUnit []*BusinessUnit `xml:"BusinessUnit,omitempty"`
} `xml:"AssociatedBusinessUnits,omitempty"`
Roles struct {
Role []*Role `xml:"Role,omitempty"`
} `xml:"Roles,omitempty"`
LanguageLocale *Locale `xml:"LanguageLocale,omitempty"`
SsoIdentities struct {
SsoIdentity []*SsoIdentity `xml:"SsoIdentity,omitempty"`
} `xml:"SsoIdentities,omitempty"`
}
Et la méthode pour appeler le SOAP est:
func (s *SOAPClient) Call(soapAction string, request, response interface{}) error {
envelope := SOAPEnvelope{
//Header: SoapHeader{},
}
envelope.Body.Content = request
buffer := new(bytes.Buffer)
encoder := xml.NewEncoder(buffer)
//encoder.Indent(" ", " ")
if err := encoder.Encode(envelope); err != nil {
return err
}
if err := encoder.Flush(); err != nil {
return err
}
log.Println(buffer.String())
req, err := http.NewRequest("POST", s.url, buffer)
if err != nil {
return err
}
if s.auth != nil {
req.SetBasicAuth(s.auth.Login, s.auth.Password)
}
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")
req.Close = true
tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: s.tls,
},
Dial: dialTimeout,
}
client := &http.Client{Transport: tr}
res, err := client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
rawbody, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if len(rawbody) == 0 {
log.Println("empty response")
return nil
}
log.Println(string(rawbody))
respEnvelope := new(SOAPEnvelope)
respEnvelope.Body = SOAPBody{Content: response}
err = xml.Unmarshal(rawbody, respEnvelope)
if err != nil {
return err
}
fault := respEnvelope.Body.Fault
if fault != nil {
return fault
}
return nil
}
J'ai importé le package dans mon fichier go et j'aimerais avoir des conseils sur la façon d'appeler cela.
Pour utiliser le code généré, vous devrez évidemment initialiser d'abord le client soap avec l'une des fonctions "constructeur" générées NewSOAPClient
ou NewSOAPClientWithTLSConfig
.
Après cela, vous devrez préparer des valeurs two que vous pouvez utiliser comme arguments de demande et de réponse à la méthode Call
, elles représentent le contenu du corps des charges utiles de demande/réponse de savon.
Les types de ces deux valeurs dépendent du type d'appel que vous souhaitez effectuer, par exemple les appels hypothétiques create_account, update_account et delete_account nécessitent généralement des types différents. Fondamentalement, le type de la valeur request
doit être marshalable dans un xml qui correspond au xml attendu par le service soap pour l'action spécifiée , et le type de response
doit être non commercialisable à partir d'un xml qui correspond à la réponse documentée du service soap pour l'action spécifiée.
Considérez cet exemple artificiel:
Il existe un service SOAP qui vous permet de créer des utilisateurs. Pour que vous puissiez créer un utilisateur avec le service, vous devez envoyer un e-mail et un mot de passe, et si tout est ok, il le fera renvoie un identifiant. Dans un tel cas, vos deux types de demande/réponse devraient ressembler à ceci:
type CreateUserRequest struct {
Email string `xml:"Email,omitempty"`
Password string `xml:"Password,omitempty"`
}
type CreateUserResponse struct {
ID string `xml:"ID"`
}
Ensuite, le code client ressemblerait à ceci:
client := NewSOAPClient("https://soap.example.com/call", true, nil)
req := &CreateUserRequest{
Email: "[email protected]",
Password: "1234567890",
}
res := &CreateUserResponse{}
if err := client.Call("create_user", req, res); err != nil {
panic(err)
}
// if everything went well res.ID should have its
// value set with the one returned by the service.
fmt.Println(res.ID)