//This works only on refund to customer (refund what has already been captured...) private void DoRefund(Order order, ref CancelPaymentResult cancelPaymentResult, bool alreadyTriedCancel) { string merchant = IoC.Resolve <ISettingManager>().GetSettingValue(QuickPayConstants.SETTING_MERCHANTID); string protocol = "3"; string capturePostUrl = "https://secure.quickpay.dk/api"; string msgtype = "refund"; string amount = (cancelPaymentResult.Amount * 100).ToString("0", CultureInfo.InvariantCulture); //NOTE: Primary store should be changed to DKK, if you do not have internatinal agreement with pbs and quickpay. Otherwise you need to do currency conversion here. string transaction = order.AuthorizationTransactionId; string md5secret = IoC.Resolve <ISettingManager>().GetSettingValue(QuickPayConstants.SETTING_MD5SECRET); string stringToMd5 = string.Concat(protocol, msgtype, merchant, amount, transaction, md5secret); string querystring = string.Empty; string md5check = GetMD5(stringToMd5); querystring += string.Format("protocol={0}&", protocol); querystring += string.Format("msgtype={0}&", msgtype); querystring += string.Format("merchant={0}&", merchant); querystring += string.Format("amount={0}&", amount); querystring += string.Format("transaction={0}&", transaction); querystring += string.Format("md5check={0}", md5check); string retval = HttpRequestsFunctions.HttpPost(capturePostUrl, querystring); try { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(retval); XmlElement xmlElement = xmlDocument.DocumentElement; string rep_qpstatmsg = xmlElement.SelectSingleNode("qpstatmsg").InnerText; string rep_qpstat = xmlElement.SelectSingleNode("qpstat").InnerText; string rep_transaction = xmlElement.SelectSingleNode("transaction").InnerText; //refund successful if (rep_qpstat == "000") { cancelPaymentResult.PaymentStatus = PaymentStatusEnum.Refunded; } //not allowed in current state. This probably means that it has not been caputered yet. //we therefore try to just cancel, but not refund else if (rep_qpstat == "004" && (!alreadyTriedCancel)) { DoCancel(order, ref cancelPaymentResult, true); } else { cancelPaymentResult.Error = "Quickpay Caputure refund did not succeed, qpstat is:" + rep_qpstat; cancelPaymentResult.FullError = "Quickpay Caputure refund did not succeed, qpstat is:" + rep_qpstat; } } catch (Exception exception) { throw new NopException("XML response for Quickpay Capture was not successfull. Reasons could be that the host did not respond. Below is stacktrace:" + exception.Message + exception.StackTrace + exception.Source, exception.InnerException); } }
//This only works when a payment have been authorized and not captured. private void DoCancel(Order order, ref CancelPaymentResult cancelPaymentResult, bool alreadyTriedRefund) { string merchant = IoC.Resolve <ISettingManager>().GetSettingValue(QuickPayConstants.SETTING_MERCHANTID); string protocol = "3"; string capturePostUrl = "https://secure.quickpay.dk/api"; string msgtype = "cancel"; string transaction = order.AuthorizationTransactionId; string md5secret = IoC.Resolve <ISettingManager>().GetSettingValue(QuickPayConstants.SETTING_MD5SECRET); string stringToMd5 = string.Concat(protocol, msgtype, merchant, transaction, md5secret); string querystring = string.Empty; string md5check = GetMD5(stringToMd5); querystring += string.Format("protocol={0}&", protocol); querystring += string.Format("msgtype={0}&", msgtype); querystring += string.Format("merchant={0}&", merchant); querystring += string.Format("transaction={0}&", transaction); querystring += string.Format("md5check={0}", md5check); string retval = HttpRequestsFunctions.HttpPost(capturePostUrl, querystring); try { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(retval); XmlElement xmlElement = xmlDocument.DocumentElement; string rep_qpstatmsg = xmlElement.SelectSingleNode("qpstatmsg").InnerText; string rep_qpstat = xmlElement.SelectSingleNode("qpstat").InnerText; string rep_transaction = xmlElement.SelectSingleNode("transaction").InnerText; //refund successful if (rep_qpstat == "000") { cancelPaymentResult.PaymentStatus = PaymentStatusEnum.Refunded; } else if (rep_qpstat == "004" && (!alreadyTriedRefund)) { DoRefund(order, ref cancelPaymentResult, true); } else { cancelPaymentResult.Error = "Quickpay Cancel did not succeed, qpstat is:" + rep_qpstat; cancelPaymentResult.FullError = "Quickpay Cancel did not succeed, qpstat is:" + rep_qpstat; } } catch (Exception exception) { throw new NopException("XML response for Quickpay Capture was not successfull. Reasons could be that the host did not respond. Below is stacktrace:" + exception.Message + exception.StackTrace + exception.Source, exception.InnerException); } }
/// <summary> /// Captures payment /// </summary> /// <param name="order">Order</param> /// <param name="processPaymentResult">Process payment result</param> public void Capture(Order order, ref ProcessPaymentResult processPaymentResult) { bool useSandBox = IoC.Resolve <ISettingManager>().GetSettingValueBoolean(QuickPayConstants.SETTING_USE_SANDBOX); string merchant = IoC.Resolve <ISettingManager>().GetSettingValue(QuickPayConstants.SETTING_MERCHANTID); string protocol = "3"; string testmode = (useSandBox) ? "1" : "0"; const string autocapture = "0"; //in initial phase while testing system, no autocapture!. string capturePostUrl = "https://secure.quickpay.dk/api"; string msgtype = "capture"; string ordernumber = FormatOrderNumber(order.OrderId.ToString()); string currencyCode = IoC.Resolve <ICurrencyService>().PrimaryStoreCurrency.CurrencyCode; //NOTE: Primary store should be changed to DKK, if you do not have internatinal agreement with pbs and quickpay. Otherwise you need to do currency conversion here. string amount = (order.OrderTotal * 100).ToString("0", CultureInfo.InvariantCulture); //NOTE: Primary store should be changed to DKK, if you do not have internatinal agreement with pbs and quickpay. Otherwise you need to do currency conversion here. string transaction = order.AuthorizationTransactionId; string md5secret = IoC.Resolve <ISettingManager>().GetSettingValue(QuickPayConstants.SETTING_MD5SECRET); string stringToMd5 = string.Concat(protocol, msgtype, merchant, amount, autocapture, transaction, md5secret); string querystring = string.Empty; string md5check = GetMD5(stringToMd5); querystring += string.Format("protocol={0}&", protocol); querystring += string.Format("msgtype={0}&", msgtype); querystring += string.Format("merchant={0}&", merchant); querystring += string.Format("ordernumber={0}&", ordernumber); querystring += string.Format("amount={0}&", amount); querystring += string.Format("currency={0}&", currencyCode); querystring += string.Format("autocapture={0}&", autocapture); querystring += string.Format("transaction={0}&", transaction); querystring += string.Format("md5check={0}", md5check); querystring += string.Format("testmode={0}", testmode); string retval = HttpRequestsFunctions.HttpPost(capturePostUrl, querystring); try { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(retval); XmlElement xmlElement = xmlDocument.DocumentElement; string rep_qpstatmsg = xmlElement.SelectSingleNode("qpstatmsg").InnerText; string rep_qpstat = xmlElement.SelectSingleNode("qpstat").InnerText; string rep_transaction = xmlElement.SelectSingleNode("transaction").InnerText; //caputre successful if (rep_qpstat == "000") { if (IoC.Resolve <IOrderService>().CanMarkOrderAsPaid(order)) { IoC.Resolve <IOrderService>().MarkOrderAsPaid(order.OrderId); processPaymentResult.PaymentStatus = PaymentStatusEnum.Paid; } //IoC.Resolve<IOrderService>().SetCaptureResults(order.OrderId, rep_transaction, rep_qpstatmsg); } else { processPaymentResult.Error = "Quickpay Caputure did not succeed, qpstat is:" + rep_qpstat; processPaymentResult.FullError = "Quickpay Caputure did not succeed, qpstat is:" + rep_qpstat; } processPaymentResult.CaptureTransactionId = rep_transaction; processPaymentResult.CaptureTransactionResult = rep_qpstatmsg; } catch (Exception exception) { throw new NopException("XML response for Quickpay Capture was not successfull. Reasons could be that the host did not respond. Below is stacktrace:" + exception.Message + exception.StackTrace + exception.Source, exception.InnerException); } }