Braintree Payment Gateway Integration With ASP.NET Core 2.1

 In this post, we are going to implement the Braintree payment gateway with ASP.NET Core 2.1. 

 
Based on the previous post, this article is extended to implement a payment gateway. We are going to modify/extend the existing sample application by downloading the full source code from GitHub.
BraintreePayment ASP.NET Core 2.1

Let’s get started by opening the existing application. First of all, we are going to add a Braintree package. Go to NuGet to install the Braintree .NET Client Library which is supported by both the .NET Framework and .NET Core.

BraintreePayment ASP.NET Core 2.1

Configuration

This is where we configure the environment and merchant with API key for Braintree.

  1. public class BraintreeConfiguration : IBraintreeConfiguration  
  2. {  
  3.     public string Environment { get; set; }  
  4.     public string MerchantId { get; set; }  
  5.     public string PublicKey { get; set; }  
  6.     public string PrivateKey { get; set; }  
  7.     private IBraintreeGateway BraintreeGateway { get; set; }  
  8.   
  9.     public IBraintreeGateway CreateGateway()  
  10.     {  
  11.         Environment = System.Environment.GetEnvironmentVariable("BraintreeEnvironment");  
  12.         MerchantId = System.Environment.GetEnvironmentVariable("BraintreeMerchantId");  
  13.         PublicKey = System.Environment.GetEnvironmentVariable("BraintreePublicKey");  
  14.         PrivateKey = System.Environment.GetEnvironmentVariable("BraintreePrivateKey");  
  15.   
  16.         if (MerchantId == null || PublicKey == null || PrivateKey == null)  
  17.         {  
  18.             Environment = "sandbox";  
  19.             MerchantId = "9j4ynyf697k9685t";  
  20.             PublicKey = "25sy94dv3rqgg355";  
  21.             PrivateKey = "b0d5e1b1fa9dc24c263a3e83a148a7b3";  
  22.         }  
  23.   
  24.         return new BraintreeGateway(Environment, MerchantId, PublicKey, PrivateKey);  
  25.     }  
  26.   
  27.     public IBraintreeGateway GetGateway()  
  28.     {  
  29.         if (BraintreeGateway == null)  
  30.         {  
  31.             BraintreeGateway = CreateGateway();  
  32.         }  
  33.   
  34.         return BraintreeGateway;  
  35.     }  
  36. }  

Payments Controller

Generate Client-Token

Initially, an HttpGet method named GenerateToken gets called to generate the client-token for authorization to initialize the client UI.

  1. [HttpGet, Route("GenerateToken")]  
  2. public object GenerateToken()  
  3. {  
  4.     var gateway = config.GetGateway();  
  5.     var clientToken = gateway.ClientToken.Generate();  
  6.     return clientToken;  
  7. }  

Create Transaction

Finally, the transaction is done with Amount and PaymentMethodNonce which is payment authorization for the customer generated by client script.
  1. [HttpPost, Route("Checkout")]  
  2. public object Checkout(vmCheckout model)  
  3. {  
  4.     string paymentStatus = string.Empty;  
  5.     var gateway = config.GetGateway();  
  6.   
  7.     var request = new TransactionRequest  
  8.     {  
  9.         Amount = model.Price,  
  10.         PaymentMethodNonce = model.PaymentMethodNonce,  
  11.         Options = new TransactionOptionsRequest  
  12.         {  
  13.             SubmitForSettlement = true  
  14.         }  
  15.     };  
  16.   
  17.     Result<Transaction> result = gateway.Transaction.Sale(request);  
  18.     if (result.IsSuccess())  
  19.     {  
  20.         paymentStatus = "Succeded";  
  21.   
  22.         //Do Database Operations Here  
  23.     }  
  24.     else  
  25.     {  
  26.         string errorMessages = "";  
  27.         foreach (ValidationError error in result.Errors.DeepAll())  
  28.         {  
  29.             errorMessages += "Error: " + (int)error.Code + " - " + error.Message + "\n";  
  30.         }  
  31.   
  32.         paymentStatus = errorMessages;  
  33.     }  
  34.   
  35.     return paymentStatus;  
  36. }  

