6

Up to recently the web scraping of HP warranty information worked fine, however in the last couple of weeks they have changed the web page and it seems they are using POST rather than GET now on the new page, meaning I can't really just pass the information to the URL.

I did find some hope in a solution on this page:
http://ocdnix.wordpress.com/2013/03/14/hp-server-warranty-via-the-isee-api/
But I don't understand the example script as I have not worked with Python before.

I also found this web page that shows me a good example for Dell warranty, But HP don't have a WSDL that I could work with. (I would post the link but don't have enough rep)

Using these functions I can form the request:
http://www.iislogs.com/steveschofield/execute-a-soap-request-from-powershell

I think everything will work as expected but I am struggling to form the request to register the client, I keep getting 500 errors which either means their server is broken or my request is causing an internal error.

I am for the first time completely at a loss with this.

Anybody got this to work in PowerShell or having similar issues?

Updated 22-10-13

I now have the envelope, I managed to get the Python script to run but that failed because of my proxy, so extracted the generated XML which is what I wanted as I wasn't sure how it should be formed, this looks like:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:iseeReg="http://www.hp.com/isee/webservices/">
<SOAP-ENV:Body>
    <iseeReg:RegisterClient2>
    <iseeReg:request><isee:ISEE-Registration xmlns:isee="http://www.hp.com/schemas/isee/5.00/event" schemaVersion="5.00">
<RegistrationSource>
    <HP_OOSIdentifiers>
    <OSID>
        <Section name="SYSTEM_IDENTIFIERS">
        <Property name="TimestampGenerated" value="2013/10/22 09:40:35 GMT Standard Time"/>
        </Section>
    </OSID>
    <CSID>
        <Section name="SYSTEM_IDENTIFIERS">
        <Property name="CollectorType" value="MC3"/>
        <Property name="CollectorVersion" value="T05.80.1 build 1"/>
        <Property name="AutoDetectedSystemSerialNumber" value="10"/>
        <Property name="SystemModel" value="HP ProLiant"/>
        <Property name="TimestampGenerated" value="2013/10/22 09:40:35 GMT Standard Time"/>
        </Section>
    </CSID>
    </HP_OOSIdentifiers>
    <PRS_Address>
    <AddressType>0</AddressType>
    <Address1/>
    <Address2/>
    <Address3/>
    <Address4/>
    <City/>
    <Region/>
    <PostalCode/>
    <TimeZone/>
    <Country/>
    </PRS_Address>
</RegistrationSource>
<HP_ISEECustomer>
    <Business/>
    <Name/>
</HP_ISEECustomer>
<HP_ISEEPerson>
    <CommunicationMode>255</CommunicationMode>
    <ContactType/>
    <FirstName/>
    <LastName/>
    <Salutation/>
    <Title/>
    <EmailAddress/>
    <TelephoneNumber/>
    <PreferredLanguage/>
    <Availability/>
</HP_ISEEPerson>
</isee:ISEE-Registration></iseeReg:request>
    </iseeReg:RegisterClient2>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

I then built a Powershell script that executes like this:

function Execute-SOAPRequest {
Param (
[Xml]$SOAPRequest,
[String]$URL,
[switch]$UseProxy
)

write-host "Sending SOAP Request To Server: $URL" 
$soapWebRequest = [System.Net.WebRequest]::Create($URL) 
$soapWebRequest.Headers.Add("SOAPAction",'"http://www.hp.com/isee/webservices/RegisterClient2"') 

$soapWebRequest.ContentType = 'text/xml; charset=utf-8'
$soapWebRequest.Accept = "text/xml" 
$soapWebRequest.Method = "POST" 
$soapWebRequest.UserAgent = 'RemoteSupport/A.05.05 - gSOAP/2.7'

#$soapWebRequest.ServicePoint.Expect100Continue = $False
#$soapWebRequest.ServicePoint.MaxIdleTime = 2000
$soapWebRequest.ProtocolVersion = [system.net.httpversion]::version10

if($UseProxy){
    $soapWebRequest.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
}


write-host "Initiating Send." 
$requestStream = $soapWebRequest.GetRequestStream() 
$SOAPRequest.Save($requestStream) 
$requestStream.Close() 

write-host "Send Complete, Waiting For Response." 
$resp = $soapWebRequest.GetResponse() 
$responseStream = $resp.GetResponseStream() 
$soapReader = [System.IO.StreamReader]($responseStream) 
$ReturnXml = [Xml]$soapReader.ReadToEnd() 
$responseStream.Close() 

write-host "Response Received." 

return $ReturnXml 
} 

