How to Add Stripe Payment to Your ASP.NET Project

One of the most widely used online payment companies that can be included into web apps is Stripe.

We’ll look at how to incorporate Stripe into your.NET project so that you can take payments online.

After registering, you’ll need to complete extra steps and have your email address verified in order to enable payments on your account.

The extra actions consist of:

  • Verifying your business
  • Adding your bank details (so you get paid)
  • Securing your account with two-step authentication
  • Tax calculation

The front-end application

An ASP.NET Core Web API that can take online payments through Stripe will be put up.

We’re going to add these lines to Program.cs to make sure we can add static files in the wwwroot folder.

// Program.cs
...

var app = builder.Build();

...

app.UseDefaultFiles(); // <-- Add this line
app.UseStaticFiles(); // <-- Add this line

...

app.Run();

A static index.html file will be included, and it will be located in the wwwroot folder. This will make use of the stripe.js JavaScript file, which has a onclick event listener, to call our web application’s Web API.

The online payment with Stripe will be created by the API call. When a user creates an online payment, Stripe will provide a redirect URL so they can use their servers to complete the payment.

We will use document.location.href to reroute the user to Stripe using the redirect URL that will be returned as part of the API response.

The user will be taken back to a static confirmation.html page after placing a successful order.

The product page

Beats Flex Wireless Earphones are available on our product page for $49.99 USD. In order to purchase the product, Stripe requires you to enter your email address, so we’ve included a field and a button.

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Buy our products</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-12">
                <h1>My shop</h1>
                <div class="container">
                    <div class="row">
                        <div class="row-12">
                            <h3>Beats Flex Wireless Earphones</h3>
                            <p>The Beats Flex Wireless Earphones offer a comfortable and versatile audio experience. With magnetic earbuds and up to 12 hours of battery life, they are ideal for everyday use.</p>
                            <p>USD 49.99</p>
                            Email: <input type="text" name="Email" />
                            <button class="btn btn-primary" type="submit" data-buy="1">Buy</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>

    </div>
    <script src="/js/stripe.js"></script>
</body>
</html>

The attribute data-buy, which has a value of 1, is present in the Buy button on the page. This attribute will be used to create a onclick event listener and initiate the API call.

The product page has a JavaScript reference to /js/stripe.js in order to accomplish that.

The API call is made by the onclick event listener.

Initially, we will verify that the [data-buy] is a valid number and has a value. This number will serve as the product ID.

We’ll call the parent node from the data-buy button, a div element, assuming it’s a number. The email address input for the body of the API call is contained in this.

We can now proceed with making the API call. We’ll send a POST request to /api/stripe using JSON and the JavaScript fetch API.

The email address entered in the text box and the product ID will be in the body.

Should the API call be successful, the JSON will be obtained from the response and document.location.href will be set to the redirectUrl object property in the JSON.

// /js/stripe.js
document.querySelector('[data-buy]').addEventListener('click', async (event) => {
    if (event?.target?.getAttribute('data-buy') != '') {
        var productId = Number(event.target.getAttribute('data-buy'));

        if (isNaN(productId)) {
            throw 'Not a valid product';
        }

        var parentNode = event.target.parentNode;
        var email = parentNode.querySelector(`input[name='Email']`).value;

        await fetch('/api/stripe', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ productId: productId, email: email })
        })
        .then(async(response) => {
            if (response?.ok) {
                var json = await response.json();

                document.location.href = json['redirectUrl'];
            }
        });
    }
});

The confirmation page

Lastly, we will create a simple confirmation page, confirmation.html. A notification stating that the order has been received will be included in this.

<!-- confirmation.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>We have received your order</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-12">
                <h1>Thank you</h1>
                <div class="container">
                    <div class="row">
                        <div class="row-12">
                            <p>We have received your order.</p> 
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

The Web API

A couple of models need to be created before we can configure the Web API endpoint.

Data from the request body that we are sending, including the product ID and email address, will be included in the BuyModel class. We’ll add data annotations to these fields to make sure they are validated. These annotations will confirm that the email address is valid and that the properties are required.

// BuyModel.cs
public class BuyModel
{
    [Required]
    public int ProductId { get; init; }

    [Required, EmailAddress]
    public string Email { get; init; }
}

We’ll also create a ProductModel class. This will include information about the product, including its name, ID, and cost.

// ProductModel.cs
public class ProductModel
{
    public int Id { get; }

    public string Name { get; }

    public decimal Price { get; }

    public ProductModel(int id, string name, decimal price)
    {
        Id = id;
        Name = name;
        Price = price;
    } 
}

The Stripe API key

We still need to create one more class. The API key from our Stripe account will be in the StripeOptions class. This enables us to send the user to the Stripe payment page and start a Stripe checkout session.

// StripeOptions.cs
public class StripeOptions
{
    public string? ApiKey { get; init; }
}
}

How to get the Stripe API key

Make sure Test mode is enabled in the upper-right corner of your Stripe account after logging in. This guarantees that no actual money is exchanged and that only test payments are made.

