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); }
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")); }
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 }))); }
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); }
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)); }
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); } } } }
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")); }
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); }