ideal 3.3.1

1
Hier even een berichtje, omdat ik vast loop. Vandaag kreeg ik een mail, met de mededeling dat ideal pro 3.3.1 vanaf augustus dit jaar de enige optie is. Voorheen gebruikte ik de oude 2.x versie nog van ideal pro.

Nu loop ik alleen echt compleet vast met 3.3.1 en via de ticket support hulp vragen krijg je als reactie dat je maar iemand moet inhuren om het te laten doen. Beetje raar dus....!

Daarom hoop ik, dat iemand hier ervaring heeft met ideal 3.3.1 en weet waar onderstaande code allicht mis gaat of anders mij op weg kan helpen met voorbeeld code in PHP

Ik gebruik voor een directory request:

Code: Selecteer alles

<?


class idealRequest331 {
	
	private $privateKey;
	private $privateKeyFile;
	private $privateCertFile;
	private $privateCert;
	private $publicKeyFile;
	private $sMerchantId;
	private $sSubId;
	private $privateFingerprint;
	private $TestMode = false;
	private $URL;
	private $CRLF = "\r\n";

function __construct() {
	
	$this->sMerchantId = '***';
	$this->sSubId = '***';
	$this->URL = 'ssl://ideal' . ($this->TestMode ? 'test' : '') . '.rabobank.nl:443/ideal/iDealv3';
	
	
	$this->timeStamp = gmdate('Y-m-d') . 'T' . gmdate('H:i:s') . '.000Z';
	
	$this->privateKeyFile = 'ssl/private.key'; 
	$this->privateCertFile = 'ssl/private.cer';
	$this->publicKeyFile = 'ssl/rabobank.cer';
	
	$fh = fopen($this->privateKeyFile,'r');
	$this->privateKey = openssl_get_privatekey(fread($fh,8192),'****');
	fclose($fh);
	
	
	$fh = fopen($this->privateCertFile,'r');
	$this->privateCert = openssl_x509_read(fread($fh,8192));
	fclose($fh);
	$this->privateFingerprint = $this->strToHex(sha1(base64_decode(str_replace('-----END CERTIFICATE-----', '', str_replace('-----BEGIN CERTIFICATE-----', '', $this->privateCert)))));
	
}

function strToHex($string) {
    $hex='';
    for ($i=0; $i < strlen($string); $i++)
    {
        $hex .= dechex(ord($string[$i]));
    }
    return $hex;
}

private function escapeXml($string) {
	return utf8_encode(str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string));
}

function postToHost($data, $timeout = 30) {
	
	$idx = strrpos($this->URL, ':');
	$host = substr($this->URL, 0, $idx);
	$this->URL = substr($this->URL, $idx + 1);
	$idx = strpos($this->URL, '/');
	$port = substr($this->URL, 0, $idx);
	$path = substr($this->URL, $idx);
	$fsp = fsockopen($host, $port, $errno, $errstr, $timeout);
			
	if($fsp) {
	
		fputs($fsp, 'POST ' . $path . ' HTTP/1.0' . $this->CRLF);
		fputs($fsp, 'Host: ' . substr($host, 6) . $this->CRLF);
		fputs($fsp, 'Accept: text/html' . $this->CRLF);
		fputs($fsp, 'Accept: charset=ISO-8859-1' . $this->CRLF);
		fputs($fsp, 'Content-Length:' . strlen($data) . $this->CRLF);
		fputs($fsp, 'Content-Type: text/html; charset=ISO-8859-1' . $this->CRLF . $this->CRLF);
		fputs($fsp, $data, strlen($data));

		while(!feof($fsp)) {
			$res .= @fgets($fsp, 128);
		}

		fclose($fsp);
	}
	
	else $this->setError('Error while connecting to ' . $__url, false, __FILE__, __LINE__);

	return $res;
}

function DirectoryRequest() {	
	$sXmlMessageBeforeDigest = '<?xml version="1.0" encoding="UTF-8" ?>' . $this->CRLF
	. '<DirectoryReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1">' . $this->CRLF
	. '<createDateTimestamp>' . $this->escapeXml($this->timeStamp) . '</createDateTimestamp>' . $this->CRLF
	. '<Merchant>' . $this->CRLF
	. '<merchantID>' . $this->escapeXml($this->sMerchantId) . '</merchantID>' . $this->CRLF
	. '<subID>' . $this->escapeXml($this->sSubId) . '</subID>' . $this->CRLF
	. '</Merchant>' . $this->CRLF
	. '</DirectoryReq>';
	
	$dom = new DOMDocument();
	$dom->LoadXML($sXmlMessageBeforeDigest);
	
	$canonicalized = $dom->C14N();
	openssl_private_encrypt(hash("sha256",$canonicalized),$digestValue,$this->privateKey);
	
	$signatureValue = base64_encode($digestValue);
	
	$sXmlMessage = '<?xml version="1.0" encoding="UTF-8" ?>' . $this->CRLF
	. '<DirectoryReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1">' . $this->CRLF
	. '<createDateTimestamp>' . $this->escapeXml($this->timeStamp) . '</createDateTimestamp>' . $this->CRLF
	. '<Merchant>' . $this->CRLF
	. '<merchantID>' . $this->escapeXml($this->sMerchantId) . '</merchantID>' . $this->CRLF
	. '<subID>' . $this->escapeXml($this->sSubId) . '</subID>' . $this->CRLF
	. '</Merchant>' . $this->CRLF
	. '<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">' . $this->CRLF
	. '<SignedInfo>' . $this->CRLF
	. '<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />' . $this->CRLF
	. '<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />' . $this->CRLF
	. '<Reference URI="">' . $this->CRLF
	. '<Transforms>' . $this->CRLF
	. '<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>' . $this->CRLF
	. '</Transforms>' . $this->CRLF
	. '<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />' . $this->CRLF
	. '<DigestValue>' . hash("sha256",$canonicalized) . '</DigestValue>' . $this->CRLF
	. '</Reference>' . $this->CRLF
	. '</SignedInfo>' . $this->CRLF
	. '<SignatureValue>' . $signatureValue . '</SignatureValue>' . $this->CRLF
	. '<KeyInfo>' . $this->CRLF
	. '<KeyName>' . $this->privateFingerprint . '</KeyName>' . $this->CRLF
	. '</KeyInfo>' . $this->CRLF
	. '</Signature>'
	. '</DirectoryReq>';
	
	$dom = new DOMDocument();
	$dom->LoadXML($sXmlMessage);
	$sXmlMessage = $dom->C14N();
	
	//return $sXmlMessage;
	
	return $this->postToHost($sXmlMessage);

	}

}

