SOAP client in python, how to replicate with XML - python

I am using suds to send XML and I got my request working, but I'm really confused by how to replicate my results using XML. I have the XML request that my suds client is sending by using:
from suds.client import Client
ulr = "xxxxxxx"
client = Client(url)
...
client.last_received.str()
but I'm not sure where I would send that request to if I was using the requests library. How would I replicate the request from the suds client in a python request?

Most SOAP APIs are just over plain HTTP, use POST - and therefore are easily mimicked with any standard HTTP client such as Requests.
First look here to see how to view the headers and body that suds is sending - it is then a matter of replicating these headers/XML body and passing them into the Requests library.
One defining characteristic in 99% of all HTTP SOAP API's is that your request is going to the same end-point for each request (for example 'http://yyy.com:8080/Posting/LoadPosting.svc), and the actual action is specified in the header using SOAPAction header). Contrast this to a RESTful API where the action is implied with the verb + end-point you call (POST /user, GET /menu etc.)

Related

Create SOAP requst by zeep

I'm working on WSDL. I need to create SOAP request using by zeep package. So I implemented the code that
from zeep import Client
service = Client('https://api.mindbodyonline.com/0_5_1/ClientService.asmx?wsdl')
request = service.service.GetClientServices
But I could not move on. Because I could not login through this request and pass parameters. I want to fill following all requirement through this request. could anyone tell me that how to pass all this parameters by this request.
This is HTTP headers
SOAPAction: "http://clients.mindbodyonline.com/api/0_5_1/GetClientServices"
Content-Type: text/xml; charset="utf-8"

Pass Additional header to twilio

When I access any api under example.com/v3/ , I need to pass headers like ** token, clientip **, etc. and its mandatory headers.
Now when I make request to example.com/v3/notify , headers like token, clients are passed. This url is redirected internally to -> example.com/twilio.
I am stuck at forwarding these headers internally to the example.com/twilio
What shall I do to forwarded these headers as well?
Sample Code in Python which makes call to twiml_url(example.com/twilio):
client.calls.create(
to=call_number,
from_=TWILIO_FROM_NUMBER,
url=twiml_url,
method="GET",
fallback_method="GET",
status_callback_method="GET",
record="false"
)
Twilio developer evangelist here.
You can't get Twilio to send extra headers on your behalf. Twilio implements it's own header validation so that you can validate requests came from Twilio itself.
I would recommend implementing those checks and turning off your own header validation for requests made to the URL you use for Twilio.

Receive and process a SOAP message

Got a service provider (Safaricom) that has decided to use SOAP to send mobile money payment notifications to businesses. When the mobile user pays (either through USSD or via a web interface) the mobile money service will send a SOAP message that we are supposed to consume.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:c2b="http://cps.huawei.com/cpsinterface/c2bpayment">
<soapenv:Header/>
<soapenv:Body>
<c2b:C2BPaymentValidationRequest>
<TransactionType>PayBill</TransactionType>
<TransID>1234560000007031</TransID>
<TransTime>20140227082020</TransTime>
<TransAmount>123.00</TransAmount>
<BusinessShortCode>12345</BusinessShortCode>
<BillRefNumber></BillRefNumber>
<InvoiceNumber></InvoiceNumber>
<MSISDN>254722703614</MSISDN>
<KYCInfo>
<KYCName>[Personal Details][First Name]</KYCName>
<KYCValue>Hoiyor</KYCValue>
</KYCInfo>
<KYCInfo>
<KYCName>[Personal Details][Middle Name]</KYCName>
<KYCValue>G</KYCValue>
</KYCInfo>
<KYCInfo>
<KYCName>[Personal Details][Last Name]</KYCName>
<KYCValue>Chen</KYCValue>
</KYCInfo>
</c2b:C2BPaymentValidationRequest>
</soapenv:Body> </soapenv:Envelope>
Don't worry the above details are public information
Question is, using a framework like bottle (or even Django) how do I "accept" this message and how do I extract the details from within the message.
I've used suds-jurko to consume Soap Services but I've never been on the receiving end of a SOAP call.
At minimum though am able to get the message using payment_data = request.body.read()
from bottle import request
payment_data = request.body.read()
print(payment_data)
From there though I've tried using XML parsers in python but its getting complicated. Is there a way for suds (or zeep) to allow me to get the data from the xml object?
I hope it's not late for an answer:
For the C2B transactions there is a project on github https://github.com/kn9ts/project-mulla it takes the request from the checkout in POST form, converts it to a SOAP request, send it to safaricom, receives the response from safaricom and gives a response in Json format.

Python: Making a request with suds

