Add custom headers to SOAP request using zeep.Client Python - python-3.x

I have problems creating and adding custom headers to SOAP header. If I write a RAW request it works, but I want to use zeep library in Python3
I tried to add theese headers
header = xsd.Element(
'headerMDMPeticio',xsd.ComplexType([
xsd.Element('idSistemaOrigen',xsd.String()),
xsd.Element(
'headerMidominio',xsd.ComplexType([
xsd.Element('usuariConnectat',xsd.String()),
xsd.Element('rolUsuariConnectat',xsd.String())
])
)
])
)
header_value = header(headerMidominio={'usuariConnectat':'user','rolUsuariConnectat':'roleExample'})
extracted from theese book https://buildmedia.readthedocs.org/media/pdf/python-zeep/master/python-zeep.pdf (page 18)
Here is the python code for generate XML that I'm using
from django.shortcuts import render
from django.utils import timezone
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin,PermissionRequiredMixin
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, TemplateView, FormView
from zeep import Client, xsd
from zeep.wsse.username import UsernameToken
from lxml import etree
from .models import MDMRelCodiProjecte
def codiprojecte_list(request):
codis = MDMRelCodiProjecte.objects.filter(data_esborrat__isnull=True).order_by('data_modificat')
#Consultamos al servicio SOAP
url_service = "https://services.dev.midominio.edu/soa/extern/SOAP12/MDMCodisProjectes/v01_00"
url_wsdl = url_service+"/?wsdl"
soapClient = Client(url_wsdl,wsse=UsernameToken('developer_user','miPasswordEnTextoPlano'))
soapClient.service._binding_options['address'] = url_service # En el WSDL viene con una URL incorrecta --> ponemos la correcta!
id_service = '100045976'
soapDataUserPass = {'Username':'developer_user','Password':'miPasswordEnTextoPlano'}
node = soapClient.create_message(soapClient.service, 'consultarCodiProjecteMDM',id_service)
print (node)
print (etree.tostring(node,pretty_print=True))
#print(soapClient.service.consultarCodiProjecteMDM(id_service,soapDataUsosDada))
return render(request, 'codi_projecte/codiprojecte_list.html', {'codis':codis})
Expected (extracted from SOAP UI), focus on v01:headerMDMPeticio and children of this node. Inside body I also need to ADD v012:usosDada to request.
Accept-Encoding: gzip,deflate
Content-Type: application/soap+xml;charset=UTF-8;action="http://services.dev.midominio.edu/soa/servei/CodisProjectesMDM/v01_00/consultarCodiProjecteMDMInput"
Content-Length: 1811
Host: services.dev.midominio.edu
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:v01="http://midominio.edu/soa/esquema/ElementsComunsMDM/v01_00" xmlns:v011="http://midominio.edu/soa/esquema/ElementsComuns/v01_01" xmlns:v012="http://midominio.edu/soa/servei/MDMCodisProjectes/v01_00">
<soap:Header>
<wsse:Security soap:mustUnderstand="true" 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">
<wsse:UsernameToken wsu:Id="UsernameToken-6e6f6d657365617363757472656e6f6F">
<wsse:Username>developer_user</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">miPasswordEnTextoPlano</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">rndomDataHash+rndomtxt==</wsse:Nonce>
<wsu:Created>2019-06-05T08:20:45.644Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
<v01:headerMDMPeticio>
<v01:idSistemaOrigen>1</v01:idSistemaOrigen>
<v01:headerMidominio>
<v011:usuariConnectat>usuarioPlataforma</v011:usuariConnectat>
<v011:rolUsuariConnectat>pepitoPalote</v011:rolUsuariConnectat>
</v01:headerMidominio>
</v01:headerMDMPeticio>
</soap:Header>
<soap:Body>
<v012:consultarCodiProjecteMDMInput>
<v012:idMDM>100045976</v012:idMDM>
<v012:usosDada>
<v01:arrayUsosDeDadaItem>
<v01:tipus>Prova persona</v01:tipus>
</v01:arrayUsosDeDadaItem>
</v012:usosDada>
</v012:consultarCodiProjecteMDMInput>
</soap:Body>
</soap:Envelope
And this is that I generate with my Python code
<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope">
<soap-env:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>developer_user</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">miPasswordEnTextoPlano</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap-env:Header>
<soap-env:Body>
<ns0:consultarCodiProjecteMDMInput xmlns:ns0="https://services.dev.midominio.edu/soa/servei/MDMCodisProjectes/v01_00">
<ns0:idMDM>100045976</ns0:idMDM>
</ns0:consultarCodiProjecteMDMInput>
</soap-env:Body>
</soap-env:Envelope>

