Пример #1
0
        private dynamic HandlePayRequest(dynamic arg)
        {
            if (!this.CurrentUser.HasClaim("admin"))
            {
                return(403);
            }

            var param = ((JObject)arg.body.Value);

            DateTime paidWhen     = param.Value <DateTime>("paidWhen").ToLocalTime();
            string   soIdentifier = param.Value <string>("saleOrderIdentifier");
            string   apCode       = param.Value <string>("apCode");
            var      form         = new JObject();

            form.Add("apCode", apCode);

            var paymentLog = new PaymentLog()
            {
                PaymentSource       = param.Value <string>("paymentMethod"),
                Amount              = param.Value <decimal>("amount"),
                IsErrorCode         = false,
                ResponseCode        = "00",
                IsPaymentSuccess    = true,
                SaleOrderIdentifier = soIdentifier,
                PaymentDate         = paidWhen,
                FormResponse        = form
            };

            CommerceModule.HandlePayment(this.SiteDatabase, paymentLog, paidWhen);

            return(paymentLog);
        }
Пример #2
0
        private dynamic HandlePaymentPostback(dynamic arg)
        {
            JObject postback = JObject.FromObject(this.Request.Form.ToDictionary());

            var soId = postback.Value <string>("order_no");
            var code = postback.Value <string>("res_cd");

            var log = PaymentLog.FromContext(this.Context);

            log.PaymentSource = PaymentMethod.TreePay;
            log.Amount        = postback.Value <decimal>("trade_mony");
            if (soId.Length == 20)
            {
                log.SaleOrderIdentifier = soId.Substring(0, 17);
            }
            else
            {
                log.SaleOrderIdentifier = soId;
            }
            log.IsErrorCode      = code != "0000";
            log.ResponseCode     = code;
            log.IsPaymentSuccess = false;

            var paymentDateString = log.FormResponse.Value <int>("trade_ymd").ToString();
            var paymentTimeString = log.FormResponse.Value <int>("trade_hms").ToString();

            if (paymentTimeString.Length < 6)
            {
                paymentTimeString = "0" + paymentTimeString;
            }

            DateTime paymentDate = DateTime.Now;

            if (!log.IsErrorCode)
            {
                if (DateTime.TryParseExact(paymentDateString + paymentTimeString,
                                           "yyyyMMddHHmmss", CultureInfo.InvariantCulture,
                                           DateTimeStyles.AssumeLocal, out paymentDate) == false)
                {
                    paymentDate = DateTime.Now;
                }
            }

            // find existing payment of same sale order
            var existing = this.SiteDatabase.Query <PaymentLog>().Where(l => l.SaleOrderIdentifier == log.SaleOrderIdentifier).ToList();

            // check for same auth_no, if it is already exists
            // return
            foreach (var item in existing)
            {
                if (log.FormResponse.auth_no == item.FormResponse.auth_no)
                {
                    return(this.Response.AsRedirect("/support/" + log.SaleOrderIdentifier));
                }
            }

            CommerceModule.HandlePayment(this.SiteDatabase, log, paymentDate);

            return(this.Response.AsRedirect("/support/" + log.SaleOrderIdentifier + "?paymentsuccess"));
        }
Пример #3
0
        private StandardModel HandlePaySbuyPostback(dynamic arg)
        {
            JObject         postback        = JObject.FromObject(this.Request.Form.ToDictionary());
            PaySbuyPostback paysbuyPostback = postback.ToObject <PaySbuyPostback>();

            // Since before 02 Dec, 2015. Paysbuy had been sending SO with prefix 00.
            var soId = paysbuyPostback.result.Substring(2);
            var code = paysbuyPostback.result.Substring(0, 2);

            var log = PaymentLog.FromContext(this.Context);

            log.PaymentSource       = PaymentMethod.PaySbuy;
            log.Amount              = paysbuyPostback.amt;
            log.Fee                 = paysbuyPostback.fee;
            log.SaleOrderIdentifier = soId;
            log.IsErrorCode         = code != "00";
            log.ResponseCode        = code;
            log.IsPaymentSuccess    = false;

            var      paymentDateString = log.FormResponse.Value <string>("payment_date");
            DateTime paymentDate;

            if (!log.IsErrorCode)
            {
                paymentDate = DateTime.ParseExact(paymentDateString, "d/M/yyyy H:m:s", new CultureInfo("th-TH"));
            }
            else
            {
                paymentDate = DateTime.Now;
            }

            CommerceModule.HandlePayment(this.SiteDatabase, log, paymentDate);

            var page = ContentModule.GetPage(this.SiteDatabase, "/__/commerce/thankyou", true);

            var so = this.SiteDatabase.Query <SaleOrder>().Where(s => s.SaleOrderIdentifier == soId).FirstOrDefault();

            return(new StandardModel(this, page, JObject.FromObject(new
            {
                SaleOrderIdentification = soId,
                Log = log,
                IsSplitPayment = so.Status == PaymentStatus.Deposit || so.PaymentStatus == PaymentStatus.Deposit
            })));
        }