$test = new idealRequest331();

print $test->DirectoryRequest();

Als response krijg ik signature invalid. Omdat ik weet, dat de signature, keyfile en passphrase allemaal in orde zijn, moet er ergens een fout in deze code zitten. Dezelfde signature, keyfile en passphrase werken immers wel met mijn 2.x koppeling.

Iemand een idee?
Online Dierenspeciaalzaak is het adres voor uw huisdier.
Ohw en... Online Dierenspeciaalzaak BLOG!

Re: ideal 3.3.1

2
iDEAL Professional van Rabobank neem ik aan? De iDeal modules EN support van Rabobank zijn echt om te huilen. Maak je gebruik van een CMS?
Wellicht is het beter om een andere module te gebruiken.
Actief in webshopontwikkeling

Re: ideal 3.3.1

3
Ik gebruik geen CMS. Ik programmeer zelf. Inmiddels heb ik wel de code wat 'verbeterd'. Ik gebruik nu om te signeren de open source signeer module 'xmlseclibs.php'. Deze wordt door de ING ook gebruikt. Ik heb daar ook de passphrase in ingevoerd...

Dan kom ik op de code:

Code: Selecteer alles

<?

ini_set('display_errors',1); 
error_reporting(E_ALL);
require_once("xmlseclibs.php");

class idealRequest331 {
	
	private $privateKey;
	private $privateKeyFile;
	private $privateCertFile;
	private $privateCert;
	private $publicKeyFile;
	private $sMerchantId;
	private $sSubId;
	private $privateFingerprint;
	private $TestMode = false;
	private $URL;
	private $CRLF = "\r\n";

function __construct() {
	
	$this->sMerchantId = '***';
	$this->sSubId = '***';
	$this->URL = 'ssl://ideal' . ($this->TestMode ? 'test' : '') . '.rabobank.nl:443/ideal/iDealv3';
	
	
	$this->timeStamp = gmdate('Y-m-d') . 'T' . gmdate('H:i:s') . '.000Z';
	
	$this->privateKeyFile = 'ssl/private.key'; 
	$this->privateCertFile = 'ssl/private.cer';
	$this->publicKeyFile = 'ssl/rabobank.cer';
	
	$fh = fopen($this->privateKeyFile,'r');
	$this->privateKey = openssl_get_privatekey(fread($fh,8192),'***');
	fclose($fh);
	
	
	$fh = fopen($this->privateCertFile,'r');
	$this->privateCert = openssl_x509_read(fread($fh,8192));
	fclose($fh);
	$this->privateFingerprint = strtoupper(sha1(base64_decode(str_replace('-----END CERTIFICATE-----', '', str_replace('-----BEGIN CERTIFICATE-----', '', $this->privateCert)))));
	
}

function escapeXml($string) {
	return utf8_encode(str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string));
}

function postToHost($data, $timeout = 30) {
	
	$idx = strrpos($this->URL, ':');
	$host = substr($this->URL, 0, $idx);
	$this->URL = substr($this->URL, $idx + 1);
	$idx = strpos($this->URL, '/');
	$port = substr($this->URL, 0, $idx);
	$path = substr($this->URL, $idx);
	$fsp = fsockopen($host, $port, $errno, $errstr, $timeout);
	$res = '';
	
	if($fsp) {
	
		fputs($fsp, 'POST ' . $path . ' HTTP/1.0' . $this->CRLF);
		fputs($fsp, 'Host: ' . substr($host, 6) . $this->CRLF);
		fputs($fsp, 'Accept: text/html' . $this->CRLF);
		fputs($fsp, 'Accept: charset=ISO-8859-1' . $this->CRLF);
		fputs($fsp, 'Content-Length:' . strlen($data) . $this->CRLF);
		fputs($fsp, 'Content-Type: text/html; charset=ISO-8859-1' . $this->CRLF . $this->CRLF);
		fputs($fsp, $data, strlen($data));

		while(!feof($fsp)) {
			$res .= @fgets($fsp, 128);
		}

		fclose($fsp);
	}
	
	else $this->setError('Error while connecting to ' . $__url, false, __FILE__, __LINE__);

	return $res;
}

