Menu

Creating Credit Card Charges With Stripe And .NET

Creating Credit Card Charges With Stripe And .NET

In this post I'll be going over the Stripe API and more specifically, using it in a .NET environment. I'll say right now that Stripe and the internet do not make this an easy task for a .NET developer. Stripe offers examples in everything except .NET and most online examples use 3rd party libraries to get the job done. But where's the fun in that. I'll be going over the entire process without using any 3rd party apps, and just using the native .NET classes and the HTTP API services that Stripe provides.

Checkout vs Stripe.js

First things first. You have 2 options when it comes to implementing Stripe on your own website. The simple and fast approach is using the pre-built copy and paste Stripe Checkout script. It will automatically add a payment button on your website and upon clicking it will load all of the appropriate pre-built form controls for you. Everything on the front-end is essentially handled by Stripe.

It does have a few drawbacks however that I should mention. For one, you can't set the display price dynamically like you can with Stripe.js. At least not easily. You will have to create the Checkout script dynamically yourself, either on the server, or through JavaScript. A dynamic script, if you will. Particularly if you have a very web 2.0 ajaxy pricing UI. The checkout script looks like the following. You can set the amount to charge, the display text and the display image.


<script id="gatewayscript"
    src="https://checkout.stripe.com/checkout.js" class="stripe-button"
    data-key="pk_test_your_key_goes_here"
    data-amount="2000"
    data-name="your name"
    data-description="2 widgets"
    data-image="your display image"
    data-locale="auto"
    data-zip-code="true">
  </script>

And secondly, you have very little control of this UI/UX on the Checkout form. Which isn't a bad thing mind you, as it does look very nice and it handles validation very well on its own. By default Checkout will have just an email, credit card number, expiration date and CVC field with a submit button. But if you have a more specific design that you have in mind, or you would like to add custom fields to the interface then you're going to have to go with Stripe.js.

Stripe.js

Stripe.js is the way to go if you're looking for a very custom payment solution. If you need to specify prices dynamically or have any other type of custom forms and fields that are needed for payment, then this is the way to go. Checkout in fact does use stripe.js, however it obfuscates that from the developer. Here, you'll have to do much of what Checkout offers, yourself, such as validating credit card formats and sending the token back to the server. So in this post, I'll be going this entire process. All without using any 3rd party libraries. So let's start off by including the stripe.js script in our head section.


<script type="text/javascript" src="https://js.stripe.com/v2/"></script>

Specify The Publishable Key

If you log into to your Stripe dashboard you will see a tab for your API Keys. From here you can refresh they keys or disable any you are no longer using. We'll be using the test publish keys for this.

Setting Up Stripe.js In .NET

<script type="text/javascript">
  Stripe.setPublishableKey('pk_test_LJdf08df980fs0dfD');
</script>

We can specify the publish key somewhere after the stripe.js reference.

Generating A User Token

Tokens are one-time use and short-lived ID's that you can use to charge a users credit card or pretty much do any other task with Stripe. Normally once a user enters their payment info, stripe.js will validate the data and then create a token. No charges have been made at this point however.

Here is a quick form with the important fields required to generate a token.


<form id="payment-form">
    Card Number
    <input type="text" size="20" data-stripe="number" value="4242424242424242" />

    Expiration (MM/YY)
    <input type="text" size="2" data-stripe="exp_month" value="12" />
    <input type="text" size="2" data-stripe="exp_year" value="17" />

    CVC
    <input type="text" size="4" data-stripe="cvc" value="123" />

    Billing Zip
    <input type="text" size="6" data-stripe="address_zip" value="12345" />

   <input type="submit" class="submit" value="Submit Payment">
</form>

A few important things to note. We don't want to give our input's a name because we DO NOT want that data to be passed to our own server. We want Stripe to handle the entire transaction and all we want is the output, which is the token. So instead, we need to append custom data- attributes to our forms, and Stripe uses the highlighted names above to do so. In this manner, all we need to do, as you'll see next, is just pass the entire form to Stripe and it will take care of extracting the correct fields.

Capture the submit

Before we submit our token to the sever, we'll need to cancel our own submit and make a request to Stripe to generate it for us. And we can do that with the following script.


$(function() {
  var $form = $('#payment-form');
  $form.submit(function(event) {
    // Disable the submit button to prevent repeated clicks:
    $form.find('.submit').prop('disabled', true);

    // Request a token from Stripe:
    Stripe.card.createToken($form, stripeResponseHandler);

    // Prevent the form from being submitted:
    return false;
  });
});