Пример #4
0
        private List <AccountantMonthlyReceipt> FindReceipt(int year, int month)
        {
            var begin = new DateTime(year, month, 1, 0, 0, 0, DateTimeKind.Utc); // first second of last month

            // the first month we use new receipt identifier format is 2019/11
            if (begin >= new DateTime(2019, 11, 1, 0, 0, 0, DateTimeKind.Utc))
            {
                // set receipt identifier
                CommerceModule.SetReceiptIdentifier(this.SiteDatabase, begin);
            }

            var end = begin.AddMonths(1);

            end = end.AddMilliseconds(-1); // one second before start of this month

            var thaiTimeZone        = TimeZoneInfo.FindSystemTimeZoneById("SE Asia Standard Time");
            var negativeTicksOffset = thaiTimeZone.BaseUtcOffset.Ticks * -1;

            begin = begin.AddTicks(negativeTicksOffset);
            end   = end.AddTicks(negativeTicksOffset);

            var paymentsThisMonth = this.SiteDatabase.Query <PaymentLog>()
                                    .Where(l => l.__createdAt >= begin && l.__createdAt <= end)
                                    .OrderBy(l => l.__createdAt)
                                    .ThenBy(l => l.Id).ToList();

            List <Receipt> receipts = new List <Receipt>();

            foreach (var l in paymentsThisMonth)
            {
                var receipt = this.SiteDatabase.Query <Receipt>().Where(r => r.PaymentLogId == l.Id).FirstOrDefault();
                if (receipt == null)
                {
                    continue;
                }
                receipts.Add(receipt);
            }

            var result = this.GetAccountantMonthlyReceipt(receipts, paymentsThisMonth);

            return(result);
        }
Пример #5
0
        private dynamic HandlePaymentPostback(dynamic arg)
        {
            JObject postback = JObject.FromObject(this.Request.Form.ToDictionary());

            var soId = postback.Value <string>("order_no");
            var code = postback.Value <string>("res_cd");

            var log = PaymentLog.FromContext(this.Context);

            log.PaymentSource = PaymentMethod.TreePay;
            log.Amount        = postback.Value <decimal>("trade_mony");
            if (soId.Length == 20)
            {
                log.SaleOrderIdentifier = soId.Substring(0, 17);
            }
            else
            {
                log.SaleOrderIdentifier = soId;
            }
            log.IsErrorCode      = code != "0000";
            log.ResponseCode     = code;
            log.IsPaymentSuccess = false;

            var      paymentDateString = log.FormResponse.Value <int>("trade_ymd").ToString();
            var      paymentTimeString = log.FormResponse.Value <int>("trade_hms").ToString();
            DateTime paymentDate;

            if (!log.IsErrorCode)
            {
                paymentDate = DateTime.ParseExact(paymentDateString + paymentTimeString, "yyyyMMddHHmmss", new CultureInfo("th-TH"));
            }
            else
            {
                paymentDate = DateTime.Now;
            }

            CommerceModule.HandlePayment(this.SiteDatabase, log, paymentDate);

            return(this.Response.AsRedirect("/support/" + log.SaleOrderIdentifier));
        }
