In Python, how to set _soapheaders for Zeep using Dictionaries? - python-3.x

In working with a SOAP api, the wsdl spec describes the api key passed in the header in a complex namespaced structure as well as additional non-namespaced XML that relates to a paging mechanism for accessing bulk results successively:
Specification:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="https://webservice_address_here">
<soapenv:Header>
<ns:apiKey>
<api_key>***</api_key>
</ns:apiKey>
<pager>
<page>1</page>
<per_page>100</per_page>
</pager>
</soapenv:Header>
</soapenv:Envelope>
API Documentation:
Pagination; this method returns paginated results. To specify pages or
results per page, use the pager header:
<soapenv:Header>
<ns:pager>
<page>1</page>
<per_page>100</per_page>
</ns:pager>
</soapenv:Header> Max per page is 100
Pagination information is returned in a pager header:
<soapenv:Header>
<ns:pager>
<page>1</page>
<per_page>100</per_page>
<next_page>2</next_page>
<page_items>100</page_items>
<total_items>2829</total_items>
<total_pages>29</total_pages>
</ns:pager>
</soapenv:Header>
The answer, How to set soap headers in zeep when header has multiple elements, describes a similar scenario, without the namespace "ns" but with "acm." I have not been successful in using this method.
This works, allowing access to the api but without the pager making it mostly useless for any methods that return more than 100 results:
from zeep import Client, xsd
# Generate the header structure
header = xsd.Element(
'{wsdl}AuthenticateRequest',
xsd.ComplexType([xsd.Element("{wsdl}api_key", xsd.String())])
)
# Insert values into header placeholders
self._header_value = header(api_key=self.api_key)
This does not work:
from zeep import Client, xsd
# Generate the header structure
header = xsd.Element(
'Header',
xsd.ComplexType([
xsd.Element(
'{wsdl}AuthenticateRequest',
xsd.ComplexType([
xsd.Element('{wsdl}api_key', xsd.String()),
])
),
xsd.Element(
'pager',
xsd.ComplexType([
xsd.Element('page', xsd.String()),
xsd.Element('per_page', xsd.String()),
])
),
])
)
# ERROR HERE: Insert values into header placeholders
self._header_value = header(api_key=self.api_key, pager={'page':1,'per_page':100})
Error: TypeError: ComplexType() got an unexpected keyword argument 'api_key'. Signature: AuthenticateRequest: {api_key: xsd:string}, pager: {page: xsd:string, per_page: xsd:string}
This also does not work:
header = xsd.Element(
'{wsdl}AuthenticateRequest',
xsd.ComplexType([xsd.Element("{wsdl}api_key", xsd.String())]),
xsd.Element(
'pager',
xsd.ComplexType([
xsd.Element('page', xsd.String()),
xsd.Element('per_page', xsd.String()),
])
)
)
# ERROR HERE: Insert values into header placeholders
self._header_value = header(api_key=self.api_key, pager={"page":1,"per_page":100})
'pager' is not defined in the wsdl but the server expects that it could be there.
TypeError: ComplexType() got an unexpected keyword argument 'pager'.
Signature: api_key: xsd:string
Recent Failed (2022) Attempt Using #markoan answer:
def get_pager(self, page: int = 1, per_page: int = 100):
""" Create header that contains the page and records per page. """
pager_header = xsd.Element(
'pager',
xsd.ComplexType([
xsd.Element(
'page', xsd.Integer()
),
xsd.Element(
'per_page', xsd.Integer()
)
])
)
return pager_header(page=page, per_page=per_page)
def call(self, endpoint: str, *args, **kwargs):
"""Allows calling of any client service defined in the WSDL."""
# get the endpoint
endpoint = getattr(self.client.service, endpoint)
# get SOAP authentication header which includes the API key embedded from CFG
headers = [self.get_header()]
# add the pager complex element to headers if required in kwargs
if page := kwargs.get("page"):
per_page = kwargs.get("per_page") or 100
headers.append(self.get_pager(page, per_page))
# call the endpoint with provided unnamed and named parameters if any
result = endpoint(*args, **kwargs, _soapheaders=headers)
# serialize and return result
return self.serialize(result)
What is the simplest way using Zeep to set the namespace api_key and non-namespaced complex pager element?

