Python soap requests (VIES) - python

I'm trying to send soap request to check if clients NIP is valid via Python
import requests
url="http://ec.europa.eu/taxation_customs/vies/checkVatTestService.wsdl"
headers = {"content-type" : "application/soap+xml"}
body = """
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:ec.europa.eu:taxud:vies:services:checkVat:types">
<soapenv:Header/>
<soapenv:Body>
<urn:checkVat>
<urn:countryCode>SK</urn:countryCode>
<urn:vatNumber>2020016449</urn:vatNumber>
</urn:checkVat>
</soapenv:Body>
</soapenv:Envelope>
"""
response = requests.post(url, data = body, headers = headers)
print(response)
I always get code 200 which means it's invalid, but their webpage says it is valid.
I've seen other methods, but I really need to use this one.

Your code will produce the following result:
<Response [200]>
which is correct, but it's not what you expect, because I believe there are a few misunderstandings at play here.
First of all, <Response [200]> is the response of the HTTP request, not the response of the web service. Don't confuse the two. You are making a SOAP call over HTTP. That HTTP response will have a HTTP response code, which in this case is 200, and a SOAP payload with the response of the web service inside, and that's what's you are mostly interested in.
Second, you are not calling the web service endpoint. You are making a request to the WSDL of the web service. The two are different. You could have noticed that by replacing the last line of code with print(response.text) and you would have seen the WSDL content there.
The endpoint of the service is found inside the WSDL and it is http://ec.europa.eu/taxation_customs/vies/services/checkVatTestService. This is where you have to POST the request.
Third, based on the documentation in the WSDL, this seems a test service that gives you back all the possible responses of the service depending on which VAT number you use:
<xsd:documentation>
Specific disclaimer for this service -----------------------------------------
Here is the list of VAT Number to use to receive each kind of answer :
100 = Valid request with Valid VAT Number
200 = Valid request with an Invalid VAT Number
201 = Error : INVALID_INPUT
202 = Error : INVALID_REQUESTER_INFO
300 = Error : SERVICE_UNAVAILABLE
301 = Error : MS_UNAVAILABLE
302 = Error : TIMEOUT
400 = Error : VAT_BLOCKED
401 = Error : IP_BLOCKED
500 = Error : GLOBAL_MAX_CONCURRENT_REQ
501 = Error : GLOBAL_MAX_CONCURRENT_REQ_TIME
600 = Error : MS_MAX_CONCURRENT_REQ
601 = Error : MS_MAX_CONCURRENT_REQ_TIME
For all the other cases, The web service will responds with a "SERVICE_UNAVAILABLE" error.
</xsd:documentation>
Use this code instead:
import requests
url="http://ec.europa.eu/taxation_customs/vies/services/checkVatTestService"
headers = {"content-type" : "application/soap+xml"}
body = """
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:ec.europa.eu:taxud:vies:services:checkVat:types">
<soapenv:Header/>
<soapenv:Body>
<urn:checkVat>
<urn:countryCode>SK</urn:countryCode>
<urn:vatNumber>2020016449</urn:vatNumber>
</urn:checkVat>
</soapenv:Body>
</soapenv:Envelope>
"""
response = requests.post(url, data = body, headers = headers)
print(response.text)
When you call it you will get (formatting not included):
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>SERVICE_UNAVAILABLE</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
which is exactly what I expect because the documentation says it: For all the other cases, The web service will responds with a "SERVICE_UNAVAILABLE" error.
If I want a a valid response I only need to change the VAT number to this within the SOAP request message: <urn:vatNumber>100</urn:vatNumber> and now the service responds with (formatting not included):
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<checkVatResponse xmlns="urn:ec.europa.eu:taxud:vies:services:checkVat:types">
<countryCode>SK</countryCode>
<vatNumber>100</vatNumber>
<requestDate>2022-03-27+02:00</requestDate>
<valid>true</valid>
<name>John Doe</name>
<address>123 Main St, Anytown, UK</address>
</checkVatResponse>
</soap:Body>
</soap:Envelope>

Related

Getting '401 unauthorized' when trying to send a GET request to systeminfo.xml

