- Introduction
- Application Architecture
- Design of Application
- Security - JWT Token Based Authentication
- Development Environment
- Technologies
- Tools
- Web Api Endpoints
- Solution Structure
- Swagger - API Documentation
- Application Logging - NLogging
- How to run the Application
- Demo - Merchant Portal and Gateway Client
- Unit Testing in ASP.NET Core
This is an ASP.NET Core Application that allows a merchant to process a payment through a secure payment gateway. The payment gateway communicates with an issuing bank (simulator) to perform payment transactions requested by the client.
The diagram illustrates the flow of the application as follows:
- Client: The client submits an order for an item on an online store
- Online Store: The online store contacts the payment gateway, which in turn requests the client to authenticate himself with his credentials.
- Payment Gateway: Once the authentication is completed, the payment gateway requires the client to confirm and pay for the order
- Issuing Bank: The payment gateway confirms the transaction through an issuing bank, which in turns credit the merchant’s account and debit the client’s account
- Onion Architecture
JWT Token based authentication is implementated to secure the WebApi for the Payment Gateway. When the user logins to the payment gateway, the gateway issues a valid token after validating the user credentials. The API Gateway sends the token to the client. The client app uses the token for the subsequent request.
In the appsettings.json
file, the secret key has been defined as follows:
{
"AppSettings": {
"Secret": "Checkout.com helps your business to offer more payment methods and currencies"
},
- C# NET
- ASP.NET Core 2.1 Web API
- Entity Framework Core (For Data Access)
- Swash Buckle (For API Documentation)
- xUnit (For Unit Testing)
- Fluent Validations in ASP.NET Core Web API (For API validations)
- NLogging (For Application Logging)
- ASP.NET Core Dependency Injection
- Moq Unit Test (For configuring test-time-only mock versions of dependencies)
- RestSharp Library (For consuming REST APIs)
- Uri: "api/bank"
[HttpPost]
- To perform debit and credit transactions
- Uri: "api/payment/authenticate"
[HttpPost]
- To authenticate user and issue a valid token - Uri: "api/payment"
[HttpPost]
- To process payment through gateway - Uri: "api/payment"
[HttpGet("{id}")]
- To retrieve all transactions by passing a merchant unique identifier as parameter
Swashbuckle Nuget package added to the "Payment.WebApi" and Swagger Middleware configured in the startup.cs for API documentation. when running the WebApi service, the swagger UI can be accessed through the swagger endpoint "/swagger".
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Payment API", Version = "V1" });
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory log)
{
app.UseSwagger();
app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "post API v1"); });
}
- Configure Fluent Validation
In the startup.cs
, the following configurations are added:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddFluentValidation();
services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = (context) =>
{
var errors = context.ModelState.Values.SelectMany(x => x.Errors.Select(e => e.ErrorMessage)).ToList();
var result = new
{
Code = "00009",
Message = "Validation Errors",
Errors = errors
};
return new BadRequestObjectResult(result);
};
});
}
- Testing the custom validator with Postman
The NLogging Nuget package has been added to the Payment Gateway project for monitoring. The logs are stored in the C:\Users\Public\checkout\
folder.
<targets>
<target name="logfile" xsi:type="File" fileName="C:/Users/Public/checkout/LOG/${shortdate}_log.txt" layout="${longdate} ${level:uppercase=true} ${message}"/>
</targets>
- Download the BAK SQL files from the repo.
- Restore the BAK files against SQL server to create the necessary tables and sample data
- Open the solution (.sln) in Visual Studio 2017 or later version
- Configure the SQL connection string in
Bank.WebApi -> appsettings.json
andPayment.WebApi -> appsettings.json
- Run the following projects in the solution:
- Bank.WebApi
- Payment.WebApi
- Merchant.UI by setting multiple startups projects in the solution's properties
Password | User Type | |
---|---|---|
[email protected] | test | shopper |
- xUnit Project: Payment.Test
Configure the PaymentTestController
to mock the dependencies of the PaymentController
in the Payment.WebApi to carry out the unit testing.
Example:
public class PaymentTestController
{
private readonly Mock<IUserService> _userService;
private readonly Mock<ICardService> _cardService;
private readonly Mock<ITransactService> _transactService;
private Mock<Common.Logger.ILogger> _logger;
public PaymentTestController()
{
_userService = new Mock<IUserService>();
_cardService = new Mock<ICardService>();
_transactService = new Mock<ITransactService>();
_logger = new Mock<Common.Logger.ILogger>();
}
[Fact]
public void User_Pay_OkObjectResult()
{
var controller = new PaymentController(_userService.Object, _cardService.Object, _transactService.Object, _logger.Object);
var pay = new Payments()
{
AccountNumber = 2,
Amount = 100,
CardNumber = 4261392791756353,
Cvv = 812,
ExpiryDate = DateTime.Now.AddDays(5),
Token = "token",
MerchantAccountNumber = 3
};
var data = controller.Post(pay);
Assert.IsType<OkObjectResult>(data);
}