Here is the complete code for Payments Controller.

  1. [ApiController, Route("api/[controller]"), Produces("application/json")]  
  2. public class PaymentsController : ControllerBase  
  3. {  
  4.     public IBraintreeConfiguration config = new BraintreeConfiguration();  
  5.   
  6.     public static readonly TransactionStatus[] transactionSuccessStatuses =  
  7.         {  
  8.             TransactionStatus.AUTHORIZED,  
  9.             TransactionStatus.AUTHORIZING,  
  10.             TransactionStatus.SETTLED,  
  11.             TransactionStatus.SETTLING,  
  12.             TransactionStatus.SETTLEMENT_CONFIRMED,  
  13.             TransactionStatus.SETTLEMENT_PENDING,  
  14.             TransactionStatus.SUBMITTED_FOR_SETTLEMENT  
  15.         };  
  16.   
  17.     [HttpGet, Route("GenerateToken")]  
  18.     public object GenerateToken()  
  19.     {  
  20.         var gateway = config.GetGateway();  
  21.         var clientToken = gateway.ClientToken.Generate();  
  22.         return clientToken;  
  23.     }  
  24.   
  25.     [HttpPost, Route("Checkout")]  
  26.     public object Checkout(vmCheckout model)  
  27.     {  
  28.         string paymentStatus = string.Empty;  
  29.         var gateway = config.GetGateway();  
  30.   
  31.         var request = new TransactionRequest  
  32.         {  
  33.             Amount = model.Price,  
  34.             PaymentMethodNonce = model.PaymentMethodNonce,  
  35.             Options = new TransactionOptionsRequest  
  36.             {  
  37.                 SubmitForSettlement = true  
  38.             }  
  39.         };  
  40.   
  41.         Result<Transaction> result = gateway.Transaction.Sale(request);  
  42.         if (result.IsSuccess())  
  43.         {  
  44.             paymentStatus = "Succeded";  
  45.   
  46.             //Do Database Operations Here  
  47.         }  
  48.         else  
  49.         {  
  50.             string errorMessages = "";  
  51.             foreach (ValidationError error in result.Errors.DeepAll())  
  52.             {  
  53.                 errorMessages += "Error: " + (int)error.Code + " - " + error.Message + "\n";  
  54.             }  
  55.   
  56.             paymentStatus = errorMessages;  
  57.         }  
  58.   
  59.         return paymentStatus;  
  60.     }  
  61. }  

Html View

In index.html, we need to add a drop-in library reference.

  1. <script src="//js.braintreegateway.com/web/dropin/1.9.4/js/dropin.min.js" type="text/javascript"></script>  

The below code snippet is where (<div id="dropin"></div>) to render Drop-in UI in payment.html where a user can input card information. After providing valid card information, checkout action is performed by clicking on the Checkout button.

  1. <div class="container-fluid">  
  2.     <div class="row">  
  3.         <h3> {{title}} - {{cartmodel.Price}}$</h3>  
  4.         <div id="dropin"></div>  
  5.         <button type="submit" id="checkout" class="btn btn-sm  btn-success button">  
  6.             Checkout <i class="fa fa-shopping-cart"></i>  
  7.         </button>  
  8.         <h5>{{paymentresult}}</h5>  
  9.     </div>  
  10. </div>  

AngularJS Controller

Get client token

To create the Drop-in UI, we need to provide client-token generated by the server for authorization.

  1. //Generate View  
  2. braintree.dropin.create({  
  3.     authorization: client_token,  
  4.     container: '#dropin',  
  5.     card: {  
  6.         overrides: {  
  7.             styles: {  
  8.                 input: {  
  9.                     color: 'blue',  
  10.                     'font-size''18px'  
  11.                 },  
  12.                 '.number': {  
  13.                     'font-family''monospace'  
  14.                 },  
  15.                 '.invalid': {  
  16.                     color: 'red'  
  17.                 }  
  18.             },  
  19.             fields: {  
  20.                 number: {  
  21.                     //placeholder: 'Card Number',  
  22.                     formatInput: true // Turn off automatic formatting  
  23.                 }  
  24.             }  
  25.         }  
  26.     }  
  27.   
  28. }, function (createErr, instance) {  
  29.   
  30. });  

Request Payment Method

