how to use JavaScript callout and httpClient to invoke the SOAP-based Avalara Tax Service (avatax) ?

I have a synchronous request to be made to another webservice before making the call to target endpoint and I'm using javascript to construct this request.

When I test the constructed request in SOAPUI , I get the expected response

However, when I use the below in javascript -

var myResult = httpClient.get("https://development.avalara.net/Tax/TaxSvc.asmx/v2",reqcont);

I get below as response . how to use httpClient in order to pass the request along with URL to get valid response ?

<HTML><HEAD><link rel="alternate" type="text/xml" href="http://development.avalara.net/Tax/TaxSvc.svc?disco"/><STYLE type="text/css">#content{ FONT-SIZE: 0.7em; PADDING-BOTTOM: 2em; MARGIN-LEFT: 30px}BODY{MARGIN-TOP: 0px; MARGIN-LEFT: 0px; COLOR: #000000; FONT-FAMILY: Verdana; BACKGROUND-COLOR: white}P{MARGIN-TOP: 0px; MARGIN-BOTTOM: 12px; COLOR: #000000; FONT-FAMILY: Verdana}PRE{BORDER-RIGHT: #f0f0e0 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #f0f0e0 1px solid; MARGIN-TOP: -5px; PADDING-LEFT: 5px; FONT-SIZE: 1.2em; PADDING-BOTTOM: 5px; BORDER-LEFT: #f0f0e0 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #f0f0e0 1px solid; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e5e5cc}.heading1{MARGIN-TOP: 0px; PADDING-LEFT: 15px; FONT-WEIGHT: normal; FONT-SIZE: 26px; MARGIN-BOTTOM: 0px; PADDING-BOTTOM: 3px; MARGIN-LEFT: -30px; WIDTH: 100%; COLOR: #ffffff; PADDING-TOP: 10px; FONT-FAMILY: Tahoma; BACKGROUND-COLOR: #003366}.intro{MARGIN-LEFT: -15px}</STYLE><TITLE>TaxSvc Service</TITLE></HEAD><BODY><DIV id="content"><P>TaxSvc Service</P><BR/><P>You have created a service.<P class='intro'>To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:</P> <BR/><PRE>svcutil.exe <A HREF="http://development.avalara.net/Tax/TaxSvc.svc?wsdl">http://development.avalara.net/Tax/TaxSvc.svc?wsdl</A></PRE><P>You can also access the service description as a single file:<BR/><PRE><A HREF="http://development.avalara.net/Tax/TaxSvc.svc?singleWsdl">http://development.avalara.net/Tax/TaxSvc.svc?singleWsdl</A></PRE></P></P><P/>This will generate a configuration file and a code file that contains the client class. Add the two files to your client application and use the generated client class to call the Service. For example:<BR/><P class='intro'><B>C#</B></P><PRE><font color="blue">class </font><font color="teal">Test </font>{ <font color="blue"> static void </font>Main() { <font color="teal">TaxSvcClient</font> client = <font color="blue">new </font><font color="teal">TaxSvcClient</font>(); <font color="green"> // Use the 'client' variable to call operations on the service. </font><font color="green"> // Always close the client. </font> client.Close(); } } </PRE><BR/><P class='intro'><B>Visual Basic</B></P><PRE><font color="blue">Class </font><font color="teal">Test </font><font color="blue"> Shared Sub </font>Main() <font color="blue"> Dim </font>client As <font color="teal">TaxSvcClient</font> = <font color="blue">New </font><font color="teal">TaxSvcClient</font>() <font color="green"> ' Use the 'client' variable to call operations on the service. </font><font color="green"> ' Always close the client. </font> client.Close() <font color="blue"> End Sub </font><font color="blue">End Class</font></PRE></DIV></BODY></HTML>

Solved Solved
1 5 1,622
2 ACCEPTED SOLUTIONS

This "https://development.avalara.net/Tax/TaxSvc.asmx/v2" looks like just a SOAP service information page, which via httpClient returning response as HTML page content.

Also is the WSDL publicly available as i tried and it ever loads? Also make you are passing correct input request.

View solution in original post

Your question asked "how to use the httpClient from JavaScript?" But I think you really want to know, "how can I invoke the Avalara Tax Service from an Apigee Edge API Proxy?"

@Faij Ahmad is correct : the URL you mentioned is just a service description page. It gives information about the service (useful for humans) - it is not the endpoint for the service (useful for apps).

Searching on Google, I found the actual WSDL for the Avalara Tax service is here:

https://development.avalara.net/Tax/TaxSvc.wsdl

The WSDL is just a machine-readable service description (WSDL = Web Services Description Language). Again, it is not the app endpoint, but the WSDL tells me the app endpoint. It is https://development.avalara.net/Tax/TaxSvc.asmx?Ping

What I would do:

  • Figure out how to construct a request to the Avalara service you want.
  • Use ServiceCallout (not JS and httpClient) to invoke the service

By googling around and playing, and with no thanks to the avalara developer documentation which I found to be confusing, I was able to build a request to invoke the Ping operation on that TaxService, and get a real response.

