Self-hosted Bitcoin payment system

Cryptocurrency paywall for on-chain payments

If you don't know what Bitcoin is and would like to start from basics, see my other article

I have created a system that lets you request payments in Bitcoin. It is minimalistic, uses self-hosted pruned node (only requiring a couple of GB storage to run) and operates on a single HD wallet seed.

You can test it by visiting my test shop page. It creates a new payment request for you and lets you pay with Bitcoin on the test chain. Testnet coins are obtainable for free, so you can freely participate in this demo. Switching it to real Bitcoin would be as easy as tweaking some settings in my local Bitcoin node and the payment system.

It works by creating a brand new payment address for each payment request, and then watches that address until it contains the required funds with at least two confirmations (configurable). This is a very straightforward way one would implement such a system, since on blockchain you can't really tell which transaction is what otherwise.

Obviously, accepting payments on-chain is slow and costly. A better solution would be to use something like Lightning Network to do that, which would be nearly instant and almost free. However, that would come with its own set of challenges, like setting up Lightning daemon behind a pruned Bitcoin node or making room for incoming transactions in a Lightning channel. Not to mention that much fewer people use Lightning. While the current solution makes it only worthwhile to accept payments above $10 to make up for transaction costs, I think that being a Segregated Witness native solution offers a nice middle ground between transaction costs, availability and implementation difficulty.


The technology used is the Perl programming language and the Mojolicious framework. Bitcoin keys and addresses are generated by Bitcoin::Crypto library, and the Bitcoin node is handled by Bitcoin::RPC library. Payment requests are created via HTTP API, which is secured with client secret keys - each request must be signed with a SHA256 hash created from its contents with a secret key appended at the end. Overall, the implementation is pretty minimalistic, and creation of a system that interacts with it is a task that can be easily finished in a couple of hours. The fact that it uses no third party services is compatible with Bitcoin philosophy: don't trust, verify.

This system is fully open source with a very liberal BSD license. You can view its code on my Github page.

Comments? Suggestions? Send to
Published on 2021-09-05