/// <summary> /// Runs the specified argument. /// </summary> /// <param name="arg">The argument.</param> /// <param name="context">The context.</param> /// <returns> /// A cart with federate payment component /// </returns> public override async Task <CartEmailArgument> Run(CartEmailArgument arg, CommercePipelineExecutionContext context) { Condition.Requires(arg).IsNotNull($"{this.Name}: The cart can not be null"); var cart = arg.Cart; if (!cart.HasComponent <FederatedPaymentComponent>()) { return(arg); } var payment = cart.GetComponent <FederatedPaymentComponent>(); if (string.IsNullOrEmpty(payment.PaymentMethodNonce)) { context.Abort( await context.CommerceContext.AddMessage( context.GetPolicy <KnownResultCodes>().Error, "InvalidOrMissingPropertyValue", new object[] { "PaymentMethodNonce" }, "Invalid or missing value for property 'PaymentMethodNonce'."), context); return(arg); } var braintreeClientPolicy = context.GetPolicy <BraintreeClientPolicy>(); if (string.IsNullOrEmpty(braintreeClientPolicy.Environment) || string.IsNullOrEmpty(braintreeClientPolicy.MerchantId) || string.IsNullOrEmpty(braintreeClientPolicy.PublicKey) || string.IsNullOrEmpty(braintreeClientPolicy.PrivateKey)) { await context.CommerceContext.AddMessage( context.GetPolicy <KnownResultCodes>().Error, "InvalidClientPolicy", new object[] { "BraintreeClientPolicy" }, $"{this.Name}. Invalid BraintreeClientPolicy"); return(arg); } try { var gateway = new BraintreeGateway(braintreeClientPolicy.Environment, braintreeClientPolicy.MerchantId, braintreeClientPolicy.PublicKey, braintreeClientPolicy.PrivateKey); var request = new TransactionRequest { Amount = payment.Amount.Amount, PaymentMethodNonce = payment.PaymentMethodNonce, BillingAddress = ComponentsHelper.TranslatePartyToAddressRequest(payment.BillingParty, context), Options = new TransactionOptionsRequest { SubmitForSettlement = false } }; var result = gateway.Transaction.Sale(request); if (result.IsSuccess()) { var transaction = result.Target; payment.TransactionId = transaction?.Id; payment.TransactionStatus = transaction?.Status?.ToString(); payment.PaymentInstrumentType = transaction?.PaymentInstrumentType?.ToString(); var cc = transaction?.CreditCard; payment.MaskedNumber = cc?.MaskedNumber; payment.CardType = cc?.CardType?.ToString(); if (cc?.ExpirationMonth != null) { payment.ExpiresMonth = int.Parse(cc.ExpirationMonth); } if (cc?.ExpirationYear != null) { payment.ExpiresYear = int.Parse(cc.ExpirationYear); } } else { var errorMessages = string.Concat(result.Message, " ", result.Errors.DeepAll().Aggregate(string.Empty, (current, error) => current + ("Error: " + (int)error.Code + " - " + error.Message + "\n"))); context.Abort( await context.CommerceContext.AddMessage( context.GetPolicy <KnownResultCodes>().Error, "CreatePaymentFailed", new object[] { "PaymentMethodNonce" }, $"{this.Name}. Create payment failed :{ errorMessages }"), context); } return(arg); } catch (BraintreeException ex) { context.Abort( await context.CommerceContext.AddMessage( context.GetPolicy <KnownResultCodes>().Error, "CreatePaymentFailed", new object[] { "PaymentMethodNonce", ex }, $"{this.Name}. Create payment failed."), context); return(arg); } }
/// <summary> /// Runs the specified argument. /// </summary> /// <param name="arg">The argument.</param> /// <param name="context">The context.</param> /// <returns> /// A cart with federate payment component /// </returns> public override async Task <Order> Run(Order arg, CommercePipelineExecutionContext context) { Condition.Requires(arg).IsNotNull($"{this.Name}: order can not be null."); var order = arg; if (!order.HasComponent <OnHoldOrderComponent>()) { var invalidOrderStateMessage = $"{this.Name}: Expected order in '{context.GetPolicy<KnownOrderStatusPolicy>().OnHold}' status but order was in '{order.Status}' status"; context.Abort( await context.CommerceContext.AddMessage( context.GetPolicy <KnownResultCodes>().ValidationError, "InvalidOrderState", new object[] { context.GetPolicy <KnownOrderStatusPolicy>().OnHold, order.Status }, invalidOrderStateMessage).ConfigureAwait(false), context); } var cart = context.CommerceContext.GetEntity <Cart>(c => c.Id.Equals(order.GetComponent <OnHoldOrderComponent>().TemporaryCart.EntityTarget, StringComparison.OrdinalIgnoreCase)); if (cart == null || !cart.HasComponent <FederatedPaymentComponent>()) { return(arg); } var payment = cart.GetComponent <FederatedPaymentComponent>(); if (string.IsNullOrEmpty(payment.PaymentMethodNonce)) { context.Abort( await context.CommerceContext.AddMessage( context.GetPolicy <KnownResultCodes>().Error, "InvalidOrMissingPropertyValue", new object[] { "PaymentMethodNonce" }, "Invalid or missing value for property 'PaymentMethodNonce'.").ConfigureAwait(false), context); return(arg); } if (!string.IsNullOrEmpty(payment.TransactionId)) { // Federated Payment was not changed return(arg); } var braintreeClientPolicy = context.GetPolicy <BraintreeClientPolicy>(); if (!(await braintreeClientPolicy.IsValid(context.CommerceContext).ConfigureAwait(false))) { return(arg); } try { var gateway = new BraintreeGateway(braintreeClientPolicy?.Environment, braintreeClientPolicy?.MerchantId, braintreeClientPolicy?.PublicKey, braintreeClientPolicy?.PrivateKey); // void order payment if (order.HasComponent <FederatedPaymentComponent>()) { var orderPayment = order.GetComponent <FederatedPaymentComponent>(); // void order payment var voidResult = gateway.Transaction.Void(orderPayment.TransactionId); if (voidResult.IsSuccess()) { context.Logger.LogInformation($"{this.Name} - Void Payment succeeded: {orderPayment.Id}"); orderPayment.TransactionStatus = voidResult.Target.Status.ToString(); await this.GenerateSalesActivity(order, orderPayment, context).ConfigureAwait(false); } else { var errorMessages = voidResult.Errors.DeepAll().Aggregate(string.Empty, (current, error) => current + ("Error: " + (int)error.Code + " - " + error.Message + "\n")); context.Abort( await context.CommerceContext.AddMessage( context.GetPolicy <KnownResultCodes>().Error, "PaymentVoidFailed", new object[] { orderPayment.TransactionId }, $"{this.Name}. Payment void failed for transaction { orderPayment.TransactionId }: { errorMessages }").ConfigureAwait(false), context); return(arg); } } var request = new TransactionRequest { Amount = payment.Amount.Amount, PaymentMethodNonce = payment.PaymentMethodNonce, BillingAddress = ComponentsHelper.TranslatePartyToAddressRequest(payment.BillingParty), Options = new TransactionOptionsRequest { SubmitForSettlement = false } }; var result = gateway.Transaction.Sale(request); if (result.IsSuccess()) { var transaction = result.Target; payment.TransactionId = transaction?.Id; payment.TransactionStatus = transaction?.Status?.ToString(); payment.PaymentInstrumentType = transaction?.PaymentInstrumentType?.ToString(); var cc = transaction?.CreditCard; payment.MaskedNumber = cc?.MaskedNumber; payment.CardType = cc?.CardType?.ToString(); if (cc?.ExpirationMonth != null) { payment.ExpiresMonth = int.Parse(cc.ExpirationMonth, System.Globalization.CultureInfo.InvariantCulture); } if (cc?.ExpirationYear != null) { payment.ExpiresYear = int.Parse(cc.ExpirationYear, System.Globalization.CultureInfo.InvariantCulture); } } else { var errorMessages = result.Errors.DeepAll().Aggregate(string.Empty, (current, error) => current + ("Error: " + (int)error.Code + " - " + error.Message + "\n")); context.Abort( await context.CommerceContext.AddMessage( context.GetPolicy <KnownResultCodes>().Error, "CreatePaymentFailed", new object[] { "PaymentMethodNonce" }, $"{this.Name}. Create payment failed :{ errorMessages }").ConfigureAwait(false), context); } return(arg); } catch (BraintreeException ex) { await context.CommerceContext.AddMessage( context.GetPolicy <KnownResultCodes>().Error, "InvalidClientPolicy", new object[] { "BraintreeClientPolicy", ex }, $"{this.Name}. Invalid BraintreeClientPolicy").ConfigureAwait(false); return(arg); } }