I want to get the configuration of devices on my XProtect Corporate account, I am following this post
http://doc.developer.milestonesys.com/html/reference/protocols/imageserver_getdevices.html
but I am getting 401, unauthorized every time.
Until now I have managed to authenticate myself and got a token, now as i have the corporate account, I will need to send the token for the authorization, I am using requests lib in python to send a GET request like this
head = {'Authorization': 'Token {}'.format(myToken)}
response = requests.get('http://server-ip/rcserver/sysmteminfo.xml', headers=head)
print response
I am not sure about how to send my token in this get request
Any help will be highly appreciated
So I finally able to get the configuration of all the devices on the server. Problem was, the above approach works for XProtect Enterprise and XProtect Professional only, if you have an XProtect Corporate, you need a NTLM authentication and you have to call GetConfiguration function on the Server SOAP protocol.
r2= '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><GetConfiguration xmlns="http://videoos.net/2/XProtectCSServerCommand"><token>' + str(myToken) + '</token></GetConfiguration></soap:Body></soap:Envelope>'
data_len = str(len(r2))
s.sendall("POST /ManagementServer/ServerCommandService.svc HTTP/1.1\r\nHost: server-ip\r\nContent-Type: text/xml; charset=utf-8\r\nAuthorization: Basic (base64 encoded '*[BASIC]\username:password*')\r\nContent-Length: "+data_len+"\r\nSOAPAction: http://videoos.net/2/XProtectCSServerCommand/IServerCommandService/GetConfiguration\r\n\r\n"+ r2)

How to send a request using suds client with multiple elements in the request

I am having an issue sending a suds request.
I sent a request to a different method just using the following:
from suds.client import Client
client = Client(wsdlurl)
client.service.Login(name, employid)
This came back with the correct response as name and employid are direct children elements of Login.
But how can I send a request using the below:
<soapenv:Body>
<v12:getStuff>
<v12:stuffSelect>
<!--Optional:-->
<v12:stuffIDs>
<!--Zero or more repetitions:-->
<v12:num></v12:num>
</v12:stuffIDs>
</v12:stuffSelect>
</v12:getStuff>
</soapenv:Body>
</soapenv:Envelope>
The reason for this is so I can add a dynamic value into num
I've tried it like this:
return self.client.service.getStuff.stuffSelect.stuffIDs(**{'stuffID': stuff_id, })
But get this error
AttributeError: 'Method' object has no attribute 'stuffSelector'
I assume you are using https://bitbucket.org/jurko/suds. It is essential you know your wsdl interface; suds can provide it partly at run-time:
# ... 'client' via wsdl url, login
# get example
http_status, payload = client.service.your_wsdl_get_stuff_method()
stuffIDs = []
if http_status == 200:
for stuff_id in payload: # depending on your wsdl
stuffIDs.append(stuff_id)
# upload example
stuffSelect = client.factory.create('stuffSelect') # structure generated by suds from wsdl
stuffSelect.your_wdsl_stuff_ids_name = stuffIDs # (maybe debug to see your name)
params = foo, bar, stuffSelect
svr_response = client.service.your_wsdl_upload_method(*params)

Python + SOAP : The message with Action \'\' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher

Trying to access this soap webservice using python requests : http://bsestarmfdemo.bseindia.com/MFUploadService/MFUploadService.svc?WSDL
Here is my request :
import requests
url="http://bsestarmfdemo.bseindia.com/MFUploadService/MFUploadService.svc?WSDL"
#headers = {'content-type': 'application/soap+xml'}
headers = {'content-type': 'application/soap+xml'}
body = """<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/">
<soap:Header/>
<soap:Body>
<tem:getPassword>
<!--Optional:-->
<tem:UserId>1003201</tem:UserId>
<!--Optional:-->
<tem:MemberId>10032</tem:MemberId>
<!--Optional:-->
<tem:Password>xxxxxxxx</tem:Password>
<!--Optional:-->
<tem:PassKey>xxxxxx123</tem:PassKey>
</tem:getPassword>
</soap:Body>
</soap:Envelope>"""
response = requests.post(url,data=body,headers=headers)
print (response.content)
This the response :
b'Sendera:ActionNotSupportedThe message with Action \'\' cannot be processed at
the receiver, due to a ContractFilter mismatch at the
EndpointDispatcher. This may be because of either a contract mismatch
(mismatched Actions between sender and receiver) or a binding/security
mismatch between the sender and the receiver. Check that sender and
receiver have the same contract and the same binding (including
security requirements, e.g. Message, Transport,
None).'
If I understand correctly, I probably need to set the action in the request, but can't figure out how to do that. I'm entirely new to soap in python, please suggest how to fix this.
Thanks!
Just add the SOAPAction onto the header, for example:
headers = {'Content-type': 'text/xml;charset=UTF-8',
'SOAPAction': 'http://google.com/ISearchService/Find'
}

Post Item Walmart Partner API Python