i'm testing out SUDS library and I'm trying to make a simple request to an endpoint but i get unusual output. Why?
from suds.client import Client
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
url = "http://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway"
client = Client(url)
print client
Output:
Martynass-MacBook-Air:CH martynas$ python ch.py
DEBUG:suds.xsd.schema:loaded:
schema collection
Schema:0x109a7db90
(raw)
<schema/>
(model)
DEBUG:suds.xsd.schema:MERGED:
Schema:0x109a7db90
(raw)
<schema/>
(model)
You can't use suds for this servce, suds is based on SOAP, which is another web service protocol. What you can do is send an xml request and get a response.
import requests
target_url = "http://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway"
headers={'Content-type': 'text/xml'}
print requests.post(target_url, data=xml, headers=headers).text
Where the xml is defined according to their schemes.
http://xmlgw.companieshouse.gov.uk/example_http.html
This is one examaple
xml = ('''
<GovTalkMessage xmlns="http://www.govtalk.gov.uk/schemas/govtalk/govtalkheader"
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
xmlns:gt="http://www.govtalk.gov.uk/schemas/govtalk/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.govtalk.gov.uk/schemas/govtalk/govtalkheader">
<EnvelopeVersion>1.0</EnvelopeVersion>
<Header>
<MessageDetails>
<Class>CompanyDetails</Class>
<Qualifier>request</Qualifier>
<TransactionID>14456553</TransactionID>
</MessageDetails>
<SenderDetails>
<IDAuthentication>
<SenderID>My_SenderID</SenderID>
<Authentication>
<Method>CHMD5</Method>
<Value>e999e113407884fa410fa2f53bc23952</Value>
</Authentication>
</IDAuthentication>
<EmailAddress>sometest#some.email.address</EmailAddress>
</SenderDetails>
</Header>
<GovTalkDetails>
<Keys/>
</GovTalkDetails>
<Body>
<CompanyDetailsRequest xmlns="http://xmlgw.companieshouse.gov.uk/v1-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlgw.companieshouse.gov.uk/v1-0/schema/CoDets.xsd">
<CompanyNumber>01002361</CompanyNumber>
<GiveMortTotals>1</GiveMortTotals>
</CompanyDetailsRequest>
</Body>
</GovTalkMessage>
''')
<Class>CompanyDetails</Class> What type of info you're getting. kinda what "function" to call
<Authentication>
<Method>CHMD5</Method>
<Value>e999e113407884fa410fa2f53bc23952</Value>
</Authentication>
</IDAuthentication>
Here you would put the login info i guess
<CompanyDetailsRequest xmlns="http://xmlgw.companieshouse.gov.uk/v1-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlgw.companieshouse.gov.uk/v1-0/schema/CoDets.xsd">
<CompanyNumber>01002361</CompanyNumber>
<GiveMortTotals>1</GiveMortTotals>
</CompanyDetailsRequest>
The "function" call and it's parameters
Now this will give me a response telling me the authorization failed. So if you have an account there, this should work for you.
Here you can find the list of schemes they have for different types of request. Some of them have sample request to help you out.
http://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/SchemaStatusOutput
Here is the complete guide of all their schemes.
http://xmlgw.companieshouse.gov.uk/data_usage_guide_dec_2013.pdf
There aren't any wsdl definitions for that site. Try something like
http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL
for your url
then you can try something like
client.service.GetWeatherInformation()
From the suds document, "You will need to know the url for WSDL for each service used."
An explicit example
from suds.client import Client
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
url = " http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL"
client = Client(url)
client.service.GetWeatherInformation()
Outputs a ton of data.
Suds does not make it easy to discover the service, it's better to first test a bit with soapui or generate a human-readable doc of the wsdl with this xslt : http://code.google.com/p/wsdl-viewer/ . So you know the structure of requests and replies, and which services are available.
Requests and responses in soap are xml trees, so once you get the result, you need to access the content of the xml tag that contains the information you're interested in. Here is an example that should work ( I don't have a username, but the result.Status.Success works ).
import suds
client = suds.client.Client("http://webservices.data-8.co.uk/companieshouse.asmx?WSDL")
result = client.service.GetCompanyDetails("username", "password", 1234)
print result.Status.Success
print result.Result.CompanyName
You can not make a request against .xsd. XSD is definition of the exchanged message. You must make a request against webservice Looking here you can find more info about that web service. But also there is pricing page indicating that you must pay to use their service. Probably when you pay you will get username and password to authenticate with the service.

multipart/form-data File upload request from Flash to GAE misses data

I have a google app engine request handler that processes multipart/form-data request from file uploads. It works fine with a html form but with the flash uploader it seems that no parameters are passed through.
Here is the data I have put together:
https://gist.github.com/martinheidegger/b8ee4982eb9580b9baa9
It contains the two http requests, one working, one broken together with the log output for logging.info("%s" % self.request.POST);
What am I missing? Why does the flash request not "arrive" at the GAE?
Are you receiving the POST request but missing all the POST data?
It could be due to the HTTP headers were not sent properly in Flash.
Try to read and parse directly from the HTTP request body and you should get something.

Categories

Resources