function signXML($message) {
	$messageAsXML = new DOMDocument();
	$messageAsXML->loadXML($message);
	
	$objDSig = new XMLSecurityDSig();
	$objDSig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
	$objDSig->addReference($messageAsXML, XMLSecurityDSig::SHA256, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature'), array('force_uri' => true));

	$objKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type' => 'private'));
	
	$objKey->loadKey($this->privateKeyFile, TRUE);
	$objDSig->sign($objKey);

	$fingerprint = $this->privateFingerprint;

	$objDSig->addKeyInfoAndName($fingerprint);
	$objDSig->appendSignature($messageAsXML->documentElement);

	return $messageAsXML->saveXML();
}

function DirectoryRequest() {	
	$sXmlMessage = '<?xml version="1.0" encoding="UTF-8" ?>' . $this->CRLF
	. '<DirectoryReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1">' . $this->CRLF
	. '<createDateTimestamp>' . $this->escapeXml($this->timeStamp) . '</createDateTimestamp>' . $this->CRLF
	. '<Merchant>' . $this->CRLF
	. '<merchantID>' . $this->escapeXml($this->sMerchantId) . '</merchantID>' . $this->CRLF
	. '<subID>' . $this->escapeXml($this->sSubId) . '</subID>' . $this->CRLF
	. '</Merchant>' . $this->CRLF
	. '</DirectoryReq>';
	
	//return $this->signXML($sXmlMessage);
	
	//return $sXmlMessage;
	
	return $this->postToHost($this->signXML($sXmlMessage));

	}

}

$test = new idealRequest331();

print $test->DirectoryRequest();

Bizar genoeg wel wederom signature invalid. Tips zijn welkom.

Ik gebruik inderdaad ideal van de rabo en de documentatie en support is inderdaad dramatisch.
Online Dierenspeciaalzaak is het adres voor uw huisdier.
Ohw en... Online Dierenspeciaalzaak BLOG!
Advertentie

Met Shopify maak je zelf je eigen webwinkel dankzij meer dan honderd thema’s en de complete appstore. Shopify sluit ook goed aan op dropshippers. De software is technisch volledig SEO-geoptimaliseerd en biedt alle sociale media-integraties. Meer info op Shopify.com.

Re: ideal 3.3.1

5
Hoi NOP Webdesign,

Ik loopt tegen soortgelijke problemen aan, echter ik ontwikkel in .NET Framework. Door externe restricties kan ik geen gebruik maken van ingebouwde SignedXml classes etc., dus ik wil hetzelfde doen als wat jij in je eerste post deed: Zelf een sha256 digest maken van de bericht inhoud en vervolgens de digest versleutelen en toevoegen.

Mijn voornaamste probleem is, dat ik niet met zekerheid kan zeggen wat die CN14 canonicalization met de berichtinhoud doet en ik denk dat ik hierdoor al de verkeerde digest genereer als basis.

Om mijn werkwijze te toetsen, probeer ik nu van een ontvangen retourbericht van de bank (foutmelding, maar dat boeit niet ;) de daarin meegezonden digest zelf ook te berekenen. Als dat lukt, weet ik dat ik goed zit. Tot nu toe niet gelukt helaas, dus ik hoop dat je nog wat tips hebt die jou naar de oplossing leidde.

Bedankt alvast.

Re: ideal 3.3.1

6
Er waren best wel wat punten waar ik fout zat. Maar wat jou probleem betreft, zou ik het zoeken in het volgende.

In PHP is de uitkomst van eerst een sha256 hash aanmaken en die RSA encrypten compleet anders dan via openssl_sign meteen RSA_SHA256 encryptie doen.

Een alternatief in PHP om alsnog een RSA_SHA256 encryptie te krijgen, als deze niet standaard op de server staat. Wat bij PHP versie < 5.3 het geval is, is:

Code: Selecteer alles

$fh = fopen(PRIVATE_KEYFILE,'r');
$priv_key_id = openssl_get_privatekey(fread($fh,8192),PRIV_PASSPHRASE);
fclose($fh);
$pinfo = openssl_pkey_get_details($priv_key_id);
$hash = hash('sha256', $data);
$t = '3031300d060960864801650304020105000420';
$t .= $hash;
$pslen = $pinfo['bits']/8 - (strlen($t)/2 + 3);

$eb = '0001' . str_repeat('FF', $pslen) . '00' . $t;
$eb = pack('H*', $eb);
openssl_private_encrypt($eb, $signature, $priv_key_id, OPENSSL_NO_PADDING); 
Ik heb niet genoeg kennis van RSA algoritmes om bovenstaande te bevatten. Ik heb dit ook maar 'gevonden' op internet. Allicht kun je er ook in .NET iets mee? Ik kan je in elk geval wel verzekeren, dat het in PHP absoluut werkt. De uitkomst van bovenstaande is absoluut gelijk aan openssl_sign met SHA256 algoritme.