Pass The Token To Your Server

But the token doesn't really do anything, remember that. It's just a way for us to start to make requests. We'll need to push that token over to the server. And we can do that easily with a hidden field. The idea is that once the token is returned by Stripe, we'll inject a hidden field onto our page, and in our postback event, we'll capture it and use it for our intended purposes. The createToken function above takes as inputs the form with our users credit card information and a callback function which will be called once the token is generated. And this is where we'll want to force the page submit.


function stripeResponseHandler(status, response)
{
    var res = response;

    if (response.error)
    {
        alert('error');
    }

    else
    {
        // Get the token ID:
        var $form = $('#payment-form');
        var token = response.id;

        // Insert the token ID into the form so it gets submitted to the server:
        $form.append($('').val(token));

        // Submit the form:
        $form.get(0).submit();
    }
}

Also, note that the response object will also return any errors that Stripe may have encountered when processing the credit card information, such as invalid numbers or expired dates and such. So validation isn't solely left to the developer, which is good.

Setting Up Stripe.js In .NET

If no errors were found however, then we can grab the generated token from the response object and inject a hidden field onto our form. We can then force the submit and we're good to go.

Charging A Customer

Now that we have a token created, we can use it to make a charge. I'll be using a .NET Web Form for this example, so in the Page_Load event I'll check if we're currently making a postback. If we are, then we can grab the Stripe token that was inserted into the hidden field.


protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        if (Request["stripetoken"] != null)
            CreateStripeTransaction();
    }
}

Authenticate Account

In order to make Stripe requests you'll need to specify your Secret Key, which you can get from your Stripe dashboard. The Stripe RESTful API uses HTTP Basic Auth in order to authenticate requests. To make the process easier, here is a quick function that will set the correct authentication header, which takes in the WebRequest object as a parameter and the username and password. Note that the password is blank for Stripe requests.

Also note, do not share your Secret Key with anyone. If it any point it is exposed, then head on over to the dashboard to generate a new one.


public void SetBasicAuthHeader(WebRequest request, string username, string password)
{
    string auth = username + ":" + password;
    auth = Convert.ToBase64String(Encoding.Default.GetBytes(auth));
    request.Headers["Authorization"] = "Basic " + auth;
}

Now that we have our Secret Key and our authentication function, we can move on with making our HTTP request. In order to make a Stripe Charge, we'll need to make a request to the following endpoint:

Endpoint: https://api.stripe.com/v1/charges


private void CreateStripeTransaction()
{
    var stripetoken = Request["stripetoken"];       // comes from stripe.js

    string data = string.Format("amount=300&currency=usd&source={0}&description=testcharge", token);
    byte[] dataStream = Encoding.UTF8.GetBytes(data);
    string charge_id = string.Empty;
    var endpoint = "https://api.stripe.com/v1/charges";
    string username = "Your Stripe Key Goes Here";
    WebRequest request = HttpWebRequest.Create(endpoint);

    SetBasicAuthHeader(request, username, "");  // BASIC AUTH
    request.Method = "POST";
    request.ContentLength = dataStream.Length;
    Stream newstream = request.GetRequestStream();

    newstream.Write(dataStream, 0, dataStream.Length);
    newstream.Close();

    var response = request.GetResponse();

    // get the result
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        JsonSerializer json = new JsonSerializer();
        JObject content = JObject.Parse(reader.ReadToEnd());

        charge_id = content["id"].ToString();
    }

    response.Close();
}

This function will make a request to Stripe, will charge the card in question for the appropriate amount and it will return an identifier for the charge. It won't however store any user related data, which I'll cover how to do next.

Creating A New Customer

If you are looking for a way to continuously charge customers on intervals or after certain actions, then you'll need to create a Customer object in Stripe. And good news, that token that we created using Stripe.js can also be used to create a customer. You'll just need to pass it to the Stripe request as the source parameter, which is highlighted down below. Everything else in the function, is for the most part the exact same as the CreateStripeTransaction function.

Endpoint: https://api.stripe.com/v1/customers