I find it's easier to work with Zeep if we have a valid and complete WSDL.
A simple API service WSDL that expects an element without namespace would import a schema with no namespace like this:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" >
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<s:import schemaLocation="namespaceLessElement.xsd"/>
<s:element name="Api" minOccurs="0" maxOccurs="1">
</s:element>
<s:element name="ApiResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="ApiResult" type="s:int"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="apiKey">
<s:complexType>
<s:sequence>
<s:element name="api_key" type="s:string"></s:element>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="ApiSoapIn">
<wsdl:part name="parameters" element="tns:Api"/>
</wsdl:message>
<wsdl:message name="ApiSoapOut">
<wsdl:part name="parameters" element="tns:ApiResponse"/>
</wsdl:message>
<wsdl:message name="ApiKeyHeader">
<wsdl:part name="ApiKeyHeaderParam" element="tns:apiKey"/>
</wsdl:message>
<wsdl:message name="PagerHeader">
<wsdl:part name="PagerHeaderParam" ref="pager"/>
</wsdl:message>
<wsdl:portType name="ApiSoap">
<wsdl:operation name="Api">
<wsdl:documentation>This is a test WebService. Returns a number</wsdl:documentation>
<wsdl:input message="tns:ApiSoapIn"/>
<wsdl:output message="tns:ApiSoapOut"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ApiSoap" type="tns:ApiSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Api">
<soap:operation soapAction="http://tempuri.org/Api" style="document"/>
<wsdl:input>
<soap:header message="tns:ApiKeyHeader" part="ApiKeyHeaderParam" use="literal"/>
<soap:header message="tns:PagerHeader" part="PagerHeaderParam" use="literal"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ApiTest">
<wsdl:port name="ApiSoap" binding="tns:ApiSoap">
<soap:address location="http://superpc:8082/"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
With namespaceLessElement.xsd:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<s:schema xmlns:s="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<s:element name="pager">
<s:complexType>
<s:sequence>
<s:element name="page" type="s:int"></s:element>
<s:element name="per_page" type="s:int"></s:element>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
Note how the operation definition that expects header values points to correct messages:
<wsdl:operation name="Api">
<soap:operation soapAction="http://tempuri.org/Api" style="document"/>
<wsdl:input>
<soap:header message="tns:ApiKeyHeader" part="ApiKeyHeaderParam" use="literal"/>
<soap:header message="tns:PagerHeader" part="PagerHeaderParam" use="literal"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
and these in turn reference correct elements:
<wsdl:message name="ApiKeyHeader">
<wsdl:part name="ApiKeyHeaderParam" element="tns:apiKey"/>
</wsdl:message>
<wsdl:message name="PagerHeader">
<wsdl:part name="PagerHeaderParam" ref="pager"/>
</wsdl:message>
You should check in the WSDL of your web service that the operation describes both headers and that it includes a schema definition for both elements. In the example WSDL the service namespace is targetNamespace="http://tempuri.org/" but this should point to your web service URL.
So assuming your WSDL is valid and complete, we need to define the Client pointing to the WSDL and then set the header values using the _soapheaders parameter, similar to the method I used here but building the content reference. Zeep can take care of the different namespaces but I found issues with empty ones:
transport = Transport(cache=SqliteCache())
self.Test = Client(wsdl='http://my-endpoint.com/production.svc?wsdl', transport=transport)
# Header objects
apiKey_header = xsd.Element(
'{http://tempuri.org/}apiKey',
xsd.ComplexType([
xsd.Element(
'api_key', xsd.String()
)
])
)
pager_header = xsd.Element(
'pager',
xsd.ComplexType([
xsd.Element(
'page', xsd.Integer()
),
xsd.Element(
'per_page', xsd.Integer()
)
])
)
apiKey_header_value = apiKey_header( api_key=key)
pager_header_value = pager_header( page=page, per_page=perpage)
# Request
response = self.Test.service.Api( _soapheaders=[apiKey_header_value, pager_header_value] )
logger.debug("Result={1}".format(response))
# Prints: Result=2 (or whatever value the test API sends)
EDIT: Example of generated XML request:
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<ns0:apiKey xmlns:ns0="http://tempuri.org/">
<api_key>1230011</api_key>
</ns0:apiKey>
<pager>
<page>2</page>
<per_page>10</per_page>
</pager>
</soap-env:Header>
<soap-env:Body>
<ns0:Api xmlns:ns0="http://tempuri.org/"/>
</soap-env:Body>
</soap-env:Envelope>
Make sure that the header that has a namespace is defined with the correct URL.
If you still have problems it may mean your WSDL does not define all elements or that it's not linking correctly to external XSDs. In those cases one option is to save a local copy os the WSDL and linked XSDs, then edit the files to fix references and then point Zeep to that local file instead.