Verder is mijn ervaring, dat $XML->C14N(); het XML bericht niet zichtbaar veranderd. Als dit wel het geval is, heb je fouten in je XML, die er dan uitgefilterd worden. Daar zou het dus niet in moeten zitten.

Daarbij heeft het mij meer geholpen om een directory request net zo lang mee te sleutelen, tot ik een geldige response kreeg. Het proberen te ontcijferen van de response signature kom je weer voor andere uitdagingen mee te staan. Ik zou eerst eens proberen zelf een geldige signature te maken.
Online Dierenspeciaalzaak is het adres voor uw huisdier.
Ohw en... Online Dierenspeciaalzaak BLOG!

Re: ideal 3.3.1

7
Aha thanx! De digest moet dus eerst nog gereed gemaakt worden voordat deze versleuteld wordt.
Neemt niet weg, dat de simpele plain-text, base64 encoded digest die in het veld <DigestValue> zit nog steeds met slechts het SHA256 algoritme gevonden moet kunnen worden.

Ik zie hier ook dat de C14N transformation wel degelijk wat dingen verandert, of dat terecht is weet ik niet:
- de <?xml ?> header is verdwenen
- elke regel eindigend op CRLF krijgt &#xD; achter elke regel

Hoe ziet bij jou je $data eruit waarover je de hash opvraagt?

Mijn directory request ziet er bijv zo uit:

Code: Selecteer alles

<?xml version="1.0" encoding="utf-8"?>
<DirectoryReq version="3.3.1" xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1">
  <createDateTimestamp>2013-05-23T10:43:18.123Z</createDateTimestamp>
  <Merchant>
    <merchantID>1234567890</merchantID>
    <subID>0</subID>
  </Merchant>
</DirectoryReq>
De hash na C14N =

Code: Selecteer alles

Hex: 55-60-A1-0D-31-41-84-57-12-54-E9-F6-56-BA-89-55-45-D7-A4-21-A4-76-3A-74-92-44-66-98-69-4F-30-48
B64: VWChDTFBhFcSVOn2VrqJVUXXpCGkdjp0kkRmmGlPMEg=

Re: ideal 3.3.1

8
Die veranderingen met C14N kloppen inderdaad wel. Goed opgemerkt. Was ik even vergeten...

De digest value vergelijken met wat je uit een request krijgt komt meer bij kijken heb ik ook gemerkt.

Ik had in eerste instantie gewoon via de DOM het signature element uit de XML verwijdert, dan een C14N export gedaan van de XML en daar dan een digest van maken. Echter kreeg ik dan ook een ander resultaat.

Als je met XPATH transform echter het signature element er uit gooit, is het resultaat anders. Het resultaat is dan wel juist. Blijkbaar is een 'standard transformation' zoals in de ideal stukken beschreven dus ook nog iets om echt rekening mee te houden. Ook daar ging ik de mist in...

Daarom was voor mij het wel een uitkomst om inderdaad gewoon de xmlseclibs library te gebruiken. Zonder zou ik er ook niet uit komen. Er komt echt teveel bij kijken. Als je dit echt niet kunt gebruiken om wat voor reden dan ook, denk ik dat je hier een zware dobber aan zult krijgen!

Dit is bijna alles wat ik zo gauw kan bedenken wat met mijn code mis was.

Wel is er dan nog het volgende.

In de code staat om de fingerprint te berekenen ook nog dat het SSL certificaat ingelezen wordt. Deze moet vervolgens wel nog even ge-exporteerd worden natuurlijk... Dat was ook vrij stom van me achteraf gezien.

Zelf heb ik nu, omdat de webserver waar ik op draai PHP 5.2.x draait dat verzoeken getekend worden met o.a. het stukje wat ik in bovenstaande postte om de encryptie toe te passen. Bij de controle op binnenkomende berichten kan ik op dit moment enkel controleren of überhaupt het juiste certificaat is gebruikt (fingerprint controle) en de digest. De handtekening zelf kan ik niet controleren omdat ik geen workaround weet om openssl_verify heen te komen.

Dan zal ik je nog een hint geven wat ik ook fout deed. Let op, dat je oude certificaat en key van de voorgaande ideal versie onbruikbaar zijn. Zelfs het public certificaat is veranderd met 3.3.1. Ook heb je voor 3.3.1 een 2048 bits sleutel nodig. Ook hier ging het bij mij mis.

Best veel mis toch? Nu werkt het bij mij in elk geval wel! :)
Online Dierenspeciaalzaak is het adres voor uw huisdier.
Ohw en... Online Dierenspeciaalzaak BLOG!

Re: ideal 3.3.1

10
Thnx voor de tips, maar ik ben er inmiddels op een andere manier uitgekomen.

Lang verhaal kort voor iedereen die op dit forum komt en ook een ouder framework dan .Net 4.5 moet gebruiken: ik kon de SignedXml class eerst niet gebruiken in .Net 3.5 omdat deze standaard geen rsa-sha256 signature ondersteunde. Echter met een uitbreiding van deze library wel!

Dus, geen gedoe met zelf de digest en signature maken. :)

Re: ideal 3.3.1