private string CreateStripeCustomer(string token)
{
    string customer_id = string.Empty;
    string endpoint = "https://api.stripe.com/v1/customers";
    string data = string.Format("description=testcustomer&source={0}&email={1}", token, txtEmail.Text.Trim());
    byte[] dataStream = Encoding.UTF8.GetBytes(data);
    string username = "Your Secret Key";
    WebRequest request = HttpWebRequest.Create(endpoint);

    SetBasicAuthHeader(request, username, "");  // BASIC AUTH
    request.Method = "POST";
    request.ContentLength = dataStream.Length;
    Stream newstream = request.GetRequestStream();

    newstream.Write(dataStream, 0, dataStream.Length);
    newstream.Close();

    var response = request.GetResponse();

    // get the result
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        // deserialize json to retrieve the Customer ID
        JsonSerializer json = new JsonSerializer();
        JObject content = JObject.Parse(reader.ReadToEnd());

        customer_id = content["id"].ToString();
     }

    response.Close();
    return customer_id;
}

This HTTP Request will return the Customers Stripe token. We can store this token in our database and use that in order to to make new Charges for that particular customer. And that can easily be done by adding the customer parameter to the Charge request, instead of a source.


string data = string.Format("amount=300&currency=usd&customer={0}&description=testcharge", token);
byte[] dataStream = Encoding.UTF8.GetBytes(data);

Any future Stripe API requests will follow the exact same pattern. You'll need the endpoint, then you'll need to piece together the parameter string for that request, which you can find here, and then you'll need to follow the same steps that are listed above. Very quick to implement, very secure, and most importantly, you never once touch the users personal information yourself, as everything is handled by the Stripe API.

I hope anyone attempting to implement the Stripe API in .NET found this useful. And if you have any questions, feel free to drop them down below.

Walter G. author of blog post
Walter Guevara is a Computer Scientist, software engineer, startup founder and previous mentor for a coding bootcamp. He has been creating software for the past 20 years.

Get the latest programming news directly in your inbox!

Have a question on this article?

You can leave me a question on this particular article (or any other really).

Ask a question

Community Comments

s
sand
12/5/2016 11:44:21 PM
at this point var response = request.GetResponse(); am getting an error 'The remote server returned an error: (401) Unauthorized' please help.. Thanks
thatsoftwaredude.com logo
Walt
3/9/2017 4:36:06 PM
More than likely, your final signed request is off. If it's missing any field, or if any value is out of order it will generate that error unfortunately. I'd recommend going line by line ensuring that each one is there and in the correct alphanumeric order.
y
3/13/2018 12:46:02 PM
i am trying to implement your example. i am having a few issues. would yiu be able to help me out? thx
thatsoftwaredude.com logo
Walt
11/4/2018 9:14:47 PM
Sent you an email Yechiel!
J
John
1/3/2019 10:54:04 AM
Walter, I'm getting "Authentication failed because the remote party has closed the transport stream." This is when I'm trying to capture the charge. Could it be with the data line? String.Format("amount=" & ramount & "&currency=usd&source={0}&description=Event Registration", stripetoken) the ramount is the amount on the authorized charge and stripetoken is the token returned on the card authorization. Please help. My website is hosted by godaddy with 4.0/4.5 loaded.
thatsoftwaredude.com logo
Walt
1/3/2019 12:31:10 PM
Hey there John! Hm. Interesting. It could be the .NET version for sure. I've written/tested the code on 4.6+ I believe. I wouldn't recommend upgrading the version of course, but I would try to set up a throwaway site running 4.6+ on your GoDaddy and try that same code and see if you get the same results. But also, be sure to encode your request to the appropriate URL encoding. These requests can be finicky about such things. Let me know if that works!
J
John
1/10/2019 8:36:14 AM
Stripe requires a security protocol of tls12 I had to upgrade my hosting account to use .net 4.6+ and point my web.config to use the updated framework and it works great. I only wish that the stripe documentation was more clear that a create charge does an authorization and capture by default. Thanks for your help
thatsoftwaredude.com logo
Walt
1/10/2019 11:39:16 AM
Awesome to hear John! And thanks for the great info. I'm sure that it is going to help many folks caught in that same situation.
R
6/16/2020 10:31:29 AM
How are you getting a HTML form to submit back to a ASP.NET page? You do not have a runat="server" attribute or form action.
S
12/19/2020 8:58:55 AM
If you are looking the latest solution of Stripe checkout integration in ASP.NET Web Forms or ASP.NET Core MVC, check out the demo: https://techtolia.com/Stripe/
m
mike
5/2/2021 5:12:56 PM
thanks! Could not find anything that didn't implement old Nuget packages, even the ServiceType.Stripe examples use the .NET sdk rather than Core
Ad Unit

Current Poll

Total Votes:
Q:
Submit

Add a comment