/// <summary>Attempts to debit the specified amount from the supplied payment card.</summary>
 /// <remarks>Because the SagePay gateway requires a shopping basket, this overload will create
 ///  a simple basket containing a single line item whose description is auto-generated from the 
 /// supplied order details.</remarks>
 public PaymentResponse Purchase(string merchantReference, Money amount, PaymentCard card)
 {
     var data = MakePostData();
     data.Add("TxType", "PAYMENT");
     data.Add("VendorTxCode", merchantReference);
     data.Add("Amount", amount.ToString("0.00"));
     data.Add("Currency", amount.Currency.Iso3LetterCode);
     data.Add("CardHolder", card.CardHolder);
     data.Add("CardNumber", card.CardNumber);
     data.Add("CardType", TranslateCardType(card.CardType));
     data.Add("ExpiryDate", card.ExpiryDate.ToString());
     data.Add("Basket", CreateBasketString(merchantReference, amount));
     data.Add("Description", "DUMMY DESCRIPTION");
     var postData = FormatPostData(data);
     var uri = postUris[this.mode];
     var httpResponse = http.Post(uri, postData);
     var response = this.ParseResponse(httpResponse);
     return (response);
 }
        private string BuildDirectPaymentRequestMessage(PaymentCard card, Money amount, string paymentAction)
        {
            var pairs = new Dictionary<string, string> {
                                                           {"VERSION", this.environment.Version},
                                                           {"SIGNATURE", this.environment.Signature},
                                                           {"USER", this.environment.Username},
                                                           {"PWD", this.environment.Password},
                                                           {"METHOD", "DoDirectPayment"}, //Required
                                                           {"PAYMENTACTION", paymentAction}, //Other option is Authorization. Use when we do Auth and capture.
                                                           {"IPADDRESS", "192.168.1.1"}, //TODO Required for fraud purposes.
                                                           {"AMT", amount.ToString("0.00")},
                                                           {"CREDITCARDTYPE", CardTypeToPayPalCardStringMap[card.CardType]},
                                                           {"ACCT", card.CardNumber},
                                                           {"EXPDATE", card.ExpiryDate.TwoDigitMonth + card.ExpiryDate.Year},
                                                           {"CVV2", card.CV2},
                                                           //TODO billing address data for PayPal.
                                                           {"FIRSTNAME", "Bob"},
                                                           {"LASTNAME", "Le Builder"},
                                                           {"STREET", "1972 Toytown"},
                                                           {"CITY", "London"},
                                                           {"STATE", "London"},
                                                           {"ZIP", "N1 3JS"},
                                                           //TODO check how values for currency relate to PayPal currency codes
                                                           //https://cms.paypal.com/uk/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_country_codes
                                                           {"COUNTRYCODE", "GB"}, //TODO
                                                           {"CURRENCYCODE", amount.Currency.Iso3LetterCode}
                                                       };

            var values =
                pairs.Select(pair => String.Format("{0}={1}", pair.Key, HttpUtility.UrlEncode(pair.Value)));
            return (String.Join("&", values.ToArray()));
        }