Пример #6
0
        public static void HandlePayment(NancyBlackDatabase db, PaymentLog log, DateTime paidWhen)
        {
            // ensure only one thread is processing this so
            lock (BaseModule.GetLockObject(log.SaleOrderIdentifier))
            {
                // find the sale order
                var so = db.Query <SaleOrder>()
                         .Where(row => row.SaleOrderIdentifier == log.SaleOrderIdentifier)
                         .FirstOrDefault();

                bool isPaymentReceived = false;

                JArray exceptions = new JArray();

                if (so == null)
                {
                    exceptions.Add(JObject.FromObject(new
                    {
                        type        = "Wrong SO Number",
                        description = "Wrong SO Number"
                    }));

                    goto EndPayment;
                }

                log.SaleOrderId = so.Id;
                log.PaymentDate = paidWhen;

                // check duplicated payment log (sometime we got double request from PaySbuy)
                if (log.PaymentSource == PaymentMethod.PaySbuy && !log.IsErrorCode)
                {
                    var jsonStr            = ((JObject)log.FormResponse).ToString();
                    var duplicatedRequests = db.QueryAsJObject("PaymentLog", "FormResponse eq '" + jsonStr + "'").ToList();

                    if (duplicatedRequests.Count > 0)
                    {
                        exceptions.Add(JObject.FromObject(new
                        {
                            type        = "Duplicated Request",
                            description = string.Format(
                                "Duplicated with Id: {0}", duplicatedRequests.First().Value <int>("Id"))
                        }));

                        goto EndPayment;
                    }
                }

                // Wrong Payment Status
                if (so.PaymentStatus == PaymentStatus.PaymentReceived)
                {
                    so.IsDuplicatePayment = true;
                    exceptions.Add(JObject.FromObject(new
                    {
                        type        = "Wrong Status",
                        description = string.Format(
                            "Current paymentlog status of SO is: {0}", PaymentStatus.DuplicatePayment)
                    }));
                }

                // Error code received
                if (log.IsErrorCode)
                {
                    so.PaymentStatus = PaymentStatus.WaitingForPayment;
                    exceptions.Add(JObject.FromObject(new
                    {
                        type        = "Error Code",
                        description = "Error Code Received from Payment Processor: " + log.ResponseCode
                    }));

                    goto EndPayment;
                }

                // after this line will never be run until EndPayment when IsErrorCode == true
                if (so.PaymentStatus != PaymentStatus.PaymentReceived && log.Amount != so.TotalAmount)
                {
                    log.IsPaymentSuccess   = true;
                    so.PaymentStatus       = PaymentStatus.Deposit;
                    so.PaymentReceivedDate = DateTime.Now; // Need to use this to manage queue

                    exceptions.Add(JObject.FromObject(new
                    {
                        type        = "Split Payment",
                        description = string.Format(
                            "Expects: {0} amount from SO, payment is {1}", so.TotalAmount, log.Amount)
                    }));

                    var paymentlogs = db.Query <PaymentLog>()
                                      .Where(p => p.SaleOrderIdentifier == so.SaleOrderIdentifier);

                    var splitPaymentLogs = (from sPLog in paymentlogs
                                            where sPLog.IsErrorCode == false
                                            select sPLog).ToList();

                    isPaymentReceived = so.TotalAmount <= splitPaymentLogs.Sum(splog => splog.Amount) + log.Amount;
                }

                if (exceptions.Count == 0 || isPaymentReceived)
                {
                    log.IsPaymentSuccess = true;

                    so.PaymentStatus       = PaymentStatus.PaymentReceived;
                    so.PaymentReceivedDate = DateTime.Now;
                }

EndPayment:

                log.Exception = exceptions;
                db.UpsertRecord <PaymentLog>(log);

                CommerceModule.PaymentOccured(so, db);

                if (log.IsPaymentSuccess)
                {
                    // Set Receipt number
                    var rc = db.UpsertRecord <Receipt>(new Receipt()
                    {
                        SaleOrderId = so.Id, PaymentLogId = log.Id
                    });
                    rc.SetIdentifier();
                    db.UpsertRecord(rc);

                    CommerceModule.PaymentSuccess(so, db);
                }

                db.UpsertRecord <SaleOrder>(so);

                // reset the one time code used
                foreach (var item in so.ItemsDetail)
                {
                    if (item.Url.StartsWith("/promotions/code"))
                    {
                        if (item.Attributes.onetime != null)
                        {
                            var product = db.GetById <Product>(item.Id);
                            product.Url = product.Url.Replace("/promotions/code", "/promotions/code/archive-onetime");
                            db.UpsertRecord(product);
                        }
                    }
                }

                // Automate change status to WaitingForOrder for add item to PO
                if (exceptions.Count == 0 || isPaymentReceived)
                {
                    if (so.Status == SaleOrderStatus.Confirmed)
                    {
                        so.Status = SaleOrderStatus.WaitingForOrder;
                        db.UpsertRecord <SaleOrder>(so);
                    }
                }
            }
        }
