internal static string EncodeCredentialsAsQueryString(Credentials credentials)
 {
     QueryStringBuilder builder = new QueryStringBuilder();
     foreach (CredentialsNameValuePair nv in credentials.Attributes)
     {
         builder.Append(nv.Name, nv.Value);
     }
     return builder.ToString();
 }
        /// <summary>
        /// Returns a transaction from a notification code
        /// </summary>
        /// <param name="credentials">PagSeguro credentials</param>
        /// <param name="notificationCode">Transaction notification code</param>
        /// <returns><c cref="T:Uol.PagSeguro.Transaction">Transaction</c></returns>
        public static Transaction CheckTransaction(Credentials credentials, string notificationCode)
        {
            if (credentials == null)
                throw new ArgumentNullException("credentials");
            if (String.IsNullOrEmpty(notificationCode))
                throw new ArgumentNullException("notificationCode");

            UriBuilder uriBuilder = new UriBuilder(PagSeguroConfiguration.NotificationUri);
            StringBuilder pathBuilder = new StringBuilder(uriBuilder.Path);
            pathBuilder.Append('/');
            pathBuilder.Append(HttpUtility.UrlEncode(notificationCode));
            pathBuilder.Append('/');
            uriBuilder.Path = pathBuilder.ToString();
            uriBuilder.Query = ServiceHelper.EncodeCredentialsAsQueryString(credentials);

            WebRequest request = WebRequest.Create(uriBuilder.Uri);
            request.Method = ServiceHelper.GetMethod;
            request.Timeout = PagSeguroConfiguration.RequestTimeout;

            PagSeguroTrace.Info(String.Format(CultureInfo.InvariantCulture, "NotificationService.CheckTransaction(notificationCode={0}) - begin", notificationCode));

            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (XmlReader reader = XmlReader.Create(response.GetResponseStream()))
                    {
                        Transaction transaction = new Transaction();
                        TransactionSerializer.Read(reader, transaction);

                        PagSeguroTrace.Info(String.Format(CultureInfo.InvariantCulture, "NotificationService.CheckTransaction(notificationCode={0}) - end {1}", notificationCode, transaction));
                        return transaction;
                    }
                }
            }
            catch (WebException exception)
            {
                PagSeguroServiceException pse = ServiceHelper.CreatePagSeguroServiceException((HttpWebResponse)exception.Response);
                PagSeguroTrace.Error(
                    String.Format(CultureInfo.InvariantCulture, "NotificationService.CheckTransaction(notificationCode={0}) - error {1}", notificationCode, pse));
                throw pse;
            }
        }
 /// <summary>
 /// Calls the PagSeguro web service and register this request for payment
 /// </summary>
 /// <param name="credentials">PagSeguro credentials</param>
 /// <returns>The Uri to where the user needs to be redirected to in order to complete the payment process</returns>
 public Uri Register(Credentials credentials)
 {
     return PaymentService.Register(credentials, this);
 }
        /// <summary>
        /// Search transactions associated with this set of credentials within a date range
        /// </summary>
        /// <param name="credentials"></param>
        /// <param name="initialDate"></param>
        /// <returns></returns>
        public static TransactionSearchResult SearchByDate(Credentials credentials, DateTime initialDate)
        {
            if (credentials == null)
                throw new ArgumentNullException("credentials");

            return SearchByDateCore(credentials, initialDate, DateTime.MaxValue, 0, 0);
        }
        /// <summary>
        /// Common implmentation of all SearchByDate methods
        /// </summary>
        /// <param name="credentials">PagSeguro credentials. Required.</param>
        /// <param name="initialDate"></param>
        /// <param name="finalDate">End of date range. Use DateTime.MaxValue to search without an upper boundary.</param>
        /// <param name="pageNumber">Page number, starting with 1. If passed as 0, it will call the web service to get the default page, also page number 1.</param>
        /// <param name="resultsPerPage">Results per page, optional.</param>
        /// <returns></returns>
        private static TransactionSearchResult SearchByDateCore(Credentials credentials, DateTime initialDate, DateTime finalDate, int pageNumber, int resultsPerPage)
        {
            UriBuilder uriBuilder = new UriBuilder(PagSeguroConfiguration.SearchUri);

            QueryStringBuilder query = new QueryStringBuilder(ServiceHelper.EncodeCredentialsAsQueryString(credentials));

            query.Append(InitialDateParameterName, initialDate);

            if (finalDate < DateTime.MaxValue)
            {
                query.Append(FinalDateParameterName, finalDate);
            }

            if (pageNumber > 0)
            {
                query.Append(PageNumberParameterName, pageNumber);
            }

            if (resultsPerPage > 0)
            {
                query.Append(MaxPageResultsParameterName, resultsPerPage);
            }

            uriBuilder.Query = query.ToString();

            PagSeguroTrace.Info(String.Format(CultureInfo.InvariantCulture, "TransactionSearchService.SearchByDate(initialDate={0}, finalDate={1}) - begin", initialDate, finalDate));

            WebRequest request = WebRequest.Create(uriBuilder.Uri);
            request.Method = ServiceHelper.GetMethod;
            request.Timeout = PagSeguroConfiguration.RequestTimeout;

            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (XmlReader reader = XmlReader.Create(response.GetResponseStream()))
                    {
                        TransactionSearchResult result = new TransactionSearchResult();
                        TransactionSearchResultSerializer.Read(reader, result);
                        PagSeguroTrace.Info(String.Format(CultureInfo.InvariantCulture, "TransactionSearchService.SearchByDate(initialDate={0}, finalDate={1}) - end {2}", initialDate, finalDate, result));
                        return result;
                    }
                }
            }
            catch (WebException exception)
            {
                PagSeguroServiceException pse = ServiceHelper.CreatePagSeguroServiceException((HttpWebResponse)exception.Response);
                PagSeguroTrace.Error(String.Format(CultureInfo.InvariantCulture, "TransactionSearchService.SearchByDate(initialDate={0}, finalDate={1}) - error {2}", initialDate, finalDate, pse));
                throw pse;
            }
        }
        /// <summary>
        /// Search transactions associated with this set of credentials within a date range
        /// </summary>
        /// <param name="credentials"></param>
        /// <param name="initialDate"></param>
        /// <param name="finalDate"></param>
        /// <param name="pageNumber"></param>
        /// <param name="resultsPerPage"></param>
        /// <returns></returns>
        public static TransactionSearchResult SearchByDate(Credentials credentials, DateTime initialDate, DateTime finalDate, int pageNumber, int resultsPerPage)
        {
            if (credentials == null)
                throw new ArgumentNullException("credentials");
            if (DateTime.Compare(initialDate, finalDate) > 0)
                throw new ArgumentException("initialDate must be before finalDate", "initialDate");
            if (pageNumber <= 0)
                throw new ArgumentOutOfRangeException("pageNumber", pageNumber, "pageNumber must be greater than zero");
            if (resultsPerPage <= 0)
                throw new ArgumentOutOfRangeException("resultsPerPage", resultsPerPage, "resultsPerPage must be greater than zero");

            return SearchByDateCore(credentials, initialDate, finalDate, pageNumber, resultsPerPage);
        }
        /// <summary>
        /// Search transactions associated with this set of credentials within a date range
        /// </summary>
        /// <param name="credentials"></param>
        /// <param name="initialDate"></param>
        /// <param name="finalDate"></param>
        /// <returns></returns>
        public static TransactionSearchResult SearchByDate(Credentials credentials, DateTime initialDate, DateTime finalDate)
        {
            if (credentials == null)
                throw new ArgumentNullException("credentials");
            if (DateTime.Compare(initialDate, finalDate) > 0)
                throw new ArgumentException("initialDate must be before finalDate", "initialDate");

            return SearchByDateCore(credentials, initialDate, finalDate, 0, 0);
        }
        /// <summary>
        /// Search transactions associated with this set of credentials within a date range
        /// </summary>
        /// <param name="credentials"></param>
        /// <param name="initialDate"></param>
        /// <param name="pageNumber"></param>
        /// <returns></returns>
        public static TransactionSearchResult SearchByDate(Credentials credentials, DateTime initialDate, int pageNumber)
        {
            if (credentials == null)
                throw new ArgumentNullException("credentials");
            if (pageNumber <= 0)
                throw new ArgumentOutOfRangeException("pageNumber", pageNumber, "pageNumber must be greater than zero");

            return SearchByDateCore(credentials, initialDate, DateTime.MaxValue, pageNumber, 0);
        }