How to Create a Bitcoin/Lightning Email Paywall with BTCPay

Britt Kelly recently gave a presentation about how BTCPay is for more than just processing payments for merchants. I thought I'd share a use case I implemented myself recently.

Since earn.com announced it was deprecating its paid messaging service in late 2019, I decided to take a shot at replacing its functionality with my own self hosted setup. You can see my live form on the contact page at lopp.net.

How Earn.com Worked

The Earn.com service operated as a centralized custodian and escrow service. Users who wanted to offer their expertise via a paid contact form would create an account and set their pay threshold. People who wanted to contact them would also have to create an Earn.com account, deposit bitcoin, and send their message to the other user. If that user responded in a timely manner, Earn would credit the balance to their internal account, otherwise it would be credited back to the sender's internal account. If either user wanted to actually get their bitcoin, they'd have to request a withdrawal which would take a day or two to be processed.

How Does this BTCPay Setup Work?

If a user wishes to contact you, they fill out a form on your web site with their message. The message then gets stored on your web server and the user is forwarded to a payment page on your BTCPay server. If the payment is made then the user will be redirected to a success page. Once the payment is confirmed, your BTCPay server will then make a call back to your web server, which will email the message to you. If no payment is ever processed, you don't see the message.

The pro to this setup is that you have all the flexibility of running your own wallet and directly taking ownership of the funds. The con is that there is no longer an escrow component; the person sending the message is trusting you to respond to it. Note that it's theoretically possible to build your own system that uses 2-of-3 multisig with an escrow agent either on-chain or even on Lightning Network, but it's not currently supported via BTCPay.

Implementation Guide

  1. Install BTCPay on a machine you control.
  2. Have a web site to which you can add the form and processing scripts. My examples are in PHP, so to use them your web server will need to have PHP support.
  3. Add the form HTML to your web site; my form is here. Note that my form is more complicated than necessary because it has extra error handling and encryption features. The important part is that the form submits to itself and executes the server-side script you configure in the next step.
  4. The server-side form submission handler is here. While my example includes the file at the top of the contact page, you could just copy the code into your contact page. Note that this handles both my "free" (proof of work protected) form and my paid form, so you may not want any of the "formType" logic.

You'll want to replace the constants defined at the top of the file:
BTCPAY_STORE_ID = the Id you can find in your store settings as seen above
BTCPAY_CALLBACK_URL = the URL on your site for the script you'll set up in step 5;
SUCCESS_URL = URL on your site to a "payment received" success page you create;
BTCPAY_INVOICE_API_URL = "https://yourbtcpaydomain.com/api/v1/invoices";

5.  The server-side callback script is here. You'll need to set 3 constants:
BTCPAY_IP_ADDRESS = the IP address of your BTCPay server
YOUR_EMAIL_ADDRESS = the email to which you want paid messages delivered
YOUR_DOMAIN = your web site domain, only used for an error edge case

Voilà!

That's all there is to it! Of course you should test to make sure that the system is configured correctly; you don't want anyone paying for priority messages that don't get delivered! There are, of course, plenty of options on the BTCPay side that I glossed over, such as the fact that you ought to be able to use this system to accept both on-chain payments and Lightning Network payments.