Could anyone please help me how to accomplish the correct DigestValue in the XML document? I have some XML examples from the creator, but somehow I cannot generate the same SHA256 hash in PHP.
The documentation says that the <soap:Body> should be hashed using SHA256 algorithm. Well, from what I understand I need to
canonicalize the xml (c14n)
create a SHA256 hash from it
base64 encode it
The hash result from this example should be obviously
TWpSLQpOXSUe8k6Q8lAd7DyMhWkTIcbHNifrPnWDG/M=
How to accomplish it in php from the code below?
I tried this:
$xml='<soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-AB79979F3364F5119A14761286403964"><Trzba xmlns="http://fs.mfcr.cz/eet/schema/v3"><Hlavicka dat_odesl="2016-09-19T19:06:37+02:00" prvni_zaslani="false" uuid_zpravy="ab1bc7a0-5ab0-4d61-a170-2982f2d83784"/><Data celk_trzba="34113.00" cerp_zuct="679.00" cest_sluz="5460.00" dan1="-172.39" dan2="-530.73" dan3="975.65" dat_trzby="2016-08-05T00:30:12+02:00" dic_popl="CZ1212121218" id_pokl="/5546/RO24" id_provoz="273" porad_cis="0/6460/ZQ42" pouzit_zboz1="784.00" pouzit_zboz2="967.00" pouzit_zboz3="189.00" rezim="0" urceno_cerp_zuct="324.00" zakl_dan1="-820.92" zakl_dan2="-3538.20" zakl_dan3="9756.46" zakl_nepodl_dph="3036.00"/><KontrolniKody><pkp cipher="RSA2048" digest="SHA256" encoding="base64">JvCv0lXfT74zuviJaHeO91guUfum1MKhq0NNPxW0YlBGvIIt+I4QxEC3QP6BRwEkIS14n2WN+9oQ8nhQPYwZX7L4W9Ie7CYv1ojcl/YiF4560EdB3IpRNRj3UjQlwSZ5ucSM9vWqp0UTbhJDSUk5/WjC/CEiSYv7OQIqa0NJ0f0+ldzGveLRSF34eu2iqAhs/yfDnENlnMDPVB5ko/zQO0vcC93k5DEWEoytTIAsKd6jKSO7eama8Qe+d0wq9vBzudkfLgCe2C1iERJuyHknhjo9KOx10h5wk99QqVGX8tthpAmryDcX2N0ZGkzJHuzzebnYsxXFYI2tKOJLiLLoLQ==</pkp><bkp digest="SHA1" encoding="base16">3F9119C1-FBF34535-D30B60F8-9859E4A6-C8C8AAFA</bkp></KontrolniKody></Trzba></soap:Body>';
$doc = new DOMDocument('1.0','UTF-8');
$doc->loadXML($xml);
echo base64_encode(hash('SHA256',$doc->C14N(true),true));
But this is returning me other hash value :-( Maybe I am just taking the wrong part of the XML source. Any ideas from what part of text/how did they count the hash and how to have the same result in php? The whole working example (taken from [http://www.etrzby.cz/assets/cs/prilohy/CZ1212121218.valid.v3.1.xml) is this:
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><wsse:Security 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" soap:mustUnderstand="1"><wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-A79845F15C5549CA0514761283545351">MIIEmDCCA4CgAwIBAgIEdHOXJzANBgkqhkiG9w0BAQsFADB3MRIwEAYKCZImiZPyLGQBGRYCQ1oxQzBBBgNVBAoMOsSMZXNrw6EgUmVwdWJsaWthIOKAkyBHZW5lcsOhbG7DrSBmaW5hbsSNbsOtIMWZZWRpdGVsc3R2w60xHDAaBgNVBAMTE0VFVCBDQSAxIFBsYXlncm91bmQwHhcNMTYwOTMwMDkwMzU5WhcNMTkwOTMwMDkwMzU5WjBDMRIwEAYKCZImiZPyLGQBGRYCQ1oxEzARBgNVBAMTCkNaMDAwMDAwMTkxGDAWBgNVBA0TD3ByYXZuaWNrYSBvc29iYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnNUPW8rAlLi2KAwu12W1vqLj02mWIifq/Jp0/tUjf9B8RpkDAD3GOqDdVuHSfxej92WiEouDy7X8uXzIDdZu4pXA3t3KntxM8rAlu2U6SqtF3kTR+AJCdwfkM53U3z4/qoyKqdQ8lGuMxJKs7X5uIjcY/UDSXMK9OTmXRhndjYcX1oILr5F2ONf1Z0kWyl/S9wI0cl0gQ1F91mzqgnlH80u2inMmmBp42ndR4TGS1nvjer5D73bkLg07TdeqnUg609WwjUJN96OKZMsKXzBMzt09NbhQcABWnAWbRTSVhsAdDO8vfmWx2C+gXUlkIvtO+9fbj81GS1xdNoAkpARUcCAwEAAaOCAV4wggFaMAkGA1UdEwQCMAAwHQYDVR0OBBYEFL/0b0Iw6FY33UT8iJEy1V7nZVR6MB8GA1UdIwQYMBaAFHwwdqzM1ofR7Mkf4nAILONf3gwHMA4GA1UdDwEB/wQEAwIGwDBjBgNVHSAEXDBaMFgGCmCGSAFlAwIBMAEwSjBIBggrBgEFBQcCAjA8DDpUZW50byBjZXJ0aWZpa8OhdCBieWwgdnlkw6FuIHBvdXplIHBybyB0ZXN0b3ZhY8OtIMO6xI1lbHkuMIGXBgNVHR8EgY8wgYwwgYmggYaggYOGKWh0dHA6Ly9jcmwuY2ExLXBnLmVldC5jei9lZXRjYTFwZy9hbGwuY3JshipodHRwOi8vY3JsMi5jYTEtcGcuZWV0LmN6L2VldGNhMXBnL2FsbC5jcmyGKmh0dHA6Ly9jcmwzLmNhMS1wZy5lZXQuY3ovZWV0Y2ExcGcvYWxsLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAvXdWsU+Ibd1VysKnjoy6RCYVcI9+oRUSSTvQQDJLFjwn5Sm6Hebhci8ERGwAzd2R6uqPdzl1KCjmHOitypZ66e+/e9wj3BaDqgBKRZYvxZykaVUdtQgG0819JZmiXTbGgOCKiUPIXO80cnP7U1ZPkVNV7WZwh0I2k/fg1VLTI5HA/x4BeD77wiEOExa7eqePJET0jpTVK3LxSW59LLIJROh4/kfKQbTvDL5Ypw8WagAMVCPvWnGJIcUru+ApLU4pZD9bdHSa1Ib4LpFhtWrkHYM/XqKbj2bNKKjTo5T3sU0Bf2QD3QzkmcjlNVG0V+qAgimwTdPueU/mtExw+7z1/A==</wsse:BinarySecurityToken><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-A79845F15C5549CA0514761283545705"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI="#id-A79845F15C5549CA0514761283545594"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList=""/></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>M8/dBI/LLuwxP8ZoeRKVVpzIhQhyUDI0l6bglhNWKC0=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>DlFiF51sdtc0zeqgCsuSY6EU5emX7Hka6Ox3gviR4dpqyrwj6O8cm4oWkUTl+erINf9CpOG2y1z5y83+DubuGmiOPsACeEZjwF5TCme/uU1tzXs+LsLS8WXZvuMUejFOrUFEUKyzRvHJW5lskV/DhiMsTwJ/MEtGtjRVuWnAEcHxq/3ALsc3HfSi/qAqAiGlz3OpIKf3Hai6iiD37eJwHNd9QdJy4D32DJwY4Gw21ku7TO3FiLdtBT+Xdr3At8sWbbihFwErKrutT/FAVQKffUzCjHdEm9//W/shHufxYdnEh0m8cYp5Z5xK2bfnfhaKPB0rUZrrcw8T7LlvZKGogg==</ds:SignatureValue><ds:KeyInfo Id="KI-A79845F15C5549CA0514761283545482"><wsse:SecurityTokenReference 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" wsu:Id="STR-A79845F15C5549CA0514761283545513"><wsse:Reference URI="#X509-A79845F15C5549CA0514761283545351" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></SOAP-ENV:Header><soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-A79845F15C5549CA0514761283545594"><Trzba xmlns="http://fs.mfcr.cz/eet/schema/v3"><Hlavicka dat_odesl="2016-08-19T19:06:37+02:00" prvni_zaslani="false" uuid_zpravy="2da635a5-d712-459d-9674-c12f335c39f7"/><Data celk_trzba="34113.00" cerp_zuct="679.00" cest_sluz="5460.00" dan1="-172.39" dan2="-530.73" dan3="975.65" dat_trzby="2016-08-05T00:30:12+02:00" dic_popl="CZ00000019" dic_poverujiciho="CZ683555118" id_pokl="/5546/RO24" id_provoz="273" porad_cis="0/6460/ZQ42" pouzit_zboz1="784.00" pouzit_zboz2="967.00" pouzit_zboz3="189.00" rezim="0" urceno_cerp_zuct="324.00" zakl_dan1="-820.92" zakl_dan2="-3538.20" zakl_dan3="9756.46" zakl_nepodl_dph="3036.00"/><KontrolniKody><pkp cipher="RSA2048" digest="SHA256" encoding="base64">a0asEiJhFCBlVtptSspKvEZhcrvnzF7SQ55C4DhnStnSu1b37GUI2+Dlme9P94UCPZ1oCUPJdsYOBZ3IX6aEgEe0FJKXYX0kXraYCJKIo3g64wRchE7iblIOBCK1uHh8qqHA66Isnhb6hqBOOdlt2aWO/0jCzlfeQr0axpPF1mohMnP3h3ICaxZh0dnMdju5OmMrq+91PL5T9KkR7bfGHqAoWJ0kmxY/mZumtRfGil2/xf7I5pdVeYXPgDO/Tojzm6J95n68fPDOXTDrTzKYmqDjpg3kmWepLNQKFXRmkQrkBLToJWG1LDUDm3UTTmPWzq4c0XnGcXJDZglxfolGpA==</pkp><bkp digest="SHA1" encoding="base16">9356D566-A3E48838-FB403790-D201244E-95DCBD92</bkp></KontrolniKody></Trzba></soap:Body></soap:Envelope>
Related
I'm receiving from an external web service an XML like this(notice the colons inside the tags)
XML
<?xml version='1.0' encoding='UTF-8'?>
<env:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns0="http://webservice/CrsWSApi.wsdl/types/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Body>
<ns0:callwsapiResponseElement>
<ns0:result>
<ns0:object>BTS</ns0:object>
<ns0:receiver>BTSV45_ANSF_PROD-AKITT</ns0:receiver>
<ns0:sender>ANSFP</ns0:sender>
<ns0:data>
{"name":"Paolo", "cognome": Rossi, "data":"18/11/1983"}
</ns0:data>
<ns0:errormess xsi:nil="true"/>
<ns0:errorcode xsi:nil="true"/>
<ns0:status>1</ns0:status>
<ns0:sessionid>akit1</ns0:sessionid>
</ns0:result>
</ns0:callwsapiResponseElement>
</env:Body>
</env:Envelope>
if I use this function to parse it
PHP
$xml = simplexml_load_string($xml) or die("Error: Cannot create object");
I'm always receiving Error. If I remove the colons it works as expected. Is there a way to make this works without manipulating the colons before the xml parsing?
I want to avoid this manipulation
PHP
$xml = preg_replace(['/env:/','/:env(?!=)/','/ns0:/','/:ns0(?!=)/'], '', $myXMLData);
UPDATE
I already accepted a good answer that is reporting usefull links on how namespases are working in an xml environment, but I want to share another way to obtain the same result without parsing an xpath expression. We can you use the children method of simple_xml_loadstring specifiying the second parameter as a namespace.
fot the above code you can obtain the ns0:data content with this code(before you have to change the if statement as the accepted answer)
PHP
$xml = simplexml_load_string($response);
echo $xml
->children("env", true)
->Body
->children("ns0", true)
->callwsapiResponseElement
->result
->data;
// This will print
{"name":"Paolo", "cognome": Rossi, "data":"18/11/1983"}
For me it is very curious the return of simplexml_load_string (https://www.php.net/manual/en/function.simplexml-load-string.php):
This function may return Boolean false, but may also return a non-Boolean value which evaluates to false. Please read the section on Booleans for more information. Use the === operator for testing the return value of this function.
And indeed if you replace the or die:
<?php
$response = <<<XML
<?xml version='1.0' encoding='UTF-8'?>
<env:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns0="http://webservice/CrsWSApi.wsdl/types/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Body>
<ns0:callwsapiResponseElement>
<ns0:result>
<ns0:object>BTS</ns0:object>
<ns0:receiver>BTSV45_ANSF_PROD-AKITT</ns0:receiver>
<ns0:sender>ANSFP</ns0:sender>
<ns0:data>
{"name":"Paolo", "cognome": Rossi, "data":"18/11/1983"}
</ns0:data>
<ns0:errormess xsi:nil="true"/>
<ns0:errorcode xsi:nil="true"/>
<ns0:status>1</ns0:status>
<ns0:sessionid>akit1</ns0:sessionid>
</ns0:result>
</ns0:callwsapiResponseElement>
</env:Body>
</env:Envelope>
XML;
$xml = simplexml_load_string($response);
if($xml===false){
die();
}
echo $xml->xpath("//*[local-name() = 'receiver']")[0];
Results:
BTSV45_ANSF_PROD-AKITT
You can then use the namespaces to find your data. This is a nice post Reference - How do I handle Namespaces (Tags and Attributes with a Colon in their Name) in SimpleXML?
I'm trying to convert the following response into an array in PHP, I want to reach the data inside 'Timbre', I need the values of:
UUID
FechaTimbrado
SelloSAT
The solutions I've tried around here convert the nodes ok, but I can't find a way to reach nothing beyond 'Timbre', hope you can help me find a way to do this, here's the response I'm receiving:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<ResponseHeader trackId="119588" RequestDateTime="2017-11-09T11:55:39.0205969-06:00" IPCaller="187.190.165.93" ClienteId="0" Estatus="1" ID="91a407fe-c1c2-40af-bc2d-5aee58606161" Detail="" Ambiente="DESARROLLO-01" xmlns="https://cfdi.timbrado.com.mx/timbradov2">
<CFDI Id="CFDI33" FechaHora="2017-11-09T11:45:30" RFCEmisor="XXXHHK2343434" RFCReceptor="GFGDS45&667" Serie="G" Folio="35010" />
</ResponseHeader>
</soap:Header>
<soap:Body>
<GeneraTimbreResponse xmlns="https://cfdi.timbrado.com.mx/timbradov2">
<GeneraTimbreResult>
<Timbre>
<tfd:TimbreFiscalDigital xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/cfd/TimbreFiscalDigital/TimbreFiscalDigitalv11.xsd" Version="1.1" UUID="91A407FE-C1C2-40AF-BC2D-5AEE58606161" FechaTimbrado="2017-11-09T11:55:39" RfcProvCertif="ASE0209252Q1" Leyenda="Timbre de prueba" SelloCFD="WCldH0Oan7h2VK3MuMM3Nv8HAg/OlCaKF2VLz/1u81yvZItgZuYia1Aaz27hOYsqBZ/m5/OhAaL6TZ43MZSF6zK9tZz+Fgu9wS2QJ+ubk/83oIjQDwLHCuJL/l5VRZI29RoPUfs3VDb+tD9mqeEinQwfLJG1YkoCIWC/4oXxL1oX5DEXqMW/sK52jpJh7exyqw+GzBA+LUBaSi+aGHlown8cEQmZOZieeUW5uXjDPQBdJBZ/XkRgfqzAiS/Tfj9a61B0Nrm7JyejagPZVW7E3gbcmFunWTbGwNEYvqWkgtnO7aoTzrVcjK3YX4t2zKPt8F7BGq+MSL/fge174IttGQ==" NoCertificadoSAT="20001000000300022323" SelloSAT="NhzPGgUh+1vQJkidObRpp+IgjSdOm6wwgMVVcPdEVmVEbFgCBW42a7grzg8toe9d/ZlHhka5g6h63E5jp3xKcq2KnWw+dQbrbh8xDNHC+7tPXEJN9T5JU8ZifpvTIu9g89TYERUs/4sLgAYtqAmV9AIQK17LoAIiNRdUzwWiiHUCLaqL7k0bmJYvfeuYAnkw52LfyxzLDg6TyodT/1LjJVwhGLyaOcOwCDObHH8ukZj0d2aOwOEE0IJBbbIgh3VaIp0/EvvFn1I1F9BnrLHVZFEcR3ZeP/TyLJmuOtxLGDnPtnaVQTrt0sQb43bG2R2ut5Bt3uS12xOMx3IfDr/3FQ==" />
</Timbre>
</GeneraTimbreResult>
</GeneraTimbreResponse>
</soap:Body>
</soap:Envelope>
So I solved it like this, if anyone knows a 'classier' way , let me know
//here I read the result string I posted above
$soap = simplexml_load_string(html_entity_decode($this->resultado_timbre));
//I read the nodes until I reach the 'Timbre' one
$response = $soap->children('http://www.w3.org/2003/05/soap-envelope')->Body->children()->children()->children()->Timbre->children('tfd',TRUE);
//The attributes are readable in a nice array
$atributos=$response->attributes();
Hope it helps someone!
I have a long string.
<?xml version="1.0" encoding="utf-8"?>
<GamePlaySession xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<selectedFederation>-1</selectedFederation>
<selectedComissioner>-1</selectedComissioner>
<myCash>0</myCash>
<myTokens>0</myTokens>
<myLevel>0</myLevel>
<shownBlurbCount>0</shownBlurbCount>
<isNewPlayer>true</isNewPlayer>
<inTutorialMode>true</inTutorialMode>
<flavorTutorialClear>false</flavorTutorialClear>
<calendarTutorialClear>false</calendarTutorialClear>
<resultTutorialClear>false</resultTutorialClear>
<storePurchaseTutorialClear>false</storePurchaseTutorialClear>
<storeRefreshTutorialClear>false</storeRefreshTutorialClear>
<storeTutorialClear>false</storeTutorialClear>
<transitionMessageClear>false</transitionMessageClear>
<storeCardsBought>0</storeCardsBought>
<storePurchases>
<boolean>false</boolean>
<boolean>false</boolean>
<boolean>false</boolean>
</storePurchases>
<newGamePlus>false</newGamePlus>
<currentYear>0</currentYear>
<currentMonth>0</currentMonth>
<numberOfYears>10</numberOfYears>
<worldChampCardNumber>0</worldChampCardNumber>
<titleChampCardNumber>0</titleChampCardNumber>
<tagChampCardNumbers>
<int>0</int>
<int>0</int>
</tagChampCardNumbers>
<worldChampLastCardNumber>0</worldChampLastCardNumber>
<titleChampLastCardNumber>0</titleChampLastCardNumber>
<tagChampLastCardNumbers>
<int>-1</int>
<int>-1</int>
</tagChampLastCardNumbers>
<firstShopCards>false</firstShopCards>
I want to store it inside a column. I am using urlencode as well as mysql_real_escape_string() but it doesn't work. Anyone knows how can I store it?
Similarly to this question, I'm trying to calculate a document hash value for a SEPA container file. This is the container my code currently generates:
<?xml version="1.0" encoding="UTF-8"?>
<conxml xmlns="urn:conxml:xsd:container.nnn.003.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:conxml:xsd:container.nnn.003.02 container.nnn.003.02.xsd">
<ContainerId>
<SenderId>TEST</SenderId>
<IdType>EBIC</IdType>
<TimeStamp>090237000</TimeStamp>
</ContainerId>
<CreDtTm>2014-02-14T09:32:37+01:00</CreDtTm>
<MsgPain008>
<HashValue>942AB2F57DBAF6302EDC526472098DF38C540EB75E1913DAB0DF416D168C3253</HashValue>
<HashAlgorithm>SHA256</HashAlgorithm>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.003.02">
<CstmrDrctDbtInitn>
<GrpHdr>
<MsgId>testmsg-1</MsgId>
<CreDtTm>2014-02-14T09:32:37+01:00</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>0.01</CtrlSum>
<InitgPty>
<Nm>TestCo</Nm>
</InitgPty>
</GrpHdr>
<PmtInf>
<PmtInfId>testmsg-1-pmt-1</PmtInfId>
<PmtMtd>DD</PmtMtd>
<BtchBookg>true</BtchBookg>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>0.01</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<LclInstrm>
<Cd>CORE</Cd>
</LclInstrm>
<SeqTp>OOFF</SeqTp>
</PmtTpInf>
<ReqdColltnDt>2014-02-14+01:00</ReqdColltnDt>
<Cdtr>
<Nm>TestCo</Nm>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>DE54100000000000012345</IBAN>
</Id>
</CdtrAcct>
<CdtrAgt>
<FinInstnId>
<BIC>MARKDEF1100</BIC>
</FinInstnId>
</CdtrAgt>
<CdtrSchmeId>
<Id>
<PrvtId>
<Othr>
<Id>DE46ZZZ00000012345</Id>
<SchmeNm>
<Prtry>SEPA</Prtry>
</SchmeNm>
</Othr>
</PrvtId>
</Id>
</CdtrSchmeId>
<DrctDbtTxInf>
<PmtId>
<EndToEndId>testmsg-1-2</EndToEndId>
</PmtId>
<InstdAmt Ccy="EUR">0.01</InstdAmt>
<DrctDbtTx>
<MndtRltdInf>
<MndtId>Test-1</MndtId>
<DtOfSgntr>2014-02-14+01:00</DtOfSgntr>
</MndtRltdInf>
</DrctDbtTx>
<DbtrAgt>
<FinInstnId>
<BIC>MARKDEF1200</BIC>
</FinInstnId>
</DbtrAgt>
<Dbtr>
<Nm>Other Test</Nm>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>DE90200000000000098765</IBAN>
</Id>
</DbtrAcct>
<RmtInf>
<Ustrd>Test</Ustrd>
</RmtInf>
</DrctDbtTxInf>
</PmtInf>
</CstmrDrctDbtInitn>
</Document>
</MsgPain008>
</conxml>
According to a bank-supplied format checking tool my file is mostly correct, except for the hash. Since PHP's implementation of SHA256 is probably not at fault I think I'm doing something wrong when canonicalizing the document.
The code in question is rather simple:
function documentHash($element)
{
$text = $element->C14N(true, true);
return strtoupper(hash('sha256', $text));
}
$element is the DOMElement containing the <Document> node. This function is called during the creation of the container file; thus the xmlns:xsi parameter is not applied to the node. However, manually adding it did not seem to improve matters.
The generated hash is wrong - it's 058098433DAC5D66ED34933CFFD98BF65CAD5C97CC45F9B0619B1FF96C3930E7; the expected value according to the format checker is 942AB2F57DBAF6302EDC526472098DF38C540EB75E1913DAB0DF416D168C3253. Now the question is what I'm doing wrong here - or rather how the I have to massage my XML in order to please the bank.
Here is what $text looks like: (Unfortunately, canonicalized XML does not make for pretty code blocks.)
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.003.02"><CstmrDrctDbtInitn><GrpHdr><MsgId>testmsg-1</MsgId><CreDtTm>2014-02-14T09:32:37+01:00</CreDtTm><NbOfTxs>1</NbOfTxs><CtrlSum>0.01</CtrlSum><InitgPty><Nm>TestCo</Nm></InitgPty></GrpHdr><PmtInf><PmtInfId>testmsg-1-pmt-1</PmtInfId><PmtMtd>DD</PmtMtd><BtchBookg>true</BtchBookg><NbOfTxs>1</NbOfTxs><CtrlSum>0.01</CtrlSum><PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl><LclInstrm><Cd>CORE</Cd></LclInstrm><SeqTp>OOFF</SeqTp></PmtTpInf><ReqdColltnDt>2014-02-14+01:00</ReqdColltnDt><Cdtr><Nm>TestCo</Nm></Cdtr><CdtrAcct><Id><IBAN>DE54100000000000012345</IBAN></Id></CdtrAcct><CdtrAgt><FinInstnId><BIC>MARKDEF1100</BIC></FinInstnId></CdtrAgt><CdtrSchmeId><Id><PrvtId><Othr><Id>DE46ZZZ00000012345</Id><SchmeNm><Prtry>SEPA</Prtry></SchmeNm></Othr></PrvtId></Id></CdtrSchmeId><DrctDbtTxInf><PmtId><EndToEndId>testmsg-1-2</EndToEndId></PmtId><InstdAmt Ccy="EUR">0.01</InstdAmt><DrctDbtTx><MndtRltdInf><MndtId>Test-1</MndtId><DtOfSgntr>2014-02-14+01:00</DtOfSgntr></MndtRltdInf></DrctDbtTx><DbtrAgt><FinInstnId><BIC>MARKDEF1200</BIC></FinInstnId></DbtrAgt><Dbtr><Nm>Other Test</Nm></Dbtr><DbtrAcct><Id><IBAN>DE90200000000000098765</IBAN></Id></DbtrAcct><RmtInf><Ustrd>Test</Ustrd></RmtInf></DrctDbtTxInf></PmtInf></CstmrDrctDbtInitn></Document>
I've been trying to get the id field to pull and have no idea where I'm going wrong. The rest of the data pulls correctly but I'm trying to add something new to some existing code and everything I've tried hasn't worked. Below is my XML and the PHP code I've been working off of.
I haven't worked with a combo of xml and php before so I could really use a push in the right direction.
<?xml version="1.0" encoding="UTF-8"?>
<enterprise>
<person>
<sourcedid>
<source>Spirit Awards</source>
<id>SP8675309</id>
</sourcedid>
<userid>...</userid>
<name>
<fn>...</fn>
</name>
<email>...</email>
</person>
PHP code:
function get_userid(){
return $this->uid;
}
function __construct($xmlData){
$this->uid = (string)$xmlData->id;
}
SimpleXMLdocs makes this ... well ... simple. The XML you've posted is missing a closing </enterprise> tag. Assuming the XML you're actually parsing includes the closing tag, consider:
$str = '<?xml version="1.0" encoding="UTF-8"?>
<enterprise>
<person>
<sourcedid>
<source>Spirit Awards</source>
<id>SP8675309</id>
</sourcedid>
<userid>...</userid>
<name>
<fn>...</fn>
</name>
<email>...</email>
</person>
</enterprise>
';
$xml = simplexml_load_string($str);
$var = (string) $xml->person->sourcedid->id;
echo $var; // outputs: SP8675309