$SOAPRequest = [Xml](Get-Content 'C:\Temp\SoapEnv.xml')
$URL = 'https://services.isee.hp.com/ClientRegistration/ClientRegistrationService.asmx'

Execute-SOAPRequest $SOAPRequest $URL -UseProxy

But now I am getting additional errors rather than the 500 I was getting so getting closer?? Error details are:

Exception calling "GetRequestStream" with "0" argument(s): "The server committed a protocol violation. Section=ResponseStatusLine"
At C:\Temp\HP Register Client.ps1:29 char:54
+     $requestStream = $soapWebRequest.GetRequestStream <<<< () 
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
OneLogicalMyth
  • 188
  • 1
  • 9

6 Answers6

3

try this. . works for me just fine: Note: Only the request tag needs to be escaped.

$SOAPRequest= [xml]@"
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:iseeReg="http://www.hp.com/isee/webservices/">
<SOAP-ENV:Body>
    <iseeReg:RegisterClient2>
    <iseeReg:request>&lt;isee:ISEE-Registration xmlns:isee="http://www.hp.com/schemas/isee/5.00/event" schemaVersion="5.00"&gt;
&lt;RegistrationSource&gt;
    &lt;HP_OOSIdentifiers&gt;
    &lt;OSID&gt;
        &lt;Section name="SYSTEM_IDENTIFIERS"&g`enter code here`t;
        &lt;Property name="TimestampGenerated" value="2013/12/06 14:04:24 EST"/&gt;
        &lt;/Section&gt;
    &lt;/OSID&gt;
    &lt;CSID&gt;
        &lt;Section name="SYSTEM_IDENTIFIERS"&gt;
        &lt;Property name="CollectorType" value="MC3"/&gt;
        &lt;Property name="CollectorVersion" value="T05.80.1 build 1"/&gt;
        &lt;Property name="AutoDetectedSystemSerialNumber" value="10"/&gt;
        &lt;Property name="SystemModel" value="HP ProLiant"/&gt;
        &lt;Property name="TimestampGenerated" value="2013/12/06 14:04:24 EST"/&gt;
        &lt;/Section&gt;
    &lt;/CSID&gt;
    &lt;/HP_OOSIdentifiers&gt;
    &lt;PRS_Address&gt;
    &lt;AddressType&gt;0&lt;/AddressType&gt;
    &lt;Address1/&gt;
    &lt;Address2/&gt;
    &lt;Address3/&gt;
    &lt;Address4/&gt;
    &lt;City/&gt;
    &lt;Region/&gt;
    &lt;PostalCode/&gt;
    &lt;TimeZone/&gt;
    &lt;Country/&gt;
    &lt;/PRS_Address&gt;
&lt;/RegistrationSource&gt;
&lt;HP_ISEECustomer&gt;
    &lt;Business/&gt;
    &lt;Name/&gt;
&lt;/HP_ISEECustomer&gt;
&lt;HP_ISEEPerson&gt;
    &lt;CommunicationMode&gt;255&lt;/CommunicationMode&gt;
    &lt;ContactType/&gt;
    &lt;FirstName/&gt;
    &lt;LastName/&gt;
    &lt;Salutation/&gt;
    &lt;Title/&gt;
    &lt;EmailAddress/&gt;
    &lt;TelephoneNumber/&gt;
    &lt;PreferredLanguage/&gt;
    &lt;Availability/&gt;
