Introduction
Based on previous post this article is extended to implement payment gateway. We are going to modify/extend existing sample application by downloading full source code from github.
Let’s get started by opening the existing application, first of all we are going to add Braintree package. Go to NuGet to install Braintree .NET Client Library which is supported by both .NET Framework, .NET Core.
Configuration: This is where we configured the environment, merchant with API key for Braintree.
public class BraintreeConfiguration : IBraintreeConfiguration
{
public string Environment { get; set; }
public string MerchantId { get; set; }
public string PublicKey { get; set; }
public string PrivateKey { get; set; }
private IBraintreeGateway BraintreeGateway { get; set; }
public IBraintreeGateway CreateGateway()
{
Environment = System.Environment.GetEnvironmentVariable("BraintreeEnvironment");
MerchantId = System.Environment.GetEnvironmentVariable("BraintreeMerchantId");
PublicKey = System.Environment.GetEnvironmentVariable("BraintreePublicKey");
PrivateKey = System.Environment.GetEnvironmentVariable("BraintreePrivateKey");
if (MerchantId == null || PublicKey == null || PrivateKey == null)
{
Environment = "sandbox";
MerchantId = "9j4ynyf697k9685t";
PublicKey = "25sy94dv3rqgg355";
PrivateKey = "b0d5e1b1fa9dc24c263a3e83a148a7b3";
}
return new BraintreeGateway(Environment, MerchantId, PublicKey, PrivateKey);
}
public IBraintreeGateway GetGateway()
{
if (BraintreeGateway == null)
{
BraintreeGateway = CreateGateway();
}
return BraintreeGateway;
}
}
Payments Controller:
Generate Client-Token: Initially HttpGet method named GenerateToken get called to generate client-token for authorization to initialize client UI.
[HttpGet, Route("GenerateToken")]
public object GenerateToken()
{
var gateway = config.GetGateway();
var clientToken = gateway.ClientToken.Generate();
return clientToken;
}
Create Transaction: Finally transaction is done with Amount and PaymentMethodNonce which is payment authorization for customer generated by client script.
[HttpPost, Route("Checkout")]
public object Checkout(vmCheckout model)
{
string paymentStatus = string.Empty;
var gateway = config.GetGateway();
var request = new TransactionRequest
{
Amount = model.Price,
PaymentMethodNonce = model.PaymentMethodNonce,
Options = new TransactionOptionsRequest
{
SubmitForSettlement = true
}
};
Result<Transaction> result = gateway.Transaction.Sale(request);
if (result.IsSuccess())
{
paymentStatus = "Succeded";
}
else
{
string errorMessages = "";
foreach (ValidationError error in result.Errors.DeepAll())
{
errorMessages += "Error: " + (int)error.Code + " - " + error.Message + "\n";
}
paymentStatus = errorMessages;
}
return paymentStatus;
}
Finally the full Payments Controller.
[ApiController, Route("api/[controller]"), Produces("application/json")]
public class PaymentsController : ControllerBase
{
public IBraintreeConfiguration config = new BraintreeConfiguration();
public static readonly TransactionStatus[] transactionSuccessStatuses =
{
TransactionStatus.AUTHORIZED,
TransactionStatus.AUTHORIZING,
TransactionStatus.SETTLED,
TransactionStatus.SETTLING,
TransactionStatus.SETTLEMENT_CONFIRMED,
TransactionStatus.SETTLEMENT_PENDING,
TransactionStatus.SUBMITTED_FOR_SETTLEMENT
};
[HttpGet, Route("GenerateToken")]
public object GenerateToken()
{
var gateway = config.GetGateway();
var clientToken = gateway.ClientToken.Generate();
return clientToken;
}
[HttpPost, Route("Checkout")]
public object Checkout(vmCheckout model)
{
string paymentStatus = string.Empty;
var gateway = config.GetGateway();
var request = new TransactionRequest
{
Amount = model.Price,
PaymentMethodNonce = model.PaymentMethodNonce,
Options = new TransactionOptionsRequest
{
SubmitForSettlement = true
}
};
Result<Transaction> result = gateway.Transaction.Sale(request);
if (result.IsSuccess())
{
paymentStatus = "Succeded";
}
else
{
string errorMessages = "";
foreach (ValidationError error in result.Errors.DeepAll())
{
errorMessages += "Error: " + (int)error.Code + " - " + error.Message + "\n";
}
paymentStatus = errorMessages;
}
return paymentStatus;
}
}
Html View:
In index.html we need to add drop-in library reference.
<script src="//js.braintreegateway.com/web/dropin/1.9.4/js/dropin.min.js" type="text/javascript"></script>
Below code snippet is where(<div id="dropin"></div>) to render Drop-in UI in payment.html where user can input card information. After providing valid card information, checkout action is performed by clicking on Checkout button.
<div class="container-fluid">
<div class="row">
<h3> {{title}} - {{cartmodel.Price}}$</h3>
<div id="dropin"></div>
<button type="submit" id="checkout" class="btn btn-sm btn-success button">
Checkout <i class="fa fa-shopping-cart"></i>
</button>
<h5>{{paymentresult}}</h5>
</div>
</div>
AngularJS Controller:
Get client token: To create dropin UI we need to provide client-token generated by server for authorization.
braintree.dropin.create({
authorization: client_token,
container: '#dropin',
card: {
overrides: {
styles: {
input: {
color: 'blue',
'font-size': '18px'
},
'.number': {
'font-family': 'monospace'
},
'.invalid': {
color: 'red'
}
},
fields: {
number: {
formatInput: true
}
}
}
}
}, function (createErr, instance) {
});
Request Payment Method: This is where client request for payment method information(PaymentMethodNonce), later PaymentMethodNonce will use in server to charge a card.
document.getElementById("checkout").addEventListener('click', function () {
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Error', err);
return;
}
$scope.cartmodel.PaymentMethodNonce = payload.nonce;
$scope.checkOut();
});
});
Finally the full Client Script.
templatingApp.controller('PaymentController', ['$scope', '$http', function ($scope, $http) {
$scope.title = "Braintree Payment";
$scope.paymentresult = null;
$scope.cartmodel = {
FirstName: "Shashangka",
LastName: "LastName",
Email: "shashangka@gmail.com",
Street: "Bejpara, Jessore",
Price: 50
};
PaymentGateway();
function PaymentGateway() {
$http({
method: 'GET',
url: '/api/Payments/GenerateToken'
}).then(function successCallback(response) {
var client_token = response.data;
braintree.dropin.create({
authorization: client_token,
container: '#dropin',
card: {
overrides: {
styles: {
input: {
color: 'blue',
'font-size': '18px'
},
'.number': {
'font-family': 'monospace'
},
'.invalid': {
color: 'red'
}
},
fields: {
number: {
formatInput: true
}
}
}
}
}, function (createErr, instance) {
document.getElementById("checkout").addEventListener('click', function () {
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Error', err);
return;
}
$scope.cartmodel.PaymentMethodNonce = payload.nonce;
$scope.checkOut();
});
});
});
}, function errorCallback(response) {
console.log(response);
});
};
$scope.checkOut = function () {
console.log($scope.cartmodel);
$http({
method: 'POST',
url: '/api/Payments/Checkout',
data: $scope.cartmodel
}).then(function successCallback(response) {
console.log(response.data);
$scope.paymentresult = response.data;
}, function errorCallback(response) {
console.log(response);
});
};
}]);
Testing: Ready-made payment Drop-in UI, Test Card No: 378282246310005 or 4111111111111111
After successful transaction below screen will appear.
Braintree: As we can see the list of transaction in Braintree.
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