Related

Azure API Management WSDL Import Failing on SOAP Encoding's Array Type

I'm trying to create an API from a WSDL and currently getting this error back from Azure APIM during the import step:
Error: Parsing error : Line 17, position 22: Unable to import API from WSDL: Undefined
complexType 'http://schemas.xmlsoap.org/soap/encoding/:Array' is used as a base for
complex type restriction.
I'm gathering that the Array type is not WSI-compliant, but would love insight as to how I can tinker with the WSDL to make it work? I don't own the service which generated the WSDL, but the WSDL hasn't changed since it was incepted and the provider has said it's okay for us to mess with it to get the Azure APIM import step to work. Just meaning, since Azure APIM's a passthrough what can I slice out of the WSDL which would still (a) let Azure APIM import it, and (b) allow the calls to successfully flow through Azure APIM at runtime?
I slimmed down the WSDL to this, but let me know if anything looks off as the original WSDL is ~5,500 lines:
<?xml version="1.0"?>
<definitions
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s0="urn:ChestersCopperpotsServiceSoap"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:atls="http://tempuri.org/vc/atl/server/"
targetNamespace="urn:ChestersCopperpotsServiceSoap"
xmlns="http://schemas.xmlsoap.org/wsdl/"
>
<types>
<s:schema targetNamespace="urn:ChestersCopperpotsServiceSoap" attributeFormDefault="qualified" elementFormDefault="qualified">
<s:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<s:complexType name="CMessage">
<s:sequence>
<s:element name="Code" type="s:int"/>
<s:element name="Text" type="s:string"/>
</s:sequence>
</s:complexType>
<s:complexType name="GetMessages_return_Array">
<s:complexContent>
<s:restriction base="soapenc:Array">
<s:attribute ref="soapenc:arrayType" wsdl:arrayType="s0:CMessage[]"/>
</s:restriction>
</s:complexContent>
</s:complexType>
<s:complexType name="MyHeader">
<s:sequence>
<s:element name="m_SessionID" type="s:string"/>
</s:sequence>
</s:complexType>
</s:schema>
</types>
<message name="GetMessagesIn">
</message>
<message name="GetMessagesOut">
<part name="return" type="s0:GetMessages_return_Array"/>
</message>
<message name="m_Header">
<part name="m_Header" type="s0:MyHeader"/>
</message>
<portType name="ChestersCopperpotsServiceSoap">
<operation name="GetMessages">
<input message="s0:GetMessagesIn"/>
<output message="s0:GetMessagesOut"/>
</operation>
</portType>
<binding name="ChestersCopperpotsServiceSoap" type="s0:ChestersCopperpotsServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
<operation name="GetMessages">
<soap:operation soapAction="#GetMessages" style="rpc"/>
<input>
<soap:body use="encoded" namespace="urn:ChestersCopperpotsService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<soap:header message="s0:m_Header" part="m_Header" use="encoded" namespace="urn:ChestersCopperpotsService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="urn:ChestersCopperpotsService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<soap:header message="s0:m_Header" part="m_Header" use="encoded" namespace="urn:ChestersCopperpotsService" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="ChestersCopperpotsService">
<port name="ChestersCopperpotsServiceSoap" binding="s0:ChestersCopperpotsServiceSoap">
<soap:address location="http://localhost:80/ChestersCopperpots/ccSOAP.dll?Handler=Default"/>
</port>
</service>
</definitions>
Full message stack from Azure APIM is:
Informational: ParsingXMLStarted : Started parsing XML
Informational: ParsingXMLComplete : Completed parsing XML
Verbose: WsdlImportRuleVerifyWadl11Schema : WSDL validated against XML Schema
Informational: WsdlPrecheckComplete : Completed WSDL verification. WSDL is considered valid.
Informational: WsdlParsingStarted : Service : Endpoint :
Informational: WsdlIdentification : WsdlVersion: 'Wsdl11' TargetNamespace: 'urn:ChestersCopperpotsServiceSoap'.
Informational: LoadedSchema : Target Namespace: 'urn:ChestersCopperpotsServiceSoap'.
Informational: LoadedSchemas : Loaded '1' schemas.
Informational: LoadedTypes : Loaded '0' types.
Informational: LoadedMessages : Loaded '3' messages.
Informational: LoadedInterfaces : Loaded '1' interfaces.
Informational: LoadedBindings : Loaded '1' bindings.
Informational: LoadedServices : Loaded '1' services.
Informational: WsdlParsingComplete : Parsed 1 operations and 3 messages
Informational: ApiType : Creating SOAP Passthrough API
Informational: APICreated : Name : chesterscopperpotsservice Service Url: http://localhost:80/ChestersCopperpots/ccSOAP.dll?Handler=Default
Informational: XsdParsing : Starting to parse urn:ChestersCopperpotsServiceSoap
Error: Parsing error : Line 17, position 22: Unable to import API from WSDL: Undefined complexType 'http://schemas.xmlsoap.org/soap/encoding/:Array' is used as a base for complex type restriction.
my money is on this part (which in lack of row #, I suspect this is where the error get's triggered). The SOAP-to-REST transformation in APIM only supports "embedded" arrays, whereas yours is referring to another definition ("s0.CMessage" above). Try replacing that bit with
<s:complexType name="GetMessages_return_Array">
<sequence>
<element name="ArrayOfCMessages" type="CMessage" minOccurs="1" maxOccurs="1"/>
</sequence>
</s:complexType>

Recipient type for the original signer is not changed from signer to CarbonCopy

I have goan through the answer for below question
Docusign call back from Docusign Connect not happening on change signer_
My question is - In the callback ( using legacy data format ) I dont see reciepient's type changed to "CarbonCopy" for original signer who has delegated to another signer rather I see the "delegated to" having "Signer" as type in the callback.
Is this something related to Connect configuration? I didn't found relevant setting actually.
This works for my demo account though, but not for customer's DocuSign account.
I have handled this "CarbonCopy" tag in the integration so this is needed information for me.
Is there any setting at account level that controls the recipient type for the original signer is changed from signer to CarbonCopy?
Edit-
In Below sample, mainsigner#yyy.com has delegated to delegatedto#yyy.com , So I would expect a new RecipientStatus node for mainsigner#yyy.com with Type as "CarbonCopy"
<?xml version="1.0" encoding="utf-8"?>
<DocuSignEnvelopeInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.docusign.net/API/3.0">
<EnvelopeStatus>
<RecipientStatuses>
<RecipientStatus>
<Type>CarbonCopy</Type>
<Email>abc#xxx.com</Email>
<UserName>ABC</UserName>
<RoutingOrder>1</RoutingOrder>
<Sent>2021-10-28T11:51:53.177</Sent>
<DeclineReason/>
<Status>Completed</Status>
<RecipientIPAddress/>
<CustomFields>
<CustomField>NonSignerCarbonCopy</CustomField>
<CustomField/>
<CustomField/>
</CustomFields>
<AccountStatus>Active</AccountStatus>
<RecipientId>d4bee1ca-8af2-4d45-83b9-xxxxxxxxx</RecipientId>
</RecipientStatus>
<RecipientStatus>
<Type>Signer</Type>
<Email>delegatedto#yyy.com</Email>
<UserName>delegatedto</UserName>
<RoutingOrder>1</RoutingOrder>
<Sent>2021-11-04T07:44:41.59</Sent>
<Delivered>2021-11-04T07:55:46.007</Delivered>
<Signed>2021-11-04T07:56:03.007</Signed>
<DeclineReason/>
<Status>Completed</Status>
<RecipientIPAddress>ipaddress</RecipientIPAddress>
<CustomFields>
<CustomField>S||mainsigner#yyy.com</CustomField>
<CustomField/>
<CustomField/>
</CustomFields>
<TabStatuses>
<TabStatus>
<TabType>SignHere</TabType>
<Status>Signed</Status>
<XPosition>187</XPosition>
<YPosition>508</YPosition>
<TabLabel>Sign Here</TabLabel>
<TabName>SignHere</TabName>
<TabValue/>
<DocumentID>336845219</DocumentID>
<PageNumber>2</PageNumber>
</TabStatus>
<TabStatus>
<TabType>DateSigned</TabType>
<Status>Signed</Status>
<XPosition>195</XPosition>
<YPosition>816</YPosition>
<TabLabel>Date Signed</TabLabel>
<TabName>DateSigned</TabName>
<TabValue>11/4/2021 | 7:56 AM PDT</TabValue>
<DocumentID>336845219</DocumentID>
<PageNumber>2</PageNumber>
</TabStatus>
</TabStatuses>
<RecipientAttachment>
<Attachment>
<Data>somedaata</Data>
<Label>DSXForm</Label>
</Attachment>
</RecipientAttachment>
<AccountStatus>Closed</AccountStatus>
<EsignAgreementInformation>
<AccountEsignId>GUID</AccountEsignId>
<UserEsignId>GUID</UserEsignId>
<AgreementDate>2021-11-04T07:55:46.007</AgreementDate>
</EsignAgreementInformation>
<FormData>
<xfdf>
<fields>
<field name="DateSigned">
<value>11/4/2021 | 7:56 AM PDT</value>
</field>
</fields>
</xfdf>
</FormData>
<RecipientId>98525aa9-ae3e-4d1c-aa48-xxxxxxxxxx</RecipientId>
</RecipientStatus>
</RecipientStatuses>
<TimeGenerated>2021-11-04T07:56:23.8331339</TimeGenerated>
<EnvelopeID>ee738247-57a4-49d7-8914-xxxxxxxx</EnvelopeID>
<Subject>C345</Subject>
<UserName>Admin</UserName>
<Email>Admin#yyy.com</Email>
<Status>Completed</Status>
<Created>2021-10-28T11:51:51.707</Created>
<Sent>2021-11-04T07:44:41.637</Sent>
<Delivered>2021-11-04T07:55:46.273</Delivered>
<Signed>2021-11-04T07:56:03.007</Signed>
<Completed>2021-11-04T07:56:03.007</Completed>
<ACStatus>Original</ACStatus>
<ACStatusDate>2021-10-28T11:51:51.707</ACStatusDate>
<ACHolder>Admin</ACHolder>
<ACHolderEmail>Admin#yyy.com</ACHolderEmail>
<ACHolderLocation>DocuSign</ACHolderLocation>
<SigningLocation>Online</SigningLocation>
<SenderIPAddress>ipaddress </SenderIPAddress>
<EnvelopePDFHash/>
<CustomFields/>
<AutoNavigation>true</AutoNavigation>
<EnvelopeIdStamping>true</EnvelopeIdStamping>
<AuthoritativeCopy>false</AuthoritativeCopy>
<DocumentStatuses>
<DocumentStatus>
<ID>888888888</ID>
<Name>C3459</Name>
<TemplateName/>
<Sequence>1</Sequence>
</DocumentStatus>
</DocumentStatuses>
</EnvelopeStatus>
<DocumentPDFs>
<DocumentPDF>
<Name>CertificateOfCompletion_GUID.pdf</Name>
<PDFBytes>Bn8iUlJSRa7MTExKzHx1DNb//bFeKyLoldo39X9/S
.........
and here are the subscribed events
Envelope Sent
Envelope Signed/Completed
Envelope Declined
Envelope Voided
Recipient Signed/Completed
Recipient Declined

Routing Order / Signing Group information in the connect response?

I´m trying to understand the response the connect API (using the webhook status updates) sends. The documentation says, the answer only provides XML elements of EvenvelopeStatus type (plus document PDFs, if requested). This does not include current routing order information or signing group information, right?
Does anyone know, if this is true and if there is a workaround, how to get the current routing order within the connect message without parsing the recipients status?
If one of the recipients is a signing group, will the name and email field remain empty until one of the group members has viewed / signed the document? Then I would expect the name / email field to be filled with the actual signer.
Thank you for your help!
I found the answers to my questions by debugging the interface. It is like expected: names of signing groups are reported in the name tag and replaced by the actual signers name after signing has been completed. Routing status has to be "calculated" by interpreting the recipients status - no overall routing info like in the envelope:get service call.
Current routing situation can be determined from the notification message. See the status attributes for the envelope's recipients.
You need to infer the current routing status by looking at the status values for the recipients. Here is an example notification. You can see that one of the recipients is in completed status and the other is in sent status.
Remember that multiple recipients can be in sent status at the same time if the envelope is using parallel routing.
<?xml version="1.0" encoding="utf-8"?>
<DocuSignEnvelopeInformation
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.docusign.net/API/3.0">
<EnvelopeStatus>
<RecipientStatuses>
<RecipientStatus>
<Type>Signer</Type>
<Email>Sam.Spade#example.com</Email>
<UserName>Sam Spade</UserName>
<RoutingOrder>1</RoutingOrder>
<Sent>2019-05-07T10:43:40.073</Sent>
<Delivered>2019-05-07T10:44:06.023</Delivered>
<Signed>2019-05-07T10:44:12.323</Signed>
<DeclineReason xsi:nil="true"/>
<Status>Completed</Status>
<RecipientIPAddress>141.226.10.195</RecipientIPAddress>
<CustomFields/>
<TabStatuses>
<TabStatus>
<TabType>SignHere</TabType>
<Status>Signed</Status>
<XPosition>341</XPosition>
<YPosition>697</YPosition>
<TabLabel>Sign Here</TabLabel>
<TabName>SignHere</TabName>
<DocumentID>1</DocumentID>
<PageNumber>1</PageNumber>
</TabStatus>
<TabStatus>
<TabType>SignHere</TabType>
<Status>Signed</Status>
<XPosition>416</XPosition>
<YPosition>412</YPosition>
<TabLabel>Sign Here</TabLabel>
<TabName>SignHere</TabName>
<DocumentID>2</DocumentID>
<PageNumber>1</PageNumber>
</TabStatus>
<TabStatus>
<TabType>SignHere</TabType>
<Status>Signed</Status>
<XPosition>416</XPosition>
<YPosition>316</YPosition>
<TabLabel>Sign Here</TabLabel>
<TabName>SignHere</TabName>
<DocumentID>3</DocumentID>
<PageNumber>1</PageNumber>
</TabStatus>
</TabStatuses>
<AccountStatus>Active</AccountStatus>
<RecipientId>64d1f093-d51e-4d38-914e-3255f46c0e18</RecipientId>
</RecipientStatus>
<RecipientStatus>
<Type>Signer</Type>
<Email>Susan.smith#example.com</Email>
<UserName>Susan Smith</UserName>
<RoutingOrder>2</RoutingOrder>
<Sent>2019-05-07T10:44:13.76</Sent>
<DeclineReason xsi:nil="true"/>
<Status>Sent</Status>
<RecipientIPAddress/>
<CustomFields/>
<AccountStatus>Active</AccountStatus>
<RecipientId>ad82fdb5-dfe9-479e-a4ca-0032a51b076a</RecipientId>
</RecipientStatus>
</RecipientStatuses>
<TimeGenerated>2019-05-07T10:47:56.4026603</TimeGenerated>
<EnvelopeID>a65c99da-39aa-488f-909a-1b3964634758</EnvelopeID>
<Subject>Please sign this document set</Subject>
<UserName>Sam Spade</UserName>
<Email>Sam.Spade#example.com</Email>
<Status>Sent</Status>
<Created>2019-05-07T10:43:27.943</Created>
<Sent>2019-05-07T10:44:13.79</Sent>
<ACStatus>Original</ACStatus>
<ACStatusDate>2019-05-07T10:43:27.943</ACStatusDate>
<ACHolder>Sam Spade</ACHolder>
<ACHolderEmail>Sam.Spade#example.com</ACHolderEmail>
<ACHolderLocation>DocuSign</ACHolderLocation>
<SigningLocation>Online</SigningLocation>
<SenderIPAddress>141.226.10.195 </SenderIPAddress>
<EnvelopePDFHash/>
<CustomFields>
<CustomField>
<Name>Order ID</Name>
<Show>True</Show>
<Required>False</Required>
<Value/>
</CustomField>
<CustomField>
<Name>Sales order</Name>
<Show>True</Show>
<Required>False</Required>
<Value>16</Value>
</CustomField>
<CustomField>
<Name>AccountId</Name>
<Show>false</Show>
<Required>false</Required>
<Value>3964103</Value>
<CustomFieldType>Text</CustomFieldType>
</CustomField>
<CustomField>
<Name>AccountName</Name>
<Show>false</Show>
<Required>false</Required>
<Value>World Wide Corp</Value>
<CustomFieldType>Text</CustomFieldType>
</CustomField>
<CustomField>
<Name>AccountSite</Name>
<Show>false</Show>
<Required>false</Required>
<Value>demo</Value>
<CustomFieldType>Text</CustomFieldType>
</CustomField>
</CustomFields>
<AutoNavigation>true</AutoNavigation>
<EnvelopeIdStamping>true</EnvelopeIdStamping>
<AuthoritativeCopy>false</AuthoritativeCopy>
<DocumentStatuses>
<DocumentStatus>
<ID>1</ID>
<Name>Order acknowledgement</Name>
<TemplateName/>
<Sequence>1</Sequence>
</DocumentStatus>
<DocumentStatus>
<ID>2</ID>
<Name>Battle Plan</Name>
<TemplateName/>
<Sequence>2</Sequence>
</DocumentStatus>
<DocumentStatus>
<ID>3</ID>
<Name>Lorem Ipsum</Name>
<TemplateName/>
<Sequence>3</Sequence>
</DocumentStatus>
</DocumentStatuses>
</EnvelopeStatus>
</DocuSignEnvelopeInformation>

how to make http request from xml soap?

I am implementing one of the payment gateway(Advance cash) in my application.Here is the link :
Adv documentaion
According to its documentation I have to made request for transaction. But the request mention in it in xml format.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsm="http://wsm.advcash/">
<soapenv:Header/>
<soapenv:Body>
<wsm:sendMoney>
<arg0>
<apiName>api_name</apiName>
<authenticationToken>token</authenticationToken>
<accountEmail>name#example.com</accountEmail>
</arg0>
<arg1>
<amount>1.00</amount>
<currency>USD</currency>
<email>name#example.com</email>
<note>Some note</note>
<savePaymentTemplate>false</savePaymentTemplate>
</arg1>
</wsm:sendMoney>
</soapenv:Body>
</soapenv:Envelope>
I think it is kind of soap request,I want to know how to request this and what are the parameters I have to send using my node js application using "request" npm module.Please help.
You should use node-soap package. There is a request option which override the request module.
I made a sample, take a look
service.ts:
const service = {
UserService: {
ServicePort: {
getUserById(args) {
const user = { id: args.id, name: faker.name.findName(), email: faker.internet.email() };
return user;
}
}
}
};
service.wsdl:
<definitions name="Service" targetNamespace="http://localhost:8001/get-started/service.wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://localhost:8001/get-started/service.wsdl"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<message name="GetUserByIdInput">
<part name="id" type="xsd:string"></part>
</message>
<message name="GetUserByIdOutput">
<part name="id" type="xsd:string"></part>
<part name="name" type="xsd:string"></part>
<part name="email" type="xsd:string"></part>
</message>
<portType name="ServicePortType">
<operation name="getUserById">
<input message="tns:GetUserByIdInput"/>
<output message="tns:GetUserByIdOutput"></output>
</operation>
</portType>
<binding name="ServiceSoapBinding" type="tns:ServicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getUserById">
<soap:operation soapAction="getUserById"/>
<input message="tns:GetUserByIdInput">
<soap:body parts="id" use="literal"/>
</input>
<output message="tns:GetUserByIdOutput">
<soap:body parts="id" use="literal"/>
<soap:body parts="name" use="literal"/>
<soap:body parts="email" use="literal"/>
</output>
</operation>
</binding>
<service name="UserService">
<documentation>Get started service</documentation>
<port name="ServicePort" binding="tns:ServiceSoapBinding">
<soap:address location="http://localhost:8001/get-started"/>
</port>
</service>
</definitions>
request.xml:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tns="http://localhost:8001/get-started/service.wsdl">
<soap:Body>
<tns:getUserById>
<id>8104d3c3-de13-432f-b4a0-a62f84f6206a</id>
</tns:getUserById>
</soap:Body>
</soap:Envelope>
server.spec.ts:
it('should get correct result using http request and static xml', async (done: jest.DoneCallback) => {
const xml = fs.readFileSync(path.resolve(__dirname, './static-xml.xml'), 'utf8');
const uuid = '8104d3c3-de13-432f-b4a0-a62f84f6206a';
const options = {
url,
method: 'POST',
body: xml,
headers: {
'Content-Type': 'text/xml;charset=utf-8',
'Accept-Encoding': 'gzip,deflate',
'Content-Length': xml.length
}
};
const rawXml = await request(options);
parser.parseString(rawXml, (err, actualValue) => {
if (err) {
done(err);
}
console.log('actualValue: ', JSON.stringify(actualValue));
expect(actualValue['soap:Envelope']['soap:Body']['tns:getUserByIdResponse']['tns:id']).toBe(uuid);
done();
});
});
The result:
actualValue: {"soap:Envelope":{"$":{"xmlns:soap":"http://schemas.xmlsoap.org/soap/envelope/","xmlns:tns":"http://localhost:8001/get-started/service.wsdl"},"soap:Body":{"tns:getUserByIdResponse":{"tns:id":"bf0f6172-2f53-4b33-94c8-9ff9ed8fd431","tns:name":"Theo Leannon","tns:email":"Brent.Berge#hotmail.com"}}}}
Here is the demo: https://github.com/mrdulin/nodejs-soap/tree/master/src/get-started

OC 2.0 Fedex shipping method not working

We tried to Fedex shipping method in our opencart website.
It Display the "Error" text.
ERRORERRORcrs691The PurposeOfShipmentType is null, empty or invalid.
The PurposeOfShipmentType is null, empty or invalid.crs1000
Use this xml
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://fedex.com/ws/rate/v13">
<SOAP-ENV:Body>
<RateRequest>
<WebAuthenticationDetail>
<UserCredential>
<Key>XXXXX</Key>
<Password>XXXXX</Password>
</UserCredential>
</WebAuthenticationDetail>
<ClientDetail>
<AccountNumber>XXXXX</AccountNumber>
<MeterNumber>XXXXX</MeterNumber>
</ClientDetail>
<TransactionDetail>
<CustomerTransactionId>MY-RATE-REQUEST</CustomerTransactionId>
</TransactionDetail>
<Version>
<ServiceId>crs</ServiceId>
<Major>13</Major>
<Intermediate>0</Intermediate>
<Minor>0</Minor>
</Version>
<ReturnTransitAndCommit>true</ReturnTransitAndCommit>
<RequestedShipment>
<ShipTimestamp>2012-10-09T14:28:07.9489435+05:30</ShipTimestamp>
<DropoffType>REGULAR_PICKUP</DropoffType>
<PackagingType>YOUR_PACKAGING</PackagingType>
<Shipper>
<Address>
<StreetLines>Sardarnagar Main Road, Rajkot</StreetLines>
<City>Rajkot</City>
<StateOrProvinceCode>GJ</StateOrProvinceCode>
<PostalCode>360001</PostalCode>
<CountryCode>IN</CountryCode>
</Address>
</Shipper>
<Recipient>
<Address>
<StreetLines>Radhekrishna App. Main Road , Rajkot</StreetLines>
<City>Bhuj</City>
<StateOrProvinceCode>GJ</StateOrProvinceCode>
<PostalCode>370001</PostalCode>
<CountryCode>IN</CountryCode>
</Address>
</Recipient>
<ShippingChargesPayment>
<PaymentType>SENDER</PaymentType>
<Payor>
<ResponsibleParty>
<AccountNumber>XXXXX</AccountNumber>
</ResponsibleParty>
</Payor>
</ShippingChargesPayment>
<CustomsClearanceDetail>
<DutiesPayment>
<PaymentType>RECIPIENT</PaymentType>
</DutiesPayment>
<DocumentContent>NON_DOCUMENTS</DocumentContent>
<CustomsValue>
<Currency>INR</Currency>
<Amount>299.000000</Amount>
</CustomsValue>
<CommercialInvoice>
<Purpose>NOT_SOLD</Purpose>
</CommercialInvoice>
</CustomsClearanceDetail>
<RateRequestTypes>ACCOUNT</RateRequestTypes>
<RateRequestTypes>LIST</RateRequestTypes>
<PackageCount>1</PackageCount>
<RequestedPackageLineItems>
<SequenceNumber>1</SequenceNumber>
<GroupPackageCount>1</GroupPackageCount>
<Weight>
<Units>KG</Units>
<Value>1</Value>
</Weight>
</RequestedPackageLineItems>
</RequestedShipment>
</RateRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Resources