&lt;/HP_ISEEPerson&gt;
&lt;/isee:ISEE-Registration&gt;</iseeReg:request>
    </iseeReg:RegisterClient2>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
"@

You'll have to do the same thing for the warranty xml like so then just re-run the soap web request.

$hpgdid = $ReturnXml.envelope.body.RegisterClient2Response.RegisterClient2Result.Gdid
$hptoken = $ReturnXml.envelope.body.RegisterClient2Response.RegisterClient2Result.registrationtoken


$warrantyxml = [xml]@"
<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:isee="http://www.hp.com/isee/webservices/">
  <SOAP-ENV:Header>
    <isee:IseeWebServicesHeader>
      <isee:GDID>$hpgdid</isee:GDID>
      <isee:registrationToken>$hptoken</isee:registrationToken>
      <isee:OSID/>
      <isee:CSID/>
    </isee:IseeWebServicesHeader>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <isee:GetOOSEntitlementList2>
      <isee:request>
        &lt;isee:ISEE-GetOOSEntitlementInfoRequest
    xmlns:isee="http://www.hp.com/schemas/isee/5.00/entitlement"
    schemaVersion="5.00"&gt;
  &lt;HP_ISEEEntitlementParameters&gt;
    &lt;CountryCode&gt;ES&lt;/CountryCode&gt;
    &lt;SerialNumber&gt;CZ10130050&lt;/SerialNumber&gt;
    &lt;ProductNumber&gt;519841-425&lt;/ProductNumber&gt;
    &lt;EntitlementType&gt;&lt;/EntitlementType&gt;
    &lt;EntitlementId&gt;&lt;/EntitlementId&gt;
    &lt;ObligationId&gt;&lt;/ObligationId&gt;
  &lt;/HP_ISEEEntitlementParameters&gt;
&lt;/isee:ISEE-GetOOSEntitlementInfoRequest&gt;
      </isee:request>
    </isee:GetOOSEntitlementList2>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
"@

$xmlstring = [string]$ReturnXml.Envelope.Body.GetOOSEntitlementList2Response.GetOOSEntitlementList2Result.Response

$warranty_info = [xml]@"
$xmlstring
"@

 $warranty_info."ISEE-GetOOSEntitlementInfoResponse"
  • Thanks for this, I am now not getting errors with the XML, but the web request is still giving me: `Exception calling "GetRequestStream" with "0" argument(s): "The server committed a protocol violation. Section=ResponseStatusLine"` Any ideas, what code are you using? Thanks again. – OneLogicalMyth Dec 09 '13 at 08:51
  • I'm using powershell as well. I'm not going through a proxy though. Try adding $soapWebRequest.keepalive = $false. http://stackoverflow.com/questions/2482715/the-server-committed-a-protocol-violation-section-responsestatusline-error – user3076063 Dec 09 '13 at 16:52
  • Sorry it took me so long to get back to you, I have been really busy with work. Your answer and explanation is great. Just wish I could get it to work behind a proxy. Thanks. – OneLogicalMyth Feb 24 '14 at 22:27
3

I have built this into a PowerShell Module, I moved the SOAP Requests to separate XML files, and used CDATA to make them much more readable. It works pretty well for me. it can be found on GitHub:

https://github.com/dotps1/HPWarranty

Thanks for all of the info on this page, really helped!

tomohulk
  • 592
  • 2
  • 9
  • 22
0

You need to escape the XML being transferred like below. Also make sure that the TimestampGenerated is formatted properly as well.

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:iseeReg="http://www.hp.com/isee/webservices/">
<SOAP-ENV:Body>
    <iseeReg:RegisterClient2>
    <iseeReg:request>&lt;isee:ISEE-Registration xmlns:isee="http://www.hp.com/schemas/isee/5.00/event" schemaVersion="5.00"&gt;
