FILE: ideal.cls.php
[code]
<?php

	class IdealRequest
	{
		private $aErrors = array();

		// Security settings
		protected $sSecurePath;
		protected $sPrivateKeyPass;
		protected $sPrivateKeyFile;
		protected $sPrivateCertificateFile;
		protected $sPublicCertificateFile;

		// Account settings
		protected $sAquirerUrl;
		protected $sMerchantId;
		protected $sSubId;

		// Constants
		protected $LF = "\n";
		protected $CRLF = "\r\n";

		public function __construct()
		{
			$this->sPrivateKeyFile = 'private.key';
			$this->sPrivateCertificateFile = 'private.cer';
		}

		// Should point to directory with .cer and .key files
		public function setSecurePath($sPath)
		{
			$this->sSecurePath = $sPath;
		}

		// Set password to generate signatures
		public function setPrivateKey($sPass)
		{
			$this->sPrivateKeyPass = $sPass;
		}

		// Set MerchantID id and SubID
		public function setMerchant($sMerchantId, $sSubId = 0)
		{
			$this->sMerchantId = $sMerchantId;
			$this->sSubId = $sSubId;
		}

		// Set aquirer (Use: Rabobank, ING Bank, etc)
		public function setAquirer($sIssuer, $bTestMode = false)
		{
			if(stripos($sIssuer, 'rabo') !== false) // Rabobank
			{
				$this->sPublicCertificateFile = 'rabobank.cer';
				$this->sAquirerUrl = 'ssl://ideal' . ($bTestMode ? 'test' : '') . '.rabobank.nl:443/ideal/iDeal';
			}
			elseif(stripos($sIssuer, 'ing') !== false) // ING Bank
			{
				$this->sPublicCertificateFile = 'ingbank.cer';
				$this->sAquirerUrl = 'ssl://ideal' . ($bTestMode ? 'test' : '') . '.secure-ing.com:443/ideal/iDeal';
			}
			elseif(stripos($sIssuer, 'abn') !== false) // ABN Amro
			{
				$this->sPublicCertificateFile = 'abnamro.cer';
				$this->sAquirerUrl = 'ssl://idealm-et.abnamro.nl:443/';
			}
			elseif(stripos($sIssuer, 'fortis') !== false) // Fortis Bank
			{
				$this->sPublicCertificateFile = 'fortisbank.cer';
				// $this->sAquirerUrl = 'ssl://;
			}
			elseif(stripos($sIssuer, 'sns') !== false) // SNS Bank
			{
				$this->sPublicCertificateFile = 'snsbank.cer';
				// $this->sAquirerUrl = 'ssl://';
			}
			else // Unknown issuer
			{
				$this->setError('Unknown aquirer. Please use Rabobank, ING Bank, ABN Amro, SNS Bank or Fortis.', false, __FILE__, __LINE__);
				return false;
			}
		}




		// Error functions
		protected function setError($sDesc, $sCode = false, $sFile = 0, $sLine = 0)
		{
			$this->aErrors[] = array('desc' => $sDesc, 'code' => $sCode, 'file' => $sFile, 'line' => $sLine);
		}

		public function getErrors()
		{
			return $this->aErrors;
		}

		public function hasErrors()
		{
			return (sizeof($this->aErrors) ? true : false);
		}



		protected function checkConfiguration($settings = array('sSecurePath', 'sPrivateKeyPass', 'sPrivateKeyFile', 'sPrivateCertificateFile', 'sPublicCertificateFile', 'sAquirerUrl', 'sMerchantId'))
		{
			$bOk = true;

			for($i = 0; $i < sizeof($settings); $i++)
			{
				// echo $settings[$i] . ' = ' . $this->$settings[$i] . '<br>';

				if(empty($this->$settings[$i]))
				{
					$bOk = false;
					$this->setError('Setting ' . $settings[$i] . ' was not configurated.', false, __FILE__, __LINE__);
				}
			}

			return $bOk;
		}



		// Utils
		protected function postToHost($url, $data, $timeout = 30)
		{
			$idx = strrpos($url, ':');
			$host = substr($url, 0, $idx);
			$url = substr($url, $idx + 1);
			$idx = strpos($url, '/');
			$port = substr($url, 0, $idx);
			$path = substr($url, $idx);

			$fsp = fsockopen($host, $port, $errno, $errstr, $timeout);
			$res = '';
			
			if($fsp)
			{
				fputs($fsp, 'POST ' . $path . ' HTTP/1.0' . $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($errstr, $errno, __FILE__, __LINE__);
			}

			return $res;
		}

		protected function parseFromXml($key, $xml)
		{
			$begin = 0;
			$end = 0;
			$begin = strpos($xml, '<' . $key . '>');
			
			if($begin === false)
			{
				return false;
			}

			$begin += strlen($key) + 2;
			$end = strpos($xml, '</' . $key . '>');

			if($end === false)
			{
				return false;
			}

			$result = substr($xml, $begin, $end - $begin);
			$result = $this->unescapeXml($result);

			return utf8_decode($result);
		}

		protected function removeSpaceCharacters($string)
		{
			return preg_replace('/\s/', '', $string);
		}

		protected function escapeXml($string)
		{
			$string = str_replace('&', '&amp;', $string);
			$string = str_replace('<', '&lt;', $string);
			$string = str_replace('>', '&gt;', $string);
			$string = str_replace('"', '&quot;', $string);
			return $string;
		}

		protected function unescapeXml($string)
		{
			$string = str_replace('&quot;', '"', $string);
			$string = str_replace('&lt;', '<', $string);
			$string = str_replace('&gt;', '>', $string);
			$string = str_replace('&amp;', '&', $string);
			return $string;
		}



		// Security functions
		protected function getCertificateFingerprint($bPublicCertificate = false)
		{
			if($fp = fopen($this->sSecurePath . ($bPublicCertificate ? $this->sPublicCertificateFile : $this->sPrivateCertificateFile), 'r'))
			{
				$sRawData = fread($fp, 8192);
				fclose($fp);

				$sData = openssl_x509_read($sRawData);

				if(!openssl_x509_export($sData, $sData))
				{
					$this->setError('Error in certificate ' . $this->sSecurePath . $this->sPrivateCertificateFile, false, __FILE__, __LINE__);
					return false;
				}
			
				$sData = str_replace('-----BEGIN CERTIFICATE-----', '', $sData);
				$sData = str_replace('-----END CERTIFICATE-----', '', $sData);

				return strtoupper(sha1(base64_decode($sData)));
			}
			else
			{
				$this->setError('Certificate file ' . $this->sSecurePath . $this->sPrivateCertificateFile . ' not found.', false, __FILE__, __LINE__);
			}
		}

		protected function getSignature($sMessage)
		{
			$sMessage = preg_replace('/\s/', '', $sMessage);

			if($fp = fopen($this->sSecurePath . $this->sPrivateKeyFile, 'r'))
			{
				$sRawData = fread($fp, 8192);
				fclose($fp);

				$sPrivateKey = openssl_get_privatekey($sRawData, $this->sPrivateKeyPass);
				$sSignature = '';

				openssl_sign($sMessage, $sSignature, $sPrivateKey);
				openssl_free_key($sPrivateKey);

				return $sSignature;
			}
		}

		protected function verifySignature($sData, $sSignature)
		{
			$bOk = false;

			if($fp = fopen($this->sSecurePath . $this->sPublicCertificateFile, 'r'))
			{
				$sRawData = fread($fp, 8192);
				fclose($fp);

				$sPublicKey = openssl_get_publickey($sRawData);
				$bOk = (openssl_verify($sData, $sSignature, $sPublicKey) ? true : false);
				openssl_free_key($sPublicKey);
			}

			return $bOk;
		}
	}




	class IssuerRequest extends IdealRequest
	{
		public function __construct()
		{
			parent::__construct();
		}

		// Execute request (Lookup issuer list)
		public function doRequest()
		{
			if($this->checkConfiguration())
			{
				$sTimestamp = gmdate('Y-m-d') . 'T' . gmdate('H:i:s') . '.000Z';
				$sMessage = $this->removeSpaceCharacters($sTimestamp . $this->sMerchantId . $this->sSubId);

				$sToken = $this->getCertificateFingerprint();
				$sTokenCode = base64_encode($this->getSignature($sMessage));

				$sXmlMessage = '<?xml version="1.0" encoding="UTF-8" ?>' . $this->LF
				. '<DirectoryReq xmlns="http://www.idealdesk.com/Message" version="1.1.0">' . $this->LF
				. '<createDateTimeStamp>' . utf8_encode($sTimestamp) . '</createDateTimeStamp>' . $this->LF
				. '<Merchant>' . $this->LF
				. '<merchantID>' . utf8_encode($this->sMerchantId) . '</merchantID>' . $this->LF
				. '<subID>' . utf8_encode($this->sSubId) . '</subID>' . $this->LF
				. '<authentication>SHA1_RSA</authentication>' . $this->LF
				. '<token>' . utf8_encode($sToken) . '</token>' . $this->LF
				. '<tokenCode>' . utf8_encode($sTokenCode) . '</tokenCode>' . $this->LF
				. '</Merchant>' . $this->LF
				. '</DirectoryReq>';

				$sXmlReply = $this->postToHost($this->sAquirerUrl, $sXmlMessage, 10);

				if($sXmlReply)
				{
					if($this->parseFromXml('errorCode', $sXmlReply)) // Error found
					{
						// Add error to error-list
						$this->setError($this->parseFromXml('errorMessage', $sXmlReply), $this->parseFromXml('errorCode', $sXmlReply), __FILE__, __LINE__);					
					}
					else
					{
						$aIssuerList = array();

						while(strpos($sXmlReply, '<issuerID>'))
						{							
							$sIssuerId = $this->parseFromXml('issuerID', $sXmlReply);
							$sIssuerName = $this->parseFromXml('issuerName', $sXmlReply);
							$sIssuerList = $this->parseFromXml('issuerList', $sXmlReply);

							if(strcmp($sIssuerList, 'Short') === 0)
							{
								$aIssuerList[$sIssuerId] = $sIssuerName;
							}

							$sXmlReply = substr($sXmlReply, strpos($sXmlReply, '</issuerList>') + 13);
						}

						return $aIssuerList;
					}
				}
			}

			return false;
		}
	}




	class TransactionRequest extends IdealRequest
	{
		protected $sOrderId;
		protected $sOrderDescription;
		protected $iOrderAmount;
		protected $sReturnUrl;
		protected $sIssuerId;
		protected $sEntranceCode;

		// Transaction info
		protected $sTransactionId;
		protected $sTransactionUrl;

		public function __construct()
		{
			parent::__construct();

			// Random EntranceCode
			$this->sEntranceCode = sha1(rand(1000000, 9999999));
		}

		public function setOrderId($sOrderId)
		{
			$this->sOrderId = substr($sOrderId, 0, 16);
		}

		public function setOrderDescription($sOrderDescription)
		{
			$this->sOrderDescription = substr($sOrderDescription, 0, 32);
		}

		public function setOrderAmount($fOrderAmount)
		{
			$this->iOrderAmount = round($fOrderAmount * 100);
		}

		public function setReturnUrl($sReturnUrl)
		{
			$this->sReturnUrl = substr($sReturnUrl, 0, 512);
		}

		public function setIssuerId($sIssuerId)
		{
			$this->sIssuerId = $sIssuerId;
		}

		public function setEntranceCode($sEntranceCode)
		{
			$this->sEntranceCode = substr($sEntranceCode, 0, 40);
		}

		// Execute request (Setup transaction)
		public function doRequest()
		{
			if($this->checkConfiguration() && $this->checkConfiguration(array('sOrderId', 'sOrderDescription', 'iOrderAmount', 'sReturnUrl', 'sReturnUrl', 'sIssuerId', 'sEntranceCode')))
			{
				$sTimestamp = gmdate('Y-m-d') . 'T' . gmdate('H:i:s') . '.000Z';
				$sMessage = $this->removeSpaceCharacters($sTimestamp . $this->sIssuerId . $this->sMerchantId . $this->sSubId . $this->sReturnUrl . $this->sOrderId . $this->iOrderAmount . 'EUR' . 'nl' . $this->sOrderDescription . $this->sEntranceCode);
				$sToken = $this->getCertificateFingerprint();
				$sTokenCode = $this->getSignature($sMessage);
				$sTokenCode = base64_encode($sTokenCode);

				$sXmlMessage = '<?xml version="1.0" encoding="UTF-8" ?>' . $this->LF
				. '<AcquirerTrxReq xmlns="http://www.idealdesk.com/Message" version="1.1.0">' . $this->LF
				. '<createDateTimeStamp>' . utf8_encode($sTimestamp) .  '</createDateTimeStamp>' . $this->LF
				. '<Issuer>' . $this->LF
				. '<issuerID>' . utf8_encode($this->sIssuerId) . '</issuerID>' . $this->LF
				. '</Issuer>' . $this->LF
				. '<Merchant>' . $this->LF 
				. '<merchantID>' . utf8_encode($this->sMerchantId) . '</merchantID>' . $this->LF
				. '<subID>' . utf8_encode($this->sSubId) . '</subID>' . $this->LF
				. '<authentication>SHA1_RSA</authentication>' . $this->LF
				. '<token>' . utf8_encode($sToken) . '</token>' . $this->LF
				. '<tokenCode>' . utf8_encode($sTokenCode) . '</tokenCode>' . $this->LF
				. '<merchantReturnURL>' . utf8_encode($this->escapeXml($this->sReturnUrl)) . '</merchantReturnURL>' . $this->LF
				. '</Merchant>' . $this->LF
				. '<Transaction>' . $this->LF
				. '<purchaseID>' . utf8_encode($this->escapeXml($this->sOrderId)) . '</purchaseID>' . $this->LF
				. '<amount>' . utf8_encode($this->iOrderAmount) . '</amount>' . $this->LF
				. '<currency>EUR</currency>' . $this->LF
				. '<expirationPeriod>PT30M</expirationPeriod>' . $this->LF
				. '<language>nl</language>' . $this->LF
				. '<description>' . utf8_encode($this->escapeXml($this->sOrderDescription)) . '</description>' . $this->LF
				. '<entranceCode>' . utf8_encode($this->escapeXml($this->sEntranceCode)) . '</entranceCode>' . $this->LF
				. '</Transaction>' . $this->LF 
				. '</AcquirerTrxReq>';

				$sXmlReply = $this->postToHost($this->sAquirerUrl, $sXmlMessage, 10);

				if($sXmlReply)
				{
					if($this->parseFromXml('errorCode', $sXmlReply)) // Error found
					{
						// Add error to error-list
						$this->setError($this->parseFromXml('errorMessage', $sXmlReply), $this->parseFromXml('errorCode', $sXmlReply), __FILE__, __LINE__);					
					}
					else
					{
						$this->sTransactionId = $this->parseFromXml('transactionID', $sXmlReply);
						$this->sTransactionUrl = html_entity_decode($this->parseFromXml('issuerAuthenticationURL', $sXmlReply));

						return $this->sTransactionId;
					}
				}
			}

			return false;
		}

		// Start transaction
		public function doTransaction()
		{
			if((sizeof($this->aErrors) == 0) && $this->sTransactionId && $this->sTransactionUrl)
			{
				header('Location: ' . $this->sTransactionUrl);
				exit;
			}

			$this->setError('Please setup a valid transaction request first.', false, __FILE__, __LINE__);
			return false;
		}
	}




	class StatusRequest extends IdealRequest
	{
		// Account info
		protected $sAccountCity;
		protected $sAccountName;
		protected $sAccountNumber;

		// Transaction info
		protected $sTransactionId;
		protected $sTransactionStatus;

		public function __construct()
		{
			parent::__construct();
		}

		// Set transaction id
		public function setTransactionId($sTransactionId)
		{
			$this->sTransactionId = $sTransactionId;
		}

		// Get account city
		public function getAccountCity()
		{
			if(!empty($this->sAccountCity))
			{
				return $this->sAccountCity;
			}

			return '';
		}

		// Get account name
		public function getAccountName()
		{
			if(!empty($this->sAccountName))
			{
				return $this->sAccountName;
			}

			return '';
		}

		// Get account number
		public function getAccountNumber()
		{
			if(!empty($this->sAccountNumber))
			{
				return $this->sAccountNumber;
			}

			return '';
		}

		// Execute request
		public function doRequest()
		{
			if($this->checkConfiguration() && $this->checkConfiguration(array('sTransactionId')))
			{
				$sTimestamp = gmdate('Y-m-d') . 'T' . gmdate('H:i:s') . '.000Z';
				$sMessage = $this->removeSpaceCharacters($sTimestamp . $this->sMerchantId . $this->sSubId . $this->sTransactionId);
				$sToken = $this->getCertificateFingerprint();
				$sTokenCode = $this->getSignature($sMessage);
				$sTokenCode = base64_encode($sTokenCode);

				$sXmlMessage = '<?xml version="1.0" encoding="UTF-8" ?>' . $this->LF
				. '<AcquirerStatusReq xmlns="http://www.idealdesk.com/Message" version="1.1.0">' . $this->LF
				. '<createDateTimeStamp>' . utf8_encode($sTimestamp) . '</createDateTimeStamp>' . $this->LF
				. '<Merchant>' 
				. '<merchantID>' . utf8_encode($this->sMerchantId) . '</merchantID>' . $this->LF
				. '<subID>' . utf8_encode($this->sSubId) . '</subID>' . $this->LF
				. '<authentication>SHA1_RSA</authentication>' . $this->LF
				. '<token>' . utf8_encode($sToken) . '</token>' . $this->LF
				. '<tokenCode>' . utf8_encode($sTokenCode) . '</tokenCode>' . $this->LF
				. '</Merchant>' . $this->LF
				. '<Transaction>' 
				. '<transactionID>' . utf8_encode($this->sTransactionId) . '</transactionID>' . $this->LF
				. '</Transaction>' 
				. '</AcquirerStatusReq>';

				$sXmlReply = $this->postToHost($this->sAquirerUrl, $sXmlMessage, 10);

				if($sXmlReply)
				{
					if($this->parseFromXml('errorCode', $sXmlReply)) // Error found
					{
						// Add error to error-list
						$this->setError($this->parseFromXml('errorMessage', $sXmlReply), $this->parseFromXml('errorCode', $sXmlReply), __FILE__, __LINE__);					
					}
					else
					{
						$sTimestamp = $this->parseFromXml('createDateTimeStamp', $sXmlReply);
						$sTransactionId = $this->parseFromXml('transactionID', $sXmlReply);
						$sTransactionStatus = $this->parseFromXml('status', $sXmlReply);

						$sAccountNumber = $this->parseFromXml('consumerAccountNumber', $sXmlReply);
						$sAccountName = $this->parseFromXml('consumerName', $sXmlReply);
						$sAccountCity = $this->parseFromXml('consumerCity', $sXmlReply);

						$sMessage = $this->removeSpaceCharacters($sTimestamp . $sTransactionId . $sTransactionStatus . $sAccountNumber);

						$sSignature = base64_decode($this->parseFromXml('signatureValue', $sXmlReply));
						$sFingerprint = $this->parseFromXml('fingerprint', $sXmlReply);

						if(strcasecmp($sFingerprint, $this->getCertificateFingerprint(true)) !== 0)
						{
							// Invalid Fingerprint
							$this->setError('Unknown fingerprint.', false, __FILE__, __LINE__);
						}
						elseif($this->verifySignature($sMessage, $sSignature) == false)
						{
							// Invalid Fingerprint
							$this->setError('Bad signature.', false, __FILE__, __LINE__);
						}
						else
						{
							// $this->sTransactionId = $sTransactionId;
							$this->sTransactionStatus = strtoupper($sTransactionStatus);

							$this->sAccountCity = $sAccountCity;
							$this->sAccountName = $sAccountName;
							$this->sAccountNumber = $sAccountNumber;

							return $this->sTransactionStatus;
						}
					}
				}
			}

			return false;
		}
	}
?>
[/code]




FILE: step1.php
[code]
<?php

	// Invoegen van classes
	require_once(dirname(__FILE__) . '/ideal.cls.php');

	$oIssuerRequest = new IssuerRequest();

	// Algemene iDEAL instellingen
	$oIssuerRequest->setSecurePath(dirname(__FILE__) . '/ssl/'); // Verwijst naar de beveiligde map met certificaten e.d.
	$oIssuerRequest->setPrivateKey('PrivateKeyPass'); // Het wachtwoord waarmee private.key is gegenereerd.
	$oIssuerRequest->setAquirer('Rabobank', true); // Je bank (Rabobank, ING Bank, etc)
	$oIssuerRequest->setMerchant('YourMerchantId', '0'); // Je MerchantID/SubId


	// Opvragen van order informatie.
	$sOrderId = rand(1000000, 9999999); // Uniek order ID
	$sOrderDescription = 'Order omschrijving'; // Omschrijving
	$fOrderAmount = rand(100, 99999) / 100; // Bedrag (in decimaal!!)


	// Opvragen van alle beschikbare iDEAL banken.
	$sIssuerOptions = '';

	if($aIssuerList = $oIssuerRequest->doRequest())
	{
		// Maak een keuzelijst met banken
		foreach($aIssuerList as $k => $v)
		{
			$sIssuerOptions .= '<option value="' . $k . '">' . htmlentities($v) . '</option>';
		}
	}
	else
	{
		$sIssuerOptions .= '<option value="0">-</option>';

		// Je kunt $oIssuerRequest->getErrors() gebruiken om de lijst met opgetreden fouten op te vragen.
		print_r($oIssuerRequest->getErrors());
	}

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
	<head>
		<title>iDEAL - Stap 1: Opvragen van beschikbare iDEAL banken.</title>
	</head>
	<body>
		<form action="step2.php" method="post">
			<h1>Uw iDEAL transactie</h1>
			<p><b>Order ID:<br /><input type="text" name="order_id" size="30" value="<?php echo $sOrderId; ?>"><br /><br />Order omschrijving:<br /><textarea rows="8" name="order_description" cols="40"><?php echo $sOrderDescription; ?></textarea><br /><br />Order bedrag:<br /><input name="order_amount" size="30" type="text" value="<?php echo number_format($fOrderAmount, 2, '.', ''); ?>"> (EUR)<br /><br />Kies uw bank:<br /><select name="order_issuer" size="1"><?php echo $sIssuerOptions; ?></select><br /><br /><br /><input name="_submit" type="submit" value="verder &gt;&gt;"></b></p>
		</form>
	</body>
</html>
[/code]




FILE: step2.php
[code]
<?php

	// Opvragen van order informatie uit POST data.
	$sOrderId = $_POST['order_id']; // Unieke verwijzing naar de order
	$sOrderDescription = substr($_POST['order_description'], 0, 32); // Maximaal 32 karakters
	$fOrderAmount = $_POST['order_amount']; // Bedrag in CENTEN!
	$sIssuerId = $_POST['order_issuer']; // ID van de geselecteerde bank

	// De URL waar de bezoeker naar toe wordt gestuurd nadat de ideal betaling is afgerond (of bij fouten)
	$sReturnUrl = 'http://www.domeinnaam.nl/step3.php';

	// Genereer een zelf op te geven EntranceCode (tot 40 karakters)
	$sEntranceCode = sha1($sOrderId . '_' . date('YmdHis'));



	// Invoegen van classes
	include(dirname(__FILE__) . '/ideal.cls.php');

	$oTransactionRequest = new TransactionRequest();

	// Algemene iDEAL instellingen
	$oTransactionRequest->setSecurePath(dirname(__FILE__) . '/ssl/'); // Verwijst naar de beveiligde map met certificaten e.d.
	$oTransactionRequest->setPrivateKey('PrivateKeyPass'); // Het wachtwoord waarmee private.key is gegenereerd.
	$oTransactionRequest->setAquirer('Rabobank', true); // Je bank (Rabobank, ING Bank, etc)
	$oTransactionRequest->setMerchant('YourMerchantId', '0'); // Je MerchantID/SubId


	// Order instellingen
	$oTransactionRequest->setOrderId($sOrderId);
	$oTransactionRequest->setOrderDescription($sOrderDescription);
	$oTransactionRequest->setOrderAmount($fOrderAmount);

	$oTransactionRequest->setReturnUrl($sReturnUrl);
	$oTransactionRequest->setIssuerId($sIssuerId);
	$oTransactionRequest->setEntranceCode($sEntranceCode);


	if($sTransactionId = $oTransactionRequest->doRequest()) // Voer het transactie verzoek uit (bij succes ontvang je een TransactionID)
	{
		// Sla de TransactieID, EntranceCode en overige order informatie op (bijv. in de database).
		// ...

		// Ga verder met de transactie (de bezoeker wordt doorgestuurd naar de website van zijn/haar bank)
		$oTransactionRequest->doTransaction();
	}

	// Je kunt $oTransactionRequest->getErrors() gebruiken om de lijst met opgetreden fouten op te vragen.
	print_r($oTransactionRequest->getErrors());

?>
[/code]




FILE: step3.php
[code]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
	<head>
		<title>iDEAL - Stap 3: Opvragen van de transactie status.</title>
	</head>
	<body>
<?php

	// Zoek het TransactieID en EntranceCode op in $_GET
	$sTransactionId = $_GET['trxid'];
	$sEntranceCode = $_GET['ec'];


	// Controlleer of de TransactieID/EntranceCode combinatie bestaat in de database
	if(true) // Transactie bestaat/geldig
	{
		// Invoegen van classes
		include(dirname(__FILE__) . '/ideal.cls.php');

		$oStatusRequest = new StatusRequest();

		// Algemene iDEAL instellingen
		$oStatusRequest->setSecurePath(dirname(__FILE__) . '/ssl/'); // Verwijst naar de beveiligde map met certificaten e.d.
		$oStatusRequest->setPrivateKey('PrivateKeyPass'); // Het wachtwoord waarmee private.key is gegenereerd.
		$oStatusRequest->setAquirer('Rabobank', true); // Je bank (Rabobank, ING Bank, etc)
		$oStatusRequest->setMerchant('YourMerchantId', '0'); // Je MerchantID/SubId

		// Transactie instellingeN
		$oStatusRequest->setTransactionId($sTransactionId); // Het ID van de transactie waarvan je de status wilt controleren.

		// Vraag de status van de transactie op (SUCCESS, CANCELLED, FAILURE, OPEN, EXPIRED)
		if($sStatus = $oStatusRequest->doRequest())
		{
			// Update status rapportage (bijv. in de database).
			// ...

			echo '<p>Uw betaling via iDEAL heeft als status ' . $sStatus . '.</p>';

			if(strcasecmp($sStatus, 'SUCCESS') === 0) // Indien SUCCESS, worden ook enkele bankgegevens van de bezoeker meegegeven
			{
				echo '<p><b>Uw bankrekening gegevens</b><br>Rekeningnummer: ' . $oStatusRequest->getAccountNumber() . '<br>T.n.v.: ' . $oStatusRequest->getAccountName() . '<br>Te: ' . $oStatusRequest->getAccountCity() . '</p>';
			}
		}
		else
		{
			// Je kunt $oStatusRequest->getErrors() gebruiken om de lijst met opgetreden fouten op te vragen.
			print_r($oStatusRequest->getErrors());
		}
	}

?>
	</body>
</html>
[/code]