Zeep requires that you define your headers in the special kwarg _soapheaders, like so:
from zeep import Client
wsdl = 'http://localhost/services/Assets?wsdl'
client = Client(wsdl)
request_data = {
"InterplayPathURI" : "interplay://TGAvid/Projects",
"SearchGroup" : {
"Operator" : "OR",
"AttributeCondition" : {
"Condition" : "EQUALS",
"Attribute" :
{"Group" : "SYSTEM",
"Name": "Type",
"_value_1": "masterclip"},
},
},
"MaxResults" : "500",
}
header_value = {
"credentialsHeader" : {
"Username" : "administrator",
"Password" : "Avid123"
}
}
result = client.service.Search(**request_data, _soapheaders=header_value)

Related

Type Error and got an unexpected keyword argument: When passing dict to Python Zeep's Client.Service call

I have the following XML which I am sending to the target web application using SOAPUI and it works.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://www.docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header/>
<soapenv:Body>
<RequestMessage xmlns="http://www.ercot.com/schema/2007-06/nodal/ews/message">
<Header>
<Verb>create</Verb>
<Noun>OutageSet</Noun>
<ReplayDetection>
<Nonce>72465</Nonce>
<Created>2022-12-27T00:40:00-07:00</Created>
</ReplayDetection>
<Revision>004</Revision>
<Source>TAEPTC</Source>
<!--Optional:-->
<UserID>API_OutplanOSITCC</UserID>
</Header>
<Payload>
<OutageSet xmlns="http://www.ercot.com/schema/2007-06/nodal/ews">
<Outage>
<OutageInfo>
<outageType>PL</outageType>
<Requestor>
<name>API_OutplanOSITCC</name>
<userFullName>APIOutplanOSITCC</userFullName>
</Requestor>
<Disclaimer>tempdisclaimer</Disclaimer>
<disclaimerAck>true</disclaimerAck>
</OutageInfo>
<TransmissionOutage>
<operatingCompany>TAEPTC</operatingCompany>
<equipmentName>1589</equipmentName>
<equipmentIdentifier>_{072D6FCA-D121-49E7-AC9D-CDF5D4DB3D70}</equipmentIdentifier>
<transmissionType>DSC</transmissionType>
<fromStation>AIRLINE</fromStation>
<outageState>O</outageState>
<emergencyRestorationTime>1</emergencyRestorationTime>
<natureOfWork>OE</natureOfWork>
</TransmissionOutage>
<Schedule>
<plannedStart>2023-01-16T10:00:00</plannedStart>
<plannedEnd>2023-01-17T10:00:00</plannedEnd>
<earliestStart>2023-01-16T10:00:00</earliestStart>
<latestEnd>2023-01-17T12:00:00</latestEnd>
</Schedule>
</Outage>
</OutageSet>
</Payload>
</RequestMessage>
</soapenv:Body>
</soapenv:Envelope>
I am trying to generate the XML using python's zeep module and for that I have the modifeid xml and converting that to dict using xmltodict module.
Below is the XMLtoDIct code sinppet -
import xmltodict
import pprint
import json
my_xml = """
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://www.docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header/>
<soapenv:Body>
<RequestMessage xmlns="http://www.ercot.com/schema/2007-06/nodal/ews/message">
<Header>
<Verb>create</Verb>
<Noun>OutageSet</Noun>
<ReplayDetection>
<Nonce>72465</Nonce>
<Created>2022-12-27T00:40:00-07:00</Created>
</ReplayDetection>
<Revision>004</Revision>
<Source>TAEPTC</Source>
<!--Optional:-->
<UserID>API_OutplanOSITCC</UserID>
</Header>
<Payload>
<OutageSet xmlns="http://www.ercot.com/schema/2007-06/nodal/ews">
<Outage>
<OutageInfo>
<outageType>PL</outageType>
<Requestor>
<name>API_OutplanOSITCC</name>
<userFullName>APIOutplanOSITCC</userFullName>
</Requestor>
<Disclaimer>tempdisclaimer</Disclaimer>
<disclaimerAck>true</disclaimerAck>
</OutageInfo>
<TransmissionOutage>
<operatingCompany>TAEPTC</operatingCompany>
<equipmentName>1589</equipmentName>
<equipmentIdentifier>_{072D6FCA-D121-49E7-AC9D-CDF5D4DB3D70}</equipmentIdentifier>
<transmissionType>DSC</transmissionType>
<fromStation>AIRLINE</fromStation>
<outageState>O</outageState>
<emergencyRestorationTime>1</emergencyRestorationTime>
<natureOfWork>OE</natureOfWork>
</TransmissionOutage>
<Schedule>
<plannedStart>2023-01-16T10:00:00</plannedStart>
<plannedEnd>2023-01-17T10:00:00</plannedEnd>
<earliestStart>2023-01-16T10:00:00</earliestStart>
<latestEnd>2023-01-17T12:00:00</latestEnd>
</Schedule>
</Outage>
</OutageSet>
</Payload>
</RequestMessage>
</soapenv:Body>
</soapenv:Envelope>
"""
my_dict = xmltodict.parse(my_xml, process_namespaces= True)
#pp = pprint.PrettyPrinter(indent=2)
print(my_dict)
Below is the dict after conversion -
{'http://schemas.xmlsoap.org/soap/envelope/:Envelope': {'http://schemas.xmlsoap.org/soap/envelope/:Header': None, 'http://schemas.xmlsoap.org/soap/envelope/:Body': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:RequestMessage': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:Header': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:Verb': 'create', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Noun': 'OutageSet', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:ReplayDetection': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:Nonce': '72465', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Created': '2022-12-27T00:40:00-07:00'}, 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Revision': '004', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Source': 'TAEPTC', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:UserID': 'API_OutplanOSITCC'}, 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Payload': {'http://www.ercot.com/schema/2007-06/nodal/ews:OutageSet': {'http://www.ercot.com/schema/2007-06/nodal/ews:Outage': {'http://www.ercot.com/schema/2007-06/nodal/ews:OutageInfo': {'http://www.ercot.com/schema/2007-06/nodal/ews:outageType': 'PL', 'http://www.ercot.com/schema/2007-06/nodal/ews:Requestor': {'http://www.ercot.com/schema/2007-06/nodal/ews:name': 'API_OutplanOSITCC', 'http://www.ercot.com/schema/2007-06/nodal/ews:userFullName': 'APIOutplanOSITCC'}, 'http://www.ercot.com/schema/2007-06/nodal/ews:Disclaimer': 'tempdisclaimer', 'http://www.ercot.com/schema/2007-06/nodal/ews:disclaimerAck': 'true'}, 'http://www.ercot.com/schema/2007-06/nodal/ews:TransmissionOutage': {'http://www.ercot.com/schema/2007-06/nodal/ews:operatingCompany': 'TAEPTC', 'http://www.ercot.com/schema/2007-06/nodal/ews:equipmentName': '1589', 'http://www.ercot.com/schema/2007-06/nodal/ews:equipmentIdentifier': '_{072D6FCA-D121-49E7-AC9D-CDF5D4DB3D70}', 'http://www.ercot.com/schema/2007-06/nodal/ews:transmissionType': 'DSC', 'http://www.ercot.com/schema/2007-06/nodal/ews:fromStation': 'AIRLINE', 'http://www.ercot.com/schema/2007-06/nodal/ews:outageState': 'O', 'http://www.ercot.com/schema/2007-06/nodal/ews:emergencyRestorationTime': '1', 'http://www.ercot.com/schema/2007-06/nodal/ews:natureOfWork': 'OE'}, 'http://www.ercot.com/schema/2007-06/nodal/ews:Schedule': {'http://www.ercot.com/schema/2007-06/nodal/ews:plannedStart': '2023-01-16T10:00:00', 'http://www.ercot.com/schema/2007-06/nodal/ews:plannedEnd': '2023-01-17T10:00:00', 'http://www.ercot.com/schema/2007-06/nodal/ews:earliestStart': '2023-01-16T10:00:00', 'http://www.ercot.com/schema/2007-06/nodal/ews:latestEnd': '2023-01-17T12:00:00'}}}}}}}}
however, when I am passing this dict to the request data like below -
request_data = {'http://www.ercot.com/schema/2007-06/nodal/ews/message:RequestMessage': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:Header': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:Verb': 'create', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Noun': 'OutageSet', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:ReplayDetection': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:Nonce': '72465', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Created': '2022-12-27T00:40:00-07:00'}, 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Revision': '004', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Source': 'TAEPTC', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:UserID': 'API_OutplanOSITCC'}, 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Payload': {'http://www.ercot.com/schema/2007-06/nodal/ews:OutageSet': {'http://www.ercot.com/schema/2007-06/nodal/ews:Outage': {'http://www.ercot.com/schema/2007-06/nodal/ews:OutageInfo': {'http://www.ercot.com/schema/2007-06/nodal/ews:outageType': 'PL', 'http://www.ercot.com/schema/2007-06/nodal/ews:Requestor': {'http://www.ercot.com/schema/2007-06/nodal/ews:name': 'API_OutplanOSITCC', 'http://www.ercot.com/schema/2007-06/nodal/ews:userFullName': 'APIOutplanOSITCC'}, 'http://www.ercot.com/schema/2007-06/nodal/ews:Disclaimer': 'tempdisclaimer', 'http://www.ercot.com/schema/2007-06/nodal/ews:disclaimerAck': 'true'}, 'http://www.ercot.com/schema/2007-06/nodal/ews:TransmissionOutage': {'http://www.ercot.com/schema/2007-06/nodal/ews:operatingCompany': 'TAEPTC', 'http://www.ercot.com/schema/2007-06/nodal/ews:equipmentName': '1589', 'http://www.ercot.com/schema/2007-06/nodal/ews:equipmentIdentifier': '_{072D6FCA-D121-49E7-AC9D-CDF5D4DB3D70}', 'http://www.ercot.com/schema/2007-06/nodal/ews:transmissionType': 'DSC', 'http://www.ercot.com/schema/2007-06/nodal/ews:fromStation': 'AIRLINE', 'http://www.ercot.com/schema/2007-06/nodal/ews:outageState': 'O', 'http://www.ercot.com/schema/2007-06/nodal/ews:emergencyRestorationTime': '1', 'http://www.ercot.com/schema/2007-06/nodal/ews:natureOfWork': 'OE'}, 'http://www.ercot.com/schema/2007-06/nodal/ews:Schedule': {'http://www.ercot.com/schema/2007-06/nodal/ews:plannedStart': '2023-01-16T10:00:00', 'http://www.ercot.com/schema/2007-06/nodal/ews:plannedEnd': '2023-01-17T10:00:00', 'http://www.ercot.com/schema/2007-06/nodal/ews:earliestStart': '2023-01-16T10:00:00', 'http://www.ercot.com/schema/2007-06/nodal/ews:latestEnd': '2023-01-17T12:00:00'}}}}}}
print("Call URL")
print(client.service.MarketTransactions(**request_data))
I am getting the below error -
Creating client.
zeep.transports: Loading remote data from: http://www.w3.org/2001/xml.xsd
Making request.
Call URL
Traceback (most recent call last):
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\ERCOT_Test.py", line 110, in <module>
print(client.service.MarketTransactions(**request_data))
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\venv\lib\site-packages\zeep\proxy.py", line 46, in __call__
return self._proxy._binding.send(
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\venv\lib\site-packages\zeep\wsdl\bindings\soap.py", line 123, in send
envelope, http_headers = self._create(
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\venv\lib\site-packages\zeep\wsdl\bindings\soap.py", line 73, in _create
serialized = operation_obj.create(*args, **kwargs)
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\venv\lib\site-packages\zeep\wsdl\definitions.py", line 222, in create
return self.input.serialize(*args, **kwargs)
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\venv\lib\site-packages\zeep\wsdl\messages\soap.py", line 73, in serialize
body_value = self.body(*args, **kwargs)
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\venv\lib\site-packages\zeep\xsd\elements\element.py", line 58, in __call__
instance = self.type(*args, **kwargs)
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\venv\lib\site-packages\zeep\xsd\types\complex.py", line 63, in __call__
return self._value_class(*args, **kwargs)
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\venv\lib\site-packages\zeep\xsd\valueobjects.py", line 106, in __init__
items = _process_signature(self._xsd_type, args, kwargs)
File "C:\Users\SGUPTA\PycharmProjects\ERCOT\venv\lib\site-packages\zeep\xsd\valueobjects.py", line 241, in _process_signature
raise TypeError(
TypeError: {http://www.ercot.com/schema/2007-06/nodal/ews/message}RequestMessage() got an unexpected keyword argument 'http://www.ercot.com/schema/2007-06/nodal/ews/message:RequestMessage'. Signature: `Header: {http://www.ercot.com/schema/2007-06/nodal/ews/message}HeaderType, Request: {http://www.ercot.com/schema/2007-06/nodal/ews/message}RequestType, Payload: {http://www.ercot.com/schema/2007-06/nodal/ews/message}PayloadType`
Process finished with exit code 1
is this because of the namespaces in both RequestMessage and Outageset nodes?
Here is my complete code -
from zeep.wsse.signature import BinarySignature
from zeep.wsse import utils
from datetime import datetime, timedelta
import contextlib
import os
import requests
from requests_pkcs12 import Pkcs12Adapter
from zeep.transports import Transport
from zeep import Client, Settings
from pathlib import Path
from tempfile import NamedTemporaryFile
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption
from cryptography.hazmat.primitives.serialization.pkcs12 import load_key_and_certificates
import random
import logging.config
# USE THE MOST VERBOSE LOGGING LEVEL
logging.config.dictConfig({
'version': 1,
'formatters': {
'verbose': {
'format': '%(name)s: %(message)s'
}
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'loggers': {
'zeep.transports': {
'level': 'DEBUG',
'propagate': True,
'handlers': ['console'],
},
}
})
class BinarySignatureTimestamp(BinarySignature):
def apply(self, envelope, headers):
security = utils.get_security_header(envelope)
created = datetime.utcnow()
expired = created + timedelta(seconds=1 * 60)
timestamp = utils.WSU('Timestamp')
timestamp.append(utils.WSU('Created', created.replace(microsecond=0).isoformat() + 'Z'))
timestamp.append(utils.WSU('Expires', expired.replace(microsecond=0).isoformat() + 'Z'))
security.append(timestamp)
super().apply(envelope, headers)
return envelope, headers
def verify(self, envelope):
return envelope
#contextlib.contextmanager
def pfx_to_pem(pfx_path, pfx_password):
''' Decrypts the .pfx file to be used with requests. '''
pfx = Path(pfx_path).read_bytes()
private_key, main_cert, add_certs = load_key_and_certificates(pfx, pfx_password.encode('utf-8'), None)
with NamedTemporaryFile(suffix='.pem', delete=False) as t_pem:
with open(t_pem.name, 'wb') as pem_file:
pem_file.write(private_key.private_bytes(Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()))
pem_file.write(main_cert.public_bytes(Encoding.PEM))
for ca in add_certs:
pem_file.write(ca.public_bytes(Encoding.PEM))
yield t_pem.name
def generate_nonce(length=15):
"""Generate pseudorandom number."""
return ''.join([str(random.randint(0, 9)) for i in range(length)])
# CERTIFICATES PATHS
api_p12_key = os.path.join('C:\\Users\\SGUPTA\\ALL\\Projects\\AEPE2\\API Outplan OSI TCC MOTE.p12')
api_certificate = os.path.join('C:\\Users\\SGUPTA\\ALL\\Projects\\AEPE2\\OSITCC.crt')
api_pfx_key = os.path.join('C:\\Users\\SGUPTA\\ALL\\Projects\\AEPE2\\API Outplan OSI TCC MOTE.pfx')
# SETUP
wsdl_file = os.path.join('C:\\Users\\SGUPTA\\ALL\\Projects\\AEPE2\\Nodal.wsdl')
api_base_url = "https://testmisapi.ercot.com"
session = requests.Session()
session.mount(api_base_url,
Pkcs12Adapter(pkcs12_filename=api_p12_key, pkcs12_password='HIDDEN'))
session.verify = None
transport = Transport(session=session)
settings = Settings(forbid_entities=False)
# CREATE CLIENT
print("Creating client.")
with pfx_to_pem(pfx_path=api_pfx_key, pfx_password='AEP') as pem_fle:
client = Client(wsdl=wsdl_file, settings=settings, transport=transport,
wsse=BinarySignatureTimestamp(pem_fle, api_certificate, "AEP"))
print("Making request.")
request_data = {'http://www.ercot.com/schema/2007-06/nodal/ews/message:RequestMessage': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:Header': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:Verb': 'create', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Noun': 'OutageSet', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:ReplayDetection': {'http://www.ercot.com/schema/2007-06/nodal/ews/message:Nonce': '72465', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Created': '2022-12-27T00:40:00-07:00'}, 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Revision': '004', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Source': 'TAEPTC', 'http://www.ercot.com/schema/2007-06/nodal/ews/message:UserID': 'API_OutplanOSITCC'}, 'http://www.ercot.com/schema/2007-06/nodal/ews/message:Payload': {'http://www.ercot.com/schema/2007-06/nodal/ews:OutageSet': {'http://www.ercot.com/schema/2007-06/nodal/ews:Outage': {'http://www.ercot.com/schema/2007-06/nodal/ews:OutageInfo': {'http://www.ercot.com/schema/2007-06/nodal/ews:outageType': 'PL', 'http://www.ercot.com/schema/2007-06/nodal/ews:Requestor': {'http://www.ercot.com/schema/2007-06/nodal/ews:name': 'API_OutplanOSITCC', 'http://www.ercot.com/schema/2007-06/nodal/ews:userFullName': 'APIOutplanOSITCC'}, 'http://www.ercot.com/schema/2007-06/nodal/ews:Disclaimer': 'tempdisclaimer', 'http://www.ercot.com/schema/2007-06/nodal/ews:disclaimerAck': 'true'}, 'http://www.ercot.com/schema/2007-06/nodal/ews:TransmissionOutage': {'http://www.ercot.com/schema/2007-06/nodal/ews:operatingCompany': 'TAEPTC', 'http://www.ercot.com/schema/2007-06/nodal/ews:equipmentName': '1589', 'http://www.ercot.com/schema/2007-06/nodal/ews:equipmentIdentifier': '_{072D6FCA-D121-49E7-AC9D-CDF5D4DB3D70}', 'http://www.ercot.com/schema/2007-06/nodal/ews:transmissionType': 'DSC', 'http://www.ercot.com/schema/2007-06/nodal/ews:fromStation': 'AIRLINE', 'http://www.ercot.com/schema/2007-06/nodal/ews:outageState': 'O', 'http://www.ercot.com/schema/2007-06/nodal/ews:emergencyRestorationTime': '1', 'http://www.ercot.com/schema/2007-06/nodal/ews:natureOfWork': 'OE'}, 'http://www.ercot.com/schema/2007-06/nodal/ews:Schedule': {'http://www.ercot.com/schema/2007-06/nodal/ews:plannedStart': '2023-01-16T10:00:00', 'http://www.ercot.com/schema/2007-06/nodal/ews:plannedEnd': '2023-01-17T10:00:00', 'http://www.ercot.com/schema/2007-06/nodal/ews:earliestStart': '2023-01-16T10:00:00', 'http://www.ercot.com/schema/2007-06/nodal/ews:latestEnd': '2023-01-17T12:00:00'}}}}}}
print("Call URL")
print(client.service.MarketTransactions(**request_data))
The same code is working when I am calling another webservice just by sending the header(does not have a namespace) in the request data like below -
from zeep.wsse.signature import BinarySignature
from zeep.wsse import utils
from datetime import datetime, timedelta
import contextlib
import os
import requests
from requests_pkcs12 import Pkcs12Adapter
from zeep.transports import Transport
from zeep import Client, Settings
from pathlib import Path
from tempfile import NamedTemporaryFile
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption
from cryptography.hazmat.primitives.serialization.pkcs12 import load_key_and_certificates
import random
import logging.config
# USE THE MOST VERBOSE LOGGING LEVEL
logging.config.dictConfig({
'version': 1,
'formatters': {
'verbose': {
'format': '%(name)s: %(message)s'
}
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'loggers': {
'zeep.transports': {
'level': 'DEBUG',
'propagate': True,
'handlers': ['console'],
},
}
})
class BinarySignatureTimestamp(BinarySignature):
def apply(self, envelope, headers):
security = utils.get_security_header(envelope)
created = datetime.utcnow()
expired = created + timedelta(seconds=1 * 60)
timestamp = utils.WSU('Timestamp')
timestamp.append(utils.WSU('Created', created.replace(microsecond=0).isoformat()+'Z'))
timestamp.append(utils.WSU('Expires', expired.replace(microsecond=0).isoformat()+'Z'))
security.append(timestamp)
super().apply(envelope, headers)
return envelope, headers
def verify(self, envelope):
return envelope
#contextlib.contextmanager
def pfx_to_pem(pfx_path, pfx_password):
''' Decrypts the .pfx file to be used with requests. '''
pfx = Path(pfx_path).read_bytes()
private_key, main_cert, add_certs = load_key_and_certificates(pfx, pfx_password.encode('utf-8'), None)
with NamedTemporaryFile(suffix='.pem', delete=False) as t_pem:
with open(t_pem.name, 'wb') as pem_file:
pem_file.write(private_key.private_bytes(Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()))
pem_file.write(main_cert.public_bytes(Encoding.PEM))
for ca in add_certs:
pem_file.write(ca.public_bytes(Encoding.PEM))
yield t_pem.name
def generate_nonce(length=15):
"""Generate pseudorandom number."""
return ''.join([str(random.randint(0, 9)) for i in range(length)])
# CERTIFICATES PATHS
api_p12_key = os.path.join('C:\\Users\\SGUPTA\\ALL\\Projects\\AEPE2\\API Outplan OSI TCC MOTE.p12')
api_certificate = os.path.join('C:\\Users\\SGUPTA\\ALL\\Projects\\AEPE2\\OSITCC.crt')
api_pfx_key = os.path.join('C:\\Users\\SGUPTA\\ALL\\Projects\\AEPE2\\API Outplan OSI TCC MOTE.pfx')
# SETUP
wsdl_file = os.path.join('C:\\Users\\SGUPTA\\ALL\\Projects\\AEPE2\\Nodal.wsdl')
api_base_url = "https://testmisapi.ercot.com"
session = requests.Session()
session.mount(api_base_url,
Pkcs12Adapter(pkcs12_filename=api_p12_key, pkcs12_password='AEP'))
session.verify = None
transport = Transport(session=session)
settings = Settings(forbid_entities=False)
# CREATE CLIENT
print("Creating client.")
with pfx_to_pem(pfx_path=api_pfx_key, pfx_password='hidden') as pem_fle:
client = Client(wsdl=wsdl_file, settings=settings, transport=transport,
wsse=BinarySignatureTimestamp(pem_fle, api_certificate, "AEP"))
print("Making request.")
request_data = {
"Header": {
"Verb": "get",
"Noun": "SystemStatus",
"ReplayDetection": {
"Nonce": generate_nonce(),
"Created": "2022-11-10T15:34:00-06:00"},
"Revision": "1",
"Source": "API Outplan OSI TCC",
"UserID": "API_OutplanOSITCC",
}
}
print("Call URL")
print(client.service.MarketInfo(**request_data))
Could anyone please advise how to fix this and what needs to be changed?
Thanks
Sugata

Why the error occured when i tried to send a POST request with QWebEngineHttpRequest (PyQt5)?

I try to get JSON Object from source, but getting only errors.
Now I'm trying to understand what I'm doing wrong.
This code works well with other resources.
Maybe It`s not problem with code, but with web-source.
import sys
import json
from PyQt5.QtCore import QByteArray, QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineCore import QWebEngineHttpRequest
from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineSettings
from pprint import pprint
def on_load_finished():
"""Handle response"""
engine.toPlainText(handle_to_html) # get json
def handle_to_html(html):
"""Handle html"""
print(html)
QApplication.quit()
if __name__ == "__main__":
app = QApplication(sys.argv)
engine = QWebEnginePage()
url = "https://sportsapi.betway.com/api/Events/V2/GetEvents"
request = QWebEngineHttpRequest(url=QUrl(url), method=QWebEngineHttpRequest.Post)
request.setHeader(QByteArray(b"Content-Type"), QByteArray(b"application/json"))
payload = {
"LanguageId": 1,
"ClientTypeId": 2,
"BrandId": 3,
"JurisdictionId": 1,
"ClientIntegratorId": 1,
"ExternalIds": [9032262, 9038528, 9037778],
"MarketCName": "win-draw-win",
"ScoreboardRequest": {"ScoreboardType": 3, "IncidentRequest": {}},
"BrowserId": 3,
"OsId": 3,
"ApplicationVersion": "",
"BrowserVersion": "97.0.4692.99",
"OsVersion": "NT 10.0",
"SessionId": "null",
"TerritoryId": 227,
"CorrelationId": "06779075-21e2-4ba8-8e91-d71a981621fe",
"VisitId": "d1088cdf-13a8-42d0-be90-b34fd1332c36",
"ViewName": "sports",
"JourneyId": "833a4c0c-3354-499f-9d52-949df6d159f9",
}
request.setPostData(bytes(json.dumps(payload), "utf-8"))
engine.load(request)
engine.loadFinished.connect(on_load_finished)
app.exec_()
Errors are looks like
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Message>An error has occurred.</Message>
</Error>
Maybe It`s not problem with code, but with web-source.

Python Zeep WSDL Unexpected Elements Traceback

I can't handle this below.
XMLParseError: Unexpected element 'metadata', expected 'id' error.
I also try strict=False settings but that time zeep returned as none.
from zeep import Client
import zeep
wsdl = 'https://api.n11.com/ws/CategoryService.wsdl'
cl = Client(wsdl=wsdl)
request_data = {"auth":{'appKey' : ***,
'appSecret' : **},'categoryId':int(1003221),"pagingData":{'pageSize':1,'currentPage':0}}
print(cl.service.GetCategoryAttributes(**request_data))
Thanks.
I faced the same problem with the same API. My solution is changing zeep's settings.
You should use xsd_ignore_sequence_order=True.
I hope it's not too late.
settings = Settings(strict=False, xml_huge_tree=True, xsd_ignore_sequence_order=True)
read more:
https://docs.python-zeep.org/en/master/settings.html#module-zeep.settings
Solution:
firstly, to check logs:
import logging.config
logging.config.dictConfig({
'version': 1,
'formatters': {
'verbose': {
'format': '%(name)s: %(message)s'
}
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'loggers': {
'zeep.transports': {
'level': 'DEBUG',
'propagate': True,
'handlers': ['console'],
},
}
})
Second:
from zeep import Client
from zeep.plugins import HistoryPlugin
wsdl = 'https://api.n11.com/ws/CategoryService.wsdl'
from zeep import Client, Settings
settings = Settings(strict=False, xml_huge_tree=True)
history = HistoryPlugin()
from zeep.transports import Transport
transport = Transport(timeout=10)
key={'appKey' : '**',
'appSecret' : '**',
}
cat= {'categoryId':1003221}
dat= {'pageSize':1,'currentPage':1}
client = Client(wsdl=wsdl, transport=transport, plugins=[history], settings=settings)
with client.settings(raw_response=False,strict=False, xml_huge_tree=True):
response = client.service.GetCategoryAttributes(key,1003221,pagingData=dat)
#assert response.status_code == 200
#assert response.content
#node = client.create_message(client.service, 'GetCategoryAttributes',key,1003221,pagingData=dat)
from lxml import etree
try:
for hist in [history.last_sent, history.last_received]:
print(etree.tostring(hist["envelope"], encoding="unicode", pretty_print=True))
except (IndexError, TypeError):
# catch cases where it fails before being put on the wire
pass
lastly, you can parse with bs4 for xml content:
from bs4 import BeautifulSoup
soup = BeautifulSoup(ass, 'lxml')
soup.find('category').find('metadata')

Nearby and Text Search Zero Results

I am trying to get via Python the plain text result from the gmaps / places API. There is a Google Python Libary but wanted to use the real API via a normel requests or urllib call.
import requests
import json
import urllib3
#tried:
sUrl1 = 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=kindergarten&location=50.73464,12.52528&radius=50000&fields=formatted_address,name&key=[myapikey]'
sUrl2 = 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=kindergarten&location=50.73464'+ r',' + '12.52528&radius=50000&fields=formatted_address'+ r',' + 'name&key=[myapikey]'
sUrl3 = 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=kindergarten&location=50.73464'+ r',' + '12.52528&radius=50000&fields=formatted_address'+ r',' + 'name&key=[myapikey]&verify=false'
sUrl4 = 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=kindergarten&location=50.73464;12.52528&radius=50000&fields=formatted_address;name&key=[myapikey]'
print (requests.get(sUrl1).text)
print (requests.get(sUrl2).text)
print (requests.get(sUrl3).text)
print (requests.get(sUrl4).text)
Did the same for urllib3, and tried to give it as params but always get this:
{
"html_attributions" : [],
"results" : [],
"status" : "ZERO_RESULTS"
}
When i click on the links (print (sUrl1 or sUrl2 or sUrl3 or sUrl4) ) - I get a wonderful result.
In my API Key there is a "-" but if this is the problem?
Do i need some more headers?
What is the problem?
Can you help?
Thanks
If you add headers it works!
Code for Textsearch - works fine - needed to add headers
headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
'Connection': 'keep-alive' ,
'Host': 'maps.googleapis.com',
'Referer': 'maps.googleapis.com',
'TE': 'Trailers',
'Upgrade-Insecure-Requests': '1'
}
urlparams = {
u'query': u'xxx Berlin XXX',
u'location': str(lat)+","+str(long),
u'radius': u'10',
u'fields': u'place_id',
u'key': u'[mySecretKey]'
}
response = requests.get('https://maps.googleapis.com/maps/api/place/textsearch/json', params=urlparams,headers=headers)
myjson = json.loads(response.text)
print (myjson)
place_id = myjson['results'][0]['place_id']

how to append child to element using smooks groovy

I am trying to use Smooks with Groovy to appendChild() to elements. So far I've been unable to do so.
Sample input file
<?xml version="1.0"?>
<orders>
<order res="0">
<header>
<date>Wed Nov 27 13:45:28 EST 2013</date>
<customer number="9404089839">Harish Nanda M</customer>
</header>
<orderitems>
<orderitem>
<product>007</product>
<quantity>7</quantity>
<price>7.90</price>
</orderitem>
<orderitem>
<product>005</product>
<quantity>3</quantity>
<price>7.20</price>
</orderitem>
</orderitems>
</order>
<order res="0">
<header>
<date>Wed Nov 27 13:45:28 EST 2013</date>
<customer number="2036139296">Sandesh G</customer>
</header>
<orderitems>
<orderitem>
<product>0023</product>
<quantity>87</quantity>
<price>57.90</price>
</orderitem>
<orderitem>
<product>005</product>
<quantity>3</quantity>
<price>7.20</price>
</orderitem>
</orderitems>
</order>
</orders>
Smooks config file
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:core="http://www.milyn.org/xsd/smooks/smooks-core-1.3.xsd" xmlns:g="http://www.milyn.org/xsd/smooks/groovy-1.1.xsd">
<core:filterSettings type="SAX"/>
<g:groovy executeOnElement="order">
<g:imports>
import org.milyn.xml.DomUtils;
import org.milyn.javabean.context.BeanContext;
import org.milyn.javabean.repository.BeanRepository;
import org.w3c.dom.*;
import groovy.xml.dom.DOMCategory;
import groovy.xml.dom.DOMUtil;
import groovy.xml.DOMBuilder;
import groovy.util.XmlSlurper;
</g:imports>
<g:script>
<!-- javax.xml.transform.dom.DOMSource source = new javax.xml.transform.dom.DOMSource(element);
javax.xml.transform.Transformer transformer = javax.xml.transform.TransformerFactory.newInstance().newTransformer();
javax.xml.transform.stream.StreamResult result = new
javax.xml.transform.stream.StreamResult(new java.io.StringWriter());
transformer.transform(source, result); String ss =
result.getWriter().toString(); def ord = new
XmlSlurper().parseText(ss) //ord.xxxx = "2222"; println
ord.orderitems.orderitem.product.text()*.toInteger().sum();
element.appendChild("res"); //element['#res'] = element.'#res'.toInteger() +
ord.orderitems.orderitem.product.text()*.toInteger().sum();
writeFragment(element);
-->
</g:script>
</g:groovy>
</smooks-resource-list>

Resources