&lt;RegistrationSource&gt;
    &lt;HP_OOSIdentifiers&gt;
    &lt;OSID&gt;
        &lt;Section name="SYSTEM_IDENTIFIERS"&gt;
        &lt;Property name="TimestampGenerated" value="2013/12/05 19:24:58 GMT"/&gt;
        &lt;/Section&gt;
    &lt;/OSID&gt;
    &lt;CSID&gt;
        &lt;Section name="SYSTEM_IDENTIFIERS"&gt;
        &lt;Property name="CollectorType" value="MC3"/&gt;
        &lt;Property name="CollectorVersion" value="T05.80.1 build 1"/&gt;
        &lt;Property name="AutoDetectedSystemSerialNumber" value="10"/&gt;
        &lt;Property name="SystemModel" value="HP ProLiant"/&gt;
        &lt;Property name="TimestampGenerated" value="2013/12/05 19:24:58 GMT"/&gt;
        &lt;/Section&gt;
    &lt;/CSID&gt;
    &lt;/HP_OOSIdentifiers&gt;
    &lt;PRS_Address&gt;
    &lt;AddressType&gt;0&lt;/AddressType&gt;
    &lt;Address1/&gt;
    &lt;Address2/&gt;
    &lt;Address3/&gt;
    &lt;Address4/&gt;
    &lt;City/&gt;
    &lt;Region/&gt;
    &lt;PostalCode/&gt;
    &lt;TimeZone/&gt;
    &lt;Country/&gt;
    &lt;/PRS_Address&gt;
&lt;/RegistrationSource&gt;
&lt;HP_ISEECustomer&gt;
    &lt;Business/&gt;
    &lt;Name/&gt;
&lt;/HP_ISEECustomer&gt;
&lt;HP_ISEEPerson&gt;
    &lt;CommunicationMode&gt;255&lt;/CommunicationMode&gt;
    &lt;ContactType/&gt;
    &lt;FirstName/&gt;
    &lt;LastName/&gt;
    &lt;Salutation/&gt;
    &lt;Title/&gt;
    &lt;EmailAddress/&gt;
    &lt;TelephoneNumber/&gt;
    &lt;PreferredLanguage/&gt;
    &lt;Availability/&gt;
&lt;/HP_ISEEPerson&gt;
&lt;/isee:ISEE-Registration&gt;</iseeReg:request>
    </iseeReg:RegisterClient2>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Another option instead of escaping the XML yourself would be to place it within a CDATA so that it isn't parsed: http://www.w3schools.com/xml/xml_cdata.asp

  • Thanks for this, do you have any code that you could provide to form the web request in Powershell? I can't get my above code to work. – OneLogicalMyth Dec 09 '13 at 08:52
  • I tested the above request data with the code provided and it worked for me. I didn't make any modifications to the powershell code to get the request to work. – user3067817 Dec 09 '13 at 21:53
0

Combining all the information I found all over the web, I've created the following function that does it all based on the Serial Number. Special thanks to dotps1 for his hard work.

For HP:

