Ejemplo n.º 1
0
            /// <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");
                }

                request.TenderLine.Status     = TenderLineStatus.Committed;
                request.TenderLine.IsVoidable = true;

                // For check payments, there is no extra step needed for authorizing.
                return(new AuthorizePaymentServiceResponse(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");
                }

                if (request.TenderLine.Currency.Equals(request.RequestContext.GetChannelConfiguration().Currency, StringComparison.OrdinalIgnoreCase))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "Currency payment requires currency to be different from channel currency.");
                }

                request.TenderLine.Status     = TenderLineStatus.Committed;
                request.TenderLine.IsVoidable = true;

                return(new AuthorizePaymentServiceResponse(request.TenderLine));
            }
Ejemplo n.º 3
0
            /// <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");
                }

                if (request.TenderLine.Amount > 0)
                {
                    // Positive amount indicates credit memo payment.
                    // Payment always uses full amount. Actual amount will be returned as part of tender line on response.
                    string orgUnitNumber = request.RequestContext.GetOrgUnit().OrgUnitNumber;

                    var lockRequest = new LockCreditMemoRealtimeRequest(
                        request.TenderLine.CreditMemoId,
                        orgUnitNumber,
                        request.RequestContext.GetTerminal().TerminalId);
                    CreditMemo creditMemo = request.RequestContext.Execute <SingleEntityDataServiceResponse <CreditMemo> >(lockRequest).Entity;

                    request.TenderLine.Amount     = creditMemo.Balance;
                    request.TenderLine.Currency   = creditMemo.CurrencyCode;
                    request.TenderLine.Status     = TenderLineStatus.PendingCommit;
                    request.TenderLine.IsVoidable = true;
                }
                else
                {
                    // For negative amount issue new credit memo
                    if (!string.IsNullOrWhiteSpace(request.TenderLine.CreditMemoId))
                    {
                        throw new PaymentException(
                                  PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest,
                                  "Refund to existing credit memo is not allowed. To issue credit memo identifier should be left blank.");
                    }

                    string creditMemoId = IssueCreditMemo(request.RequestContext, decimal.Negate(request.TenderLine.Amount), request.TenderLine.Currency, request.Transaction.Id, request.Transaction.ReceiptId);

                    request.TenderLine.CreditMemoId = creditMemoId;
                    request.TenderLine.Status       = TenderLineStatus.Committed;
                    request.TenderLine.IsVoidable   = false;
                }

                return(new AuthorizePaymentServiceResponse(request.TenderLine));
            }
            private static void OnAuthorizePaymentExecuting(AuthorizePaymentServiceRequest request)
            {
                // Call to get tender types (cached).
                var        dataServiceRequest = new GetChannelTenderTypesDataRequest(request.RequestContext.GetPrincipal().ChannelId, QueryResultSettings.AllRecords);
                var        response           = request.RequestContext.Execute <EntityDataServiceResponse <TenderType> >(dataServiceRequest);
                TenderType tenderType         = response.PagedEntityCollection.Results.Single(t => string.Equals(t.TenderTypeId, request.TenderLine.TenderTypeId, StringComparison.OrdinalIgnoreCase));

                switch (tenderType.OperationType)
                {
                case RetailOperation.PayCreditMemo:
                    if (request.TenderLine.Amount < 0)
                    {
                        request.RequestContext.Execute <NullResponse>(new CheckAccessServiceRequest(RetailOperation.IssueCreditMemo));
                    }

                    break;

                default:
                    request.RequestContext.Execute <NullResponse>(new CheckAccessServiceRequest(tenderType.OperationType));
                    break;
                }
            }
            /// <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");
                }

                TenderType tenderType = GetTenderType(request.RequestContext, request.TenderLine.TenderTypeId);

                // Resolve payment service.
                IRequestHandler paymentService = ResolvePaymentService(request.RequestContext, request.GetType(), request.TenderLine.TenderTypeId);

                // Calculate amount to be authorized (some tender type like currency and credit memo do not have amount set on tender line).
                CalculatePaymentAmountServiceRequest  calculateAmountRequest  = new CalculatePaymentAmountServiceRequest(request.TenderLine);
                CalculatePaymentAmountServiceResponse calculateAmountResponse = request.RequestContext.Execute <CalculatePaymentAmountServiceResponse>(calculateAmountRequest, paymentService);

                request.TenderLine = calculateAmountResponse.TenderLine;

                if (!request.TenderLine.IsPreProcessed)
                {
                    request.TenderLine.Amount = RoundAmountByTenderType(request.RequestContext, request.TenderLine.TenderTypeId, request.TenderLine.Amount, isChange: false);
                }

                // Update tender lines with amounts and exchange rates for channel and company currencies.
                CalculateTenderLineCurrencyAmounts(request.TenderLine, request.RequestContext);

                if (request.TenderLine.Amount == 0)
                {
                    throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidAmount, "An amount of zero is not allowed on the tenderline.");
                }

                // Do amount validation.
                if (!request.SkipLimitValidation)
                {
                    var validateRequest = new ValidateTenderLineForAddServiceRequest(request.Transaction, request.TenderLine, tenderType);
                    request.RequestContext.Execute <NullResponse>(validateRequest);
                }

                // Check tender line status
                AuthorizePaymentServiceResponse response;

                if (request.TenderLine.Status == TenderLineStatus.PendingCommit ||
                    request.TenderLine.Status == TenderLineStatus.Committed ||
                    request.TenderLine.Status == TenderLineStatus.Voided)
                {
                    // Return the tender line directly if already authorized
                    response = new AuthorizePaymentServiceResponse(request.TenderLine);
                }
                else
                {
                    // Process authorization.
                    response = request.RequestContext.Execute <AuthorizePaymentServiceResponse>(request, paymentService);
                }

                // If we have cashback amount set on the tender line, we add it to the amount on the tender line after authorization
                // and set the cashback amount on the tender line to 0. This is because we do not cashback field in the
                // RetailTransactionPaymentTrans table. We are doing this at this point to mimic EPOS.
                if (response.TenderLine.CashBackAmount != 0)
                {
                    CalculateAmountsWithCashBack(response.TenderLine, request.RequestContext);
                }

                return(response);
            }
