Aaron Parecki

Still here waiting for a catering cart. David came by to say hi!

Ben Werdmüller

This is so good. I agree 1000% with what Sue Gardner is arguing for here. https://www.knightfoundation.org/public-media-white-paper-2017-gardner

Aaron Parecki

Made it to the gate 2 minutes before boarding!

Ben Werdmüller

I tried to write the first version of a personal mission statement this morning before work. It's hard. Feedback is a gift! https://werd.io/pages/mission

Ben Werdmüller

Keith Chegwin, a British TV entertainer, sadly died from idiopathic pulmonary fibrosis today. Awareness is important, but coverage of the disease is mixed. This is actually one of the better ones. http://www.birminghammail.co.uk/news/showbiz-tv/keith-chegwin-dies-idiopathic-pulmonary-14023395

Aaron Parecki

It has been brought to my attention that I need to add support for the Payment Request API to my BarBot. #indiewebcamp

Aaron Parecki

Payment Requests using Stripe and Apple Pay

At IndieWebCamp Austin, I was inspired by the discussion at the Payments session. In the session, we talked about the recent Patreon fee change disaster, and how creators could use their own websites to accept payments from their supporters.

The W3C recently published a Candidate Recommendation for the new Payment Request API, which has pretty good browser support already! It turns out that Stripe has already built support for it into their library as well!

I was on the fence about trying to implement the API directly, or just using Stripe's library, and decided to take the easy route in the end. It does mean the code I wrote is mostly tied to Stripe, but they handle a bunch of edge cases and UI elements for me so it was a lot faster to implement that way.

Despite it being pretty much a drop-in replacement for their old Checkout workflow, there were a surprising number of edge cases I had to handle on my own still. For example, their button only gets activated if there is already a saved credit card in the browser, so if there aren't any existing payment methods, you have to still present a credit card UI to the user. Also you obviously need to have a fallback workflow if there is no support for the Payment Request API in the browser.

I started off by reading through the Payment Request API spec, and quickly discovered it was written from the perspective of a browser implementing it on their end, not written for developers using the API. I don't recommend reading it if you're trying to learn about this. I then discovered Google's excellent documentation on how to actually use the spec, Introduction to the Payment Request API. That one is a much better read to understand what's going on. Mozilla also has some good documentation on the API, although it's written more as a reference rather than a tutorial. In the end, I ended up just reading Stripe's documentation since I decided to use their library.

While implementing this, I decided to simplify my payment page to reduce the number of different states I had to manage. Previously, I allowed a visitor to type in their own amount. This ended up proving challenging to get to work right with Stripe's two libraries (Payment Request library and their Checkout workflow for fallback support). So instead I dropped that UI element completely. Below is what my payment page looks like if you visit it directly.

Payment page with no amount

With no amount pre-filled, the payment page does not provide a credit card option. Instead, it just links out to other services you can use to send me money. Those services will prompt you for an amount later.

I added support to my URL structure for adding a number to the end of the URL. So if you visit a URL like aaronparecki.com/pay/5, the idea is to present you with an easy way to send me $5.

In browsers that support the Payment Request API such as Chrome, and if there is already credit card info saved in the browser, I render the Stripe Payment Request button with the set amount, which looks like the below.

Payment page with pre-selected amount in Chrome

Clicking the "Pay now" button launches the browser's native Payment Request UI with the "order details" and allows the visitor to choose a credit card. (You might notice that the amount in the prompt is slightly more than $5, which is calculated by my code to result in me getting $5 after I pay the transaction fees. My assumption here is that you are trying to actually give me $5, not pay $5 for some service I provide.)

Selecting a credit card in Chrome

Unfortunately, Stripe doesn't provide a way to bootstrap this if you don't already have a credit card saved in the browser. They will hide the button completely if there are no payment methods available. In that case, I fall back to the old Checkout workflow. If you visit my pay page in Chrome to try to test this, and don't yet have a card added, you can add a card in the autofill settings in Chrome.

Manually adding a card in Chrome

Next, we see what happens if you visit this page in a browser that does not support the Payment Request API (or if there are no saved cards). In this example I used Firefox, although you can actually enable the experimental API in about:config. In this case, my code detects that the API is not present, and enables the Stripe Checkout workflow instead.

Payment page with pre-selected amount in Firefox (no Payment Request API support)

Clicking "Pay With Card" launches the Stripe UI for their Checkout workflow, which is a modal dialog. The only thing I can customize here is the title and photo.