Function Get-HPAssetInformationHC {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory,ValueFromPipeline)]
        [String]$SerialNumber
    )

    Begin {
        Function Invoke-HPIncSOAPRequest {
            Param (
                [Parameter(Mandatory)]
                [Xml]$SOAPRequest,
                [String]$Url = 'https://api-uns-sgw.external.hp.com/gw/hpit/egit/obligation.sa/1.1'
            )

            $soapWebRequest = [System.Net.WebRequest]::Create($URL) 
            $soapWebRequest.Headers.Add('X-HP-SBS-ApplicationId','hpi-obligation-hpsa')
            $soapWebRequest.Headers.Add('X-HP-SBS-ApplicationKey','ft2VGa2hx9j$')
            $soapWebRequest.ContentType = 'text/xml; charset=utf-8'
            $soapWebRequest.Accept = 'text/xml'
            $soapWebRequest.Method = 'POST'

            try {
                $SOAPRequest.Save(($requestStream = $soapWebRequest.GetRequestStream()))
                $requestStream.Close() 
                $responseStream = ($soapWebRequest.GetResponse()).GetResponseStream()
                [XML]([System.IO.StreamReader]($responseStream)).ReadToEnd()
                $responseStream.Close() 
            }
            catch {
                throw $_
            }
        }
    }

    Process {
        foreach ($S in $SerialNumber) {
            $request = @"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:int="http://interfaces.obligation.sbs.it.hp.com/">
  <soapenv:Header />
  <soapenv:Body>
    <int:retrieveServiceObligationResponsesByServiceObligationRequests>
      <context>
        <appContextName>HPSF</appContextName>
        <userLocale>en-US</userLocale>
      </context>
      <obligationRequests>
        <lnkServiceObligationDepthFilter>
          <includeProductObjectOfServiceInstance>true</includeProductObjectOfServiceInstance>
          <includeServiceObligation>true</includeServiceObligation>
          <includeServiceObligationHeaderOffer>true</includeServiceObligationHeaderOffer>
          <includeServiceObligationMessage>true</includeServiceObligationMessage>
          <maxNumberOfProductObjectOfServiceInstance>100</maxNumberOfProductObjectOfServiceInstance>
        </lnkServiceObligationDepthFilter>
        <lnkServiceObligationEnrichment>
          <iso2CountryCode>US</iso2CountryCode>
        </lnkServiceObligationEnrichment>
        <lnkServiceObligationProductObjectOfServiceIdentifier>
          <hpSerialNumber>$S</hpSerialNumber>
        </lnkServiceObligationProductObjectOfServiceIdentifier>
      </obligationRequests>
    </int:retrieveServiceObligationResponsesByServiceObligationRequests>
  </soapenv:Body>
</soapenv:Envelope>
"@

            Try {
                [XML]$entitlement = Invoke-HPIncSoapRequest -SOAPRequest $request -ErrorAction Stop
            }
            Catch {
                $P = $_
                $Global:Error.RemoveAt(0)
                throw "Failed to invoke SOAP request: $P"
            }

            Try {
                if ($entitlement) {
                    $HPAsset = $entitlement.Envelope.Body.retrieveServiceObligationResponsesByServiceObligationRequestsResponse.return

                    [PSCustomObject][Ordered]@{
                        SerialNumber           = $S
                        ProductNumber          = $HPAsset.lnkProductObjectOfServiceInstance.ProductNumber
                        SalesOrderNumber       = $HPAsset.lnkServiceObligations.salesOrderNumber | where {$_}
                        ProductDescription     = $HPAsset.lnkProductObjectOfServiceInstance.productDescription
                        ProductLineDescription = $HPAsset.lnkProductObjectOfServiceInstance.productLineDescription
                        ActiveEntitlement      = $HPAsset.lnkServiceObligations.serviceObligationActiveIndicator
                        OfferDescription       = $HPAsset.lnkServiceObligationHeaderOffer | where serviceQuantity -GE 1 | Select-Object -ExpandProperty offerDescription
                        StartDate              = $HPAsset.lnkServiceObligations.serviceObligationStartDate | ForEach-Object {[DateTime]$_}
                        EndDate                = $HPAsset.lnkServiceObligations.serviceObligationEndDate | ForEach-Object {[DateTime]$_}
                    }

                    Write-Verbose "HP asset '$($HPAsset.lnkProductObjectOfServiceInstance.productDescription)' with serial number '$S'"
                }
                else {
                    Write-Warning "No HP asset information found for serial number '$S'"
                    continue
                }
            }
            Catch {
                $P = $_
                $Global:Error.RemoveAt(0)
                throw "Failed to invoke SOAP request: $P"
            }
        }
    }
}

For Dell:

