blazorblazor-server-sidebraintree

Blazer Server: Setup Braintree Payment Javascript and .NET SDK and API


I was not able to find any examples of setting up Braintree Javascript and .NET SDK with Blazer Server application.

Brainstree workflow is to collect user credit card data in the client, which then returns a token, which Braintree calls a Nonce. This way the user's credit card data never passed thru or stored in your application. You pass the nonce to the server, which then process the payment.

I am not sure how to make the javascript work with Blazer server and then what needs to be done on the server side.


Solution

  • I was able to get the payment processes working with Braintree sandbox.

    The example is located: https://github.com/MSIH/Blazor-Braintree-Example/

    1. Add Braintree javascript library to _Host.cshtml file
    <!-- braintree-->
    <script type="text/javascript" src="https://js.braintreegateway.com/web/dropin/1.29.0/js/dropin.js">
    </script>
    
    </head>
    
    1. Add Braintree functions to _Host.cshtml file (this should go in separate js file)
    <script>
    window.brainstreePayment = (clientToken, dotNetObject) => {
        //alert(clientToken);
        var button = document.querySelector('#submit-button');
        braintree.dropin.create({
            authorization: clientToken,
            selector: '#dropin-container'
        }, function (err, instance) {
            button.addEventListener('click', function () {
                instance.requestPaymentMethod(function (requestPaymentMethodErr, payload) {
                    if (requestPaymentMethodErr) {
                        // No payment method is available.
                        // An appropriate error will be shown in the UI.
                        console.error(requestPaymentMethodErr);
                        return;
                    }      
                    dotNetObject.invokeMethodAsync('MakePayment', payload.nonce);
                });
            })
        });
    }
    </script>
    </body>
    
    1. create Payment.razor file
    @page "/PaymentSubmit/"
    
    @using Braintree;
    @using Microsoft.Extensions.Logging;
    @inject IJSRuntime JSRuntime;
    @inject ILogger<Counter> logger;
    
    
    <label for="Amount">In the Amount:</label>
    <input id="Amount" name="Amount" type="tel" min="1" @bind="@Amount" />
    <br>
    <br>
    
    <div id="dropin-container"></div>
    
    <div id="dropin-wrapper">
        <div id="checkout-message"></div>
        <div id="dropin-container"></div>
        <button id="submit-button">Pay</button>
    </div>
    <br>
    PaymentTransactionId: @PaymentTransactionId
    <br>
    
    @code {
    
       
        public string ClientToken { get; set; }   
        public string Nonce { get; set; }   
        public string Amount { get; set; }    
        public string PaymentTransactionId { get; set; }    
    
        public BraintreeGateway gateway = new BraintreeGateway
        {
            Environment = Braintree.Environment.SANDBOX,
            MerchantId = "GetFromBraintree",
            PublicKey = "GetFromBraintree",
            PrivateKey = "GetFromBraintree"
        };
    
    
        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                ClientToken = gateway.ClientToken.Generate();
                var dotNetReference = DotNetObjectReference.Create(this);        
                await JSRuntime.InvokeVoidAsync("brainstreePayment", ClientToken, dotNetReference);
            }
        }
    
        [JSInvokable("MakePayment")]
        public void MakePayment(string Nonce)
        {
    
            logger.LogWarning(Nonce);
            logger.LogWarning(Amount);
            decimal newAmount = Convert.ToDecimal(Amount);
            var request = new TransactionRequest
            {
                Amount = newAmount,
                PaymentMethodNonce = Nonce,
                Options = new TransactionOptionsRequest
                {
                    SubmitForSettlement = true
                }
            };
    
            Result<Transaction> result = gateway.Transaction.Sale(request);
            if (result.IsSuccess())
            {
                Transaction transaction = result.Target;
                logger.LogWarning("transaction success");
                PaymentTransactionId = transaction.Id;
                StateHasChanged();
    
                @*redirect*@
            }
            else if (result.Transaction != null)
            {
                @*redirect*@
                logger.LogWarning("transaction null");
            }
            else
            {
                string errorMessages = "";
                foreach (ValidationError error in result.Errors.DeepAll())
                {
                    errorMessages += "Error: " + (int)error.Code + " - " + error.Message + "\n";
                }
                logger.LogWarning("transaction error");
                logger.LogWarning(errorMessages);
            }
        }
    }