11
Ik ben ook bezig met iDeal 3.3.1. De posts hierboven hebben me al veel geholpen (waarvoor dank) maar ik krijg de Digest niet goed (ik ga ervanuit dat de message en digest van Kevin_pin correct zijn, maar ook die in de iDeal documentatie (Merchant Integratie Gids 3.3.1) heb ik geprobeerd als referentie te gebruiken en ik kom op andere waarden.

De directory request van Kevin_pin levert IXw3H+VrqxffuhtoNrFdPS5P0SPe8RTNrmVhyNZgGSc= als digestValue, als ik de methode van NOP webdesign zoals hierboven beschreven gebruik (enkele later-beschreven wijzigingen kan ik niet helemaal begrijpen, dus ik baseer me hoofdzakelijk op het tweede blok code).

Also, xmlseclib gaat allerlei namespace dingen aan de XML toevoegen, maar dit lijkt niet uit te maken?

De voorbeeldcode van ideal-simulator.nl is erg handig, maar helaas is daarvan (nog) geen 3.3.1 dus moeten we dat wiel allemaal zelf uitvinden :(

Alvast bedankt voor any feedback!

Edit: by the way, ik zit tegen de ideal-simulator aan te proberen, maar het versie veld zegt daar 1.1.0 (moet dat geen 3.3.1 zijn?), en alle errorcodes die terugkomen zijn XX0000 (de errormessages lijken wel sense te maken, bijv. Invalid signature value in XML request.)

Edit 2: @NOP webdesign, gebruik je versie 2010 van xmlseclibs? In de meest recente is geen functie "addKeyInfoAndName". Hem uit de 2010 versie copy-pasten in de meest recente lijkt overigens te werken.

Re: ideal 3.3.1

12
Sowieso, een fout in de DirectoryReq van kevin_pin is dat MerchantID max 9 integers lang mag zijn (en niet 1234567890, dat zijn er tien).

Voorbeeldcode van de ING gebruikt een schemaValidate tegen de XSD files, dit kan handig zijn bij het bughunten!

Check de documentatie en voorbeeldcodes hier: https://www.ideal-checkout.nl/sepa - ongeveer alles wat je moet weten bij elkaar.

Edit: uiteindelijk loop ik vast op de volgende error: Invalid signature value in XML request. Omdat ook ik vastzit aan een PHP < 5.3, heb ik helaas niet de beschikking over RSA_SHA256 en gebruik ik de code die NOP webdesign hierboven gepaste heeft. Echter, ik kan niet checken of het werkt. Tips? ik hoor ze graag!

Re: ideal 3.3.1

13
Dat is nou het mooie met ideal, daar kom je bijna niet achter. Je kunt alleen alle stappen doorlopen en controleren of je echt alles goed gedaan hebt.

Sowieso dien je natuurlijk xmlseclibs te gebruiken. Anders maak je het jezelf echt onnodig moeilijk.

Dat stukje code wat ik bovenstaande gepost had, is voor

private function signOpenSSL

Dat dient ter vervanging van openssl_sign

Ik zit er over te denken om de betaalmodule die ik gemaakt heb te koop aan te bieden tegen een kleine vergoeding. Zou daar vraag naar zijn? Het zou dan gaan om 20,-.

De betaalmodule is echt super eenvoudig. Een transactie request is bijvoorbeeld dit:

$StatusRequest = new idealRequest331();
$res = $StatusRequest->StatusRequest($TransactionId);


Dan is de response een array, dus $res is een array waar de response in zit.

Dus bijvoorbeeld $res['status'] is de status als de status succes is heb je ook velden als $res['iban'] en $res['amount'].

Als ik het te koop aan zou bieden, komt het inclusief een voorbeeld php bestand om uit te beelden hoe je de verschillende requests start.
Online Dierenspeciaalzaak is het adres voor uw huisdier.
Ohw en... Online Dierenspeciaalzaak BLOG!

Re: ideal 3.3.1

14
Ik denk dat daar zeker vraag naar is, in elk geval van mijn kant :)

Klinkt als handiger dan zelf nog langer doorpielen.

Re: ideal 3.3.1

15
Vreemd:
Proberen te verbinden ssl://idealtest.rabobank.nl:443/ideal/iDealv3 (zoals ook in de $this->URL in de code hierboven) geeft een 'moved' bericht terug:

Code: Selecteer alles

HTTP/1.1 302 Found Date: Mon, 15 Jul 2013 10:01:28 GMT Location: https://idealtest.rabobank.nl/ideal/logon_rabo.do Content-Length: 233 Content-Type: text/html; charset=iso-8859-1 Set-Cookie: ROUTEID=.int1; path=/ Connection: close <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> 
<html><head> <title>302 Found</title> </head>
<body> 
  <h1>Found</h1> <p>The document has moved <a href="https://idealtest.rabobank.nl/ideal/logon_rabo.do">here</a>.</p> 
</body>
</html>
In plaats van een geldige XML iDeal foutcode.
(uiteraard werkt de door de rabobank voorgestelde URL niet)

Edit: correcte URL moet zijn:

Code: Selecteer alles

ssl://idealtest.rabobank.nl:443/ideal/iDEALv3
Let op de CAPS op het eind...

Re: ideal 3.3.1

16
Het viel me ook op dat de ideal-simulator geen valid iDeal 3.3.1 XML produceert, hij is niet conform de XSD. Dan is het natuurlijk moeilijk testen...

Re: ideal 3.3.1

17
Jongens wat een gedoe met dat signen van de XML. Ik werk met .NET (C#) en gebruik de class die @kevin_pin ook gebruikt en het resultaat ziet er op zich goed uit. Ik krijg echter altijd weer de XX0000 melding: 'Invalid digest value in XML request.'

Onderstaand de code die ik gebruik:

Code: Selecteer alles

public XmlDocument SignDocument(XmlDocument doc, ISignatureProvider signatureProvider)
        {
            string signatureCanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
            string signatureMethod = @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
            string digestMethod = @"http://www.w3.org/2001/04/xmlenc#sha256";

            string signatureReferenceURI = "";

            CryptoConfig.AddAlgorithm(typeof(Security.Cryptography.RSAPKCS1SHA256SignatureDescription), signatureMethod);

            var signingCertificate = signatureProvider.GetAcceptantCertificate();

            CspParameters cspParams = new CspParameters();
            cspParams.KeyContainerName = "XML_DISG_RSA_KEY";
            RSACryptoServiceProvider key = new RSACryptoServiceProvider(cspParams);
            key.FromXmlString(signingCertificate.PrivateKey.ToXmlString(true)); /*assign the new key to signer's SigningKey */
            
            SignedXml signer = new SignedXml(doc);
            signer.SigningKey = key; // signingCertificate.PrivateKey;
           
            KeyInfoName keyName = new KeyInfoName();
            keyName.Value = signingCertificate.Thumbprint;
            signer.KeyInfo.AddClause(keyName);

            signer.SignedInfo.CanonicalizationMethod = signatureCanonicalizationMethod;
            signer.SignedInfo.SignatureMethod = signatureMethod;

            XmlDsigEnvelopedSignatureTransform envelopeTransform = new XmlDsigEnvelopedSignatureTransform();
            XmlDsigExcC14NTransform cn14Transform = new XmlDsigExcC14NTransform();

            Reference signatureReference = new Reference();
            signatureReference.Uri = signatureReferenceURI;
            signatureReference.DigestMethod = digestMethod;
            signatureReference.AddTransform(cn14Transform);            
            signatureReference.AddTransform(envelopeTransform);            

            signer.AddReference(signatureReference);

            signer.ComputeSignature();
            XmlElement signatureElement = signer.GetXml();

            doc.DocumentElement.AppendChild(signer.GetXml());

            return doc;
        }
Alle input is welkom. Alvast bedankt!

Re: ideal 3.3.1

18
skidder schreef:Vreemd:
Proberen te verbinden ssl://idealtest.rabobank.nl:443/ideal/iDealv3 (zoals ook in de $this->URL in de code hierboven) geeft een 'moved' bericht terug:

Code: Selecteer alles

HTTP/1.1 302 Found Date: Mon, 15 Jul 2013 10:01:28 GMT Location: https://idealtest.rabobank.nl/ideal/logon_rabo.do Content-Length: 233 Content-Type: text/html; charset=iso-8859-1 Set-Cookie: ROUTEID=.int1; path=/ Connection: close <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> 
<html><head> <title>302 Found</title> </head>
<body> 
  <h1>Found</h1> <p>The document has moved <a href="https://idealtest.rabobank.nl/ideal/logon_rabo.do">here</a>.</p> 
</body>
</html>
In plaats van een geldige XML iDeal foutcode.
(uiteraard werkt de door de rabobank voorgestelde URL niet)

Edit: correcte URL moet zijn:

Code: Selecteer alles

ssl://idealtest.rabobank.nl:443/ideal/iDEALv3
Let op de CAPS op het eind...
Dat is juist. Ook dat was fout. Zaten nog wel meer foutjes in... :-)
Online Dierenspeciaalzaak is het adres voor uw huisdier.
Ohw en... Online Dierenspeciaalzaak BLOG!

Re: ideal 3.3.1

19
@WJK: die digest is nogal gevoelig voor correct zijn van de XML en natuurlijk de Canonicalisatie. Misschien helpt het om een referentiebericht te hebben?

Hm ik zie dat copy-paste er een aantal spaties tussengooit, dus misschien heb je er niet zoveel aan...

Code: Selecteer alles

<?xml version="1.0" encoding="UTF-8"?> <DirectoryReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1"> <createDateTimestamp>2013-07-17T14:53:44.000Z</createDateTimestamp> 
<Merchant> <merchantID>002040774</merchantID> <subID>0</subID> </Merchant> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> 
<SignedInfo>
<CanonicalizationMethod xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> 
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> <Reference xmlns:ds="http://www.w3.org/2000/09/xmldsig#" URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<DigestValue>tmZODFnDpCuoHB+UMQXDp5YKl76wuzJES2to0eG0fWo=</DigestValue></Reference>
</SignedInfo>
<SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">XuWJQ5lhrceS17bWB029z0P1TZFYtOhckELgSwzsrZMAVNTMbPZMpFL3PrwVfvUkDI6yef8BDRxK57MYXzq1GQMlEq+JwE9wonVmecOTlqh0XIeNZMlyGaU8d9BRMPP8K92/NoJQA5zPAt5RVzb1LB/5HYP1b5mbkaTB5FPPeQk/eujMnjhTP8KxDjjKACyJlbu4U+ifpvid0k1kbOgZDJ4DsGhW+oXECmffrqHh4zR7qAOl5ukSB/HLnY0W1TTVbEpLJgDKGisVnGFy/yeRmDJCLxDohGJ4CmXIXmucfVnD+s3OWLTWdIIxgDBC9xg8rwQWPzXTELZ87XFFBt3OEA==</SignatureValue>
 <KeyInfo><KeyName>E963A6CA78A1406D3C80A091EC99CA0C04C65D9F</KeyName></KeyInfo>
</Signature>
</DirectoryReq> 
Deze geeft trouwens een SE2700 (Invalid electronic signature) omdat ik dat nog niet voor elkaar heb, maar voordat hij dat checkt is de Digest al gecheckt.

Re: ideal 3.3.1

20
Bedankt skidder. Ik ben nu zover dat mijn XML bericht goed is bevonden wat digest betreft. Ik krijg nu ook de SE2700 Invalid Electronic Signature. Ik heb mijn nieuwe certificaat in het test dashboard geplaatst en deze is ook max 5 jaar geldig. Dat zou dus allemaal goed moeten zijn. Ik heb nu even geen idee wat dit nu weer veroorzaakt. Ik zoek maar weer verder. Mocht je al wat gevonden hebben dan hoor ik het graag.

Re: ideal 3.3.1

21
Uiteindelijk ben ik in c#.net 4.5 tot de onderstaande code gekomen om een xml bericht te signen. Voor een directory request werkt dat goed. Verder heb ik nog niet gekeken, want ik wil graag de response ook verifiëren met de public key cert file van de bank.
En dat lukt nog steeds niet.

Dus, weet iemand hoe ik de response van de bank kan verifiëren?
In de oude iDEAL lukte dit allemaal, maar in v3.3.1 is me dit nog niet gelukt in c#.net framework 4.5

Code: Selecteer alles

private string signxml(string sXML)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(sXML);
            xmlDocument.PreserveWhitespace = true;

            string sCertFileLocation = "c:\certs\combined_public_and_private_key.p12";
            X509Certificate2 certificate = new X509Certificate2(sCertFileLocation, "password");

            RSA key = (RSACryptoServiceProvider)certificate.PrivateKey;

            SignedXml signedXml = new SignedXml(xmlDocument);
            signedXml.SigningKey = key;

            Reference reference = new Reference();
            reference.Uri = "";
            reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
            signedXml.AddReference(reference);

            KeyInfo keyInfo = new KeyInfo();
            KeyInfoName kin = new KeyInfoName();
            kin.Value = certificate.Thumbprint;
            keyInfo.AddClause(kin);
            signedXml.KeyInfo = keyInfo;

            signedXml.ComputeSignature();
            XmlElement xmlDigitalSignature = signedXml.GetXml();
            xmlDocument.DocumentElement.AppendChild(xmlDocument.ImportNode(xmlDigitalSignature, true));
            return xmlDocument.InnerXml;
        }

