/// <summary> /// Gets the payment service based on the tender type. /// </summary> /// <param name="context">The context.</param> /// <param name="requestType">Request type.</param> /// <param name="tenderTypeId">The id of tender type.</param> /// <returns>Tender service.</returns> private static IRequestHandler ResolvePaymentService(RequestContext context, Type requestType, string tenderTypeId) { if (string.IsNullOrWhiteSpace(tenderTypeId)) { throw new ArgumentException("tenderTypeId is null or empty", "tenderTypeId"); } TenderType tenderType = GetTenderType(context, tenderTypeId); if (tenderType == null) { var message = string.Format( CultureInfo.InvariantCulture, "Failed to load tender type with id: {0}", tenderTypeId); throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ObjectNotFound, message); } IRequestHandler paymentHandler = context.Runtime.GetRequestHandler(requestType, tenderType.OperationId); if (paymentHandler == null) { throw new ConfigurationException( ConfigurationErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidProviderConfiguration, string.Format("Unable to retrieve tender service for operation: {0}.", tenderType.OperationId)); } return(paymentHandler); }
public void OtherValues() { #region Tender Type var tenderType = new TenderType(); var tendertype = tenderType.FindAllTenderType().ToList(); ViewData["TenderType"] = new SelectList(tendertype, "TenderTypeValue", "TenderTypeName"); #endregion #region Tender Status var tderStatus = new TenderStatus(); var tenderStatus = tderStatus.FindAllTenderStatus().ToList(); ViewData["TenderStatus"] = new SelectList(tenderStatus, "TenderStatusValue", "TenderStatusName"); #endregion #region Tender Value Type var tenderValType = new TenderValType(); var tvaltype = tenderValType.FindAllTenderValType().ToList(); ViewData["TenderValType"] = new SelectList(tvaltype, "TenderValTypeValue", "TenderValTypeName"); #endregion var commondata = new List <SelectListItem>(); commondata.Insert(0, (new SelectListItem { Text = "[None]", Value = "0" })); ViewData["List"] = new SelectList(commondata, "Value", "Text"); }
//called by an ajax function public TenderlineView AddTenderline(string TenderTypeId, string TenderValue, string saleTotal, string paidTotal) { float saleTotali = float.Parse(saleTotal, CultureInfo.InvariantCulture.NumberFormat); float paidTotali = float.Parse(paidTotal, CultureInfo.InvariantCulture.NumberFormat); TenderlineView tl = new TenderlineView(); tl.TenderTypeID = Convert.ToInt32(TenderTypeId); tl.Status = "A"; TenderType tenderType = db.TenderTypes.ToList().Single <TenderType>(x => x.TenderTypeID == tl.TenderTypeID); tl.Description = tenderType.Description; tl.TenderValue = float.Parse(TenderValue, CultureInfo.InvariantCulture.NumberFormat); if (paidTotali + tl.TenderValue > saleTotali) { if (tenderType.ChangeGiven) //e.g. cash { //If the paid total goes over the sale total, then calculate change given tl.ChangeGiven = paidTotali + tl.TenderValue - saleTotali; } } return(tl); }
public ActionResult DeleteConfirmed(int id) { TenderType tenderType = db.TenderTypes.Find(id); db.TenderTypes.Remove(tenderType); db.SaveChanges(); return(RedirectToAction("Index")); }
public bool CanTenderTypeGiveChange(int tenderTypeID) { if (tenderTypeID == 0) { return(true); } TenderType tenderType = db.TenderTypes.ToList().Single <TenderType>(x => x.TenderTypeID == tenderTypeID); return(tenderType.ChangeGiven); }
public async Task UpdateTender(string tenderCode, TenderType tender) { var tenderFromDB = await _context.TenderType.FirstOrDefaultAsync(c => c.Code.Equals(tenderCode)); tender.Code = tenderFromDB.Code; _context.Entry(tenderFromDB).CurrentValues.SetValues(tender); _context.Entry(tenderFromDB).Property(x => x.CreatedDate).IsModified = false; _context.Entry(tenderFromDB).Property(x => x.CreatedBy).IsModified = false; await _context.SaveChangesAsync(); }
public ActionResult Edit([Bind(Include = "TenderTypeId,Name")] TenderType tenderType) { if (ModelState.IsValid) { db.Entry(tenderType).State = EntityState.Modified; db.SaveChanges(); return(RedirectToAction("Index")); } return(View(tenderType)); }
public ActionResult Create([Bind(Include = "TenderTypeId,Name")] TenderType tenderType) { if (ModelState.IsValid) { db.TenderTypes.Add(tenderType); db.SaveChanges(); return(RedirectToAction("Index")); } return(View(tenderType)); }
// GET: TenderType/Delete/5 public ActionResult Delete(int?id) { if (id == null) { return(new HttpStatusCodeResult(HttpStatusCode.BadRequest)); } TenderType tenderType = db.TenderTypes.Find(id); if (tenderType == null) { return(HttpNotFound()); } return(View(tenderType)); }
/// <summary> /// Round for channel payment method. /// </summary> /// <param name="request">Service request.</param> /// <returns>Rounded value.</returns> private GetRoundedValueServiceResponse GetPaymentRoundedValue(GetPaymentRoundedValueServiceRequest request) { GetChannelTenderTypesDataRequest dataServiceRequest = new GetChannelTenderTypesDataRequest(request.RequestContext.GetPrincipal().ChannelId, QueryResultSettings.AllRecords); EntityDataServiceResponse <TenderType> response = request.RequestContext.Execute <EntityDataServiceResponse <TenderType> >(dataServiceRequest); TenderType tenderType = response.PagedEntityCollection.Results.SingleOrDefault(channelTenderType => string.Equals(channelTenderType.TenderTypeId, request.TenderTypeId, StringComparison.OrdinalIgnoreCase)); RoundingMethod roundingMethod = tenderType.RoundingMethod; if (roundingMethod == RoundingMethod.None) { return(new GetRoundedValueServiceResponse(request.Value)); } decimal currencyUnit = tenderType.RoundOff; if (currencyUnit == decimal.Zero) { currencyUnit = Rounding.DefaultRoundingValue; } decimal roundedValue; if (request.IsChange) { // For change rounding up/down should be applied in opposite direction. if (roundingMethod == RoundingMethod.Down) { roundingMethod = RoundingMethod.Up; } else if (roundingMethod == RoundingMethod.Up) { roundingMethod = RoundingMethod.Down; } } // Using absolute value so payment and refund is rounded same way when rounding up or down. decimal absoluteAmount = Math.Abs(request.Value); roundedValue = Rounding.RoundToUnit(absoluteAmount, currencyUnit, roundingMethod); if (request.Value < 0) { // Revert sign back to original. roundedValue = decimal.Negate(roundedValue); } return(new GetRoundedValueServiceResponse(roundedValue)); }
/// <summary> /// Add Tender in Dinerware /// </summary> /// <param name="oTenderType"></param> /// <param name="sActionType"></param> /// <returns></returns> public int AddTenderType(TenderType oTenderType, string sActionType) { try { return(virtualDinerwareClient.AddTenderType(oTenderType, sActionType)); } catch (Exception ex) { logger.WriteLogError("**** Dinerware VirtualClient FAILURE: AddTenderType Exception Error= " + ex.Message); if (ex.InnerException != null) { logger.WriteLogError("**** InnerException = " + ex.InnerException.Message); } throw ex; } }
/// <summary> /// Customer account deposit transactions cannot be tendered with the 'On Account' payment method. /// </summary> /// <param name="context">The context.</param> /// <param name="transaction">The transaction.</param> /// <param name="tenderLineBase">The tender line.</param> public static void ValidateCustomerAccountDepositPaymentRestrictions(RequestContext context, SalesTransaction transaction, TenderLineBase tenderLineBase) { if (transaction.CartType != CartType.AccountDeposit) { return; } var getChannelTenderTypesDataRequest = new GetChannelTenderTypesDataRequest(context.GetPrincipal().ChannelId, QueryResultSettings.AllRecords); var tenderTypes = context.Runtime.Execute <EntityDataServiceResponse <TenderType> >(getChannelTenderTypesDataRequest, context).PagedEntityCollection.Results; TenderType tenderType = tenderTypes.Single(t => t.TenderTypeId.Equals(tenderLineBase.TenderTypeId)); // It should not be allowed to pay with and deposit to the same customer account. if (tenderType.OperationType == RetailOperation.PayCustomerAccount && tenderLineBase.CustomerId.Equals(transaction.CustomerId)) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CannotPayForCustomerAccountDepositWithCustomerAccountPaymentMethod, "Customer account deposit transactions cannot be tendered with the 'On Account' payment method."); } }
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> /// Calculate specific reason codes on a tender line and add them to the incoming collection. /// </summary> /// <param name="request">The request object.</param> /// <param name="requiredReasonCodes">The collection to which required reason codes are added.</param> /// <param name="reasonCodeRequirements">The required specific reason codes map.</param> /// <param name="tenderLine">The tenderLine on which to calculate required reason codes.</param> private static void CalculateRequiredSpecificReasonCodesOnTenderLine( CalculateRequiredReasonCodesServiceRequest request, IDictionary <string, ReasonCode> requiredReasonCodes, HashSet <ReasonCodeRequirement> reasonCodeRequirements, TenderLine tenderLine) { if (tenderLine.Status == TenderLineStatus.Historical) { return; } // if tenderline is a card, refrelation3 becomes tenderline.cardtypeid and tablerefid is creditcard var getChannelTenderTypesDataRequest = new GetChannelTenderTypesDataRequest(request.RequestContext.GetPrincipal().ChannelId, QueryResultSettings.AllRecords); var tenderTypes = request.RequestContext.Runtime.Execute <EntityDataServiceResponse <TenderType> >(getChannelTenderTypesDataRequest, request.RequestContext).PagedEntityCollection.Results; ReasonCodeTableRefType tableRef = ReasonCodeTableRefType.Tender; string refRelation3 = string.Empty; TenderType tenderType = tenderTypes.Where(type => type.TenderTypeId == tenderLine.TenderTypeId).SingleOrDefault(); if (tenderType.OperationId == (int)RetailOperation.PayCard) { refRelation3 = tenderLine.CardTypeId; tableRef = ReasonCodeTableRefType.CreditCard; } CalculateReasonCodesSpecificToEntity( request, tenderLine.TenderTypeId, tableRef, request.SalesTransaction.StoreId, tenderLine.TenderTypeId, refRelation3, requiredReasonCodes, reasonCodeRequirements, tenderLine.ReasonCodeLines, null); }
public static string EnumToString(this TenderType type) { switch (type) { case TenderType.CreditCard: return("CREDIT_CARD"); case TenderType.Cash: return("CASH"); case TenderType.ThirdPartyCard: return("THIRD_PARTY_CARD"); case TenderType.NoSale: return("NO_SALE"); case TenderType.SquareWallet: return("SQUARE_WALLET"); case TenderType.SquareGiftCard: return("SQUARE_GIFT_CARD"); case TenderType.Unknown: return("UNKNOWN"); case TenderType.Other: return("OTHER"); default: throw new ArgumentOutOfRangeException(); } }
// Bắt sự kiện trước khi user click button OK trong màn hình thanh toán (sau khi đã chọn phương thức thanh toán) public override void OnBeforeAddPayment(object sender, EventArgs <Transaction, TransactionPayment> args) { Transaction tran = args.Item; var a = tran.TransactionSaleAttributes; TransactionPayment tranPayment = args.ChildItem; // TransactionkeyVNPAY: Tên của SaleAttribute do user tạo ra để lưu thêm key khi tạo transaction gửi sang VNPAY TransactionSaleAttribute transactionkeyVNPAY = tran.TransactionSaleAttributes.FirstOrDefault(p => p.SaleAttribute.Name == "TransactionkeyVNPAY"); string popMappingFile = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + "\\Models\\POSMapping.json"; string popMappingText = File.ReadAllText(popMappingFile); List <POSMapping> lstPOSMapping = JsonConvert.DeserializeObject <List <POSMapping> >(popMappingText); // Lấy thông tin máy mPOS tương ứng với từng điểm bán hàng đã được setup POSMapping objMapping = lstPOSMapping.FirstOrDefault(x => x.StoreKey == tran.StoreKey && x.POSKey == tran.POSKey); if (objMapping == null) { XtraMessageBox.Show("Không tìm thấy máy mPOS.", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error); args.Cancel = true; return; } string terminalCode = objMapping.TerminalCode; TenderType paytype = tranPayment.PaymentType.Type; string id = tranPayment.PaymentType.Id; if (paytype == TenderType.Custom && id == "VNPAYCard") { // Tạo metadata MetaData data = new MetaData(); data.payerName = tran.TransactionCustomerName; data.language = "vi"; string metadata = JsonConvert.SerializeObject(data); // Tạo parameter call API ParameterTransactionAPI para = new ParameterTransactionAPI(); para.amount = Money.ToInt64(tran.Total); para.clientCode = "FTI"; para.clientTransactionCode = Guid.NewGuid().ToString(); para.metadata = "METAVALUE"; para.methodCode = "SPOSCARD"; para.orderCode = Guid.NewGuid().ToString(); para.orderDescription = ""; para.orderId = Guid.NewGuid().ToString(); para.partnerCode = "VNPAY"; para.serviceCode = "RETAIL"; para.terminalCode = terminalCode; var strParaBody = string.Format("{0}amount={1}&clientCode={2}&clientTransactionCode={3}&metadata=METAVALUE&methodCode=SPOSCARD&orderCode={4}&orderDescription={5}&orderId={6}&partnerCode=VNPAY&serviceCode=RETAIL&terminalCode={7}", "b8399f824670b0bf07c84267ca9b1dff", para.amount, para.clientCode, para.clientTransactionCode, para.orderCode, para.orderDescription, para.orderId, para.terminalCode); strParaBody = strParaBody.Replace("METAVALUE", metadata); strParaBody = strParaBody.Replace("\"{", "{").Replace("}\"", "}"); para.checksum = CallAPI.CreateMD5(strParaBody); string strPara = JsonConvert.SerializeObject(para); strPara = strPara.Replace("METAVALUE", metadata); strPara = strPara.Replace("\"{", "{").Replace("}\"", "}"); // Call API để tạo Transaction ApiResultCARD resultPaymentVNPAYCard = CallAPI.PaymentByCard(strPara); // Tạo giao dịch thanh toán bằng VNPAY Card bị lỗi => Thông báo cho user biết lỗi if (!resultPaymentVNPAYCard.success) { XtraMessageBox.Show(resultPaymentVNPAYCard.message, "Thông báo", MessageBoxButtons.OK); args.Cancel = true; return; } Thread.Sleep(15000); // Đợi 15s trước khi call API tra cứu kết quả bool tryGetDetail = true; while (tryGetDetail) { Thread.Sleep(5000); // Tạo giao dịch thanh toán bằng VNPAY Card thành công => Gọi API lấy kết quả giao dịch. ParameterRessulAPI paraResult = new ParameterRessulAPI(); paraResult.client_code = para.clientCode; paraResult.client_transaction_code = para.clientTransactionCode; paraResult.ps_transaction_code = resultPaymentVNPAYCard.data.psTransactionCode; var strParaResultBody = string.Format("{0}client_code={1}&client_transaction_code={2}&ps_transaction_code={3}", "b8399f824670b0bf07c84267ca9b1dff", paraResult.client_code, paraResult.client_transaction_code, paraResult.ps_transaction_code); paraResult.checksum = CallAPI.CreateMD5(strParaResultBody); string strParaResult = JsonConvert.SerializeObject(paraResult); ApiResultOrderDetail resultOrderDetail = CallAPI.GetTransactionDetail(paraResult); if (!resultOrderDetail.success) { XtraMessageBox.Show("Lấy kết quả giao dịch lỗi: " + resultOrderDetail.message, "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error); args.Cancel = true; return; } else { if (resultOrderDetail.data.psResponseCode == null) { tryGetDetail = true; } else if (resultOrderDetail.data.psResponseCode == "000") { XtraMessageBox.Show("Giao dịch thành công!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information); transactionkeyVNPAY.AttributeValue = para.clientTransactionCode; tran.TransactionSaleAttributes.Add(transactionkeyVNPAY); tryGetDetail = false; return; } else { XtraMessageBox.Show("Giao dịch thất bại!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error); tryGetDetail = false; args.Cancel = true; return; } } } } else if (paytype == TenderType.Custom && id == "VNPAYQRCode") { // Tạo metadata MetaData data = new MetaData(); data.payerName = tran.TransactionCustomerName; data.language = "vi"; string metadata = JsonConvert.SerializeObject(data); // Tạo parameter call API ParameterTransactionAPI para = new ParameterTransactionAPI(); para.amount = Money.ToInt64(tran.Total); para.clientCode = "FTI"; para.clientTransactionCode = Guid.NewGuid().ToString(); para.metadata = "METAVALUE"; para.methodCode = "QRCODE"; para.orderCode = Guid.NewGuid().ToString(); para.orderDescription = ""; para.orderId = Guid.NewGuid().ToString(); para.partnerCode = "VNPAY"; para.serviceCode = "RETAIL"; para.terminalCode = terminalCode; var strParaBody = string.Format("{0}amount={1}&clientCode={2}&clientTransactionCode={3}&metadata=METAVALUE&methodCode=QRCODE&orderCode={4}&orderDescription={5}&orderId={6}&partnerCode=VNPAY&serviceCode=RETAIL&terminalCode={7}", "b8399f824670b0bf07c84267ca9b1dff", para.amount, para.clientCode, para.clientTransactionCode, para.orderCode, para.orderDescription, para.orderId, para.terminalCode); strParaBody = strParaBody.Replace("METAVALUE", metadata); strParaBody = strParaBody.Replace("\"{", "{").Replace("}\"", "}"); para.checksum = CallAPI.CreateMD5(strParaBody); string strPara = JsonConvert.SerializeObject(para); strPara = strPara.Replace("METAVALUE", metadata); strPara = strPara.Replace("\"{", "{").Replace("}\"", "}"); // Call API để tạo Transaction ApiResultQR resultPaymentVNPAYQR = CallAPI.PaymentByQR(strPara); // Tạo giao dịch thanh toán bằng VNPAY QR bị lỗi => Thông báo cho user biết lỗi if (!resultPaymentVNPAYQR.success) { XtraMessageBox.Show(resultPaymentVNPAYQR.message, "Thông báo", MessageBoxButtons.OK); args.Cancel = true; return; } Thread.Sleep(15000); // Đợi 15s trước khi call API tra cứu kết quả bool tryGetDetail = true; while (tryGetDetail) { Thread.Sleep(5000); // Tạo giao dịch thanh toán bằng VNPAY Card thành công => Gọi API lấy kết quả giao dịch. ParameterRessulAPI paraResult = new ParameterRessulAPI(); paraResult.client_code = para.clientCode; paraResult.client_transaction_code = para.clientTransactionCode; paraResult.ps_transaction_code = resultPaymentVNPAYQR.data.psTransactionCode; var strParaResultBody = string.Format("{0}client_code={1}&client_transaction_code={2}&ps_transaction_code={3}", "b8399f824670b0bf07c84267ca9b1dff", paraResult.client_code, paraResult.client_transaction_code, paraResult.ps_transaction_code); paraResult.checksum = CallAPI.CreateMD5(strParaResultBody); string strParaResult = JsonConvert.SerializeObject(paraResult); ApiResultOrderDetail resultOrderDetail = CallAPI.GetTransactionDetail(paraResult); if (!resultOrderDetail.success) { XtraMessageBox.Show("Lấy kết quả giao dịch lỗi: " + resultOrderDetail.message, "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error); args.Cancel = true; return; } else { if (resultOrderDetail.data.psResponseCode == null) { tryGetDetail = true; } else if (resultOrderDetail.data.psResponseCode == "000") { XtraMessageBox.Show("Giao dịch thành công!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information); transactionkeyVNPAY.AttributeValue = para.clientTransactionCode; tran.TransactionSaleAttributes.Add(transactionkeyVNPAY); tryGetDetail = false; return; } else { XtraMessageBox.Show("Giao dịch thất bại!", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error); tryGetDetail = false; args.Cancel = true; return; } } } } }
public TenderTypeVM() { // Initialise the entity or inserts will fail TheEntity = new TenderType(); }
public async Task CreateTender(TenderType tender) { _context.TenderType.Add(tender); await _context.SaveChangesAsync(); }
public void SaveMerchantProfiles(string sessionToken, string serviceId, TenderType tenderType, List<MerchantProfile> merchantProfiles ) { if (_msgFormat == MessageFormat.SOAP.ToString()) { using (var client = new CWSServiceInformationClient(ConfigurationManager.AppSettings["Bindings.StsSoap"])) { try { // Referencing the STS service directly requires the merchant profiles to be in an arry instead of type List. // When generating proxies from the WSDL you can specify to use lists instead of arrays. client.SaveMerchantProfiles(sessionToken, serviceId, tenderType, merchantProfiles.ToArray()); } catch (FaultException ex) { SoapFaultHandler.HandleFaultException(ex); } } } else // REST JSON or XML { var isJson = string.Equals(_msgFormat, MessageFormat.JSON.ToString()); var requestString = RestBaseUri + "/merchProfile?serviceId=" + serviceId; var request = RestHelper.CreateRestRequest(merchantProfiles, requestString, HttpMethod.PUT, sessionToken, isJson); try { RestHelper.GetResponse(request, isJson); } catch(Exception ex) { RestFaultHandler.HandleFaultException(ex, isJson); } } }
/// <summary> /// Validate that all payments made with same tender type do not exceed limits defined for tender type. /// </summary> /// <param name="salesTransaction">Sales transaction.</param> /// <param name="tenderLine">Tender line to validate.</param> /// <param name="tenderType">Tender type information.</param> private static void ValidateTransactionLimits(SalesTransaction salesTransaction, TenderLine tenderLine, TenderType tenderType) { if (salesTransaction == null) { throw new ArgumentNullException("salesTransaction"); } if (tenderLine == null) { throw new ArgumentNullException("tenderLine"); } if (tenderType == null) { throw new ArgumentNullException("tenderType"); } decimal amountAlreadyPaidWithSameTenderType = salesTransaction.TenderLines.Where(t => t.Status != TenderLineStatus.Voided && t.TenderTypeId == tenderLine.TenderTypeId).Sum(t => t.Amount); decimal totalAmountPaidWithTenderType = tenderLine.Amount + amountAlreadyPaidWithSameTenderType; var validationFailures = new Collection <DataValidationFailure>(); // Card refund does not honor MaximumAmountPerTransaction. // Only check the limit when the tender is not card refund. if (!IsCardRefund(tenderType, tenderLine)) { if (tenderType.MaximumAmountPerTransaction > 0 && Math.Abs(totalAmountPaidWithTenderType) > tenderType.MaximumAmountPerTransaction) { validationFailures.Add(new DataValidationFailure(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_PaymentExceedsMaximumAmountPerTransaction, "tenderLine.Amount")); } } if (validationFailures.Any()) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_AggregateValidationError, validationFailures, "Payment amount exceeds limits defined per transaction."); } }
/// <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); }
/// <summary> /// Gets the change. /// </summary> /// <param name="request">The request.</param> /// <returns> /// A response containing the change tender line. /// </returns> private static GetChangePaymentServiceResponse GetChange(GetChangePaymentServiceRequest request) { if (request == null) { throw new ArgumentNullException("request"); } if (string.IsNullOrWhiteSpace(request.PaymentTenderTypeId)) { throw new PaymentException(PaymentErrors.Microsoft_Dynamics_Commerce_Runtime_InvalidPaymentRequest, "request.TenderTypeId is null or empty."); } TenderType overtenderTenderType = GetTenderType(request.RequestContext, request.PaymentTenderTypeId); if (overtenderTenderType == null) { throw new DataValidationException( DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ObjectNotFound, string.Format("Tender type with id '{0}' not found", request.PaymentTenderTypeId)); } string changeTenderTypeId; if (overtenderTenderType.AboveMinimumChangeAmount != decimal.Zero && Math.Abs(request.ChangeAmount) > Math.Abs(overtenderTenderType.AboveMinimumChangeAmount) && !string.IsNullOrWhiteSpace(overtenderTenderType.AboveMinimumChangeTenderTypeId)) { // Use "above minimum change tender type" if amount exceeds configured value. changeTenderTypeId = overtenderTenderType.AboveMinimumChangeTenderTypeId; } else { changeTenderTypeId = overtenderTenderType.ChangeTenderTypeId; } if (string.IsNullOrWhiteSpace(changeTenderTypeId)) { // If change tender type is not configured using tender type of last payment (ePOS behavior) changeTenderTypeId = overtenderTenderType.TenderTypeId; } TenderType changeTenderType = GetTenderType(request.RequestContext, changeTenderTypeId); if (changeTenderType == null) { // If change tender type is not configured using tender type of last payment (ePOS behavior) changeTenderType = overtenderTenderType; } request.ChangeTenderTypeId = changeTenderType.TenderTypeId; // Round change amount. request.ChangeAmount = RoundAmountByTenderType(request.RequestContext, request.ChangeTenderTypeId, request.ChangeAmount, isChange: true); IRequestHandler paymentService = ResolvePaymentService(request.RequestContext, request.GetType(), request.ChangeTenderTypeId); GetChangePaymentServiceResponse response = request.RequestContext.Runtime.Execute <GetChangePaymentServiceResponse>(request, request.RequestContext, paymentService); // Update tender lines with amounts and exchange rates for channel and company currencies. CalculateTenderLineCurrencyAmounts(response.TenderLine, request.RequestContext); return(response); }
public List<MerchantProfile> GetMerchantProfiles(string sessionToken, string serviceId, TenderType tenderType, string merchantProfileId = null) { if (_msgFormat == MessageFormat.SOAP.ToString()) { using (var client = new CWSServiceInformationClient(ConfigurationManager.AppSettings["Bindings.StsSoap"])) { try { return client.GetMerchantProfiles(sessionToken, serviceId, tenderType).ToList(); } catch (FaultException ex) { SoapFaultHandler.HandleFaultException(ex); } } } else // REST JSON or XML { var isJson = string.Equals(_msgFormat, MessageFormat.JSON.ToString()); // For REST, to return all Merchant Profiles by merchantProfileId. Otherwise return all Merchant Profiles by service ID. var requestString = ""; if(!string.IsNullOrEmpty(merchantProfileId)) requestString = RestBaseUri + "/merchProfile?merchantProfileId=" + merchantProfileId; else requestString = RestBaseUri + "/merchProfile?serviceId=" + serviceId; HttpWebRequest request = WebRequest.Create(requestString) as HttpWebRequest; request.Method = HttpMethod.GET.ToString(); request.Credentials = new NetworkCredential(sessionToken, ""); request.ContentType = isJson ? "application/json" : "application/xml"; // You'll need to use the Rest merchant profile Id Data Contract for serializing. This is then converted to use the standard data contract. var restMerchProfiles = new List<MerchantProfileId>(); try { restMerchProfiles = RestHelper.GetResponseList<MerchantProfileId>(request, isJson); } catch (Exception ex) { RestFaultHandler.HandleFaultException(ex, isJson); } var merchProfiles = new List<MerchantProfile>(); foreach (var rmp in restMerchProfiles) { var mp = new MerchantProfile(); mp.ProfileId = rmp.id; mp.ServiceId = rmp.href.Split('=')[1]; merchProfiles.Add(mp); } return merchProfiles; } return null; }
/// <summary> /// Validate that amount on tender line do not exceed limits defined for tender type. /// </summary> /// <param name="context">The request context.</param> /// <param name="salesTransaction">Sales transaction.</param> /// <param name="tenderLine">Tender line to validate.</param> /// <param name="tenderType">Tender type information.</param> private static void ValidateTenderLineLimits(RequestContext context, SalesTransaction salesTransaction, TenderLine tenderLine, TenderType tenderType) { if (salesTransaction == null) { throw new ArgumentNullException("salesTransaction"); } if (tenderLine == null) { throw new ArgumentNullException("tenderLine"); } if (tenderType == null) { throw new ArgumentNullException("tenderType"); } decimal amountDue = RoundAmountByTenderType(context, tenderLine.TenderTypeId, salesTransaction.AmountDue, isChange: false); var validationFailures = new Collection <DataValidationFailure>(); if (tenderLine.Amount != 0 && (Math.Sign(amountDue) != Math.Sign(tenderLine.Amount))) { validationFailures.Add(new DataValidationFailure(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_IncorrectPaymentAmountSign, "tenderLine.Amount")); } if (tenderType.MaximumAmountPerLine > 0 && Math.Abs(tenderLine.Amount) > tenderType.MaximumAmountPerLine) { // 1396 = The maximum amount allowed is: validationFailures.Add(new DataValidationFailure(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_PaymentExceedsMaximumAmountPerLine, "tenderLine.Amount")); } if (tenderType.MinimumAmountPerLine > 0 && Math.Abs(tenderLine.Amount) < tenderType.MinimumAmountPerLine) { // 1397 = The minimum amount allowed is: validationFailures.Add(new DataValidationFailure(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_PaymentExceedsMinimumAmountPerLine, "tenderLine.Amount")); } // Card refund does not honor overtender/undertender limits. // Only check those limits when the tender is not card refund. if (!IsCardRefund(tenderType, tenderLine)) { if (Math.Abs(amountDue) < Math.Abs(tenderLine.Amount)) { if (!tenderType.IsOvertenderAllowed) { // 1391 = No change allowed: validationFailures.Add(new DataValidationFailure(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_ChangebackIsNotAllowed, "tenderLine.Amount")); } if (tenderType.MaximumOvertenderAmount > 0 && tenderType.MaximumOvertenderAmount < (Math.Abs(tenderLine.Amount) - Math.Abs(amountDue))) { validationFailures.Add(new DataValidationFailure(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_OvertenderAmountExceedsMaximumAllowedValue, "tenderLine.Amount")); } } else if (Math.Abs(amountDue) > Math.Abs(tenderLine.Amount)) { if (!tenderType.IsUndertenderAllowed) { // 1394 = This payment must be used to finalize the transaction: validationFailures.Add(new DataValidationFailure(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_PaymentMustBeUsedToFinalizeTransaction, "tenderLine.Amount")); } if (tenderType.MaximumUndertenderAmount > 0 && (Math.Abs(amountDue) - Math.Abs(tenderLine.Amount)) > tenderType.MaximumUndertenderAmount) { validationFailures.Add(new DataValidationFailure(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_BalanceAmountExceedsMaximumAllowedValue, "tenderLine.Amount")); } if (tenderLine.CashBackAmount > 0) { validationFailures.Add(new DataValidationFailure(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_PaymentMustBeUsedToFinalizeTransaction, "tenderLine.Amount")); } } } if (tenderType.OperationType == RetailOperation.PayCard) { validationFailures.AddRange(ValidateCardTypeLimits(context, tenderLine)); } if (validationFailures.Any()) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_AggregateValidationError, validationFailures, "Payment amount exceeds limits defined per transaction."); } }
public bool IsMerchantProfileInitialized(string sessionToken, string serviceId, string merchantProfileId, TenderType tenderType) { if (_msgFormat == MessageFormat.SOAP.ToString()) { using (var client = new CWSServiceInformationClient(ConfigurationManager.AppSettings["Bindings.StsSoap"])) { try { return client.IsMerchantProfileInitialized(sessionToken, serviceId, merchantProfileId, tenderType); } catch (FaultException ex) { SoapFaultHandler.HandleFaultException(ex); } } } else // REST JSON or XML { var isJson = string.Equals(_msgFormat, MessageFormat.JSON.ToString()); // No body is required for GetServiceInformation in the HttpWebRequest. var requestString = RestBaseUri + "/merchProfile/" + merchantProfileId + "/OK?serviceId=" + serviceId; HttpWebRequest request = WebRequest.Create(requestString) as HttpWebRequest; request.Method = HttpMethod.GET.ToString(); request.Credentials = new NetworkCredential(sessionToken, ""); request.ContentType = isJson ? "application/json" : "application/xml"; try { return Boolean.Parse(RestHelper.GetResponse(request, isJson)); } catch(Exception ex) { RestFaultHandler.HandleFaultException(ex, isJson); } } return false; }
/// <summary> /// Gets a value indicating whether a tender is card refund. /// </summary> /// <param name="tenderType">The tender type.</param> /// <param name="tenderLine">The tender line.</param> /// <returns>The result value.</returns> private static bool IsCardRefund(TenderType tenderType, TenderLine tenderLine) { return(tenderType.OperationType == RetailOperation.PayCard && tenderLine.Amount < 0); }
/// <summary> /// New Transaction Track for Ticket /// </summary> /// <param name="theInfo"></param> /// <param name="targetTicket"></param> /// <param name="targetTender"></param> /// <param name="tenderedAmount"></param> /// <param name="amountDue"></param> /// <param name="changeDue"></param> public void newTransaction(IDisplayActions.displayActionInfo theInfo, Ticket targetTicket, TenderType targetTender, decimal tenderedAmount, decimal amountDue, decimal changeDue) { if (!ConfigurationHelper.Instance.IS_Test_Virtual_Client_Connection || !ConfigurationHelper.Instance.IS_Test_BLoyal_Connection) { return; } RefreshTicket(targetTicket); }