My request was like this:

curl -i -X POST https://development.avalara.net/Tax/TaxSvc.asmx?Ping \
  -H soapAction:http://avatax.avalara.com/services/Ping \
  -H Content-Type:text/xml \
    --data '
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:avalara="http://avatax.avalara.com/services">
  <soap:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                   soap:actor="http://schemas.xmlsoap.org/soap/actor/next">
      <wsse:UsernameToken>
        <wsse:Username>My-Account-Id</wsse:Username>
        <wsse:Password>My-License-Key</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
    <avalara:Profile>
      <avalara:Name>TEST</avalara:Name>
      <avalara:Client>ClientSOAP</avalara:Client>
      <avalara:Adapter>SOAP API</avalara:Adapter>
      <avalara:Machine>MBPRO</avalara:Machine>
    </avalara:Profile>
  </soap:Header>
  <soap:Body>
    <avalara:Ping/>
  </soap:Body>
</soap:Envelope>
'

and the response I got was a pretty standard SOAP fault:

<s:Envelope 
    xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">The user or account could not be authenticated.</faultstring>
    </s:Fault>
  </s:Body>
</s:Envelope> 

ok, so that says I got a good endpoint, but my security credentials were rejected. (I don't know why - I registered for a free trial account, but it's rejecting my creds). I'm assuming you have valid credentials for the Avalara service and you can insert them into place in the above.

How can you do the equivalent within an Apigee Proxy? Use ServiceCallout. The ServiceCallout also lets you template-ify the messaging being sent. Like this:

<ServiceCallout name='SC-AvalaraPing'>
  <Request>
    <Set>
     <Headers>
       <Header name='soapAction'>http://avatax.avalara.com/services/Ping</Header>
     </Headers>
     <Payload contentType='text/xml'>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://avatax.avalara.com/services">
  <soap:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                   soap:actor="http://schemas.xmlsoap.org/soap/actor/next">
      <wsse:UsernameToken>
        <wsse:Username>{avalara_accountid}</wsse:Username>
        <wsse:Password>{avalara_licensekey}</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
    <ser:Profile>
      <ser:Name>Apigee TEST</ser:Name>
      <ser:Client>Apigee Edge Client</ser:Client>
      <ser:Adapter>SOAP API</ser:Adapter>
      <ser:Machine>MBPRO</ser:Machine>
    </ser:Profile>
  </soap:Header>
  <soap:Body>
    <ser:Ping/>
  </soap:Body>
</soap:Envelope>
     </Payload>
     <Verb>POST</Verb>
    </Set>
  </Request>
  <Response>avalaraResponse</Response>
  <HTTPTargetConnection>
    <SSLInfo>
        <Enabled>true</Enabled>
        <IgnoreValidationErrors>true</IgnoreValidationErrors>
    </SSLInfo>
    <Properties>
      <Property name='success.codes'>2xx, 3xx, 4xx, 5xx</Property>
    </Properties>
    <URL>https://development.avalara.net/Tax/TaxSvc.asmx?Ping</URL>
  </HTTPTargetConnection>
</ServiceCallout>

Augment that policy with some XSL and an XMLToJSON policy and you can get a JSON response out.

Find attached a working API Proxy. avalara-sc-apiproxy-20180306-1145.zip

Deploy it to your org/env, and then Invoke it like this:

curl -i -u ${ACCOUNTID}:${LICENSEKEY} \
    https://${ORG}-${ENV}.apigee.net/avalara-sc/ping 

My response looks like this:

{
    "Fault": {
        "faultcode": "s:Client",
        "faultstring": {
            "lang": "en-US",
            "$": "The user or account could not be authenticated."
        }
    }
}

View solution in original post

5 REPLIES 5

This "https://development.avalara.net/Tax/TaxSvc.asmx/v2" looks like just a SOAP service information page, which via httpClient returning response as HTML page content.

Also is the WSDL publicly available as i tried and it ever loads? Also make you are passing correct input request.

@Faij Ahmad, thanks for your response! I'm now able to make a request and get successful response

Your question asked "how to use the httpClient from JavaScript?" But I think you really want to know, "how can I invoke the Avalara Tax Service from an Apigee Edge API Proxy?"

@Faij Ahmad is correct : the URL you mentioned is just a service description page. It gives information about the service (useful for humans) - it is not the endpoint for the service (useful for apps).

Searching on Google, I found the actual WSDL for the Avalara Tax service is here:

https://development.avalara.net/Tax/TaxSvc.wsdl

The WSDL is just a machine-readable service description (WSDL = Web Services Description Language). Again, it is not the app endpoint, but the WSDL tells me the app endpoint. It is https://development.avalara.net/Tax/TaxSvc.asmx?Ping

What I would do:

  • Figure out how to construct a request to the Avalara service you want.
  • Use ServiceCallout (not JS and httpClient) to invoke the service

By googling around and playing, and with no thanks to the avalara developer documentation which I found to be confusing, I was able to build a request to invoke the Ping operation on that TaxService, and get a real response.