Re: ideal 3.3.1

22
Na ongeveer 10 a 15 variaties gemaakt te hebben op een verify_signature() is het dan eindelijk gelukt. Uiteindelijk bleek het best makkelijk, maar had ik de "PreserveWhitespace = true;" net na de "signedXML.loadXML()" gezet...
Toen ik deze ervoor had gezet (ook logisch eigenlijk) ging het wel goed.
Tja.. soms is copy paste toch niet zo handig ;)

In .net Framework 4.5 werkt deze verify dus bij mij:

Code: Selecteer alles

public bool verifySignature(string sXML)
        {
            bool isValid = false;
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.PreserveWhitespace = true;
            xmlDocument.LoadXml(sXML);

            string sCertFile = "c:\certs\ideal_v3_rabobank.cer";
            X509Certificate2 cert = new X509Certificate2(sCertFile);

            CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");

            SignedXml signedXml = new SignedXml(xmlDocument);
          
            XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");            
            signedXml.LoadXml((XmlElement)nodeList[0]);

            isValid = signedXml.CheckSignature(cert, true);

            return isValid;
        }

Re: ideal 3.3.1

23
Bedankt @fhus!

Ik heb de code overgenomen en ingebouwd in de iDEAL.net module van Robin vd Knaap (https://github.com/robinvanderknaap/iDeal.NET). Deze werkte prima voor de pre 3.3.1 versie van iDeal. Ik sign nu elk XML bericht met de code van @fhus en de VerifySignature heb ik omgebouwd. Daarnaast nog een heel aantal tekstuele wijzigingen maar dat was peanuts.

Ik heb nu een iDeal.net module in .Net 4.0. Ik heb daarbij wel een referentie moeten leggen naar de Security.Cryptography.dll van http://clrsecurity.codeplex.com/. Dit is nodig voor de check in VerifySignature.

Code: Selecteer alles

CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
Al met al een hele onderneming maar ik kan weer verder om deze module te koppelen aan de bestaande website. Allemaal heel erg bedankt voor de moeite!

Re: ideal 3.3.1

24
mooi :)
In 4.5 gebruik ik een referentie naar "System.Deployment"
En is het CryptoConfig.AddAlgorithm() te gebruiken met "using System.Deployment.Internal.CodeSigning;"