Ejemplo n.º 6
0
            /// <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");
                }

                TenderLine tenderLine = request.TenderLine;

                if (tenderLine == null)
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "Customer account payment requires tender line.");
                }

                if (string.IsNullOrWhiteSpace(tenderLine.CustomerId))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "Customer account payment requires CustomerId to be set on tender line.");
                }

                SalesTransaction transaction = request.Transaction;

                if (transaction.CartType == CartType.CustomerOrder &&
                    (transaction.CustomerOrderMode == CustomerOrderMode.CustomerOrderCreateOrEdit || transaction.CustomerOrderMode == CustomerOrderMode.Cancellation))
                {
                    throw new PaymentException(
                              PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_CustomerAccountPaymentIsNotAllowedForCustomerOrderDepositAndCancellation,
                              string.Format("Customer account payment cannot be used to pay customer order deposit or cancellation (current mode {0}).", transaction.CustomerOrderMode));
                }

                if (string.IsNullOrWhiteSpace(transaction.CustomerId))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "Customer account payment requires CustomerId to be set on cart.");
                }

                Customer customerOnTransaction = GetCustomer(request.RequestContext, transaction.CustomerId);

                if (customerOnTransaction == null)
                {
                    throw new PaymentException(
                              PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest,
                              string.Format(CultureInfo.InvariantCulture, "Customer with id {0} was not found.", transaction.CustomerId));
                }

                ValidateCustomerForPayment(customerOnTransaction);

                bool   useInvoiceAccount       = !string.IsNullOrWhiteSpace(customerOnTransaction.InvoiceAccount);
                string customerAccountToCharge = useInvoiceAccount ? customerOnTransaction.InvoiceAccount : customerOnTransaction.AccountNumber;

                if (!tenderLine.CustomerId.Equals(customerAccountToCharge, StringComparison.OrdinalIgnoreCase))
                {
                    // Someone is trying to pay with unathorized account
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_PaymentUsingUnauthorizedAccount, "Customer account payment requires its own account or matching invoice account on a tender line.");
                }

                CheckIfPaymentExceedsBalance(request.RequestContext, customerOnTransaction, useInvoiceAccount, tenderLine);

                // Looks like request has successfully validated
                tenderLine.Status     = TenderLineStatus.Committed;
                tenderLine.IsVoidable = true;

                return(new AuthorizePaymentServiceResponse(tenderLine));
            }