Next, select the Developers link located on the left side of the page.

You will need to disclose the Secret key after selecting the API keys tab. To copy it, click on it.

Paste the Stripe API key into your appsettings.Development.json file inside the Stripe:ApiKey key.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "Stripe": {
    "ApiKey": "API_KEY_HERE"
  }
}

We must add the API key to the StripeOptions class in order to make sure we can read it from the appsettings.Development.json file.

This is done in Program.cs before builder.Build() is called.

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

...

builder.Services.AddOptions<StripeOptions>()
    .Bind(builder.Configuration.GetSection("Stripe")); // <-- Add this line

var app = builder.Build();

...

app.Run();

Nuget package

For usage of the API, Stripe provides a wealth of documentation.

We could use the endpoints listed in the Stripe documentation to create our own HTTP requests.

However, there is a far easier method.

To integrate Stripe payments into your.NET project, Stripe provides Stripe.net, a NuGet package. Feel free to include it in your project.

The Web API controller

Now is the time to develop the StripeController Web API controller.

We’ll create a ProductModel field named DefaultProduct inside of that. This will include information on the product.

Furthermore, we will utilize dependency injection to supply a reference for the StripeOptions.

// StripeController.cs
[Route("api/[controller]")]
[ApiController]
public class StripeController : ControllerBase
{
    private readonly ProductModel DefaultProduct 
        = new(1, "Beats Flex Wireless Earphones", 49.99m);

    private readonly StripeOptions _stripeOptions;

    public StripeController(IOptionsSnapshot<StripeOptions> stripeOptionsValue)
    {
        _stripeOptions = stripeOptionsValue.Value;
    }
}

We will then construct the endpoint. We’ll pass in a BuyModel instance as the parameter so we know the product ID and email address, and the function will be called BuyAsync. We will also give it the HttpPost attribute in addition to that.

Next, we’ll verify that the request body’s ID matches the default product ID and that the ModelState is legitimate.

Obtaining the static StripeConfiguration class from the Stripe namespace and adding the API key to the ApiKey property is how we add the key.

Next, we establish a fresh StripeSession with the following information:

  • Mode = payment
  • ClientReferenceId = A unique reference for the session
  • SuccessUrl = The full URL (including the origin) to redirect the user if they make a successful payment
  • CancelUrl = The full URL (including the origin) to redirect the user back if they cancel the payment
  • CustomerEmail = The customer’s email address
  • LineItems = Information about product such as the price and quantity

Lastly, we’ll send the user back the URL in the response to take them to the Stripe payment page.

// StripeController.cs
[Route("api/[controller]")]
[ApiController]
public class StripeController : ControllerBase
{
    private readonly ProductModel DefaultProduct 
        = new(1, "Beats Flex Wireless Earphones", 49.99m);

    private readonly StripeOptions _stripeOptions;

    public StripeController(IOptionsSnapshot<StripeOptions> stripeOptionsValue)
    {
        _stripeOptions = stripeOptionsValue.Value;
    }

    [HttpPost]
    public async Task<IActionResult> BuyAsync(BuyModel buyModel)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }

        if (buyModel.ProductId != DefaultProduct.Id)
        {
            return BadRequest();
        }

        var product = DefaultProduct;
        var origin = $"{Request.Scheme}://{Request.Host}";

        StripeConfiguration.ApiKey = _stripeOptions.ApiKey;

        // Create Stripe checkout session
        var stripeSessionService = new SessionService();

        var stripeCheckoutSession = await stripeSessionService.CreateAsync(new SessionCreateOptions
        {
            Mode = "payment",
            ClientReferenceId = Guid.NewGuid().ToString(),
            SuccessUrl = $"{origin}/confirmation.html",
            CancelUrl = $"{origin}/index.html",
            CustomerEmail = buyModel.Email, 
            LineItems = new List<SessionLineItemOptions>
            {
                new SessionLineItemOptions()
                {
                    PriceData = new SessionLineItemPriceDataOptions()
                    {
                        Currency = "USD",
                        ProductData = new SessionLineItemPriceDataProductDataOptions
                        {
                            Name = product.Name,
                        },
                        UnitAmountDecimal = product.Price * 100
                    },
                    Quantity = 1
                }
            }
        });

        return Ok(new { redirectUrl = stripeCheckoutSession.Url });
    }
}

When the user is redirected to Stripe

The user is taken to the Stripe payment screen after entering their email address and clicking the “Buy” button.

Since this is a test order, the user can fill out the form with information about the test card. You can use the test card numbers that Stripe provides you with. This contains the card numbers for various kinds of cards.

Following a successful payment, the user will be taken back to the page we initially created for confirmation.

Start accepting live payments

You will need to add an additional Stripe API key to your.NET project when you are prepared to begin taking live payments.

To obtain the Stripe API key in your Stripe account, follow the same steps again, but make sure that Test mode is turned off.

The API key you are given will differ from the one you were given during the test.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *