/// <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);
            }
示例#2
0
        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");
        }
示例#3
0
        //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);
        }
示例#4
0
        public ActionResult DeleteConfirmed(int id)
        {
            TenderType tenderType = db.TenderTypes.Find(id);

            db.TenderTypes.Remove(tenderType);
            db.SaveChanges();
            return(RedirectToAction("Index"));
        }
示例#5
0
        public bool CanTenderTypeGiveChange(int tenderTypeID)
        {
            if (tenderTypeID == 0)
            {
                return(true);
            }
            TenderType tenderType = db.TenderTypes.ToList().Single <TenderType>(x => x.TenderTypeID == tenderTypeID);

            return(tenderType.ChangeGiven);
        }
示例#6
0
        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();
        }
示例#7
0
 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));
 }
示例#8
0
        public ActionResult Create([Bind(Include = "TenderTypeId,Name")] TenderType tenderType)
        {
            if (ModelState.IsValid)
            {
                db.TenderTypes.Add(tenderType);
                db.SaveChanges();
                return(RedirectToAction("Index"));
            }

            return(View(tenderType));
        }
示例#9
0
        // 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));
        }
示例#10
0
            /// <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));
            }
示例#11
0
 /// <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;
     }
 }
示例#12
0
            /// <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;
                }
            }
示例#14
0
            /// <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);
            }
示例#15
0
        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();
            }
        }
示例#16
0
        // 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;
                        }
                    }
                }
            }
        }
示例#17
0
 public TenderTypeVM()
 {
     // Initialise the entity or inserts will fail
     TheEntity = new TenderType();
 }
示例#18
0
 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);
 }
示例#27
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);
 }