Webservice (WSDL) avec authentification SOAP (XML)
Bonjour,
Je suis en train de refaire le monde en VBA, mais je ne suis pas encore sur si c'est possible ou pas. Premier indice je n'ai pas trouvé beaucoup de ressources parlant du SOAP et du VBA sur le forum, et sur le net en général. Je suis moitié moitié, dans mes lectures certaines disent que ce n'est pas possible d'autres si... Mystère !!
Problématique je veux communiquer avec un Webservice sécurisée par un SOAP, j'ai réussi à savoir comment faite quand il n'y a pas d'authentification, simplement utiliser les formules WEBSERVICE et FILTERXML dans la feuille Excel. Maintenant je dois faire la même chose avec une enveloppe SOAP en langage XML, voici l'exemple d'une enveloppe que j'ai snifé par un packet snifer.
Je suis un peu perdu, et surtout perplexe de ne pas avoir plus trouvailles sur notre Google.
Je m'auto-réponds !
Bonjour le forum,
J'y suis arrivé, après deux ou trois semaines d’acharnement ça fonctionne je suis capable d'interroger l'API avec mon code VBA,
Je dois confesser que je ne connaissais pas le système de Webservice et API, que de nom, j'avais de vague notion d'XML, j’ignorais l’existence de SOAP et que je pensais avoir fait le tour du VBA (sans prétentions), à part quelques subtilités. Ça me fait penser que j'ose imaginer le nombre de librairies disponibles pour Excel pour lui faire faire n'importe quoi.
Je précise ça parce que je pense qu'il faut savoir de quoi il retourne pour comprendre un peu de quoi on parle. Pour que ça fonctionne avec une autre API, il va falloir lire l'XML, le SOAP, un modèle de préférence, sinon comme moi j'ai travaillé avec un snifer pour calquer les champs importants à mettre dans enveloppe SOAP.
Trêves d'intro, le vif du sujet...
Pour résumer, il a fallu créer un fichier SOAP au format XML dans le code VBA, en fait en texte "brut" pour l'envoyer via une requête HTTP toujours en VBA. Et traiter la réponse, cette partie là est encore embryonnaire.
- Pré-requis, les librairies :
Je ne suis exactement sûr desquelles sont essentielles, je les ai activées lors du tuto, mais il faut maximalement celles ci pour fonctionner. J'ai surligné en jaune celles que je pense être obligatoires.
Petit point à la co*, avec la période d’apprivoisement avec les notions précédentes (XML, API, etc), je pense avoir buté sur une chose simple, avoir la bonne adresse pour communiquer avec l'API, j'avais un truc du format https://*ADDRESSE API*/Api/v2/Downloads/***.wsdl au lieu de https://*ADDRESSE API*/Api/v2/***.asmx, je n'ai pas suffisament de connaissance pour savoir ce qu'est une bonne adresse et une mauvaise mais vérifier ce point me semble une bonne chose pour partir sur de bons rails.
- Le code:
Le code est dégeu, mais il fonctionne, je n'ai encore la mesure de ce qui est utilisé ou pas, mais dans les faits il reste plus qu'à le formater, et le rendre fonctionnel avec une fonction d'envois de données. Pour le moment on ne fait que consulter.Sub API_CALL() Dim sURL As String Dim sEnv As String Dim xmlDoc As New DOMDocument Dim sEnvlength As Integer Dim responseText As String Dim MyString As String Dim LastRow As Long MyString = "GetClaimStatus" Set ObjHttp = New MSXML2.XMLHttp sURL = "http://*ADDRESSE API*/Api/v2/***.asmx" sEnv = sEnv & "<?xml version=""1.0"" encoding=""utf-8""?>" sEnv = sEnv & "<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:wsa=""http://schemas.xmlsoap.org/ws/2004/08/addressing"" xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"" xmlns:wsu=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"">" sEnv = sEnv & " <soap:Header>" sEnv = sEnv & " <AuthenticationHeader AccountNumber=""USERNAME"" Password=""PASSWORD"" xmlns=""http://*ADDRESSE API*/webservices/"" />" sEnv = sEnv & " <wsa:Action>http://*ADDRESSE API*/webservices/GetClaimStatus</wsa:Action>" sEnv = sEnv & " <wsa:MessageID>urn:uuid:5e261edc-603f-46dc-8d62-a39ad3986f26</wsa:MessageID>" sEnv = sEnv & " <wsa:ReplyTo>" sEnv = sEnv & " <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>" sEnv = sEnv & " </wsa:ReplyTo>" sEnv = sEnv & " <wsa:To>http://*ADDRESSE API*/Api/v2/***.asmx</wsa:To>" sEnv = sEnv & " <wsse:Security>" sEnv = sEnv & " <wsu:Timestamp wsu:Id=""Timestamp"">" sEnv = sEnv & " <wsu:Created>" & Format(Now(), "yyyy-MM-dd") & "T" & Format(Now() + TimeSerial(5, 0, 0), "hh:mm:ss") & "Z</wsu:Created>" '+ TimeSerial(5, 0, 0) means + 5 hours, because Test is + 5 hours with Montreal sEnv = sEnv & " <wsu:Expires>" & Format(Now(), "yyyy-MM-dd") & "T" & Format(Now() + TimeSerial(5, 0, 0) + TimeSerial(0, 5, 0), "hh:mm:ss") & "Z</wsu:Expires>" sEnv = sEnv & " </wsu:Timestamp>" sEnv = sEnv & " </wsse:Security>" sEnv = sEnv & " </soap:Header>" sEnv = sEnv & " <soap:Body>" sEnv = sEnv & " <GetClaimStatus xmlns=""http://*ADDRESSE API*/webservices/"">" sEnv = sEnv & " <claimIDSpecification ClaimID=""22_02_2016_01"" ClaimIDType=""ClaimNumber"" />" sEnv = sEnv & " <companyIDSpecification CompanyID=""049-246-601"" CompanyIDType=""CompanyID"" />" sEnv = sEnv & " </GetClaimStatus>" sEnv = sEnv & " </soap:Body>" sEnv = sEnv & "</soap:Envelope>" sEnvlength = Len(sEnv) ObjHttp.Open "POST", sURL, False ObjHttp.setRequestHeader "Content-Type", "text/xml; charset=utf-8" ObjHttp.setRequestHeader "Content-Length", sEnvlength ObjHttp.send (sEnv) xmlDoc.LoadXML (ObjHttp.responseText) Cells(1, 1) = ObjHttp.responseText responseText = xmlDoc.SelectNodes("//claimStatus")(0).Text 'on next i (=2) I got Error '91' - object variable or With block variable not set MsgBox responseText sEnv = "" Set xmlDoc = Nothing Set ObjHttp = Nothing End Sub
- Dernier point, il y a des balises importantes sur lesquelles j'ai au début pensé qu'elles était secondaires, "Timestamp" je me suis résolu à les faire dynamiques, pour qu'elles prennent l'exacte heure du moment, le TimeSerial(5, 0, 0), c'est parce que j'ai un décalage de 5 heures avec le serveur, le TimeSerial(0, 5, 0) c'est pour ajouter 5 minutes à la date et heure actuelle pour calculer l'expiration. Par contre, <wsu:Timestamp wsu:Id=""Timestamp"">" à l'air bidon, je ne le change jamais il ça n'a pas l'air de poser problème. Idem pour <wsa:MessageID>urn:uuid:5e261edc-603f-46dc-8d62-a39ad3986f26</wsa:MessageID>". J'aurais cru qu'il aurait fallu les rendre unique mais apparemment non.