Home > Uncategorized > Handling #Stripe #webhooks in asp.net for #SCA

Handling #Stripe #webhooks in asp.net for #SCA

service_512

Stripe Webhooks are going to become very important on September 14th 2019, because that is when new EU regulations come into effect for SCA (Strong Customer Authentication). This is where, if you are handling an off-session card transaction, then the you may need to engage the user to authorise the payment.

Webhooks are HTTP endpoints that are called on certain (or all) events triggered by Stripe, here is a simple example of a webhook handler written in C#, that will send an email with the data from Stripe to you. In the future, I will develop this further to actually handle the SCA transaction.

So, lets get started, with a simple ASHX file as follows;

<%@ WebHandler Language=C# Class=StripeWebhook.handler %>
using System;
using System.Web;
using System.IO;

namespace StripeWebhook
{
    public class handler : System.Web.IHttpHandler
    {
        public void ProcessRequest (HttpContext context)
        {
            context.Response.Write(OK);
            var poststring = new StreamReader(context.Request.InputStream).ReadToEnd(); 
            Email.Send(you@gmail.com,Received a Stripe Webhook call, poststring);
        }
    
        public bool IsReusable {
            get {
                return false;
            }
        }
    }
}

Now, the Email.Send is pretty boiler plate, and I’m leaving out my credentials with Amazon SES.

using System;
using System.Configuration;
using System.Net.Mail;
using System.Text;

namespace StripeWebhook
{