Пример #7
0
        private dynamic HandlePaymentPostback(dynamic arg)
        {
            JObject postback = JObject.FromObject(this.Request.Form.ToDictionary());

            var soId = postback.Value <string>("order_no");
            var code = postback.Value <string>("res_cd");

            var log = PaymentLog.FromContext(this.Context);

            log.PaymentSource = PaymentMethod.TreePay;
            log.Amount        = postback.Value <decimal>("trade_mony");
            if (soId.Length == 20)
            {
                log.SaleOrderIdentifier = soId.Substring(0, 17);
            }
            else
            {
                log.SaleOrderIdentifier = soId;
            }
            log.IsErrorCode      = code != "0000";
            log.ResponseCode     = code;
            log.IsPaymentSuccess = false;

            var paymentDateString = log.FormResponse.Value <int>("trade_ymd").ToString();
            var paymentTimeString = log.FormResponse.Value <int>("trade_hms").ToString();

            if (paymentTimeString.Length < 6)
            {
                paymentTimeString = "0" + paymentTimeString;
            }

            DateTime paymentDate = default(DateTime);

            if (!log.IsErrorCode)
            {
                if (DateTime.TryParseExact(paymentDateString + paymentTimeString,
                                           "yyyyMMddHHmmss", CultureInfo.InvariantCulture,
                                           DateTimeStyles.AssumeLocal, out paymentDate) == false)
                {
                    paymentDate = DateTime.Now;
                }
            }

            // reponse from TreePay always be Thailand Time (SE Asia Standard Time)
            // convert to Utc DateTime (have to do this in case server use other time zone
            var thaiTimeZone = TimeZoneInfo.FindSystemTimeZoneById("SE Asia Standard Time");

            paymentDate = paymentDate.AddTicks(thaiTimeZone.BaseUtcOffset.Ticks * -1);
            paymentDate = DateTime.SpecifyKind(paymentDate, DateTimeKind.Utc);

            // find existing payment of same sale order
            var existing = this.SiteDatabase.Query <PaymentLog>().Where(l => l.SaleOrderIdentifier == log.SaleOrderIdentifier).ToList();

            // check for same auth_no, if it is already exists
            // return
            foreach (var item in existing)
            {
                if (log.FormResponse.auth_no == item.FormResponse.auth_no)
                {
                    return(this.Response.AsRedirect("/support/" + log.SaleOrderIdentifier));
                }
            }

            CommerceModule.HandlePayment(this.SiteDatabase, log, paymentDate);

            return(this.Response.AsRedirect("/support/" + log.SaleOrderIdentifier + "?paymentsuccess"));
        }
Пример #8
0
        private PaymentLog InsertPaymentLog()
        {
            JObject postback    = JObject.FromObject(this.Request.Form.ToDictionary());
            var     response    = postback.ToObject <Pg2c2pResponse>();
            var     settings    = this.CurrentSite.pg2c2p;
            var     isIntegrety = response.VerifyHash((string)settings.merchantId, (string)settings.authSercretKey);

            if (!isIntegrety)
            {
                throw new ApplicationException("Authenication Fail");
            }

            if (response.currency != "764")
            {
                throw new ApplicationException("Only support currency Thai Bath");
            }

            var so = this.SiteDatabase.GetById <SaleOrder>(int.Parse(response.user_defined_1));

            if (response.user_defined_2 != so.SaleOrderIdentifier)
            {
                throw new ApplicationException("Mishmatch Information");
            }

            var log = PaymentLog.FromContext(this.Context);

            log.PaymentSource = PaymentMethod.Pg2C2P;
            var pgAmount = decimal.Parse(response.amount);

            log.Amount              = pgAmount / 100;
            log.SaleOrderId         = so.Id;
            log.SaleOrderIdentifier = so.SaleOrderIdentifier;
            log.IsErrorCode         = response.channel_response_code != "00";
            log.ResponseCode        = response.channel_response_code;
            log.IsPaymentSuccess    = response.channel_response_code == "00";

            DateTime paymentDate = default(DateTime);

            if (!log.IsErrorCode)
            {
                if (DateTime.TryParseExact(response.transaction_datetime,
                                           "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture,
                                           DateTimeStyles.AssumeLocal, out paymentDate) == false)
                {
                    // set paymentDate as Now in case for unable to Parse (this should never happen)
                    paymentDate = DateTime.Now;
                }
            }

            // reponse from 2C2P always be Thailand Time (SE Asia Standard Time) due to configuration
            // convert to Utc DateTime (have to do this in case server use other time zone
            var thaiTimeZone = TimeZoneInfo.FindSystemTimeZoneById("SE Asia Standard Time");

            paymentDate = paymentDate.AddTicks(thaiTimeZone.BaseUtcOffset.Ticks * -1);
            paymentDate = DateTime.SpecifyKind(paymentDate, DateTimeKind.Utc);

            // find existing payment of same sale order
            var existPaymentLogs = this.SiteDatabase.Query <PaymentLog>().Where(l => l.SaleOrderId == log.SaleOrderId).ToList();

            foreach (var existLog in existPaymentLogs)
            {
                if ((string)existLog.FormResponse.order_id == response.order_id)
                {
                    throw new ApplicationException("Payment has already been saved");
                }
            }

            CommerceModule.HandlePayment(this.SiteDatabase, log, paymentDate);

            return(log);
        }