My request was like this:

curl -i -X POST https://development.avalara.net/Tax/TaxSvc.asmx?Ping \
  -H soapAction:http://avatax.avalara.com/services/Ping \
  -H Content-Type:text/xml \
    --data '
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:avalara="http://avatax.avalara.com/services">
  <soap:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                   soap:actor="http://schemas.xmlsoap.org/soap/actor/next">
      <wsse:UsernameToken>
        <wsse:Username>My-Account-Id</wsse:Username>
        <wsse:Password>My-License-Key</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
    <avalara:Profile>
      <avalara:Name>TEST</avalara:Name>
      <avalara:Client>ClientSOAP</avalara:Client>
      <avalara:Adapter>SOAP API</avalara:Adapter>
      <avalara:Machine>MBPRO</avalara:Machine>
    </avalara:Profile>
  </soap:Header>
  <soap:Body>
    <avalara:Ping/>
  </soap:Body>
</soap:Envelope>
'

and the response I got was a pretty standard SOAP fault:

<s:Envelope 
    xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">The user or account could not be authenticated.</faultstring>
    </s:Fault>
  </s:Body>
</s:Envelope> 

ok, so that says I got a good endpoint, but my security credentials were rejected. (I don't know why - I registered for a free trial account, but it's rejecting my creds). I'm assuming you have valid credentials for the Avalara service and you can insert them into place in the above.

How can you do the equivalent within an Apigee Proxy? Use ServiceCallout. The ServiceCallout also lets you template-ify the messaging being sent. Like this:

<ServiceCallout name='SC-AvalaraPing'>
  <Request>
    <Set>
     <Headers>
       <Header name='soapAction'>http://avatax.avalara.com/services/Ping</Header>
     </Headers>
     <Payload contentType='text/xml'>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://avatax.avalara.com/services">
  <soap:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                   soap:actor="http://schemas.xmlsoap.org/soap/actor/next">
      <wsse:UsernameToken>
        <wsse:Username>{avalara_accountid}</wsse:Username>
        <wsse:Password>{avalara_licensekey}</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
    <ser:Profile>
      <ser:Name>Apigee TEST</ser:Name>
      <ser:Client>Apigee Edge Client</ser:Client>
      <ser:Adapter>SOAP API</ser:Adapter>
      <ser:Machine>MBPRO</ser:Machine>
    </ser:Profile>
  </soap:Header>
  <soap:Body>
    <ser:Ping/>
  </soap:Body>
</soap:Envelope>
     </Payload>
     <Verb>POST</Verb>
    </Set>
  </Request>
  <Response>avalaraResponse</Response>
  <HTTPTargetConnection>
    <SSLInfo>
        <Enabled>true</Enabled>
        <IgnoreValidationErrors>true</IgnoreValidationErrors>
    </SSLInfo>
    <Properties>
      <Property name='success.codes'>2xx, 3xx, 4xx, 5xx</Property>
    </Properties>
    <URL>https://development.avalara.net/Tax/TaxSvc.asmx?Ping</URL>
  </HTTPTargetConnection>
</ServiceCallout>

Augment that policy with some XSL and an XMLToJSON policy and you can get a JSON response out.

Find attached a working API Proxy. avalara-sc-apiproxy-20180306-1145.zip

Deploy it to your org/env, and then Invoke it like this:

curl -i -u ${ACCOUNTID}:${LICENSEKEY} \
    https://${ORG}-${ENV}.apigee.net/avalara-sc/ping 

My response looks like this:

{
    "Fault": {
        "faultcode": "s:Client",
        "faultstring": {
            "lang": "en-US",
            "$": "The user or account could not be authenticated."
        }
    }
}

@Dino

Thanks a lot for your time and response!

I had tried out even service callout and even then was getting same HTML response and then you and @Faij Ahmad pointed out it correctly, I did not have the correct endpoint.

I previously was using the enpoint - https://development.avalara.net/Tax/TaxSvc.asmx/v2, which surprisingly works in SOAP UI ( I still don't know how) . However, when I corrected the endpoint to https://development.avalara.net/Tax/TaxSvc.asmx?GetTaxHistory , seeing what you gave in the example of ping operation, I got the expected valid SOAP response.

Thanks again!

If you still want to do in Javascript you should first note that you need to use httpClient.send() instead of httpClient.get()

var myResult = httpClient.get("https://development.avalara.net/Tax/TaxSvc.asmx/v2",reqcont);

Sample usage explained here: https://docs.apigee.com/api-services/reference/javascript-object-model

Or even better let APIGEE do some heavy lifting for you, you can directly create a SOAP to REST service.

I recommend that you use the wizard to generate the proxy. Steps:

1) Select "+ API Proxy"

2) Select SOAP Service

3) Click on "Example URL", select the your WSDL.

4) Click on "Validate" and Click "Next"

5) API Proxy Type => Select "Pass- Through SOAP"

6) Accept defaults for the remaining screen and deploy it.

You will be able to easily consume a SOAP Service with this approach and tweak it to suit your needs.

Thanks.