Re: ideal 3.3.1

25
hmm.. ik kan geen transactierequest starten..
"Het resultaat van uw betaling is nog niet bij ons bekend. U kunt desgewenst uw betaling controleren in uw Internetbankieren".
Heb alles al ge-dubbelcheckt :(

Iemand hier ervaring mee, of mij wil helpen?

Transactie status opvragen van reeds bestaande transacties lukt wel gewoon via ideal V3.3.1

Re: ideal 3.3.1

26
het enige wat ik nog kan bedenken is dat m'n transactie request xml niet goed is opgemaakt.
Hoewel ik dat al een aantal keer nagekeken heb, ben ik wel benieuwd naar de xml van iemand hier waarbij het wel goed gaat. Wil iemand daar eens een voorbeeld van posten?

Op de test url van rabobank gaat het ook niet goed.
Ik vind het erg raar dat de status requests en directory requests wel goed gaan, maar een transactie request niet :(

Dit is mij transactie request, unsigned. Heb de merchantID en de website-url even aangepast.

Code: Selecteer alles

<?xml version="1.0" encoding="UTF-8"?>
<AcquirerTrxReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1">
    <createDateTimeStamp>2013-07-30T12:08:06.000Z</createDateTimeStamp>
    <Issuer>
        <issuerID>RABONL2U</issuerID>
    </Issuer>
    <Merchant>
        <merchantID>000000000</merchantID>
        <subID>0</subID>
        <merchantReturnURL>https://www.website.nl/idealpayV3/idealreturn.aspx</merchantReturnURL>
    </Merchant>
    <Transaction>
        <purchaseID>123</purchaseID>
        <amount>1.00</amount>
        <currency>EUR</currency>
        <expirationPeriod>PT15M</expirationPeriod>
        <language>nl</language>
        <description>AE2MWHHA</description>
        <entranceCode>123</entranceCode>
    </Transaction>
</AcquirerTrxReq>

Re: ideal 3.3.1

27
opgelost :-)
Met behulp van de rabobank support nog wel!
Er stond createDateTimeStamp, met een hoofdletter S.
Deze aangepast in een kleine s en alles gaat goed.

Zovaak de boel nagekeken en de requests met elkaar vergeleken en de documentatie ernaast gelegd. En dan toch zo´n foutje.

Re: ideal 3.3.1

28
Voor php heb ik met iDEAL 1.1.0 een module geschreven die open source is en direct te gebruiken is. Voor klanten ben ik nu (oude) code aan het omzetten naar 3.3.1. Als dit is gelukt, kan ik ook eenvoudig de module omzetten.

De code (nu dus nog de 1.1.0 versie) staat op github: https://github.com/juriansluiman/SlmIdealPayment. De API voor de module zal hetzelfde blijven, het is iets dergelijks als dit:

Code: Selecteer alles

// Configuratie
$client = new SlmIdealPayment\Client\StandardClient;
$client->setRequestUrl('ssl://ideal.rabobank.nl:443/ideal/iDEALv3');
$client->setPublicCertificate('var/cert/rabobank.cer');
$client->setPrivateCertificate('var/cert/mysite.cer');
$client->setKeyFile('var/cert/key.pem');
$client->setKeyPassword('password123');

// Request
$request = new SlmIdealPayment\Request\DirectoryRequest();
$request->setMerchantId('12345678');
$request->setSubId('0');

$response = $client->sendDirectoryRequest($request);
foreach ($response->getIssuers() as $issuer) {
  echo sprintf("%s (%s)\n", $issuer->getName(), $issuer->getId());
}
Hij is in te laden via composer (slm/ideal-payment) en bevat ook verdere integratie voor Zend Framework 2 (o.a. voor configuraties, dependency injection en de service manager). Maar in principe is de gehele code ook los van het complete framework te gebruiken.

Re: ideal 3.3.1

29
fhus schreef:opgelost :-)
Met behulp van de rabobank support nog wel!
Er stond createDateTimeStamp, met een hoofdletter S.
Deze aangepast in een kleine s en alles gaat goed.

Zovaak de boel nagekeken en de requests met elkaar vergeleken en de documentatie ernaast gelegd. En dan toch zo´n foutje.
Het ligt niet aan jou ;)

In de documentatie van "Overzicht van wijzigingen" wordt er vaal createDateTimeStamp geschreven (!!!). Zie bijvoorbeeld paragraaf 3.3 en 3.8. In paragraaf 3.6 staat er weer wel createDateTimeStamp....

Re: ideal 3.3.1

30
mithras schreef:
fhus schreef:opgelost :-)
Met behulp van de rabobank support nog wel!
Er stond createDateTimeStamp, met een hoofdletter S.
Deze aangepast in een kleine s en alles gaat goed.

Zovaak de boel nagekeken en de requests met elkaar vergeleken en de documentatie ernaast gelegd. En dan toch zo´n foutje.
Het ligt niet aan jou ;)

In de documentatie van "Overzicht van wijzigingen" wordt er vaal createDateTimeStamp geschreven (!!!). Zie bijvoorbeeld paragraaf 3.3 en 3.8. In paragraaf 3.6 staat er weer wel createDateTimeStamp....
ha, het bewijs
-en dat ik niet enige ben die dit over het hoofd ziet ;)