Ejemplo n.º 7
0
            /// <summary>
            /// Authorizes the payment.
            /// This step checks whether the loyalty card has enough reward points to redeem. If yes, it decides the points
            /// to redeem based on redeem ranking.
            /// </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");
                }

                if (request.TenderLine == null)
                {
                    throw new ArgumentException("request.TenderLine cannot be null.");
                }

                if (request.RequestContext == null)
                {
                    throw new ArgumentException("request.RequestContext cannot be null.");
                }

                if (request.Transaction == null)
                {
                    throw new ArgumentException("request.Transaction cannot be null.");
                }

                // Check tender amount.
                if (request.TenderLine.Amount == 0m)
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "The tender amount must be greater than zero.");
                }

                // Check tender currency.
                if (string.IsNullOrWhiteSpace(request.TenderLine.Currency))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "The tender currency is missing.");
                }

                // Check if the transaction already has loyalty payments
                var activeTenderLines = request.Transaction.ActiveTenderLines;

                if (activeTenderLines != null && activeTenderLines.Any(line => !string.IsNullOrWhiteSpace(line.LoyaltyCardId)))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_NoMoreThanOneLoyaltyTender, "The transaction cannot contain more than one loyalty payment line.");
                }

                SalesOrder salesOrder = request.Transaction as SalesOrder;

                if (salesOrder != null && salesOrder.HasLoyaltyPayment &&
                    (salesOrder.CustomerOrderMode != CustomerOrderMode.Cancellation || salesOrder.AmountDue > decimal.Zero))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_NoMoreThanOneLoyaltyTender, "The transaction cannot contain more than one loyalty payment line.");
                }

                // Check whether the loyalty card is valid.
                var         getLoyaltyCardDataRequest = new GetLoyaltyCardDataRequest(request.TenderLine.LoyaltyCardId);
                LoyaltyCard loyaltyCard = request.RequestContext.Execute <SingleEntityDataServiceResponse <LoyaltyCard> >(getLoyaltyCardDataRequest).Entity;

                if (loyaltyCard == null || string.IsNullOrWhiteSpace(loyaltyCard.CardNumber))
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidLoyaltyCardNumber, "The loyalty card number does not exists.");
                }

                // Check whether the loyalty card is blocked.
                if (loyaltyCard.CardTenderType == LoyaltyCardTenderType.Blocked)
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_BlockedLoyaltyCard, "The loyalty card is blocked.");
                }

                if (loyaltyCard.CardTenderType == LoyaltyCardTenderType.NoTender)
                {
                    throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_NoTenderLoyaltyCard, "The loyalty card is not allowed for payment.");
                }

                // Calculate redeem trans and fill in the sales transaction.
                if (request.TenderLine.Amount >= 0)
                {
                    LoyaltyServiceHelper.FillInLoyaltyRewardPointLinesForPayment(
                        request.RequestContext,
                        request.Transaction,
                        loyaltyCard,
                        request.TenderLine.Amount,
                        request.TenderLine.Currency);
                }
                else
                {
                    LoyaltyServiceHelper.FillInLoyaltyRewardPointLinesForRefund(
                        request.RequestContext,
                        request.Transaction,
                        loyaltyCard,
                        request.TenderLine.Amount,
                        request.TenderLine.Currency);
                }

                // Set Card Type Id for Loyalty Card if not set by the client.
                if (request.TenderLine.CardTypeId == null)
                {
                    string tenderTypeId                  = request.TenderLine.TenderTypeId;
                    var    cardTypeDataRequest           = new GetCardTypeDataRequest(QueryResultSettings.AllRecords);
                    var    cardTypeInfoResponse          = request.RequestContext.Execute <EntityDataServiceResponse <CardTypeInfo> >(cardTypeDataRequest);
                    IEnumerable <CardTypeInfo> cardTypes = cardTypeInfoResponse.PagedEntityCollection.Results;
                    CardTypeInfo loyaltyCardTypeInfo     = cardTypes.FirstOrDefault(cardType => cardType.PaymentMethodId == tenderTypeId);
                    if (loyaltyCardTypeInfo == null)
                    {
                        throw new ConfigurationException(ConfigurationErrors.Microsoft_Dynamics_Commerce_Runtime_ConfigurationSettingNotFound, "The loyalty card payment as a tender type card is not configured for the channel.");
                    }

                    request.TenderLine.CardTypeId = loyaltyCardTypeInfo.TypeId;
                }

                // Authorize.
                request.TenderLine.Status     = TenderLineStatus.PendingCommit;
                request.TenderLine.IsVoidable = true;

                return(new AuthorizePaymentServiceResponse(request.TenderLine));
            }
Ejemplo n.º 8
0
            /// <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));
            }