/// <summary> /// Does the actual work of authorizing and capturing a payment /// </summary> /// <param name="invoice">The <see cref="IInvoice"/></param> /// <param name="amount">The amount to capture</param> /// <param name="args">Any arguments required to process the payment.</param> /// <returns>The <see cref="IPaymentResult"/></returns> protected override IPaymentResult PerformAuthorizeCapturePayment(IInvoice invoice, decimal amount, ProcessorArgumentCollection args) { var payment = GatewayProviderService.CreatePayment(PaymentMethodType.CreditCard, amount, PaymentMethod.Key); payment.CustomerKey = invoice.CustomerKey; payment.PaymentMethodName = PaymentMethod.Name; payment.ReferenceNumber = PaymentMethod.PaymentCode + "-" + invoice.PrefixedInvoiceNumber(); payment.Collected = true; payment.Authorized = true; var po = args.AsCreditCard(); if (string.IsNullOrEmpty(po.CardNumber)) { return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception("Error Card Number is empty")), invoice, false)); } invoice.PoNumber = invoice.PrefixedInvoiceNumber(); MerchelloContext.Current.Services.InvoiceService.Save(invoice); GatewayProviderService.Save(payment); GatewayProviderService.ApplyPaymentToInvoice(payment.Key, invoice.Key, AppliedPaymentType.Debit, "CardConnect Perform Authorize Capture Payment", amount); return(new PaymentResult(Attempt <IPayment> .Succeed(payment), invoice, CalculateTotalOwed(invoice).CompareTo(amount) <= 0)); }
/// <summary> /// Processes the Authorize and AuthorizeAndCapture transactions /// </summary> /// <param name="invoice">The <see cref="IInvoice"/> to be paid</param> /// <param name="payment">The <see cref="Core.Models.IPayment"/> record</param> /// <param name="args"></param> /// <returns>The <see cref="Core.Gateways.Payment.IPaymentResult"/></returns> public IPaymentResult InitializePayment(IInvoice invoice, IPayment payment, ProcessorArgumentCollection args) { try { var sagePayDirectIntegration = new SagePayAPIIntegration(Settings); var request = sagePayDirectIntegration.DirectPaymentRequest(); var creditCard = args.AsCreditCard(); SetSagePayApiData(request, invoice, payment, creditCard); // Incredibly frustratingly, the sagepay integration kit provided by sagepay does not support paypal integration with sagepay direct so if this is a paypal transaction, we have to build the post manually. if (request.CardType == CardType.PAYPAL) { using (var client = new HttpClient()) { var values = new Dictionary <string, string> { }; // Build the post and fix the values that the integration kit breaks... foreach (var property in request.GetType().GetAllProperties()) { if (property.CanRead && property.GetValue(request) != null) { if (property.Name == "VpsProtocol") { values.Add(property.Name, "3.00"); } else if (property.Name == "TransactionType") { values.Add("TxType", "PAYMENT"); } else { values.Add(property.Name, property.GetValue(request).ToString()); } } } var content = new FormUrlEncodedContent(values); var response = client.PostAsync(string.Format("https://{0}.sagepay.com/gateway/service/vspdirect-register.vsp", Settings.Environment), content).Result; var responseString = response.Content.ReadAsStringAsync().Result.Replace("\r\n", "&"); NameValueCollection sagePayResponseValues = HttpUtility.ParseQueryString(responseString); if (sagePayResponseValues["Status"] == "PPREDIRECT") { var redirectUrl = sagePayResponseValues["PayPalRedirectURL"] + "&token=" + sagePayResponseValues["token"]; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.SagePayPaymentUrl, redirectUrl); var returnUrl = GetWebsiteUrl() + Settings.ReturnUrl; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.ReturnUrl, returnUrl); var cancelUrl = GetWebsiteUrl() + Settings.CancelUrl; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.CancelUrl, cancelUrl); payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.SagePayTransactionCode, sagePayResponseValues["VPSTxId"]); return(new PaymentResult(Attempt <IPayment> .Succeed(payment), invoice, true)); } else { return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(sagePayResponseValues["StatusDetail"])), invoice, true)); } } } IDirectPaymentResult result = sagePayDirectIntegration.ProcessDirectPaymentRequest(request, string.Format("https://{0}.sagepay.com/gateway/service/vspdirect-register.vsp", Settings.Environment)); if (result.Status == ResponseStatus.OK) { payment.Collected = true; payment.Authorized = true; GatewayProviderService service = new GatewayProviderService(); service.ApplyPaymentToInvoice(payment.Key, invoice.Key, Core.AppliedPaymentType.Debit, "SagePay: capture authorized", invoice.Total); return(new PaymentResult(Attempt <IPayment> .Succeed(payment), invoice, true)); } else if (result.Status == ResponseStatus.THREEDAUTH) { // For 3D Secure we have to show a client side form which posts to the ACS url. Func <string, string> adjustUrl = (url) => { if (!url.StartsWith("http")) { url = GetWebsiteUrl() + (url[0] == '/' ? "" : "/") + url; } url = url.Replace("{invoiceKey}", invoice.Key.ToString(), StringComparison.InvariantCultureIgnoreCase); url = url.Replace("{paymentKey}", payment.Key.ToString(), StringComparison.InvariantCultureIgnoreCase); return(url); }; var redirectUrl = adjustUrl("/App_Plugins/Merchello.SagePay/3dsecureRedirect.aspx?"); redirectUrl += "acsurl=" + Base64Encode(result.AcsUrl); redirectUrl += "&PaReq=" + Base64Encode(result.PaReq); redirectUrl += "&MD=" + Base64Encode(result.Md); redirectUrl += "&TermUrl=" + Base64Encode(adjustUrl("/umbraco/MerchelloSagePay/SagePayApi/ThreeDSecureCallback?InvoiceKey={invoiceKey}&PaymentKey={paymentKey}")); payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.ThreeDSecureUrl, redirectUrl); var returnUrl = GetWebsiteUrl() + Settings.ReturnUrl; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.ReturnUrl, returnUrl); var cancelUrl = GetWebsiteUrl() + Settings.CancelUrl; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.CancelUrl, cancelUrl); return(new PaymentResult(Attempt <IPayment> .Succeed(payment), invoice, true)); } //else if (result.Status == ResponseStatus.PPREDIRECT) //{ // var redirectUrl = result.PayPalRedirectUrl + "&token=" + result.Token; // payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.SagePayPaymentUrl, redirectUrl); // var returnUrl = GetWebsiteUrl() + Settings.ReturnUrl; // payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.ReturnUrl, returnUrl); // var cancelUrl = GetWebsiteUrl() + Settings.CancelUrl; // payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.CancelUrl, cancelUrl); // return new PaymentResult(Attempt<IPayment>.Succeed(payment), invoice, true); //} else { return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(result.StatusDetail)), invoice, true)); } } catch (Exception ex) { return(new PaymentResult(Attempt <IPayment> .Fail(payment, ex), invoice, true)); } }
/// <summary> /// Does the actual work of creating and processing the payment /// </summary> /// <param name="invoice">The <see cref="IInvoice"/></param> /// <param name="args">Any arguments required to process the payment.</param> /// <returns>The <see cref="IPaymentResult"/></returns> protected override IPaymentResult PerformAuthorizePayment(IInvoice invoice, ProcessorArgumentCollection args) { var payment = GatewayProviderService.CreatePayment(PaymentMethodType.CreditCard, invoice.Total, PaymentMethod.Key); payment.CustomerKey = invoice.CustomerKey; payment.PaymentMethodName = PaymentMethod.Name; payment.ReferenceNumber = PaymentMethod.PaymentCode + "-" + invoice.PrefixedInvoiceNumber(); payment.Authorized = false; payment.Collected = false; //Setting the payment Amount == 0.00 to let CardConnect validate the authorization payment.Amount = Decimal.Parse("0.00"); // Have to save here to generate the payment key GatewayProviderService.Save(payment); var result = ((CardConnectPaymentProcessor)_processor).InitializePayment(invoice, payment, args.AsCreditCard()); if (!result.Payment.Success) { GatewayProviderService.ApplyPaymentToInvoice(payment.Key, invoice.Key, AppliedPaymentType.Denied, "CardConnect: request initialization error: " + result.Payment.Exception.Message, 0); } else { // Have to save here to persist the record so it can be used in later processing. GatewayProviderService.Save(payment); // In this case, we want to do our own Apply Payment operation as the amount has not been collected - // so we create an applied payment with a 0 amount. Once the payment has been "collected", another Applied Payment record will // be created showing the full amount and the invoice status will be set to Paid. GatewayProviderService.ApplyPaymentToInvoice(payment.Key, invoice.Key, AppliedPaymentType.Debit, "CardConnect Perform Authorize Payment", 0); } return(result); }
/// <summary> /// Processes the Authorize and AuthorizeAndCapture transactions /// </summary> /// <param name="invoice">The <see cref="IInvoice"/> to be paid</param> /// <param name="payment">The <see cref="Core.Models.IPayment"/> record</param> /// <param name="args"></param> /// <returns>The <see cref="Core.Gateways.Payment.IPaymentResult"/></returns> public IPaymentResult InitializePayment(IInvoice invoice, IPayment payment, ProcessorArgumentCollection args) { try { var sagePayDirectIntegration = new SagePayAPIIntegration(Settings); var request = sagePayDirectIntegration.DirectPaymentRequest(); var creditCard = args.AsCreditCard(); SetSagePayApiData(request, invoice, payment, creditCard); // Incredibly frustratingly, the sagepay integration kit provided by sagepay does not support paypal integration with sagepay direct so if this is a paypal transaction, we have to build the post manually. if (request.CardType == CardType.PAYPAL) { using (var client = new HttpClient()) { var values = new Dictionary<string, string> { }; // Build the post and fix the values that the integration kit breaks... foreach (var property in request.GetType().GetAllProperties()) { if (property.CanRead && property.GetValue(request) != null) { if (property.Name == "VpsProtocol") { values.Add(property.Name, "3.00"); } else if (property.Name == "TransactionType") { values.Add("TxType", "PAYMENT"); } else { values.Add(property.Name, property.GetValue(request).ToString()); } } } var content = new FormUrlEncodedContent(values); var response = client.PostAsync(string.Format("https://{0}.sagepay.com/gateway/service/vspdirect-register.vsp", Settings.Environment), content).Result; var responseString = response.Content.ReadAsStringAsync().Result.Replace("\r\n", "&"); NameValueCollection sagePayResponseValues = HttpUtility.ParseQueryString(responseString); if (sagePayResponseValues["Status"] == "PPREDIRECT") { var redirectUrl = sagePayResponseValues["PayPalRedirectURL"] + "&token=" + sagePayResponseValues["token"]; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.SagePayPaymentUrl, redirectUrl); var returnUrl = GetWebsiteUrl() + Settings.ReturnUrl; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.ReturnUrl, returnUrl); var cancelUrl = GetWebsiteUrl() + Settings.CancelUrl; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.CancelUrl, cancelUrl); payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.SagePayTransactionCode, sagePayResponseValues["VPSTxId"]); return new PaymentResult(Attempt<IPayment>.Succeed(payment), invoice, true); } else { return new PaymentResult(Attempt<IPayment>.Fail(payment, new Exception(sagePayResponseValues["StatusDetail"])), invoice, true); } } } IDirectPaymentResult result = sagePayDirectIntegration.ProcessDirectPaymentRequest(request, string.Format("https://{0}.sagepay.com/gateway/service/vspdirect-register.vsp", Settings.Environment)); if (result.Status == ResponseStatus.OK) { payment.Collected = true; payment.Authorized = true; GatewayProviderService service = new GatewayProviderService(); service.ApplyPaymentToInvoice(payment.Key, invoice.Key, Core.AppliedPaymentType.Debit, "SagePay: capture authorized", invoice.Total); return new PaymentResult(Attempt<IPayment>.Succeed(payment), invoice, true); } else if (result.Status == ResponseStatus.THREEDAUTH) { // For 3D Secure we have to show a client side form which posts to the ACS url. Func<string, string> adjustUrl = (url) => { if (!url.StartsWith("http")) url = GetWebsiteUrl() + (url[0] == '/' ? "" : "/") + url; url = url.Replace("{invoiceKey}", invoice.Key.ToString(), StringComparison.InvariantCultureIgnoreCase); url = url.Replace("{paymentKey}", payment.Key.ToString(), StringComparison.InvariantCultureIgnoreCase); return url; }; var redirectUrl = adjustUrl("/App_Plugins/Merchello.SagePay/3dsecureRedirect.aspx?"); redirectUrl += "acsurl=" + Base64Encode(result.AcsUrl); redirectUrl += "&PaReq=" + Base64Encode(result.PaReq); redirectUrl += "&MD=" + Base64Encode(result.Md); redirectUrl += "&TermUrl=" + Base64Encode(adjustUrl("/umbraco/MerchelloSagePay/SagePayApi/ThreeDSecureCallback?InvoiceKey={invoiceKey}&PaymentKey={paymentKey}")); payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.ThreeDSecureUrl, redirectUrl); var returnUrl = GetWebsiteUrl() + Settings.ReturnUrl; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.ReturnUrl, returnUrl); var cancelUrl = GetWebsiteUrl() + Settings.CancelUrl; payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.CancelUrl, cancelUrl); return new PaymentResult(Attempt<IPayment>.Succeed(payment), invoice, true); } //else if (result.Status == ResponseStatus.PPREDIRECT) //{ // var redirectUrl = result.PayPalRedirectUrl + "&token=" + result.Token; // payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.SagePayPaymentUrl, redirectUrl); // var returnUrl = GetWebsiteUrl() + Settings.ReturnUrl; // payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.ReturnUrl, returnUrl); // var cancelUrl = GetWebsiteUrl() + Settings.CancelUrl; // payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.CancelUrl, cancelUrl); // return new PaymentResult(Attempt<IPayment>.Succeed(payment), invoice, true); //} else { return new PaymentResult(Attempt<IPayment>.Fail(payment, new Exception(result.StatusDetail)), invoice, true); } } catch (Exception ex) { return new PaymentResult(Attempt<IPayment>.Fail(payment, ex), invoice, true); } }