Esempio n. 1
0
        /// <summary>
        /// Processes the payment.
        /// </summary>
        /// <param name="orderGroup">The order group.</param>
        /// <param name="payment">The payment.</param>
        public PaymentProcessingResult ProcessPayment(IOrderGroup orderGroup, IPayment payment)
        {
            if (HttpContext.Current == null)
            {
                return(PaymentProcessingResult.CreateSuccessfulResult("Http context is null."));
            }

            if (payment == null)
            {
                return(PaymentProcessingResult.CreateUnsuccessfulResult("Payment was not specified."));
            }

            var orderForm = orderGroup.Forms.FirstOrDefault(f => f.Payments.Contains(payment));

            if (orderForm == null)
            {
                return(PaymentProcessingResult.CreateUnsuccessfulResult(
                           "There is no order form associated with payment."));
            }

            if (orderGroup is IPurchaseOrder purchaseOrder)
            {
                if (payment.TransactionType == TransactionType.Capture.ToString())
                {
                    // return true meaning the capture request is done,
                    // actual capturing must be done on Dintero.
                    var transaction = _requestsHelper.GetTransactionDetails(payment.TransactionID, _requestsHelper.GetAccessToken());
                    var skipItems   = payment.Amount != 0 && payment.Amount < purchaseOrder.GetTotal().Amount&& !string.IsNullOrEmpty(transaction.PaymentProduct) &&
                                      !transaction.PaymentProduct.Equals("instabank", StringComparison.InvariantCultureIgnoreCase);
                    var result = payment.Amount == 0? new TransactionResult {
                        Success = true
                    } : _requestsHelper.CaptureTransaction(payment, purchaseOrder, skipItems);
                    if (result.Success)
                    {
                        return(PaymentProcessingResult.CreateSuccessfulResult(string.Empty));
                    }

                    PostProcessPayment.PostCapture(result, payment);

                    return(PaymentProcessingResult.CreateUnsuccessfulResult(
                               $@"There was an error while capturing payment with Dintero:
                           code: {
                                result.ErrorCode
                            };
                           declineReason: {
                                result.Error
                            }"));
                }

                if (payment.TransactionType == TransactionType.Void.ToString())
                {
                    var result = payment.Amount == 0 ? new TransactionResult {
                        Success = true
                    } : _requestsHelper.VoidTransaction(payment);
                    if (result.Success)
                    {
                        return(PaymentProcessingResult.CreateSuccessfulResult(string.Empty));
                    }

                    return(PaymentProcessingResult.CreateUnsuccessfulResult(
                               $@"There was an error while voiding payment with Dintero:
                           code: {
                                result.ErrorCode
                            };
                           declineReason: {
                                result.Error
                            }"));
                }

                if (payment.TransactionType == TransactionType.Credit.ToString())
                {
                    if (!(purchaseOrder is PurchaseOrder refundOrder))
                    {
                        return(PaymentProcessingResult.CreateUnsuccessfulResult("Order has invalid type."));
                    }

                    var transactionId = payment.TransactionID;
                    if (string.IsNullOrEmpty(transactionId) || transactionId.Equals("0"))
                    {
                        return(PaymentProcessingResult.CreateUnsuccessfulResult(
                                   "TransactionID is not valid or the current payment method does not support this order type."));
                    }

                    var returnForms = refundOrder.ReturnOrderForms.Where(rt =>
                                                                         rt.Status == ReturnFormStatus.Complete.ToString() && rt.Total == payment.Amount).ToList();

                    if (!returnForms.Any())
                    {
                        return(PaymentProcessingResult.CreateUnsuccessfulResult("No items found for refunding."));
                    }

                    var result = payment.Amount == 0 ? new TransactionResult {
                        Success = true
                    } : _requestsHelper.RefundTransaction(payment, returnForms, purchaseOrder.Currency);
                    if (result.Success)
                    {
                        return(PaymentProcessingResult.CreateSuccessfulResult(string.Empty));
                    }

                    PostProcessPayment.PostCredit(result, payment);

                    return(PaymentProcessingResult.CreateUnsuccessfulResult(
                               $@"There was an error while refunding payment with Dintero: code: { result.ErrorCode }; declineReason: { result.Error }"));
                }

                // right now we do not support processing the order which is created by Commerce Manager
                return(PaymentProcessingResult.CreateUnsuccessfulResult(
                           "The current payment method does not support this order type."));
            }

            if (orderGroup is ICart cart && cart.OrderStatus == OrderStatus.Completed)
            {
                return(PaymentProcessingResult.CreateSuccessfulResult(string.Empty));
            }

            _orderRepository.Save(orderGroup);

            var redirectUrl = UriUtil.GetUrlFromStartPageReferenceProperty("DinteroPaymentPage");

            return(PaymentProcessingResult.CreateSuccessfulResult(string.Empty, redirectUrl));
        }
Esempio n. 2
0
        public ActionResult Index(string error, string transaction_id, string session_id, string merchant_reference, string trackingNumber)
        {
            if (PageEditing.PageIsInEditMode)
            {
                return(new EmptyResult());
            }

            string redirectUrl = null;

            Logger.Debug($"HttpContext.Request.RawUrl: {HttpContext.Request.RawUrl}.");
            Logger.Debug($"Dintero payment error: {error}; transaction_id: {transaction_id}; session_id: {session_id}; merchant_reference: {merchant_reference}; trackingNumber: {trackingNumber}");

            var cancelUrl = UriUtil.GetUrlFromStartPageReferenceProperty("DinteroPaymentCancelPage");
            var acceptUrl = UriUtil.GetUrlFromStartPageReferenceProperty("DinteroPaymentLandingPage");

            cancelUrl = UriUtil.AddQueryString(cancelUrl, "success", "false");
            var orderNumber = merchant_reference + trackingNumber;

            InitializeResponse();

            Logger.Debug($"Lock {orderNumber}");
            LockHelper.Lock(orderNumber);

            var gateway = ServiceLocator.Current.GetInstance <DinteroPaymentGateway>();

            Logger.Debug($"Dintero payment {orderNumber} start processing");

            try
            {
                ICart currentCart;
                if (string.IsNullOrWhiteSpace(session_id))
                {
                    // redirect_url is called
                    currentCart =
                        _orderRepository.LoadCart <ICart>(PrincipalInfo.CurrentPrincipal.GetContactId(), Cart.DefaultName);

                    // in case it's redirect from Dintero, but for some reason cookies are not set OR it's redirect from checkout(trackingNumber not empty)
                    if (currentCart == null && (!string.IsNullOrWhiteSpace(transaction_id) || !string.IsNullOrEmpty(trackingNumber)))
                    {
                        var predictableOrderId = string.IsNullOrEmpty(trackingNumber) ? merchant_reference : trackingNumber;
                        Logger.Debug($"Trying to get cart by predictable order Id predictableOrderId: {predictableOrderId}");
                        currentCart = OrderHelper.GetCartByPredictableOrderId(predictableOrderId);
                        if (currentCart != null)
                        {
                            Logger.Debug($"Cart has been loaded by predictableOrderId: {predictableOrderId}");
                        }
                    }

                    Logger.Debug($"CurrentPrincipal {PrincipalInfo.CurrentPrincipal.GetContactId()}");

                    if (currentCart == null)
                    {
                        // check if cart was processed by return_url / callback_url
                        var order = OrderHelper.GetOrderByTrackingNumber(merchant_reference);
                        if (order == null)
                        {
                            Logger.Debug(
                                $"Dintero payment {orderNumber} Cart cannot be loaded!!! contactId: {PrincipalInfo.CurrentPrincipal.GetContactId()}.");

                            throw new PaymentException(PaymentException.ErrorType.ProviderError, "",
                                                       "Cart cannot be loaded!!!");
                        }

                        Logger.Debug(
                            $"Dintero payment {orderNumber} redirect to accept Url. Order status - {((IOrderGroup) order).OrderStatus}");
                        return(Redirect(DinteroPaymentGateway.UpdateAcceptUrl(order, acceptUrl,
                                                                              ((IOrderGroup)order).OrderStatus == OrderStatus.OnHold)));
                    }
                    else
                    {
                        Logger.Debug($"CurrentCart.OrderFormId= {currentCart.Forms.First().OrderFormId}");
                        Logger.Debug($"Principal From Cart {currentCart.CustomerId}");
                    }

                    if (!currentCart.Forms.Any() || !currentCart.GetFirstForm().Payments.Any())
                    {
                        Logger.Debug($"Dintero payment {orderNumber} Cart is invalid!");
                        throw new PaymentException(PaymentException.ErrorType.ProviderError, "", "Cart is invalid!");
                    }

                    Logger.Debug($"Dintero payment {orderNumber} retrieved cart for current principal");
                }
                else
                {
                    // if session_id parameter is set it means that it is either Dintero callback was sent (in pair with redirect)
                    // or on_hold transaction was processed
                    // in the first case we need to check whether redirect was processed if yes then skip
                    // in the second we need to release order (check transaction if it is authorised or failed)

                    // check if cart has been already processed by redirect_url
                    currentCart = OrderHelper.GetCartByDinteroSessionId(session_id);
                    if (currentCart == null)
                    {
                        var order = OrderHelper.GetOrderByTrackingNumber(merchant_reference);
                        if (order != null && ((IOrderGroup)order).OrderStatus == OrderStatus.OnHold)
                        {
                            Logger.Debug($"Processing OnHold Order.");
                            var result = gateway.ProcessOnHoldOrder(order.Id, transaction_id);
                            if (result == null)
                            {
                                Logger.Debug("Unable to release OnHold order.");
                            }
                            else
                            {
                                Logger.Debug($"Processing OnHold Order completed: {result.OrderStatus}.");
                            }
                        }
                        else
                        {
                            Logger.Debug($"Dintero payment {orderNumber} cart is already processed");
                        }
                        return(new HttpStatusCodeResult(HttpStatusCode.OK));
                    }

                    Logger.Debug($"CurrentPrincipal {currentCart.CustomerId}");
                    Logger.Debug($"CurrentCart.OrderFormId= {currentCart.Forms.First().OrderFormId}");
                    Logger.Debug($"Dintero payment {orderNumber} cart as retrieved by session Id");
                }

                var formPayments = currentCart.Forms.SelectMany(f => f.Payments).Select(p => p.PaymentId);

                var payment = currentCart.Forms.SelectMany(f => f.Payments).FirstOrDefault(c =>
                                                                                           c.PaymentMethodId.Equals(_requestsHelper.Configuration.PaymentMethodId));

                if (payment == null)
                {
                    Logger.Debug($"Dintero payment {orderNumber} payment is null");

                    throw new PaymentException(PaymentException.ErrorType.ProviderError, "",
                                               $"Payment was not specified ({_requestsHelper.Configuration.PaymentMethodId}). Form payments: {string.Join(";", formPayments)}");
                }

                if (string.IsNullOrWhiteSpace(transaction_id) && string.IsNullOrWhiteSpace(error))
                {
                    var sessionData = _requestsHelper.CreateTransaction(payment, currentCart, trackingNumber);

                    if (sessionData != null)
                    {
                        var cart = _orderRepository.LoadCart <Cart>(currentCart.CustomerId, Cart.DefaultName);
                        cart[DinteroConstants.DinteroSessionMetaField] = sessionData.SessionId;
                        cart.OrderForms[0][DinteroConstants.DinteroSessionMetaField] = sessionData.SessionId;
                        cart.AcceptChanges();

                        Logger.Debug($"Dintero payment {orderNumber} redirect to checkout");

                        return(Redirect(sessionData.CheckoutUrl));
                    }

                    Logger.Debug($"Dintero payment {orderNumber} redirect to cancel");

                    return(Redirect(cancelUrl));
                }

                cancelUrl = UriUtil.AddQueryString(cancelUrl, "paymentMethod", "dintero");

                if (string.IsNullOrWhiteSpace(error) && !string.IsNullOrWhiteSpace(transaction_id) &&
                    !string.IsNullOrWhiteSpace(merchant_reference))
                {
                    payment.TransactionID   = transaction_id;
                    payment.TransactionType = TransactionType.Authorization.ToString();

                    redirectUrl = gateway.ProcessSuccessfulTransaction(currentCart, payment, transaction_id,
                                                                       merchant_reference, acceptUrl, cancelUrl);
                }
                else
                {
                    TempData["Message"] = error;
                    redirectUrl         = gateway.ProcessUnsuccessfulTransaction(cancelUrl, error);
                }

                Logger.Debug($"Dintero payment {orderNumber} call post authorize");

                DinteroPaymentGateway.PostProcessPayment.PostAuthorize(payment, error, transaction_id,
                                                                       merchant_reference);
            }
            catch (Exception e)
            {
                Logger.Error($"Dintero payment {orderNumber} failed {e}");
            }
            finally
            {
                Logger.Debug("Release");
                LockHelper.Release(orderNumber);
            }

            if (string.IsNullOrWhiteSpace(session_id))
            {
                Logger.Debug($"Dintero payment {orderNumber} redirect to {redirectUrl}");
                return(Redirect(redirectUrl));
            }

            return(new HttpStatusCodeResult(HttpStatusCode.OK));
        }