This is where a client requests for payment method information (PaymentMethodNonce). Later, the PaymentMethodNonce method is used in the server to charge a card.

  1. //Checkout Submit  
  2. document.getElementById("checkout").addEventListener('click'function () {  
  3.     //event.preventDefault();  
  4.     instance.requestPaymentMethod(function (err, payload) {  
  5.         if (err) {  
  6.             console.log('Error', err);  
  7.             return;  
  8.         }  
  9.         //Token Braintree  
  10.         $scope.cartmodel.PaymentMethodNonce = payload.nonce;  
  11.         $scope.checkOut();  
  12.     });  
  13. });  

The full Client Script.

  1. templatingApp.controller('PaymentController', ['$scope''$http'function ($scope, $http) {  
  2.     $scope.title = "Braintree Payment";  
  3.     $scope.paymentresult = null;  
  4.     $scope.cartmodel = {  
  5.         FirstName: "Shashangka",  
  6.         LastName: "LastName",  
  7.         Email: "shashangka@gmail.com",  
  8.         Street: "Bejpara, Jessore",  
  9.         Price: 50  
  10.     };  
  11.   
  12.     //Generate Token PaymentGateway  
  13.     PaymentGateway();  
  14.     function PaymentGateway() {  
  15.   
  16.         $http({  
  17.             method: 'GET',  
  18.             url: '/api/Payments/GenerateToken'  
  19.         }).then(function successCallback(response) {  
  20.             //console.log(response.data);  
  21.             var client_token = response.data;  
  22.   
  23.             //Generate View  
  24.             braintree.dropin.create({  
  25.                 authorization: client_token,  
  26.                 container: '#dropin',  
  27.                 card: {  
  28.                     overrides: {  
  29.                         styles: {  
  30.                             input: {  
  31.                                 color: 'blue',  
  32.                                 'font-size''18px'  
  33.                             },  
  34.                             '.number': {  
  35.                                 'font-family''monospace'  
  36.                             },  
  37.                             '.invalid': {  
  38.                                 color: 'red'  
  39.                             }  
  40.                         },  
  41.                         fields: {  
  42.                             number: {  
  43.                                 //placeholder: 'Card Number',  
  44.                                 formatInput: true // Turn off automatic formatting  
  45.                             }  
  46.                         }  
  47.                     }  
  48.                 }  
  49.   
  50.             },function (createErr, instance) {  
  51.                 //Checkout Submit  
  52.               document.getElementById("checkout").addEventListener('click'function () {  
  53.                     //event.preventDefault();  
  54.                     instance.requestPaymentMethod(function (err, payload) {  
  55.                         if (err) {  
  56.                             console.log('Error', err);  
  57.                             return;  
  58.                         }  
  59.                         //Token Braintree  
  60.                         $scope.cartmodel.PaymentMethodNonce = payload.nonce;  
  61.                         $scope.checkOut();  
  62.                     });  
  63.                 });  
  64.             });  
  65.   
  66.         }, function errorCallback(response) {  
  67.             console.log(response);  
  68.         });  
  69.     };  
  70.   
  71.     //CheckOut  
  72.     $scope.checkOut = function () {  
  73.         console.log($scope.cartmodel);  
  74.         $http({  
  75.             method: 'POST',  
  76.             url: '/api/Payments/Checkout',  
  77.             data: $scope.cartmodel  
  78.         }).then(function successCallback(response) {  
  79.             console.log(response.data);  
  80.             $scope.paymentresult = response.data;  
  81.         }, function errorCallback(response) {  
  82.             console.log(response);  
  83.         });  
  84.     };  
  85.   
  86. }]);  

Testing

Here is the created payment Drop-in UI with Test Card No: 378282246310005 or 4111111111111111 

BraintreePayment ASP.NET Core 2.1

After a successful transaction, the below screen will appear.

BraintreePayment ASP.NET Core 2.1

Braintree

As we can see, this is the list of transactions in Braintree. 

BraintreePayment ASP.NET Core 2.1

Hope this will help. Thanks 🙂

References

  • https://developers.braintreepayments.com/start/hello-client/javascript/v3
  • https://developers.braintreepayments.com/start/hello-server/dotnet
  • https://github.com/braintree/braintree_aspnet_example