I am using walmart partner api with python script. What I am trying to do is uploading item file using httplib. Here is my code:
file = open('/opt/item.xml', 'rb')
headers = {
"Accept":ws_accept,
"WM_SVC.NAME": wm_svc_name,
"WM_CONSUMER.ID":wm_consumer_id,
"WM_SEC.TIMESTAMP": wm_sec_timestamp,
"WM_SEC.AUTH_SIGNATURE":wm_sec_auth_signature,
"WM_QOS.CORRELATION_ID": wm_qos_correlation_id,
"Content-Type": 'multipart/form-data; boundary=xxx',
"Host":'marketplace.walmartapis.com'
}
conn = httplib.HTTPSConnection('marketplace.walmartapis.com')
conn.request("POST", '/v2/feeds?feedType=item',file, headers)
response = conn.getresponse()
print response.status, response.reason
print 'response',response.read()
item.xml is sample file available in documention.
Response is here:
500 Internal Server Error
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:errors xmlns:ns2="http://walmart.com/">
<ns2:error>
<ns2:code>SYSTEM_ERROR.GMP_GATEWAY_API</ns2:code>
<ns2:description>Couldn't find MIME boundary: --xxx</ns2:description>
<ns2:info>System encountered some internal error.</ns2:info>
<ns2:severity>ERROR</ns2:severity>
<ns2:category>DATA</ns2:category>
<ns2:causes/>
<ns2:errorIdentifiers/>
</ns2:error>
</ns2:errors>
Hope someone familiar with walmart partner api. Otherwise suggest with multipart-boundary error and how can I fix this please help guys...
From my personal experience, you may want to actually ask Walmart, "Have you received my file?" I have gotten 500s and 400s from them before with their other APIs and it has gone through the first run even though the API response code was not 200.

Can I use HTTP Post Requests for SOAP? - SOAP and Django

I am wondering if I could use simply use HTTP POST Requests in order to implement a SOAP API.
If so how should I format and treat the requests?
Yep, I have done this in certain cases where SOAPpy did not work with a given schema. This should get you started.
import httplib
from xml.dom import minidom
http.request("POST", "/path/to/my/webservice", body=xml, headers = {
"Host": "myservername",
"Content-Type": "text/xml; charset=UTF-8",
"Content-Length": len(xml)
})
print minidom.parseString(http.getresponse().read())
For the content string, I would use SoapUI to make the requests manually, and then mimic the XML.
Yes, see http://www.w3schools.com/SOAP/soap_httpbinding.asp
A SOAP method is an HTTP
request/response that complies with
the SOAP encoding rules.
HTTP + XML = SOAP
A SOAP request could be an HTTP POST
or an HTTP GET request.
You'll sometimes find other transport mechanisms used for quality of service reasons, for instance using a messaging framework.
I found a great example of this in the simple-salesforce package. The code is in login.py and pasted below
soap_url = 'https://{domain}.salesforce.com/services/Soap/u/{sf_version}'
domain = 'test' if sandbox else 'login'
soap_url = soap_url.format(domain=domain, sf_version=sf_version)
username = escape(username)
password = escape(password)
# Check if token authentication is used
if 'security_token' in kwargs:
security_token = kwargs['security_token']
# Security Token Soap request body
login_soap_request_body = """<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<n1:login xmlns:n1="urn:partner.soap.sforce.com">
<n1:username>{username}</n1:username>
<n1:password>{password}{token}</n1:password>
</n1:login>
</env:Body>
</env:Envelope>""".format(username=username, password=password, token=security_token)
# Check if IP Filtering is used in cojuction with organizationId
elif 'organizationId' in kwargs:
organizationId = kwargs['organizationId']
# IP Filtering Login Soap request body
login_soap_request_body = """<?xml version="1.0" encoding="utf-8" ?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:partner.soap.sforce.com">
<soapenv:Header>
<urn:CallOptions>
<urn:client>RestForce</urn:client>
<urn:defaultNamespace>sf</urn:defaultNamespace>
</urn:CallOptions>
<urn:LoginScopeHeader>
<urn:organizationId>{organizationId}</urn:organizationId>
</urn:LoginScopeHeader>
</soapenv:Header>
<soapenv:Body>
<urn:login>
<urn:username>{username}</urn:username>
<urn:password>{password}</urn:password>
</urn:login>
</soapenv:Body>
</soapenv:Envelope>""".format(
username=username, password=password, organizationId=organizationId)
else:
except_code = 'INVALID AUTH'
except_msg = 'You must submit either a security token or organizationId for authentication'
raise SalesforceAuthenticationFailed(except_code, except_msg)
login_soap_request_headers = {
'content-type': 'text/xml',
'charset': 'UTF-8',
'SOAPAction': 'login'
}
response = requests.post(soap_url,
login_soap_request_body,
headers=login_soap_request_headers,
proxies=kwargs.get('proxies', None))

Categories