Function Get-DellAssetInformationHC {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory, ValueFromPipeline)]
        [String[]]$SerialNumber
    )

    Begin {
        # Possible API keys
        # 1adecee8a60444738f280aad1cd87d0e
        # d676cf6e1e0ceb8fd14e8cb69acd812d
        # 1adecee8a60444738f280aad1cd87d0e
        # 849e027f476027a394edd656eaef4842

        $APIKey = '849e027f476027a394edd656eaef4842'
    }

    Process {
        foreach ($S in $SerialNumber) {
            Try {
                $DellURL = "https://api.dell.com/support/v2/assetinfo/warranty/tags.xml?svctags=$S&apikey=$APIKey"

                $XML = New-Object System.Xml.XmlDocument
                $XML.Load($DellURL)
                $DellAsset = $XML.GetAssetWarrantyResponse.GetAssetWarrantyResult.Response.DellAsset

                if ($DellAsset) {
                    [PSCustomObject][Ordered]@{
                        SerialNumber            = $S
                        CustomerNumber          = $DellAsset.CustomerNumber
                        OrderNumber             = $DellAsset.OrderNumber
                        MachineDescription      = $DellAsset.MachineDescription
                        ShipDate                = $DellAsset.ShipDate
                        ServiceLevelDescription = $DellAsset.Warranties.Warranty.ServiceLevelDescription
                        StartDate               = $DellAsset.Warranties.Warranty.StartDate | ForEach-Object {[DateTime]$_}
                        EndDate                 = $DellAsset.Warranties.Warranty.EndDate | ForEach-Object {[DateTime]$_}
                    }

                    Write-Verbose "Dell asset '$($DellAsset.MachineDescription)' with serial number '$S'"
                }
                else {
                    Write-Warning "No Dell asset information found for serial number '$S'"
                }
            }
            Catch {
                $P = $_
                $Global:Error.RemoveAt(0)
                throw "Failed retrieving Dell asset information for serial number '$S': $P"
            }
        }
    }
}
DarkLite1
  • 13,637
  • 40
  • 117
  • 214
  • Thanks much! I had been using the ISEE before it broke when enterprise split off. Then went to web IE Object parsing and it was terrible. Glad to have happened over this... – ATek Nov 10 '16 at 05:18
  • One comment to this that I had to change was for proxy bypass. Adding this line. `$soapWebRequest.Proxy = [System.Net.GlobalProxySelection]::GetEmptyWebProxy()` – ATek Nov 10 '16 at 18:28
0

Any reason why we cannot just do a http POST against the publicly available URL: http://h20564.www2.hpe.com/hpsc/wc/public/find

We can do an http POST with curl like this (put this in a script, for example):

/usr/bin/curl 'http://h20564.www2.hpe.com/hpsc/wc/public/find' \ --compressed \ -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8' \ -H 'Accept-Encoding: gzip, deflate' \ -H 'Accept-Language: en-US,en;q=0.5' \ -H 'Connection: keep-alive' \ -H 'Host: h20564.www2.hpe.com' \ -H 'Referer: (missing https: here) h20564.www2.hpe.com/hpsc/wc/public/home' \ -H 'Upgrade-Insecure-Requests: 1' \ -H 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0' \ -H 'Content-Type: application/x-www-form-urlencoded' \ --data-binary '@/tmp/data' | grep hpui-standard-table

The only extra thing it needs the -H 'Cookie: ' header. I can copy the same cookie from a web lookup, but I am not sure how long that can be used.

The data file is in /tmp/data, formatted like this:

rows[0].item.countryCode=US rows[0].item.serialNumber=XXXXXXXXX rows[1].item.countryCode=US rows[1].item.serialNumber=YYYYYYYYY rows[2].item.countryCode=US rows[2].item.serialNumber= rows[3].item.countryCode=US rows[3].item.serialNumber= rows[4].item.countryCode=US rows[4].item.serialNumber= rows[5].item.countryCode=US rows[5].item.serialNumber= rows[6].item.countryCode=US rows[6].item.serialNumber= rows[7].item.countryCode=US rows[7].item.serialNumber= rows[8].item.countryCode=US rows[8].item.serialNumber= rows[9].item.countryCode=US rows[9].item.serialNumber= submitButton=Submit

zagpoint
  • 85
  • 1
  • 10
0

Now HP has developed api for getting machines product warranty. It is in testing phase however we can try it. Hope it will be moved to production As Soon As Possible. You have to go through the document here and fill the details they required. You will have your own api key to work with.

https://developers.hp.com/css-enroll

Thanks, Prabha.