using CPSAPIModels; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Runtime.InteropServices; using System.Timers; namespace CPSConnector { public class CPSConnector { public event TokenNotRefreshedEventHandler TokenNotRefreshed; /// /// Crea un nuevo conector CPS /// /// Url de la API CPS. Existente para posibles futuras necesidades /// Tiempo de expiración del token usado para autenticar las peticiones. Existente para posibles futuras necesidades public CPSConnector(string CPSApiUrl = "https://www.cloudpaymentservice.com/api", int accessTokenExpirySeconds = CPSConnector.accessTokenExpirySeconds) { this.CPSApiUrl = CPSApiUrl; this.timer = new Timer((accessTokenExpirySeconds - RefreshTokenOffset) * 1000); this.timer.Elapsed += timerElapsedEvent; this.timer.Enabled = false; this.timer.AutoReset = true; } /// /// Certifica el estado de conexión con la API CPS. /// /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode Ping(ref string APIError) { string Resource = "/ping"; string Method = "GET"; string ResponseContent = null; HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; this.ExecuteRequest(null, Method, Resource, ref httpStatusCode, ref ResponseContent, null, null, false); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } #region Session /// /// Inicia sesión sobre un terminal CPS. /// /// Petición a enviar. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode Login(CPSAPIModels.LoginRequest request, ref string APIError) { string Resource = "/login"; string Method = "POST"; string ResponseContent = null; CPSAPIModels.LoginResponse response = new CPSAPIModels.LoginResponse(); if (request == null) { APIError = "Invalid login request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid login response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (LoginResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut, false); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } else { UpdateTokens(response.AccessToken, response.RefreshToken); this.ResponseTimeOut = request.ResponseTimeOut; this.CPSAPIVersion = request.CPSAPIVersion; } return httpStatusCode; } /// /// Finaliza sesión sobre un terminal CPS /// public void Logout() { timer.Stop(); this._AccessToken = null; this._RefreshToken = null; } /// /// Inicia una transacción sobre un terminal CPS con el modo compartido activado. /// /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode StartTransaction(ref CPSAPIModels.StartTransactionResponse response, ref string APIError) { string Resource = "/starttransaction"; string Method = "GET"; string ResponseContent = null; if (response == null) { APIError = "Invalid start transaction response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (StartTransactionResponse)this.ExecuteRequest(null, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), null); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Finaliza una transacción sobre un terminal CPS con el modo compartido activado. /// /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode EndTransaction(ref CPSAPIModels.EndTransactionResponse response, ref string APIError) { string Resource = "/endtransaction"; string Method = "GET"; string ResponseContent = null; if (response == null) { APIError = "Invalid end transaction response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (EndTransactionResponse)this.ExecuteRequest(null, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), null); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } #endregion #region Terminal /// /// Devuelve información acerca del terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode TerminalInfo(CPSAPIModels.TerminalInfoRequest request, ref CPSAPIModels.TerminalInfoResponse response, ref string APIError) { string Resource = "/terminalinfo"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid terminal info request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid terminal info response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (TerminalInfoResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Devuelve el actual estado operacional del terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode TerminalOperationalStatus(TerminalOperationalStatusRequest request, ref TerminalOperationalStatusResponse response, ref string APIError) { string Resource = "/terminaloperationalstatus"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid terminal operational status request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid terminal operational status response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (TerminalOperationalStatusResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Reinicia el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode Restart(RestartRequest request, ref RestartResponse response, ref string APIError) { string Resource = "/restart"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid restart request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid restart response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (RestartResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Establece el idioma del terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode SetLanguage(SetLanguageRequest request, ref SetLanguageResponse response, ref string APIError) { string Resource = "/setlanguage"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid set language request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid set language response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (SetLanguageResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Finaliza la operación en curso en el terminal CPS. Permite la extracción del Tag en determinadas operaciones. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode EndCurrentOperation(EndCurrentOperationRequest request, ref EndCurrentOperationResponse response, ref string APIError) { string Resource = "/endcurrentoperation"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid end current operation request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid end current operation response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (EndCurrentOperationResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de lectura de Tag en el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode TagReading(TagReadingRequest request, ref TagReadingResponse response, ref string APIError) { string Resource = "/tagreading"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid tag reading request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid tag reading response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (TagReadingResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Activa/desactiva el modo configuración en el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode ConfigurationMode(ConfigurationModeRequest request, ref ConfigurationModeResponse response, ref string APIError) { string Resource = "/configurationmode"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid configuration mode request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid configuration mode response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (ConfigurationModeResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Activa/desactiva el modo autónomo en el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode StandaloneMode(StandaloneModeRequest request, ref StandaloneModeResponse response, ref string APIError) { string Resource = "/standalonemode"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid standalone mode request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid standalone mode response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (StandaloneModeResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } #endregion #region Payment /// /// Devuelve el total cobrado por el terminal CPS desde el último cierre. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode CheckTotalPaymentAmount(CheckTotalPaymentAmountRequest request, ref CheckTotalPaymentAmountResponse response, ref string APIError) { string Resource = "/checktotalpaymentamount"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid check total payment amount request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid check total payment amount response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (CheckTotalPaymentAmountResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicializa a 0 el total cobrado por el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode Closure(ClosureRequest request, ref ClosureResponse response, ref string APIError) { string Resource = "/closure"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid closure request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid closure response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (ClosureResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de cobro sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode Payment(PaymentRequest request, ref PaymentResponse response, ref string APIError) { string Resource = "/payment"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid payment request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid payment response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (PaymentResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de devolución de cobro (incluidas las recargas) sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode PaymentRefund(PaymentRefundRequest request, ref PaymentRefundResponse response, ref string APIError) { string Resource = "/paymentrefund"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid payment refund request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid payment refund response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (PaymentRefundResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de preautorización de cobro sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode PaymentPreauthorization(PaymentPreauthorizationRequest request, ref PaymentPreauthorizationResponse response, ref string APIError) { string Resource = "/paymentpreauthorization"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid payment preauthorization request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid payment preauthorization response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (PaymentPreauthorizationResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de confirmación de preautorización sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode PaymentConfirmation(PaymentConfirmationRequest request, ref PaymentConfirmationResponse response, ref string APIError) { string Resource = "/paymentconfirmation"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid payment confirmation request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid payment confirmation response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (PaymentConfirmationResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de recarga sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode Recharge(RechargeRequest request, ref RechargeResponse response, ref string APIError) { string Resource = "/recharge"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid recharge request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid recharge response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (RechargeResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de consulta de saldo financiero disponible sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode AvailableFinancialBalance(AvailableFinancialBalanceRequest request, ref AvailableFinancialBalanceResponse response, ref string APIError) { string Resource = "/availablefinancialbalance"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid available financial balance request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid available financial balance response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (AvailableFinancialBalanceResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de expedición de efectivo sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode CashExpedition(CashExpeditionRequest request, ref CashExpeditionResponse response, ref string APIError) { string Resource = "/cashexpedition"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid cash expedition request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid cash expedition response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (CashExpeditionResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } #endregion #region Discounts /// /// Inicia una operación de consulta de descuentos aplicables a una venta en el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode DiscountsChecking(DiscountsCheckingRequest request, ref DiscountsCheckingResponse response, ref string APIError) { string Resource = "/discountschecking"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid discounts checking request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid discounts checking response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (DiscountsCheckingResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de consolidación de descuentos aplicables a una venta en el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode DiscountsConsolidation(DiscountsConsolidationRequest request, ref DiscountsConsolidationResponse response, ref string APIError) { string Resource = "/discountsconsolidation"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid discounts consolidation request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid discounts consolidation response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (DiscountsConsolidationResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación anulación de descuentos consolidados a una venta en el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode ConsolidatedDiscountsAnulation(ConsolidatedDiscountsAnulationRequest request, ref ConsolidatedDiscountsAnulationResponse response, ref string APIError) { string Resource = "/consolidateddiscountsanulation"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid consolidated discounts anulation request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid consolidated discounts anulation response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (ConsolidatedDiscountsAnulationResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } #endregion #region Loyalty /// /// Inicia una operación de concesión de puntos por venta sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode AwardPoints(AwardPointsRequest request, ref AwardPointsResponse response, ref string APIError) { string Resource = "/awardpoints"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid award points request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid award points response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (AwardPointsResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de anulación de puntos concedidos sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode AwardedPointsAnulation(AwardedPointsAnulationRequest request, ref AwardedPointsAnulationResponse response, ref string APIError) { string Resource = "/awardedpointsanulation"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid awarded points anulation request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid awarded points anulation response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (AwardedPointsAnulationResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de consulta de saldo de puntos sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode AvailablePointsBalance(AvailablePointsBalanceRequest request, ref AvailablePointsBalanceResponse response, ref string APIError) { string Resource = "/availablepointsbalance"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid available points balance request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid available points balance response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (AvailablePointsBalanceResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de canjeo de puntos sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode RedeemPoints(RedeemPointsRequest request, ref RedeemPointsResponse response, ref string APIError) { string Resource = "/redeempoints"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid redeem points request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid redeem points response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (RedeemPointsResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de anulación de canjeo de puntos sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode RedeemedPointsAnulation(RedeemedPointsAnulationRequest request, ref RedeemedPointsAnulationResponse response, ref string APIError) { string Resource = "/redeemedpointsanulation"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid redeemed points anulation request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid redeemed points anulation response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (RedeemedPointsAnulationResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } /// /// Inicia una operación de obtención de catálogo de regalos canjeables sobre el terminal CPS. /// /// Petición a enviar. /// Respuesta recibida. /// Descripción ampliada del error cuando el resultado de la petición no ha sido satisfactorio. /// Código de estado HTTP que informa sobre el resultado de la petición. public HttpStatusCode GetRedeemablePresents(GetRedeemablePresentsRequest request, ref GetRedeemablePresentsResponse response, ref string APIError) { string Resource = "/getredeemablepresents"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid get redeemable presents request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid get redeemable presents response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (GetRedeemablePresentsResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), request.ResponseTimeOut); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } return httpStatusCode; } #endregion #region Private Properties private const int accessTokenExpirySeconds = 300; private const int RefreshTokenOffset = 30; private string CPSApiUrl; private string _AccessToken; private string _RefreshToken; private bool _RefreshingToken = false; private Timer timer; private uint ResponseTimeOut; private CPSAPIVersion CPSAPIVersion; private void timerElapsedEvent(Object source, ElapsedEventArgs e) { int WaitSecondsBetweenRetries = 5; int MaxRetries = RefreshTokenOffset / WaitSecondsBetweenRetries; int Retry = 1; List APIErrors = new List(); try { _RefreshingToken = true; CPSAPIModels.RefreshTokenRequest request = new CPSAPIModels.RefreshTokenRequest(); request.CPSAPIVersion = this.CPSAPIVersion; request.AccessToken = this._AccessToken; request.RefreshToken = this._RefreshToken; string APIError = null; CPSAPIModels.RefreshTokenResponse response = new CPSAPIModels.RefreshTokenResponse(); HttpStatusCode RefreshTokenHttpStatusCode = RefreshToken(request, ref response, ref APIError); while (RefreshTokenHttpStatusCode != HttpStatusCode.OK && Retry<=MaxRetries) { APIErrors.Add("Retry Number: " + Retry.ToString() + " Datetime: "+DateTime.Now.ToString()+" - APIError: " + APIError); System.Threading.Thread.Sleep(WaitSecondsBetweenRetries*1000); Retry += 1; response = new CPSAPIModels.RefreshTokenResponse(); APIError = null; RefreshTokenHttpStatusCode = RefreshToken(request, ref response, ref APIError); } } catch { } finally { _RefreshingToken = false; } if (Retry > MaxRetries) { this.OnTokenNotRefreshed(new TokenNotRefreshedEventArgs(String.Join(System.Environment.NewLine, APIErrors))); } } protected void OnTokenNotRefreshed(TokenNotRefreshedEventArgs e) { if (TokenNotRefreshed != null) { TokenNotRefreshed(this, e); } } private object ExecuteRequest(object Request, string RequestMethod, string Resource, ref HttpStatusCode httpStatusCode, ref string ResponseContent, Type ResponseType, uint? ResponseTimeOut, bool AuthorizationNeeded = true) { object Response = null; string JSONRequest = null; string RequestContentType = null; if (Request != null) { JSONRequest = JSONSerialization(Request); RequestContentType = "application/json"; } string ResponseContentType = null; uint TimeOut = this.ResponseTimeOut; if (ResponseTimeOut.HasValue) TimeOut = ResponseTimeOut.Value; httpStatusCode = Execute_HTTP_Command(this.CPSApiUrl + Resource, RequestMethod, ref ResponseContent, ref ResponseContentType, TimeOut, JSONRequest, RequestContentType, AuthorizationNeeded, Request != null && Request.GetType()!=typeof(CPSAPIModels.RefreshTokenRequest)); if (httpStatusCode == HttpStatusCode.OK) { if (ResponseContent != null && ResponseType != null && ResponseContentType.Contains("application/json")) { Response = JSONDeserialization(ResponseContent, ResponseType); } } return Response; } private string JSONSerialization(object JSONObject) { MemoryStream Stream = new MemoryStream(); DataContractJsonSerializer ser = new DataContractJsonSerializer(JSONObject.GetType()); ser.WriteObject(Stream, JSONObject); Stream.Position = 0; StreamReader reader = new StreamReader(Stream, System.Text.Encoding.UTF8); return reader.ReadToEnd(); } private object JSONDeserialization(string Serialization, Type Type) { byte[] SerializationAsBytes = new System.Text.UTF8Encoding().GetBytes(Serialization); System.IO.MemoryStream Stream = new System.IO.MemoryStream(SerializationAsBytes); Stream.Position = 0; DataContractJsonSerializer ser = new DataContractJsonSerializer(Type); return ser.ReadObject(Stream); } private HttpStatusCode Execute_HTTP_Command(string url, string RequestMethod, ref string ResponseContent, ref string ResponseContentType, uint TimeOut = 100, string RequestContent = null, string RequestContentType = null, bool AuthorizationNeeded = true, bool WaitRefreshingToken = true) { HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); if (TimeOut == 0) request.Timeout = System.Threading.Timeout.Infinite; else request.Timeout = (int)TimeOut * 1000; request.Method = RequestMethod; if (AuthorizationNeeded) { while (WaitRefreshingToken && this._RefreshingToken) { System.Threading.Thread.Sleep(150); } request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + this._AccessToken); } HttpWebResponse response = null; try { if (!String.IsNullOrEmpty(RequestContent)) { System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); Byte[] byteArray = encoding.GetBytes(RequestContent); request.ContentLength = byteArray.Length; request.ContentType = RequestContentType; Stream dataStream = request.GetRequestStream(); dataStream.Write(byteArray, 0, byteArray.Length); } response = (HttpWebResponse)request.GetResponse(); Stream responseStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.UTF8); ResponseContentType = response.ContentType; ResponseContent = reader.ReadToEnd(); httpStatusCode = response.StatusCode; } catch (System.Net.WebException Ex) { if (Ex.Response != null && Ex.Response.GetType().Equals(typeof(HttpWebResponse))) { httpStatusCode = ((HttpWebResponse)(Ex.Response)).StatusCode; } } finally { if (response!=null) { response.Close(); } } return httpStatusCode; } private bool ValidateServerCertificate(Object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) { return true; } private void UpdateTokens(string accessToken, string refreshToken) { timer.Stop(); this._AccessToken = accessToken; this._RefreshToken = refreshToken; timer.Start(); } private HttpStatusCode RefreshToken(CPSAPIModels.RefreshTokenRequest request, ref CPSAPIModels.RefreshTokenResponse response, ref string APIError) { string Resource = "/refreshtoken"; string Method = "POST"; string ResponseContent = null; if (request == null) { APIError = "Invalid refresh token request"; return HttpStatusCode.BadRequest; } if (response == null) { APIError = "Invalid refresh token response"; return HttpStatusCode.BadRequest; } HttpStatusCode httpStatusCode = HttpStatusCode.InternalServerError; response = (RefreshTokenResponse)this.ExecuteRequest(request, Method, Resource, ref httpStatusCode, ref ResponseContent, response.GetType(), null, false); if (httpStatusCode != HttpStatusCode.OK) { APIError = ResponseContent; } else { UpdateTokens(response.AccessToken, response.RefreshToken); } return httpStatusCode; } #endregion } public delegate void TokenNotRefreshedEventHandler(object sender, TokenNotRefreshedEventArgs e); public class TokenNotRefreshedEventArgs : System.EventArgs { private string _APIErrors; public string APIErrors { get { return _APIErrors; } } public TokenNotRefreshedEventArgs(string APIErrors) { this._APIErrors = APIErrors; } } }