private TransactionResponse ProcessVoidRequest(TransactionData transData, ITokenizedPayment payment) => new TransactionResponse( _authorizeTokenExService.ProcessVoidRequest( payment.Properties[AuthorizeTokenExGateway.ProviderProfileIdPropertyName] as string, string.Empty, transData.transId), false);
public TransactionResponse Process( IOrderGroup orderGroup, TransactionRequest transactionRequest, TransactionData transactionData, decimal amount, ITokenizedPayment payment) { switch (transactionData.type) { case TransactionType.Authorization: return(ProcessAuthorizeRequest(orderGroup, transactionData, payment, amount)); case TransactionType.Capture: return(ProcessPriorCaptureRequest(transactionRequest, transactionData, amount)); case TransactionType.Sale: return(ProcessSaleRequest(orderGroup, transactionData, payment, amount)); case TransactionType.Credit: return(ProcessCreditRequest(transactionRequest, transactionData, payment, amount)); case TransactionType.Void: return(ProcessVoidRequest(transactionData, payment)); case TransactionType.CaptureOnly: return(ProcessCaptureOnlyRequest(transactionRequest, transactionData, payment, amount)); default: throw new NotImplementedException("Not implemented TransactionType: " + transactionData.type); } }
public TokenizationPaymentModel(ITokenizedPayment payment, Currency orderGroupCurrency) : base(payment, orderGroupCurrency) { Token = payment.Token; ExpirationMonth = payment.ExpirationMonth; ExpirationYear = payment.ExpirationYear; }
private AuthorizeNet.Order CreatePaymentOrder(IOrderGroup orderGroup, TransactionData transactionData, ITokenizedPayment payment, decimal orderAmount) { var customer = _authorizeTokenExService.CreateCustomer(transactionData.invoiceNum, payment.BillingAddress); var address = Utilities.ToAuthorizeNetAddress(payment.BillingAddress); customer.BillingAddress = address; _authorizeTokenExService.UpdateCustomer(customer); var shippingAddress = orderGroup.Forms.First().Shipments.First().ShippingAddress; if (shippingAddress == null) { throw new PaymentException(PaymentException.ErrorType.ConfigurationError, "", "Shipping address was not specified."); } var paymentProfileId = AddCreditCard(orderGroup, customer.ProfileID, payment.Token, payment.ExpirationMonth, payment.ExpirationYear); var shippingAddressId = AddShippingAddress(customer.ProfileID, Utilities.ToAuthorizeNetAddress(shippingAddress)); var currency = orderGroup.Currency; var market = _marketService.GetMarket(orderGroup.MarketId); var merchantCurrency = _authorizeTokenExService.GetMerchantCurrency(); var shippingTotal = Utilities.ConvertMoney(orderGroup.GetShippingTotal(_orderGroupCalculator), merchantCurrency); var salesTaxTotal = Utilities.ConvertMoney( new Money(orderGroup.Forms.Sum(form => form.Shipments.Sum(shipment => _shippingCalculator.GetSalesTax(shipment, market, currency).Amount)), currency).Round(), merchantCurrency); var taxTotal = Utilities.ConvertMoney(orderGroup.GetTaxTotal(_orderGroupCalculator), merchantCurrency); var order = new AuthorizeNet.Order(customer.ProfileID, paymentProfileId, shippingAddressId) { Amount = orderAmount - taxTotal, SalesTaxAmount = salesTaxTotal, PONumber = transactionData.purchaseOrderNum, InvoiceNumber = transactionData.invoiceNum, ShippingAmount = shippingTotal + (orderGroup.PricesIncludeTax ? 0 : taxTotal - salesTaxTotal) }; var orderedLineItems = orderGroup.GetAllLineItems().OrderBy(x => x.Quantity).ToList(); var largestQuantityItem = orderedLineItems.LastOrDefault(); var lineItemsAmount = 0m; var amountWithoutLargestQtyItem = 0m; var settleSubTotalExclTax = orderAmount - order.ShippingAmount - order.SalesTaxAmount; var isFirstLineItem = true; var factor = (decimal)Math.Pow(10, DecimalDigit); var roundingDelta = 1 / factor; var itemPriceExcludingTaxMapping = GetPriceExcludingTax(orderGroup); foreach (var lineItem in orderedLineItems) { var itemCode = lineItem.Code; var itemQuantity = Convert.ToInt32(lineItem.Quantity); var displayName = string.IsNullOrEmpty(lineItem.DisplayName) ? itemCode : lineItem.DisplayName; var description = (lineItem as Mediachase.Commerce.Orders.LineItem)?.Description ?? string.Empty; if (lineItem.IsGift) { itemCode = $"Gift: {itemCode}"; displayName = $"Gift: {displayName}"; description = $"Gift: {description}"; } itemCode = Utilities.StripPreviewText(itemCode, 31); displayName = Utilities.StripPreviewText(displayName, 31); description = Utilities.StripPreviewText(description, 255); // Calculate unit price. var unitPrice = Utilities.ConvertMoney( new Money(currency.Round(itemPriceExcludingTaxMapping[lineItem.LineItemId] / lineItem.Quantity, DecimalDigit), currency), merchantCurrency); lineItemsAmount += unitPrice * lineItem.Quantity; if (lineItem.LineItemId != largestQuantityItem.LineItemId) { amountWithoutLargestQtyItem = lineItemsAmount; } // In case we have Rounding Differences between rounding Total Amount (orderAmount - amount requested for settlement) // and rounding each lineItem unit price (amount authorized), need to recalculate unit price of item has largest quantity. if (lineItem.LineItemId == largestQuantityItem.LineItemId && lineItemsAmount < settleSubTotalExclTax) { // Choose largestQuantityItem to make the unitPrice difference before and after recalculate smallest. unitPrice = (settleSubTotalExclTax - amountWithoutLargestQtyItem) / largestQuantityItem.Quantity; // Round up to make sure amount authorized >= requested for settlement amount. unitPrice = merchantCurrency.Round(unitPrice + roundingDelta, DecimalDigit); } if (!isFirstLineItem) { // If the lineitem price to add to the total exceed the Amount chosen // for the payment. The line item price is adjusted, since it will be covered by other payment method. if (unitPrice * lineItem.Quantity + order.Total > order.Amount) { var lineItemPrice = orderAmount - order.Total; // If this is the last item, then we need to round up to make sure amount authorized >= requested for settlement amount. if (lineItem.LineItemId == largestQuantityItem.LineItemId) { unitPrice = merchantCurrency.Round(lineItemPrice / lineItem.Quantity + roundingDelta, DecimalDigit); } else { unitPrice = merchantCurrency.Round(lineItemPrice / lineItem.Quantity, DecimalDigit); } } } // Note that order total calculated from authorized.net order constructor is recalculated by adding line items. order.AddLineItem(itemCode, displayName, description, itemQuantity, unitPrice, null); // We need to handle the case of first line item after being added to the order // since order total is recalculated when is added to the order. if (isFirstLineItem) { // If with the first line item the amount chosen for the payment is exceeding // the price added to the line item then should be the amount chosen. if (order.Total > orderAmount) { // In case the order has only one line item, then we need to round up to make sure amount authorized >= requested for settlement amount. if (lineItem.LineItemId == largestQuantityItem.LineItemId) { unitPrice = merchantCurrency.Round(settleSubTotalExclTax / lineItem.Quantity + roundingDelta, DecimalDigit); } else { unitPrice = merchantCurrency.Round(settleSubTotalExclTax / lineItem.Quantity, DecimalDigit); } order.RemoveLineItem(itemCode); order.AddLineItem(itemCode, displayName, description, itemQuantity, unitPrice, null); } } isFirstLineItem = false; } payment.Properties[AuthorizeTokenExGateway.ProviderProfileIdPropertyName] = customer.ProfileID; return(order); }
private TransactionResponse ProcessCreditRequest(TransactionRequest transactionRequest, TransactionData transData, ITokenizedPayment payment, decimal amount) { var transactionDetail = GetTransactionDetails(transData, transactionRequest); if (transactionDetail.transactionStatus != AuthorizeTokenExGateway.SettledStatus) { throw new PaymentException(PaymentException.ErrorType.StatusError, "", "Refund payment requires transaction status to be settled."); } // clone the Refund method in order to set InvoiceNumber var request = new AuthorizeNet.APICore.createCustomerProfileTransactionRequest { transaction = new AuthorizeNet.APICore.profileTransactionType { Item = new AuthorizeNet.APICore.profileTransRefundType { amount = amount, customerProfileId = payment.Properties[AuthorizeTokenExGateway.ProviderProfileIdPropertyName] as string, transId = transData.transId, order = new AuthorizeNet.APICore.orderExType { purchaseOrderNumber = transData.purchaseOrderNum, invoiceNumber = transData.invoiceNum } } } }; return(new TransactionResponse(_authorizeTokenExService.SendRequest(request), false)); }
private TransactionResponse ProcessCaptureOnlyRequest(TransactionRequest transactionRequest, TransactionData transData, ITokenizedPayment payment, decimal amount) { if (IsTransactionCapturedOrSettled(transData, transactionRequest)) { return(new TransactionResponse(null, true)); } // clone the capture method in order to set InvoiceNumber var request = new AuthorizeNet.APICore.createCustomerProfileTransactionRequest { transaction = new AuthorizeNet.APICore.profileTransactionType { Item = new AuthorizeNet.APICore.profileTransCaptureOnlyType { approvalCode = transData.AuthorizationCode, customerProfileId = payment.Properties[AuthorizeTokenExGateway.ProviderProfileIdPropertyName] as string, amount = amount, order = new AuthorizeNet.APICore.orderExType { purchaseOrderNumber = transData.purchaseOrderNum, invoiceNumber = transData.invoiceNum } } } }; return(new TransactionResponse(_authorizeTokenExService.SendRequest(request), false)); }
private TransactionResponse ProcessSaleRequest(IOrderGroup orderGroup, TransactionData transactionData, ITokenizedPayment payment, decimal amount) { var order = CreatePaymentOrder(orderGroup, transactionData, payment, amount); return(new TransactionResponse(_authorizeTokenExService.AuthorizeAndCapture(order), false)); }
private TransactionData CreateTransactionDataForRegularTransaction( IOrderGroup orderGroup, ITokenizedPayment tokenPayment) { var transData = new TransactionData { AuthorizationCode = tokenPayment.ValidationCode, }; if (string.IsNullOrEmpty(tokenPayment.TransactionType) || !Enum.TryParse(tokenPayment.TransactionType, out transData.type)) { var type = Settings[PaymentOptionParameterName].Equals(TransactionType.Sale.ToString(), StringComparison.OrdinalIgnoreCase) ? TransactionType.Sale : TransactionType.Authorization; if (string.IsNullOrEmpty(tokenPayment.TransactionType)) { tokenPayment.TransactionType = type.ToString(); } transData.type = type; } var orderForm = orderGroup.Forms.FirstOrDefault(form => form.Payments.Contains(tokenPayment)); if (transData.type == TransactionType.Capture && orderForm != null && orderForm.CapturedPaymentTotal != 0 && orderForm.Payments.Count(p => p.PaymentMethodId == tokenPayment.PaymentMethodId && p.TransactionType == TransactionType.Capture.ToString()) > 1) { // from the second capture, the transaction type must be CAPTURE_ONLY instead of PRIOR_AUTH_CAPTURE transData.type = TransactionType.CaptureOnly; } if (transData.type != TransactionType.Authorization) { // ProviderTransactionID might be null in site-upgrade case. Then we should get TransactionID in that case. transData.transId = !string.IsNullOrEmpty(tokenPayment.ProviderTransactionID) ? tokenPayment.ProviderTransactionID : tokenPayment.TransactionID; } if (orderGroup is IPurchaseOrder purchaseOrder) { transData.purchaseOrderNum = purchaseOrder.OrderNumber; var paymentIndex = orderGroup.Forms.SelectMany(form => form.Payments).Count(); transData.invoiceNum = $"{transData.purchaseOrderNum}-{paymentIndex}"; } else if (orderGroup is ICart) { string orderNumber; if (orderGroup is Cart cart) { orderNumber = cart.GenerateOrderNumber(cart); cart.OrderNumberMethod = c => orderNumber; cart.AcceptChanges(); } else { var orderNumberGenerator = ServiceLocator.Current.GetInstance <IOrderNumberGenerator>(); orderNumber = orderNumberGenerator.GenerateOrderNumber(orderGroup); orderGroup.Properties["OrderNumber"] = orderNumber; } transData.invoiceNum = orderNumber; } return(transData); }
/// <summary> /// Post process payment, remove token form payment. /// </summary> /// <param name="tokenPayment">Input payment, it is supposed to be a ITokenizationPayment.</param> private void PostProcessPayment(ITokenizedPayment tokenPayment) { tokenPayment.Token = string.Empty; }