Stripe's checkout widget prompting for credit card

Stripe now encourages you to use their "Stripe Elements" which includes a credit card widget, although when I attempted to go down that path, I realized that I was going to have to do a lot more work on the CSS and JS interactions for that, whereas their Checkout workflow handles everything for me.

Payment page with pre-selected amount in Safari Desktop

Here's the cool part about the Stripe Payment Request button. They have built-in support for feature-detecting Apple Pay and they turn the button into an Apple Pay button automatically! So in my code, I detect for either Payment Request API support or Apple Pay support and use the Stripe Payment Request flow in both cases.

if(window.PaymentRequest || window.ApplePaySession) { ... }

It was surprisingly easy to enable Apple Pay support! The only thing I had to do beyond supporting the Payment Request API through their widget, was verify my domain. This is actually a requirement of Apple's systems, but Stripe has done an excellent job of smoothing over the hard parts of that. They provide a "domain association file" that you download to your server, and then they provide a button you can press that will trigger Apple to verify that file on your server. Once you do that, you can start accepting Apple Pay immediately, on both desktop Safari and iOS.

Payment page with pre-selected amount in Safari iOS

On iOS Safari, the Apple Pay workflow works just like you'd expect to see it in any app! Tapping the "Pay" button launches the native UI to choose a credit card and verify your fingerprint.

Selecting the payment method in Safari iOS

Once you confirm your fingerprint, it charges your card and you'll see the push notification confirmation almost immediately!

Apple Pay payment confirmed in Safari iOS

And yes, as I was taking a screenshot of this, it registered my thumbprint and actually charged my card. Good thing Stripe makes it easy to refund transactions!

So hopefully that gives you an idea of what it takes to add support for Apple Pay and credit cards to your site! It was surprisingly straightforward thanks to Stripe's library, although wouldn't have been too bad doing it manually with the Payment Request API either.

Aaron Parecki

EFF party slash IndieWebCamp afterparty — with David, Marty, microformats, Tantek

Ben Werdmüller

A fascinating portrait of a terrifying President. Inside Trump’s Hour-by-Hour Battle for Self-Preservation

Aaron Parecki

Session grid for IndieWebCamp Austin!

Aaron Parecki

Hello from IndieWebCamp Austin!

Aaron Parecki

Found a spot without a 3 hour wait, but we have to sit in the corner — with Marty, David

Ben Werdmüller

Listening to KRCB North Bay because my sister is going to show up and sing on it tonight. http://radio.krcb.org/programs/north-bay-songwriters

Ben Werdmüller

Sometimes, just sometimes, I want to set this industry on fire, make a Ben-shaped hole in the wall, and go running for the hills. https://www.bloomberg.com/news/articles/2017-12-07/silicon-valley-is-sneaking-models-into-this-year-...

Ben Werdmüller

The flow of data is subject to trade rules - and therefore, NAFTA negotiations. It'll be interesting to see how this plays out. https://www.washingtonpost.com/business/economy/trumps-trade-deficit-obsession-could-hurt-leading-am...

Ben Werdmüller

Another excellent episode of the Daily, interviewing that bigoted cake shop owner, and the same-sex couple he turned down. https://play.radiopublic.com/the-daily-GMB3yp/ep/s1!401740dd4524a43fc06a77c57c1125a861e7a460

Ben Werdmüller

While the Republicans deservedly implode, and while we fight this atrocity of a tax bill, the Democrats are readying a candidate who will win 2020 by winning back disillusioned working class people in economically unstable swing states, right?

... Right ...?

Ben Werdmüller

I sincerely wish I could kill the part of my brain that tells me I'll never be good enough and reminds me all the reasons why. I think it's always going to be whispering at me somewhere in the background; the trick is to keep it there.

Ben Werdmüller

Interested in getting into investing? Want to help create a more progressive society? New Media Ventures is hiring: http://www.newmediaventures.org/were-hiring-2/

Ben Werdmüller

Looking for a technical cofounder? Here's how I think you could go about it. https://words.werd.io/searching-for-a-technical-cofounder-7ffd401c04b4

Ben Werdmüller

The Daily continues to be excellent. The US has set aside $5M for payments to civilian casualties in the war against the Islamic State - so why has nobody been paid? https://play.radiopublic.com/the-daily-GMB3yp/ep/s1!7532ed751d08f20dc38f99f403e0474a76f3887d