Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Dan 15 posts 86 karma points
    Jun 29, 2018 @ 16:45
    Dan
    0

    Recurring and One of Payments using PayPal and BrainTree together

    Hi,

    With the solution I am building, only anonymous customers will have the option to purchase a monthly subscription plan or a one of purchase total. The way I want this to work is the customer can add either one to their basket and then click checkout. Once the customer clicks checkout, they automatically taken to the payment page with the PayPal checkout button. Once the customer logs in to PayPal, depending on the product they have chosen, a request is automatically fired off to BrainTree to either create a new subscription or transaction.

    So far, I have got a surface controller which is called through Ajax when a customer is authorised using the PayPal button and passed the PayPal nonce. The controller calls the BrainTree service to check if the customer exists and if not create the customer. I then use the BrainTree service to fetch the associated plan created in BrainTree to the product the customer has chosen to set up a subscription. All this works fine as the customer is added and the subscription in BrainTree is set up. I can set up the invoice using the invoice service, however, the issue I have is creating and assigning a payment to the invoice as I do not have a payment method key.

    I know Merchello already supports BrainTree and PayPal payments however, they do not work as I currently need them to as a basket can include both a subscription product and a one payment product so I may need to set up a subscription and a single payment in 1 transaction, for example, a subscription can be set up ans then another one off payment will be made for the other item so creating my own payment method may not work for this.

    I currently don't handle both but I would loop through the basket items and check whether it is a subscription or one off payment method and then determine whether I need a BrainTree subscription or BrainTree transaction.

    If anyone has an idea how may start to do this, I could really use your help as I am starting to head my head against the wall.

    My code so far is as follows:

     public ActionResult CreateSubscription(FormCollection collection)
        {            
            //get current merchello customer and basket
            CustomerContext merchelloCustomer = new CustomerContext(UmbracoContext);
            LineItemCollection basketItems = merchelloCustomer.CurrentCustomer.Basket().Items;
    
            var braintreeService = new BraintreeApiService(BrainTreeHelper.GetBraintreeProviderSettings());
    
            //search if the braintree customer already exists
            ResourceCollection<Customer> customerResults = braintreeService.Customer.Search(new CustomerSearchRequest().Email.Is(collection["details[email]"]));
            Customer braintreeCustomer = null;
            if (customerResults.FirstItem == null)
            {
                //create Braintree customer (dashboard)
                var newCustomer = new CustomerRequest
                {
                    FirstName = collection["details[firstName]"],
                    LastName = collection["details[lastName]"],
                    Email = collection["details[email]"]
                };
    
                Attempt<Customer> customerResult = braintreeService.Customer.Create((ICustomer)newCustomer, collection["nonce"]); 
                if(customerResult.Success)
                {
                    braintreeCustomer = customerResult.Result; 
                }
            }
            else
            {
                braintreeCustomer = customerResults.FirstItem;
            }
    
            var subscriptionRequest = new SubscriptionRequest
            {
                PaymentMethodToken = braintreeCustomer.PaymentMethods[0].Token,
                PlanId = basketItems[0].Sku
            };
    
            Attempt<Subscription> subscription =  braintreeService.Subscription.Create(subscriptionRequest);
            if (subscription.Success)
            {
                var invoice = GenerateInvoice(basketItems, merchelloCustomer, collection["details[email]"]);
                try
                {
                    MerchelloContext.Current.Services.InvoiceService.Save(invoice);
                }
                catch(Exception ex)
                {
                    throw new Exception(ex.Message); 
                }
    
                try
                {
                    MerchelloContext.Current.Services.OrderService.Save(invoice.PrepareOrder());
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
    
                try
                {
                    var payment = MerchelloContext.Current.Services.PaymentService.CreatePayment(PaymentMethodType.Custom, invoice.Total, Guid.Empty, false);
                    invoice.AuthorizePayment(payment.Key);
                    MerchelloContext.Current.Services.GatewayProviderService.ApplyPaymentToInvoice(payment.Key, invoice.Key, AppliedPaymentType.Custom, "PayPal", invoice.Total);
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
                //empty basket
                merchelloCustomer.CurrentCustomer.Basket().Empty();
            }         
            return CurrentUmbracoPage(); 
        }
    
        private IInvoice GenerateInvoice(LineItemCollection basketItems, CustomerContext merchelloCustomer, string email)
        {
            IInvoice invoice = MerchelloContext.Current.Services.InvoiceService.CreateInvoice(Merchello.Core.Constants.InvoiceStatus.Paid);
            invoice.VersionKey = Guid.NewGuid();
            foreach (ILineItem product in basketItems)
            {
                var item = new InvoiceLineItem(LineItemType.Product, product.Name, product.Sku, product.Quantity, product.Price, product.ExtendedData);
                invoice.Items.Add(item);
            }
            invoice.BillToEmail = email;
            invoice.CurrencyCode = "GBP";
            invoice.Total = merchelloCustomer.CurrentCustomer.Basket().TotalBasketPrice;
            invoice.InvoiceNumberPrefix = "";
            return invoice;
        }
    }
    
    internal class BrainTreeHelper
    {
        public static BraintreeProviderSettings GetBraintreeProviderSettings()
        {
            return new BraintreeProviderSettings()
            {
                EnvironmentType = EnvironmentType.Sandbox,
                PublicKey = "",
                PrivateKey = "",
                MerchantId = "",
                MerchantDescriptor = new MerchantDescriptor()
                {
                    Name = "",
                    Url = "",
                    Phone = ""
                },
                DefaultTransactionOption = TransactionOption.Authorize
            }; 
        }
    }
    

    Thanks, really appreciate it.

Please Sign in or register to post replies

Write your reply to:

Draft