    public class Email
    {
        private static string FromAddress = “info@you.net”;
        private static string MailServer = “email-smtp.eu-west-1.amazonaws.com”;
        private static string Username = “*****”;
        private static string Password = “****/****”;

        /// <summary>
        /// Sends the specified recipient with reply to
        /// </summary>
        /// <param name=recipient>The recipient.</param>
        /// <param name=subject>The subject.</param>
        /// <param name=body>The body.</param>
        public static void Send(string recipient, string subject, string body)
        {
            var mail = new MailMessage(FromAddress, recipient);
            var client = new SmtpClient
            {
                Port = 25,
                EnableSsl = true,
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Host = MailServer,
                Credentials = new System.Net.NetworkCredential(
                    Username,
                    Password)
            };
            mail.Subject = subject;
            mail.Body = body;
            mail.IsBodyHtml = true;
            mail.BodyEncoding = Encoding.UTF8;
            client.Send(mail);
        }
    }
}

This, I then deploy to an IIS server, at say https://www.yourwebsite.com/stripe.ashx , and check it works by just opening the page in a browser.

I then go into Stripe, Switch to Test mode, then click Developers > Webhooks, then Add endpoint. Enter the url, of your handler, then click on “Receive all events”. then “Add Endpoint”

Make a test transaction against stripe with a test card like 4242 4242 4242 4242, and then you should receive an email like this;

{
  "id": "evt_1ElBYWGpNuQPqazsiV1UgOXs",
  "object": "event",
  "api_version": "2015-04-07",
  "created": 1560503923,
  "data": {
    "object": {
      "id": "ch_1ElBYUGpNuQPqazsGPLyUzjN",
      "object": "charge",
      "amount": 10000,
      "amount_refunded": 0,
      "application": null,
      "application_fee": null,
      "application_fee_amount": null,
      "balance_transaction": "txn_1ElBYVGpNuQPqazsEDEsOqBj",
      "billing_details": {
        "address": {
          "city": null,
          "country": null,
          "line1": null,
          "line2": null,
          "postal_code": null,
          "state": null
        },
        "email": null,
        "name": null,
        "phone": null
      },
      "captured": true,
      "created": 1560503922,
      "currency": "gbp",
      "customer": null,
      "description": "Charge for Paypal card",
      "destination": null,
      "dispute": null,
      "failure_code": null,
      "failure_message": null,
      "fraud_details": {
        
      },
      "invoice": null,
      "livemode": false,
      "metadata": {
        
      },
      "on_behalf_of": null,
      "order": null,
      "outcome": {
        "network_status": "approved_by_network",
        "reason": null,
        "risk_level": "normal",
        "risk_score": 9,
        "seller_message": "Payment complete.",
        "type": "authorized"
      },
      "paid": true,
      "payment_intent": null,
      "payment_method": "card_1ElBYUGpNuQPqazsgLWEJ5qr",
      "payment_method_details": {
        "card": {
          "brand": "visa",
          "checks": {
            "address_line1_check": null,
            "address_postal_code_check": null,
            "cvc_check": "pass"
          },
          "country": "US",
          "exp_month": 9,
          "exp_year": 2022,
          "fingerprint": "9nK3pNZASU9W8AOL",
          "funding": "credit",
          "last4": "4242",
          "three_d_secure": null,
          "wallet": null
        },
        "type": "card"
      },
      "receipt_email": null,
      "receipt_number": null,
      "receipt_url": "https:\/\/pay.stripe.com\/receipts\/acct_15s8pNGpNuQPqazs\/ch_1ElBYUGpNuQPqazsGPLyUzjN\/rcpt_FFgwbvHE1qdC84353g8eqXNRSouDIo5",
      "refunded": false,
      "refunds": {
        "object": "list",
        "data": [
          
        ],
        "has_more": false,
        "total_count": 0,
        "url": "\/v1\/charges\/ch_1ElBYUGpNuQPqazsGPLyUzjN\/refunds"
      },
      "review": null,
      "shipping": null,
      "source": {
        "id": "card_1ElBYUGpNuQPqazsgLWEJ5qr",
        "object": "card",
        "address_city": null,
        "address_country": null,
        "address_line1": null,
        "address_line1_check": null,
        "address_line2": null,
        "address_state": null,
        "address_zip": null,
        "address_zip_check": null,
        "brand": "Visa",
        "country": "US",
        "customer": null,
        "cvc_check": "pass",
        "dynamic_last4": null,
        "exp_month": 9,
        "exp_year": 2022,
        "fingerprint": "9nK3pNZASU9W8AOL",
        "funding": "credit",
        "last4": "4242",
        "metadata": {
          
        },
        "name": null,
        "tokenization_method": null
      },
      "source_transfer": null,
      "statement_descriptor": null,
      "status": "succeeded",
      "transfer_data": null,
      "transfer_group": null
    }
  },
  "livemode": false,
  "pending_webhooks": 2,
  "request": "req_HHqTmHqjKXT6iA",
  "type": "charge.succeeded"
}
Advertisements
Categories: Uncategorized
  1. June 15, 2019 at 5:52 pm

    And here’s the webhook call on a declined card due to 3d secure requirements;

    {
    “id”: “evt_1ElfetGpNuQPqazslh9kkSHt”,
    “object”: “event”,
    “api_version”: “2015-04-07”,
    “created”: 1560619639,
    “data”: {
    “object”: {
    “id”: “ch_1ElfetGpNuQPqazssdsjdGR6”,
    “object”: “charge”,
    “amount”: 1000,
    “amount_refunded”: 0,
    “application”: null,
    “application_fee”: null,
    “application_fee_amount”: null,
    “balance_transaction”: null,
    “billing_details”: {
    “address”: {
    “city”: null,
    “country”: null,
    “line1”: null,
    “line2”: null,
    “postal_code”: null,
    “state”: null
    },
    “email”: null,
    “name”: null,
    “phone”: null
    },
    “captured”: false,
    “created”: 1560619639,
    “currency”: “gbp”,
    “customer”: null,
    “description”: “Charge for Paypal card”,
    “destination”: null,
    “dispute”: null,
    “failure_code”: “authentication_required”,
    “failure_message”: “Your card was declined. This transaction requires two-factor authentication.”,
    “fraud_details”: {

    },
    “invoice”: null,
    “livemode”: false,
    “metadata”: {

    },
    “on_behalf_of”: null,
    “order”: null,
    “outcome”: {
    “network_status”: “declined_by_network”,
    “reason”: “authentication_required”,
    “risk_level”: “normal”,
    “risk_score”: 10,
    “seller_message”: “The bank returned the decline code `authentication_required`.”,
    “type”: “issuer_declined”
    },
    “paid”: false,
    “payment_intent”: null,
    “payment_method”: “card_1ElfesGpNuQPqazsXPMtXYs0”,
    “payment_method_details”: {
    “card”: {
    “brand”: “visa”,
    “checks”: {
    “address_line1_check”: null,
    “address_postal_code_check”: null,
    “cvc_check”: “pass”
    },
    “country”: “IE”,
    “exp_month”: 3,
    “exp_year”: 2020,
    “fingerprint”: “NI9PIRmFFkLSVU0Z”,
    “funding”: “credit”,
    “last4”: “3220”,
    “three_d_secure”: null,
    “wallet”: null
    },
    “type”: “card”
    },
    “receipt_email”: null,
    “receipt_number”: null,
    “receipt_url”: “https:\/\/pay.stripe.com\/receipts\/acct_15s8pNGpNuQPqazs\/ch_1ElfetGpNuQPqazssdsjdGR6\/rcpt_FGC20vJXXqGCxbKDg2KuGsDA7kR9EpT”,
    “refunded”: false,
    “refunds”: {
    “object”: “list”,
    “data”: [

    ],
    “has_more”: false,
    “total_count”: 0,
    “url”: “\/v1\/charges\/ch_1ElfetGpNuQPqazssdsjdGR6\/refunds”
    },
    “review”: null,
    “shipping”: null,
    “source”: {
    “id”: “card_1ElfesGpNuQPqazsXPMtXYs0”,
    “object”: “card”,
    “address_city”: null,
    “address_country”: null,
    “address_line1”: null,
    “address_line1_check”: null,
    “address_line2”: null,
    “address_state”: null,
    “address_zip”: null,
    “address_zip_check”: null,
    “brand”: “Visa”,
    “country”: “IE”,
    “customer”: null,
    “cvc_check”: “pass”,
    “dynamic_last4”: null,
    “exp_month”: 3,
    “exp_year”: 2020,
    “fingerprint”: “NI9PIRmFFkLSVU0Z”,
    “funding”: “credit”,
    “last4”: “3220”,
    “metadata”: {

    },
    “name”: null,
    “tokenization_method”: null
    },
    “source_transfer”: null,
    “statement_descriptor”: null,
    “status”: “failed”,
    “transfer_data”: null,
    “transfer_group”: null
    }
    },
    “livemode”: false,
    “pending_webhooks”: 2,
    “request”: “req_Ew6Mox6K6jqx7Y”,
    “type”: “charge.failed”
    }

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: