/// <summary>
        /// Checks if Xml contains an ErrorRes element, if so deserialize the ErrorRes, wrap it in an iDealException and throw.
        /// </summary>
        /// <param name="xml">Xml to check.</param>
        /// <param name="consumerMessage">Consumer message to use if errorRes.Error.consumerMessage is empty or null.</param>
        private static void CheckError(string xml, string consumerMessage)
        {
            if (xml.Contains("<AcquirerErrorRes"))
            {
                AcquirerErrorRes errorRes = (AcquirerErrorRes)SerializationHelper.DeserializeObject <AcquirerErrorRes>(xml);

                // Set consumerMessage if it has not been set by the iDEAL service
                if (String.IsNullOrEmpty(errorRes.Error.consumerMessage))
                {
                    errorRes.Error.consumerMessage = consumerMessage;
                }

                throw new IDealException(errorRes);
            }
        }
        /// <summary>
        /// Requests a transaction.
        /// </summary>
        /// <param name="transaction"><see cref="Transaction" /> to send.</param>
        /// <returns><see cref="Transaction" /> with added transaction ID and Issuer authentication URL.</returns>
        /// <exception cref="XmlSchemaValidationException">Request Xml does not comply with schema.</exception>
        /// <exception cref="IDealException">Respons from iDEAL contains an error.</exception>
        /// <exception cref="ConfigurationErrorsException">Errors in configuration file.</exception>
        /// <exception cref="UriFormatException">Returned issuer authentication Url is in invalid format.</exception>
        /// <exception cref="WebException">Error getting reply from acquirer.</exception>
        /// <exception cref="CryptographicException">Error using client certificate.</exception>
        public Transaction RequestTransaction(Transaction transaction)
        {
            if (traceSwitch.TraceInfo)
            {
                TraceLine("Start of RequestTransaction()");
            }
            if (traceSwitch.TraceVerbose)
            {
                TraceLine(Format("Parameters: transaction: {0}", transaction == null ? "NULL" : transaction.ToString()));
            }

            // Check input
            CheckMandatory("transaction", transaction);
            CheckMandatory("transaction.Amount", transaction.Amount);
            CheckMandatory("transaction.PurchaseId", transaction.PurchaseId);
            CheckMandatory("transaction.Description", transaction.Description);
            CheckMandatory("transaction.EntranceCode", transaction.EntranceCode);

            // Prepare the transaction request
            AcquirerTrxReq request = CreateRequest <AcquirerTrxReq>();

            request.Merchant = CreateMerchant <AcquirerTrxReqMerchant>();

            request.Transaction = new AcquirerTrxReqTransaction();

            request.Transaction.amount = transaction.Amount;

            request.Transaction.currency         = merchantConfig.currency;
            request.Transaction.description      = transaction.Description;
            request.Transaction.entranceCode     = transaction.EntranceCode;
            request.Transaction.expirationPeriod = merchantConfig.ExpirationPeriod;

            request.Transaction.language = merchantConfig.language;

            request.Transaction.purchaseID = transaction.PurchaseId;

            request.Issuer          = new AcquirerTrxReqIssuer();
            request.Issuer.issuerID = transaction.IssuerId;

            // Serialize the transaction request to an XML string
            string xmlRequest = SerializationHelper.SerializeObject <AcquirerTrxReq>(request);

            var xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(xmlRequest);

            var signatureElement = XmlSignature.XmlSignature.Sign(ref xmlDoc, GetMerchantRSACryptoServiceProvider(), merchantConfig.ClientCertificate.Thumbprint);

            xmlRequest = xmlDoc.OuterXml;

            // Validate the request before sending it to the service
            ValidateXML(xmlRequest);

            // Send request / get respons
            string xmlRespons = GetReplyFromAcquirer(xmlRequest, merchantConfig.acquirerUrlTRA);

            // Validate respons
            ValidateXML(xmlRespons);

            if (!XmlSignature.XmlSignature.CheckSignature(xmlRespons, (RSA)merchantConfig.aquirerCertificate.PublicKey.Key))
            {
                Trace.WriteLine("Xml response was not well signed " + xmlRespons);
                throw new ArgumentException("Response from server is not well signed");
            }

            if (traceSwitch.TraceInfo)
            {
                TraceLine("Response from RequestTransaction() was : " + xmlRespons);
            }

            // Check respons for errors
            CheckError(xmlRespons, Resources.iDealUnavailable);

            AcquirerTrxRes respons = (AcquirerTrxRes)SerializationHelper.DeserializeObject <AcquirerTrxRes>(xmlRespons);

            transaction.Id = respons.Transaction.transactionID;
            // added in v3.3.x
            transaction.TransactionCreateDateTimestamp = respons.Transaction.transactionCreateDateTimestamp;

            string issuerAuthenticationURL = respons.Issuer.issuerAuthenticationURL;

            Uri outUri;

            if (!Uri.TryCreate(issuerAuthenticationURL, UriKind.Absolute, out outUri))
            {
                throw new UriFormatException("IssuerAuthenticationUrl is not in correct format.");
            }
            transaction.IssuerAuthenticationUrl = outUri;

            transaction.AcquirerId = respons.Acquirer.acquirerID;

            if (traceSwitch.TraceInfo)
            {
                TraceLine("End of RequestTransaction()");
            }
            if (traceSwitch.TraceVerbose)
            {
                TraceLine(Format("Returnvalue: {0}", transaction.ToString()));
            }

            return(transaction);
        }
        /// <summary>
        /// Requests the status of a transaction.
        /// </summary>
        /// <param name="transactionId">Id of the <see cref="Transaction" /> to check status for.</param>
        /// <returns><see cref="Transaction" /> holding status for the transaction.</returns>
        /// <exception cref="XmlSchemaValidationException">Request Xml does not comply with schema.</exception>
        /// <exception cref="IDealException">Respons from iDEAL contains an error.</exception>
        /// <exception cref="ConfigurationErrorsException">Errors in configuration file.</exception>
        /// <exception cref="WebException">Error getting reply from acquirer.</exception>
        /// <exception cref="CryptographicException">Error using client certificate.</exception>
        public Transaction RequestTransactionStatus(string transactionId)
        {
            if (traceSwitch.TraceInfo)
            {
                TraceLine("Start of RequestTransactionStatus()");
            }
            if (traceSwitch.TraceVerbose)
            {
                TraceLine(Format("Parameters: transactionId: {0}", transactionId == null ? "NULL" : transactionId));
            }

            // Check input
            CheckMandatory("transactionId", transactionId);

            AcquirerStatusReq request = CreateRequest <AcquirerStatusReq>();

            request.Merchant = CreateMerchant <AcquirerStatusReqMerchant>();

            request.Transaction = new AcquirerStatusReqTransaction();

            request.Transaction.transactionID = transactionId;

            // Serialize the request to an XML string
            string xmlRequest = SerializationHelper.SerializeObject <AcquirerStatusReq>(request);

            var xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(xmlRequest);

            var signatureElement = XmlSignature.XmlSignature.Sign(ref xmlDoc, GetMerchantRSACryptoServiceProvider(), merchantConfig.ClientCertificate.Thumbprint);

            xmlRequest = xmlDoc.OuterXml;

            // Validate the request before sending it to the service
            ValidateXML(xmlRequest);

            // Send request / get respons
            string xmlResponse = GetReplyFromAcquirer(xmlRequest, merchantConfig.acquirerUrlSTA);

            // Validate respons
            ValidateXML(xmlResponse);

            if (!XmlSignature.XmlSignature.CheckSignature(xmlResponse, (RSA)merchantConfig.aquirerCertificate.PublicKey.Key))
            {
                Trace.WriteLine("Xml response was not well signed " + xmlResponse);
                throw new ArgumentException("Response from server is not well signed");
            }

            if (traceSwitch.TraceInfo)
            {
                TraceLine("Response from RequestTransactionStatus() was : " + xmlResponse);
            }

            // Check respons for errors
            CheckError(xmlResponse, Resources.iDealStatusCheckFailed);

            AcquirerStatusRes response = (AcquirerStatusRes)SerializationHelper.DeserializeObject <AcquirerStatusRes>(xmlResponse);

            Transaction transaction = new Transaction();

            transaction.Id                  = response.Transaction.transactionID;
            transaction.AcquirerId          = response.Acquirer.acquirerID;
            transaction.Status              = (Transaction.TransactionStatus)Enum.Parse(typeof(Transaction.TransactionStatus), response.Transaction.status);
            transaction.ConsumerIBAN        = response.Transaction.consumerIBAN;
            transaction.ConsumerBIC         = response.Transaction.consumerBIC;
            transaction.StatusDateTimestamp = response.Transaction.statusDateTimestamp;
            transaction.ConsumerName        = response.Transaction.consumerName;
            transaction.SignatureValue      = response.Signature.SignatureValue.Value;
            transaction.Amount              = response.Transaction.amount;
            transaction.Currency            = response.Transaction.currency;

            if (traceSwitch.TraceInfo)
            {
                TraceLine("End of RequestTransactionStatus()");
            }
            if (traceSwitch.TraceVerbose)
            {
                TraceLine(Format("Returnvalue: {0}", transaction.ToString()));
            }

            return(transaction);
        }
        /// <summary>
        /// Retrieves both the short list and the long list of issuers.
        /// </summary>
        /// <returns><see cref="Issuers" /> containing the long list and short list of issuers, and the datetime stamp of the last change to the lists.</returns>
        /// <exception cref="XmlSchemaValidationException">Request Xml does not comply with schema.</exception>
        /// <exception cref="IDealException">Respons from iDEAL contains an error.</exception>
        /// <exception cref="ConfigurationErrorsException">Errors in configuration file.</exception>
        /// <exception cref="WebException">Error getting reply from acquirer.</exception>
        /// <exception cref="CryptographicException">Error using client certificate.</exception>
        public Issuers GetIssuerList()
        {
            if (traceSwitch.TraceInfo)
            {
                TraceLine("Start of GetIssuerList()");
            }

            DirectoryReq request = CreateRequest <DirectoryReq>();

            request.Merchant = CreateMerchant <DirectoryReqMerchant>();

            // Serialize the request to an XML string
            string xmlRequest = SerializationHelper.SerializeObject <DirectoryReq>(request);

            var xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(xmlRequest);

            var signatureElement = XmlSignature.XmlSignature.Sign(ref xmlDoc, GetMerchantRSACryptoServiceProvider(), merchantConfig.ClientCertificate.Thumbprint);

            xmlRequest = xmlDoc.OuterXml;

            // Validate the request before sending it to the service
            ValidateXML(xmlRequest);

            // Send request / get respons
            string xmlResponse = GetReplyFromAcquirer(xmlRequest, merchantConfig.acquirerUrlDIR);

            // Validate respons
            ValidateXML(xmlResponse);

            if (!XmlSignature.XmlSignature.CheckSignature(xmlResponse, (RSA)merchantConfig.aquirerCertificate.PublicKey.Key))
            {
                if (traceSwitch.TraceInfo)
                {
                    TraceLine("Xml response was not well signed " + xmlResponse);
                }
                throw new ArgumentException("Response from server is not well signed");
            }

            if (traceSwitch.TraceInfo)
            {
                TraceLine("Response from get issuer list was : " + xmlResponse);
            }

            // Check respons for errors
            CheckError(xmlResponse, Resources.iDealUnavailable);

            DirectoryRes response = (DirectoryRes)SerializationHelper.DeserializeObject <DirectoryRes>(xmlResponse);

            // Create the return object and initialze it with the iDEAL respons Directory
            var issuers = new Issuers(response.Directory);

            if (traceSwitch.TraceInfo)
            {
                TraceLine("End of GetIssuerList()");
            }
            if (traceSwitch.TraceVerbose)
            {
                TraceLine(Format("Returnvalue: {0}", issuers.ToString()));
            }

            return(issuers);
        }