/// <summary>
            /// Voids gift card payment.
            /// </summary>
            /// <param name="request">The <see cref="VoidGiftCardRealtimeRequest"/> request.</param>
            /// <returns>The <see cref="NullResponse"/> response.</returns>
            private static NullResponse VoidGiftCardPayment(VoidGiftCardPaymentRealtimeRequest request)
            {
                var transactionClient = new TransactionService.TransactionServiceClient(request.RequestContext);

                transactionClient.VoidGiftCardPayment(request.GiftCardId, request.ChannelId, request.TerminalId);

                return(new NullResponse());
            }
            /// <summary>
            /// Cancels the payment.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>A response containing the canceled tender line.</returns>
            private static VoidPaymentServiceResponse CancelPayment(VoidPaymentServiceRequest request)
            {
                if (request == null)
                {
                    throw new ArgumentNullException("request");
                }

                if (request.TenderLine == null)
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "request.TenderLine is null.");
                }

                var voidGiftCardPayment = new VoidGiftCardPaymentRealtimeRequest(
                    request.TenderLine.GiftCardId,
                    request.RequestContext.GetPrincipal().ChannelId,
                    request.RequestContext.GetTerminal() == null ? string.Empty : request.RequestContext.GetTerminal().TerminalId);

                request.RequestContext.Execute <NullResponse>(voidGiftCardPayment);

                request.TenderLine.Status     = TenderLineStatus.Voided;
                request.TenderLine.IsVoidable = false;

                return(new VoidPaymentServiceResponse(request.TenderLine));
            }
            /// <summary>
            /// Authorizes the payment.
            /// </summary>
            /// <param name="request">The request.</param>
            /// <returns>A response containing the authorized tender line.</returns>
            private static AuthorizePaymentServiceResponse AuthorizePayment(AuthorizePaymentServiceRequest request)
            {
                if (request == null)
                {
                    throw new ArgumentNullException("request");
                }

                ValidateNotAlreadyAdded(request.Transaction, request.TenderLine.GiftCardId);

                var lockGiftCardRealtimeRequest = new LockGiftCardRealtimeRequest(
                    request.TenderLine.GiftCardId,
                    request.RequestContext.GetPrincipal().ChannelId,
                    request.RequestContext.GetTerminal() == null ? string.Empty : request.RequestContext.GetTerminal().TerminalId);
                GiftCard giftCard = request.RequestContext.Execute <SingleEntityDataServiceResponse <GiftCard> >(lockGiftCardRealtimeRequest).Entity;

                GetCurrencyValueServiceResponse convertAmountToGiftCardCurrencyResponse;

                try
                {
                    if (!request.TenderLine.Currency.Equals(request.RequestContext.GetChannelConfiguration().Currency, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new PaymentException(
                                  PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_GiftCardCurrencyMismatch,
                                  string.Format("Gift card payments are only supported in channel currency. Currency requested: {0}", request.TenderLine.Currency));
                    }

                    convertAmountToGiftCardCurrencyResponse = ToGiftCardCurrency(request.RequestContext, request.TenderLine.Amount, giftCard.CardCurrencyCode);

                    // Check if gift card has enough balance.
                    if (giftCard.BalanceInCardCurrency < convertAmountToGiftCardCurrencyResponse.RoundedConvertedAmount)
                    {
                        throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_PaymentAmountExceedsGiftBalance);
                    }
                }
                catch
                {
                    try
                    {
                        // At this point payment failed but gift card is already locked.
                        // Need to unlock gift card (better as void payment) so it can be used in future.
                        var voidGiftCardPaymentRequest = new VoidGiftCardPaymentRealtimeRequest(
                            request.TenderLine.GiftCardId,
                            request.RequestContext.GetPrincipal().ChannelId,
                            request.RequestContext.GetTerminal() == null ? string.Empty : request.RequestContext.GetTerminal().TerminalId);

                        request.RequestContext.Execute <NullResponse>(voidGiftCardPaymentRequest);
                    }
                    catch (Exception ex)
                    {
                        RetailLogger.Log.CrtServicesGiftCardServiceUnlockGiftCardFailure(ex);
                    }

                    throw;
                }

                request.TenderLine.Currency = giftCard.CardCurrencyCode;
                request.TenderLine.AmountInTenderedCurrency = convertAmountToGiftCardCurrencyResponse.RoundedConvertedAmount;
                request.TenderLine.ExchangeRate             = convertAmountToGiftCardCurrencyResponse.ExchangeRate;
                request.TenderLine.Status     = TenderLineStatus.PendingCommit;
                request.TenderLine.IsVoidable = true;

                return(new AuthorizePaymentServiceResponse(request.TenderLine));
            }