/// <summary>
		/// Adds statuses and other stuff to look like a payment has been processed correctly
		/// </summary>
		/// <param name="payment">Electronic payment to be spoofed</param>
		protected void ProcessTestPayment(IElectronicPayment payment) {

			switch (_provider.Mode) {

				default:
					return; //Nothing to do here

				case TransactionMode.AlwaysPass:
				case TransactionMode.Test:
					payment.TransactionStatus = PaymentStatus.Approved;
					break;

				case TransactionMode.AlwaysFail:
					payment.TransactionStatus = PaymentStatus.Declined;
					break;

				case TransactionMode.Random:
					Random r = new Random(DateTime.Now.Millisecond);
					payment.TransactionStatus = (r.Next(1) > 0.5) ? PaymentStatus.Approved : PaymentStatus.Declined;
					break;
			}

			//Add a fake transaction status if it was a success and this isn't live
			if (payment.TransactionStatus == PaymentStatus.Approved || payment.TransactionStatus == PaymentStatus.Referred) {
				payment.TransactionReference = "TEST-" + StringUtils.GenerateRandomText(16, "ABCDEFGHJKLMNPRSTVWXY0123456789");
			}

			//Standard response logging
			LogResponse(payment);
		}
		public override void RequestPostAuthPayment(IElectronicPayment payment) {
			if (_provider.Mode == TransactionMode.Production) {
				_provider.RequestPostAuthPayment(payment);
			} else {
				ProcessTestPayment(payment);
			}
		}
		public void PopulatePayment(IElectronicPayment payment, IBasket order, ITextTranslator translator) {

			BasketDecorator basket = new BasketDecorator(order);

			payment.LocalRequestReference = basket.OrderHeader.OrderHeaderID.ToString();
			payment.Description = string.Format(translator.GetText("web_store_purchase{0}"), payment.LocalRequestReference);
			payment.PaymentAmount = basket.GrandTotal;
			payment.PaymentDate = DateTime.Now;

            IUserDetails userDetails = (order.UserDetails != null) ? new UserDecorator(order.UserDetails) : order.AltUserDetails;

            //payment.UserInfo.UserDetails. = userDetails.FirstName + " " + userDetails.LastName; -- Is this needed?
            if(payment.UserInfo.UserDetails == null){
                payment.UserInfo.UserDetails = userDetails;
            }

			IAddress invoiceAddress = basket.OrderHeader.InvoiceAddress; 

			payment.UserInfo.UserAddress = invoiceAddress;

			if (invoiceAddress.AddressLine3 != null && invoiceAddress.AddressLine3.Length > 0) {
				payment.UserInfo.UserAddress.AddressLine2 = invoiceAddress.AddressLine2 + ", " + invoiceAddress.AddressLine3;
			} else {
				payment.UserInfo.UserAddress.AddressLine2 = invoiceAddress.AddressLine2;
			}

			payment.UserInfo.UserAddress.City = invoiceAddress.City;
			payment.UserInfo.UserAddress.Region = invoiceAddress.Region;
			payment.UserInfo.UserAddress.Postcode = invoiceAddress.Postcode;
			
			ITextTranslator ccTrans = TranslatorUtils.GetTextTranslator(typeof(CountryCode), translator.CultureCode);
			payment.UserInfo.UserAddress.CountryCode = invoiceAddress.CountryCode;
		}
		protected virtual void ProcessRequest(IElectronicPayment payment) {

			payment.PaymentDate = DateTime.Now;

			switch (Mode) {
				case TransactionMode.Production:
					throw new NotSupportedException("Cannot simulate live processing");
				case TransactionMode.AlwaysPass:
				case TransactionMode.Test:
					payment.TransactionStatus = PaymentStatus.Approved;
					break;
				case TransactionMode.AlwaysFail:
					payment.TransactionStatus = PaymentStatus.Declined;
					break;
				case TransactionMode.Random:
				default:
					payment.TransactionStatus = GetRandomStatus();
					break;
			}

			//Record this request
			LogRequest(payment);

			if ((payment.TransactionStatus == PaymentStatus.Approved || payment.TransactionStatus == PaymentStatus.Referred) 
				&& payment.TransactionReference.Length == 0) {

				//Make up some stuff
				payment.TransactionReference = "TEST-" + StringUtils.GenerateRandomText(16, "0123456789abcdef") + "-TEST";
				payment.AuthorisationCode = "TEST-" + StringUtils.GenerateRandomText(8, "0123456789abcdef") + "-TEST";
			}
		}
		protected override string RenderFormHiddenValues(IElectronicPayment payment, PaymentRequestTypes paymentType) {

			FuturePayElectronicPayment fPayment = payment as FuturePayElectronicPayment;

			StringBuilder html = new StringBuilder();

			html.Append(base.RenderFormHiddenValues(payment, paymentType));

			switch (paymentType) {
				case PaymentRequestTypes.ImmediatePayment:
				case PaymentRequestTypes.ReservePayment:

					html.Append("<!-- Start FuturePay Fields -->\r\n");
						
					html.Append("<input type=\"hidden\" name=\"futurePayType\" value=\"regular\">\r\n");

					if (fPayment.StartDate > DateTime.Now) {
						html.Append("<input type=\"hidden\" name=\"startDate\" value=\"" + fPayment.StartDate.ToString("yyyy-MM-dd") + "\">\r\n");
					} else {
						html.Append("<input type=\"hidden\" name=\"startDelayUnit\" value=\"" + fPayment.StartDelayUnit + "\">\r\n");
						html.Append("<input type=\"hidden\" name=\"startDelayMult\" value=\"" + fPayment.StartDelayMult + "\">\r\n");
					}

					html.Append("<input type=\"hidden\" name=\"noOfPayments\" value=\"" + fPayment.NumberOfPayments + "\">\r\n");

					if (fPayment.NumberOfPayments != 1) {
						html.Append("<input type=\"hidden\" name=\"intervalUnit\" value=\"" + fPayment.IntervalUnit + "\">\r\n");
						html.Append("<input type=\"hidden\" name=\"intervalMult\" value=\"" + fPayment.IntervalMult + "\">\r\n");
					}

					if (fPayment.InitialAmount != null && fPayment.InitialAmount.Amount > 0) {
						html.Append("<input type=\"hidden\" name=\"initialAmount\" value=\"" + fPayment.InitialAmount.Amount + "\">\r\n");
					}

					if (fPayment.NormalAmount != null && fPayment.NormalAmount.Amount > 0) {
						html.Append("<input type=\"hidden\" name=\"normalAmount\" value=\"" + fPayment.NormalAmount.Amount + "\">\r\n");
					}

					html.Append("<input type=\"hidden\" name=\"option\" value=\"" + fPayment.AgreementOption + "\">\r\n");

					html.Append("<!-- End FuturePay Fields -->\r\n");

					break;
				default:
					throw new InvalidOperationException("Payment request type not supported [" + paymentType + "]");
			}

			return html.ToString();

		}
		protected override string RenderFormHiddenValues(IElectronicPayment payment, PaymentRequestTypes paymentType) {

			StringBuilder html = new StringBuilder();

			html.Append("<input type=\"hidden\" name=\"MFCIsapiCommand\" value=\"Orders\">");
			html.Append("<input type=\"hidden\" name=\"LOGIN\" value=\"" + MerchantID + "\">");
			html.Append("<input type=\"hidden\" name=\"PARTNER\" value=\"" + "wfb\">");
    
			html.Append("<input type=\"hidden\" name=\"AMOUNT\" value=\"" + payment.PaymentAmount.Amount + "\">");
			html.Append("<input type=\"hidden\" name=\"TYPE\" value=\"A\">");
			html.Append("<input type=\"hidden\" name=\"ECHODATA\" value=\"True\">");

			string strCustIDConcat;
			string strSep = "|";
			strCustIDConcat = payment.UserInfo.AccountID + strSep
                + payment.UserInfo.UserDetails.FirstName + " " + payment.UserInfo.UserDetails.LastName + strSep 
				+ payment.LocalRequestReference + strSep 
				+ payment.CustomValues["strSalesOrderNumber"];
 
			html.Append("<input type=\"hidden\" name=\"CUSTID\" value=\"" + strCustIDConcat + "\">");
			html.Append("<input type=\"hidden\" name=\"METHOD\" value=\"CC\">");                                  
    
			html.Append("<input type=\"hidden\" name=\"EMAIL\" value=\"" + payment.UserInfo.UserDetails.EmailAddress + "\">");
            html.Append("<input type=\"hidden\" name=\"NAME\" value=\"" + payment.UserInfo.UserDetails.FirstName + " " + payment.UserInfo.UserDetails.LastName + "\">");
			html.Append("<input type=\"hidden\" name=\"ADDRESS\" value=\"" + payment.UserInfo.UserAddress.AddressLine1 + "\">");
			html.Append("<input type=\"hidden\" name=\"CITY\" value=\"" + payment.UserInfo.UserAddress.City + "\">");                  
			html.Append("<input type=\"hidden\" name=\"ZIP\" value=\"" + payment.UserInfo.UserAddress.Postcode + "\">");
			html.Append("<input type=\"hidden\" name=\"COUNTRY\" value=\"" + payment.UserInfo.UserAddress.CountryCode + "\">");   
    
			html.Append("<input type=\"hidden\" name=\"M_paymentType\" value=\"" + payment.CustomValues["strPaymentType"] + "\">");
			html.Append("<input type=\"hidden\" name=\"USER1\" value=\"" + payment.CustomValues["strPONumber"] + "\">");                             
			html.Append("<input type=\"hidden\" name=\"USER2\" value=\"" + payment.CustomValues["strText"] + "\">");
			html.Append("<input type=\"hidden\" name=\"USER3\" value=\"" + payment.UserInfo.UserAddress.AddressLine1 + "\">");
			html.Append("<input type=\"hidden\" name=\"USER4\" value=\"" + payment.UserInfo.UserAddress.AddressLine2 + "\">");
			html.Append("<input type=\"hidden\" name=\"USER5\" value=\"" + payment.UserInfo.UserAddress.City + "\">");
			html.Append("<input type=\"hidden\" name=\"USER6\" value=\"" + payment.UserInfo.UserAddress.Region + "\">");
			html.Append("<input type=\"hidden\" name=\"USER7\" value=\"" + payment.UserInfo.UserDetails.TelephoneNumber + "\">");
			html.Append("<input type=\"hidden\" name=\"USER8\" value=\"" + payment.UserInfo.UserDetails.FaxNumber + "\">");                          
			html.Append("<input type=\"hidden\" name=\"USER9\" value=\"" + payment.CustomValues["strdispatchLabel"] + "\">");
			html.Append("<input type=\"hidden\" name=\"USER10\" value=\"" + payment.CustomValues["strdispatchAccount"] + "\">"); 

			return html.ToString();

		}
        public BasketDecorator ProcessReceivedPayment(IElectronicPayment ccPayment, ITextTranslator translator) {

			try {

				long orderID = Int64.Parse(ccPayment.LocalRequestReference);
				IBasket basket = _dao.FindOrder(orderID);
				BasketDecorator order;

				if (basket != null) {
					order = new BasketDecorator(basket);
				} else {
					throw new InvalidOperationException("Could not find order for local ccPayment ref [" + ccPayment.LocalRequestReference + "]");
				}

				//Make a record in the database about this ccPayment
				RecordPayment(basket, ccPayment);

				//Make sure this isn't already purchased
				if (order.IsPurchased) {
					throw new InvalidOperationException("Paid for order [" + order.OrderHeader.OrderHeaderID + "] more than once");
				}

				//Make sure the amount is correct (assume the same currency)
				if (order.GrandTotal.Amount != (decimal) ccPayment.PaymentAmount.Amount) {
					throw new InvalidOperationException("Invalid ccPayment amount - expected " + order.GrandTotal.Amount
						+ ", recieved " + ccPayment.PaymentAmount.Amount + " " 
						+ ccPayment.PaymentAmount.CurrencyCode);
				}

				//Either PO or successful credit card
				if (order.OrderHeader.PaymentMethod == PaymentMethodType.PurchaseOrderInvoice 
					|| ccPayment != null && (ccPayment.TransactionStatus == PaymentStatus.Approved || ccPayment.TransactionStatus == PaymentStatus.Referred)) {

					//This is a purchase order, or a direct credit card order
                    return order;
				}

			} catch (Exception f) {
				LogManager.GetLogger(GetType()).Error(f);
			}

            return null;
		}
		public override void RequestAuthPayment(IElectronicPayment payment) {

			CreditCardPayment ccPayment = payment as CreditCardPayment;

			if (ccPayment == null) {
				
				if (payment != null) {
					Logger.Error("Payment is NOT a credit card payment");
					payment.TransactionStatus = PaymentStatus.NotSubmitted;
				} else {
					Logger.Error("Null payment supplied");
				}

				//Cannot continue
				return;
			}

			//Record this request
			LogRequest(payment);

			//This is standard
			string data = GetAuthPostData(ccPayment);
			string response = HttpUtils.ReadHtmlPage(PaymentUrl, "POST", data);

			if (response != null && response.Length > 0) {

				Logger.Info("Received response: " + response);
				NameValueCollection responseValues = GetResponseValues(response);

				if (responseValues[RESPONSE_KEY_STATUS] == STATUS_SUCCESS) {
					payment.TransactionStatus = PaymentStatus.Approved;
					payment.TransactionReference = responseValues[RESPONSE_KEY_TRANSACTION_ID];
				} else {
					payment.TransactionStatus = PaymentStatus.Declined;
				}

				//It isn't provider explicitly
				payment.PaymentDate = DateTime.Now;
			}

			//Standard response logging
			LogResponse(payment);
		}
		public override void RequestAuthPayment(IElectronicPayment payment) {
			RequestPayment(payment, EpdqCpiPaymentProvider.BANK_CHARGE_TYPE_IMMEDIATE_SALE);
		}
		public override void RequestPreAuthPayment(IElectronicPayment payment) {
			RequestPayment(payment, EpdqCpiPaymentProvider.BANK_CHARGE_TYPE_RESERVE_PAYMENT);
		}
		public override void RequestAuthPayment(IElectronicPayment payment) {
			RequestPayment(payment, VeriSignPayflowProPaymentProvider.BANK_CHARGE_TYPE_IMMEDIATE_SALE);
		}
		public override void RequestSettlePayment(IElectronicPayment payment) {
			ProcessRequest(payment);
		}
		public virtual void RequestRefund(IElectronicPayment payment) {
			throw new NotImplementedException("Not yet implemented");
		}
		private XmlDocument CreatePaymentXml(IElectronicPayment payment, string transactionType) {

			CreditCardPayment ccPayment = (CreditCardPayment) payment;
			XmlNode orderFormDoc = CreateOrderFormDoc();

			AppendCcApiStringField(ref orderFormDoc, XML_TAG_ID, payment.LocalRequestReference);
			AppendCcApiStringField(ref orderFormDoc, XML_TAG_PAYMENT_MODE, PaymentMode);
			AppendCcApiStringField(ref orderFormDoc, XML_TAG_COMMENTS, Comments);

			//Consumer
			XmlNode consumer = AppendCcApiRecord(ref orderFormDoc, XML_TAG_CONSUMER);
			AppendCcApiStringField(ref consumer, XML_TAG_EMAIL, ccPayment.UserInfo.UserDetails.EmailAddress);
			XmlNode paymentMech = AppendCcApiRecord(ref consumer, XML_TAG_PAYMENT_MECHANISM);

			//Address verification information
			if (payment.UserInfo.UserAddress.AddressLine1.Length > 0 && payment.UserInfo.UserAddress.Postcode.Length > 0) {
				AppendAvsElements(ref consumer, payment);
			}

			//Credit card
			XmlNode creditCard = AppendCcApiRecord(ref paymentMech, XML_TAG_CREDIT_CARD);
			AppendCcApiStringField(ref creditCard, XML_TAG_CREDIT_CARD_NUMBER, ccPayment.CardNumber);
			
			AppendCcApiStartDateField(ref creditCard, 
				XML_TAG_CREDIT_CARD_START_DATE, 
				ccPayment.CardValidFromMonth, 
				ccPayment.CardValidFromYear, 
				ccPayment.PaymentAmount.Currency.CurrencyCodeNumeric);

			AppendCcApiExpirationDateField(ref creditCard, 
				XML_TAG_CREDIT_CARD_EXPIRES, 
				ccPayment.CardExpiresEndMonth, 
				ccPayment.CardExpiresEndYear, 
				ccPayment.PaymentAmount.Currency.CurrencyCodeNumeric);

			if (ccPayment.CardIssueNumber.Length > 0) {
				AppendCcApiStringField(ref creditCard, XML_TAG_CREDIT_CARD_ISSUE_NUMBER, ccPayment.CardIssueNumber);
			}

			//CVM Stuff
			if (ccPayment.CardCvmNumber.Length > 0) {
				AppendCcApiStringField(ref creditCard, XML_TAG_CVM_VALUE, ccPayment.CardCvmNumber);
				AppendCcApiStringField(ref creditCard, XML_TAG_CVM_INDICATOR, "" + CVM_VALUE_SUBMITTED_BY_STORE);
			}
			
			//Transaction
			XmlNode transaction = AppendCcApiRecord(ref orderFormDoc, XML_TAG_TRANSACTION);
			AppendCcApiStringField(ref transaction, XML_TAG_TRANSACTION_TYPE, transactionType);

			//Totals
			XmlNode currentTotals = AppendCcApiRecord(ref transaction, XML_TAG_CURRENT_TOTALS);
			XmlNode totals = AppendCcApiRecord(ref currentTotals, XML_TAG_TOTALS);

			AppendCcApiMoneyField(ref totals, XML_TAG_TOTAL, ccPayment.PaymentAmount);

			if (ccPayment.Basket != null) {

                BasketDecorator basket = new BasketDecorator(ccPayment.Basket);
				
				AppendCcApiMoneyField(ref totals, XML_TAG_SHIPPING_CHARGE, basket.DeliveryPrice);
				AppendCcApiMoneyField(ref totals, XML_TAG_VAT, basket.TaxPrice);

				AppendOrderItems(ref orderFormDoc, ccPayment.Basket);
			}

			return orderFormDoc.OwnerDocument;
		}
		protected override void CheckRequestParameters(IElectronicPayment payment, PaymentRequestTypes paymentType) {

			if (InstallationID == null || InstallationID.Length == 0) {
				throw new InvalidOperationException("Invalid Installation ID");
			}

			if (payment.LocalRequestReference == null || payment.LocalRequestReference.Length == 0) {
				throw new InvalidOperationException("Invalid Local Reference");
			}

			if (payment.PaymentAmount == null || payment.PaymentAmount.Amount < 0) {
				throw new InvalidOperationException("Invalid Payment Amount");
			}
		}
		public override void RequestRefund(IElectronicPayment payment, Cuyahoga.Modules.ECommerce.Util.Money refundAmount) {
			_provider.RequestRefund(payment, refundAmount);
		}
		public override void RequestVoidPayment(IElectronicPayment payment) {
			_provider.RequestVoidPayment(payment);
		}
		public override void RequestRefund(IElectronicPayment payment) {
			_provider.RequestRefund(payment);
		}
		protected virtual void LogResponse(IElectronicPayment payment) {
			LogResponse(payment, null);
		}
		protected override string RenderFormHiddenValues(IElectronicPayment payment, PaymentRequestTypes paymentType) {

			StringBuilder html = new StringBuilder();

			switch (paymentType) {
				case PaymentRequestTypes.ImmediatePayment:
				case PaymentRequestTypes.ReservePayment:

					string authMode = AUTH_MODE_AUTH;
					if (paymentType == PaymentRequestTypes.ReservePayment) {
						authMode = AUTH_MODE_PREAUTH;
					}

					//obligatory fields
					html.Append("<input type=\"hidden\" name=\"instId\" value=\"" + InstallationID + "\">\n");
					html.Append("<input type=\"hidden\" name=\"cartId\" value=\"" + payment.LocalRequestReference + "\">\n");
					html.Append("<input type=\"hidden\" name=\"amount\" value=\"" + payment.PaymentAmount.Amount + "\">\n");
					html.Append("<input type=\"hidden\" name=\"currency\" value=\"" + payment.PaymentAmount.CurrencyCode + "\">\n");
					html.Append("<input type=\"hidden\" name=\"desc\" value=\"" + payment.Description + "\">\n");

					//Not strictly required
					html.Append("<input type=\"hidden\" name=\"authMode\" value=\"" + authMode + "\">\n");

					//Optional stuff
					if (Mode != TransactionMode.Production) {
						html.Append("<input type=\"hidden\" name=\"testMode\" value=\"" + ((int) WorldPayTestMode) + "\">\n");
					}

					//User stuff
					if (payment.UserInfo != null) {
                        html.Append("<input type=\"hidden\" name=\"name\" value=\"" + payment.UserInfo.UserDetails.FirstName + " " + payment.UserInfo.UserDetails.LastName + "\">\n");
						html.Append("<input type=\"hidden\" name=\"address\" value=\"" + payment.UserInfo.UserAddress.AddressLine1 + "\">\n");
						html.Append("<input type=\"hidden\" name=\"postcode\" value=\"" + payment.UserInfo.UserAddress.Postcode + "\">\n");
						html.Append("<input type=\"hidden\" name=\"country\" value=\"" + payment.UserInfo.UserAddress.CountryCode + "\">\n");
						html.Append("<input type=\"hidden\" name=\"tel\" value=\"" + payment.UserInfo.UserDetails.TelephoneNumber + "\">\n");
						html.Append("<input type=\"hidden\" name=\"email\" value=\"" + payment.UserInfo.UserDetails.EmailAddress + "\">\n");
					}

					//Custom values
					if (payment.CustomValues.Count > 0) {
						foreach (object key in payment.CustomValues.Keys) {
							html.Append("<input type=\"hidden\" name=\"M_" + key.ToString().Replace(" ", "-") + "\" value=\"" + payment.CustomValues[key].ToString() + "\">");
						}
					}

					break;
				default:
					throw new InvalidOperationException("Payment request type not supported [" + paymentType + "]");
			}

			return html.ToString();
		}
		private void RequestPayment(IElectronicPayment payment, string paymentType) {

			XmlDocument requestDoc = CreatePaymentXml(payment, paymentType);

			//Record this request
			LogRequest(payment);

			LogXml("Sent request", requestDoc.DocumentElement.OuterXml);
			string response = HttpUtils.ReadHtmlPage(PaymentPageUrl, "POST", PAYMENT_POSTED_FIELD_NAME + "=" + requestDoc.DocumentElement.OuterXml);
			LogXml("Received response", response);

			//Doesn't seem to like header. Hope this isn't a problem
			XMLObject responseXml = new XMLObject(XMLUtils.StripXmlHeader(response));

			string authCode = responseXml["//" + XML_TAG_TRANSACTION + "/" + XML_TAG_AUTH_CODE];
			int ccErrCode = responseXml.GetInt32Value("//" + XML_TAG_TRANSACTION + "/" 
				+ XML_TAG_CARD_PROCESS_RESPONSE + "/" + XML_TAG_CC_ERROR_CODE);

			string transactionReference = responseXml["//" + XML_TAG_TRANSACTION + "/" + XML_TAG_ID];

			payment.PaymentDate = DateTime.Now;
			payment.TransactionStatus = TranslatePaymentStatusCode(ccErrCode);
			payment.TransactionReference = transactionReference;
			payment.AuthorisationCode = authCode;
		}
		public override void RequestPostAuthPayment(IElectronicPayment payment) {
			ProcessRequest(payment);
		}
		protected void CheckRequestParameters(IElectronicPayment payment) {

			CreditCardPayment ccPayment = (CreditCardPayment) payment;
			ccPayment.CheckCardDetails();

		}
		private void SetPaymentDate(System.Web.HttpRequest postBackData, IElectronicPayment payment) {

			//transTime is milliseconds since 1970
			try {
				double transTime = Double.Parse(postBackData["transTime"]);
				DateTime transDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
				payment.PaymentDate = transDate.AddMilliseconds(transTime);
			} catch {
				payment.PaymentDate = DateTime.Now;
			}
		}
		private void AppendAvsElements(ref XmlNode consumerNode, IElectronicPayment payment) {

			XmlNode billTo = AppendCcApiRecord(ref consumerNode, XML_TAG_BILL_TO);
			XmlNode location = AppendCcApiRecord(ref billTo, XML_TAG_LOCATION);
			XmlNode address = AppendCcApiRecord(ref location, XML_TAG_ADDRESS);

			AppendCcApiStringField(ref address, XML_TAG_STREET1, payment.UserInfo.UserAddress.AddressLine1);
			AppendCcApiStringField(ref address, XML_TAG_POST_CODE, payment.UserInfo.UserAddress.Postcode);
		}
		private string CreatePaymentString(IElectronicPayment payment, string transactionType) {

			CreditCardPayment ccPayment = (CreditCardPayment) payment;
			StringBuilder postData = new StringBuilder();
			string expDate = FormatDate(ccPayment.CardExpiresEndMonth, ccPayment.CardExpiresEndYear);
    
			postData.Append("TENDER=" + PARM_TENDER_VALUE);
			postData.Append("&TRXTYPE=" + transactionType);
			postData.Append("&PARTNER=" + Partner);
			postData.Append("&USER="******"&PWD=" + Password);
			postData.Append("&VENDOR=" + Vendor);
			postData.Append("&ACCT=" + ccPayment.CardNumber);
			postData.Append("&AMT=" + payment.PaymentAmount.Amount);
			postData.Append("&EXPDATE=" + expDate);
			postData.Append("&COMMENT1=" + Comments);
            postData.Append("&STREET=" + ccPayment.UserInfo.UserAddress.AddressLine1);
            postData.Append("&ZIPCODE=" + ccPayment.UserInfo.UserAddress.Postcode);

			return postData.ToString();
		}
		public override void RequestRefund(IElectronicPayment payment, Money refundAmount) {
			ProcessRequest(payment);
		}
		public override void RequestPreAuthPayment(IElectronicPayment payment) {
			RequestPayment(payment, VeriSignPayflowProPaymentProvider.BANK_CHARGE_TYPE_RESERVE_PAYMENT);
		}
		private void RequestPayment(IElectronicPayment payment, string paymentType) {

			//Record this request
			LogRequest(payment);

			VeriSignPayflowProPaymentProvider.PayflowProComWrapper prov = new VeriSignPayflowProPaymentProvider.PayflowProComWrapper(Logger);
			int context = prov.CreateContext(IpAddress, PortNumber, 30);
			
			string requestString = CreatePaymentString(payment, paymentType);
			
			NameValueCollection response = prov.SubmitTransaction(context, requestString);
			
			prov.DestroyContext(context);
			prov.Dispose();

			int responseCode = Int32.Parse(response["RESULT"]);

			if (responseCode >= 0) {

				payment.TransactionStatus = TranslatePaymentStatusCode(responseCode);
				payment.TransactionReference = response["PNREF"];

				//Might not get a transaction reference, especially if it fails
				if (payment.TransactionReference == null) {
					payment.TransactionReference = "";
				}
			} else {
				string errorMessage = response["RESPMSG"];
				Logger.Error("Error " + responseCode + " " + errorMessage);
			}
		}
		protected virtual void LogResponse(IElectronicPayment payment, string extraInfo) {

			string logMessage = "";

			try {
				logMessage = "Received payment" 
					+ " [" + Mode + "]"
					+ ", Date [" + payment.PaymentDate 
					+ "], OrderNum [" + payment.LocalRequestReference
					+ "], TransactionRef [" + payment.TransactionReference
					+ "], Total[" + payment.PaymentAmount.Amount + " " + payment.PaymentAmount.CurrencyCode
					+ "], StatusCode [" + payment.TransactionStatus + "]";

			} catch {
				logMessage = "Received response" 
					+ " [" + Mode + "]"
					+ ", Date [" + DateTime.Now 
					+ "]";
			}

			if (extraInfo != null && extraInfo.Length > 0) {
				logMessage += ", " + extraInfo;
			}

			Logger.Info(logMessage);
		}