/// <summary>
        /// Configures and executes REST call: Supports JSON
        /// </summary>
        /// <typeparam name="T">Generic Type parameter for response object</typeparam>
        /// <param name="apiContext">APIContext object</param>
        /// <param name="httpMethod">HttpMethod type</param>
        /// <param name="resource">URI path of the resource</param>
        /// <param name="payload">JSON request payload</param>
        /// <param name="endpoint">Endpoint to use when generating the full URL for the resource. If none is specified, a default endpoint is generated by the SDK based on other config settings.</param>
        /// <param name="setAuthorizationHeader">Specifies whether or not to set the Authorization header in outgoing requests. Defaults to true.</param>
        /// <returns>Response object or null otherwise for void API calls</returns>
        /// <exception cref="PayPal.HttpException">Thrown if there was an error sending the request.</exception>
        /// <exception cref="PayPal.PaymentsException">Thrown if an HttpException was raised and contains a Payments API error object.</exception>
        /// <exception cref="PayPal.PayPalException">Thrown for any other issues encountered. See inner exception for further details.</exception>
        protected internal static T ConfigureAndExecute <T>(APIContext apiContext, HttpMethod httpMethod, string resource, string payload = "", string endpoint = "", bool setAuthorizationHeader = true)
        {
            // Verify the state of the APIContext object.
            if (apiContext == null)
            {
                throw new PayPalException("APIContext object is null");
            }

            try
            {
                var config     = apiContext.GetConfigWithDefaults();
                var headersMap = GetHeaderMap(apiContext);

                if (!setAuthorizationHeader && headersMap.ContainsKey(BaseConstants.AuthorizationHeader))
                {
                    headersMap.Remove(BaseConstants.AuthorizationHeader);
                }

                if (string.IsNullOrEmpty(endpoint))
                {
                    endpoint = GetEndpoint(config);
                }

                // Create the URI where the HTTP request will be sent.
                Uri uniformResourceIdentifier = null;
                var baseUri = new Uri(endpoint);
                if (!Uri.TryCreate(baseUri, resource, out uniformResourceIdentifier))
                {
                    throw new PayPalException("Cannot create URL; baseURI=" + baseUri + ", resourcePath=" + resource);
                }

                // Create the HttpRequest object that will be used to send the HTTP request.
                var connMngr    = ConnectionManager.Instance;
                var httpRequest = connMngr.GetConnection(config, uniformResourceIdentifier.ToString());
                httpRequest.Method = httpMethod.ToString();

                // Set custom content type (default to [application/json])
                if (headersMap != null && headersMap.ContainsKey(BaseConstants.ContentTypeHeader))
                {
                    httpRequest.ContentType = headersMap[BaseConstants.ContentTypeHeader].Trim();
                    headersMap.Remove(BaseConstants.ContentTypeHeader);
                }
                else
                {
                    httpRequest.ContentType = BaseConstants.ContentTypeHeaderJson;
                }

                // Set User-Agent HTTP header
                if (headersMap.ContainsKey(BaseConstants.UserAgentHeader))
                {
                    // aganzha
                    //iso-8859-1
                    var iso8851 = Encoding.GetEncoding("iso-8859-1", new EncoderReplacementFallback(string.Empty), new DecoderExceptionFallback());
                    var bytes   = Encoding.Convert(Encoding.UTF8, iso8851, Encoding.UTF8.GetBytes(headersMap[BaseConstants.UserAgentHeader]));
                    httpRequest.Headers["User-Agent"] = iso8851.GetString(bytes);
                    headersMap.Remove(BaseConstants.UserAgentHeader);
                }

                // Set Custom HTTP headers
                foreach (KeyValuePair <string, string> entry in headersMap)
                {
                    httpRequest.Headers[entry.Key] = entry.Value;
                }

                // Log the headers
                //foreach (string headerName in httpRequest.Headers)
                //{
                //    logger.DebugFormat(headerName + ":" + httpRequest.Headers[headerName]);
                //}

                // Execute call
                var connectionHttp = new HttpConnection(config);

                // Setup the last request & response details.
                LastRequestDetails.Value  = connectionHttp.RequestDetails;
                LastResponseDetails.Value = connectionHttp.ResponseDetails;

                var response = connectionHttp.Execute(payload, httpRequest).Result;

                if (typeof(T).Name.Equals("Object"))
                {
                    return(default(T));
                }
                else if (typeof(T).Name.Equals("String"))
                {
                    return((T)Convert.ChangeType(response, typeof(T)));
                }

                return(JsonFormatter.ConvertFromJson <T>(response));
            }
            catch (ConnectionException ex)
            {
                if (ex is HttpException)
                {
                    var httpEx = ex as HttpException;
                    //  Check to see if we have a Payments API error.
                    if (httpEx.StatusCode == HttpStatusCode.BadRequest)
                    {
                        PaymentsException paymentsEx;
                        if (httpEx.TryConvertTo <PaymentsException>(out paymentsEx))
                        {
                            throw paymentsEx;
                        }
                    }
                    else if (httpEx.StatusCode == HttpStatusCode.Unauthorized)
                    {
                        IdentityException identityEx;
                        if (httpEx.TryConvertTo <IdentityException>(out identityEx))
                        {
                            throw identityEx;
                        }
                    }
                }
                throw;
            }
            catch (PayPalException)
            {
                // If we get a PayPalException, just rethrow to preserve the stack trace.
                throw;
            }
            catch (System.Exception ex)
            {
                throw new PayPalException(ex.Message, ex);
            }
        }
        /// <summary>
        /// Generates a new OAuth token useing the specified client credentials in the authorization request.
        /// </summary>
        /// <param name="base64ClientId">The base-64 encoded credentials to be used in the authorization request.</param>
        /// <returns>The OAuth access token to use for making PayPal requests.</returns>
        private string GenerateOAuthToken(string base64ClientId)
        {
            string response = null;

            Uri uniformResourceIdentifier = null;
            Uri baseUri = null;

            if (config.ContainsKey(BaseConstants.OAuthEndpoint))
            {
                baseUri = new Uri(config[BaseConstants.OAuthEndpoint]);
            }
            else if (config.ContainsKey(BaseConstants.EndpointConfig))
            {
                baseUri = new Uri(config[BaseConstants.EndpointConfig]);
            }
            else if (config.ContainsKey(BaseConstants.ApplicationModeConfig))
            {
                string mode = config[BaseConstants.ApplicationModeConfig];
                if (mode.Equals(BaseConstants.LiveMode))
                {
                    baseUri = new Uri(BaseConstants.RESTLiveEndpoint);
                }
                else if (mode.Equals(BaseConstants.SandboxMode))
                {
                    baseUri = new Uri(BaseConstants.RESTSandboxEndpoint);
                }
                else
                {
                    throw new ConfigException("You must specify one of mode(live/sandbox) OR endpoint in the configuration");
                }
            }
            bool success = Uri.TryCreate(baseUri, OAuthTokenPath, out uniformResourceIdentifier);
            ConnectionManager connManager = ConnectionManager.Instance;
            HttpWebRequest    httpRequest = connManager.GetConnection(this.config, uniformResourceIdentifier.AbsoluteUri);

            Dictionary <string, string> headers = new Dictionary <string, string>();

            headers.Add("Authorization", "Basic " + base64ClientId);
            string postRequest = "grant_type=client_credentials";

            httpRequest.Method      = "POST";
            httpRequest.Accept      = "*/*";
            httpRequest.ContentType = "application/x-www-form-urlencoded";

            // Set User-Agent HTTP header
            var userAgentMap = UserAgentHeader.GetHeader();

            foreach (KeyValuePair <string, string> entry in userAgentMap)
            {
                // aganzha
                //iso-8859-1
                var iso8851 = Encoding.GetEncoding("iso-8859-1", new EncoderReplacementFallback(string.Empty), new DecoderExceptionFallback());
                var bytes   = Encoding.Convert(Encoding.UTF8, iso8851, Encoding.UTF8.GetBytes(entry.Value));
                httpRequest.UserAgent = iso8851.GetString(bytes);
            }

            // Set Custom HTTP headers
            foreach (KeyValuePair <string, string> header in headers)
            {
                httpRequest.Headers.Add(header.Key, header.Value);
            }

            foreach (string headerName in httpRequest.Headers)
            {
                logger.DebugFormat(headerName + ":" + httpRequest.Headers[headerName]);
            }

            HttpConnection httpConnection = new HttpConnection(config);

            try
            {
                response = httpConnection.Execute(postRequest, httpRequest);
            }
            catch (PayPal.HttpException ex)
            {
                // If we get an HTTP exception back and the status code is 401,
                // then try and generate an IdentityException object to throw.
                if (ex.StatusCode == HttpStatusCode.Unauthorized)
                {
                    IdentityException identityEx;
                    if (ex.TryConvertTo <IdentityException>(out identityEx))
                    {
                        throw identityEx;
                    }
                }

                throw;
            }

            JObject deserializedObject = (JObject)JsonConvert.DeserializeObject(response);
            string  generatedToken     = (string)deserializedObject["token_type"] + " " + (string)deserializedObject["access_token"];

            this.ApplicationId = (string)deserializedObject["app_id"];
            this.AccessTokenExpirationInSeconds = (int)deserializedObject["expires_in"];
            this.AccessTokenLastCreationDate    = DateTime.Now;
            return(generatedToken);
        }