# gmipay - Gemini Payment Processing Proxy CGI
=> gemini://simonvolpert.com/gmipay/ Canonical project page
## Motivation
Information on the Internet has traditionally been made freely available (gratis). Content creators have long been expected to serve and continue serving their content altruistically, bearing any possible cost themselves. While this setup works well enough for small scale networks and niche content, the operational expenses can mount quickly, especially for popular services and content pieces. That is, in addition to the work that went into the creation of the content in the first place.
Information doesn't just "want" to be free. It also "wants" to be expensive.
The lack of a built-in content monetization mechanism is often cited as a major weakness in the traditional Web architecture, leading to the range of unhealthy behaviors that plagues it today (advertisements, tracking, consolidation and corporatization are a few examples).
What is needed is a voluntarist system of funding content creators, which would allow creators to sell and patrons to pay for content transparently and with minimal friction. This is such a system. It acts as middleware, transparently passing through user requests after payment was made.
But a payment processing proxy script alone is not enough. The issues that make the conventional payment system impractical in this context are fundamental to those conventional systems themselves. The need for a bank account and credit card creates barriers of entry and excludes major social groups (in particular, those under a certain arbitrary age) from participating in rewarding their favorite creators. The need to give away your payment details to make even the smallest of transfers opens the payer to all manner of fraud. On the creator's side, the need to enter a predatory contract with a payment processing company just to be able to receive payments or donations proves to be a constant source of stress. The payment processor acts as a middleman, with the power to stop, change or reverse any transaction or freeze the creator's account for an indefinite period of time without explanation or recourse, all while engaging in rent-extraction via numerous visible and hidden fees. The fees thus extracted impose a lower limit on the minimum viable transaction size, making small, casual payments (exactly the "rewarding creators" usecase) impractical.
Bitcoin Cash was invented specifically to solve the above problems. The peer-to-peer nature if its transactions, coupled with its negligible transaction fees, make it well-suited to the role of gmipay's payment backend; And being simple and straightforward to build on,¹ as well as being one of the most universally accepted cryptocurrencies with the highest rate of real-world adoption, makes it a perfect match.
## Installation
You will need the following packages:
* Python 3.7 or later
* python-urllib
* python-qrcode
* mailcap (for detecting file mime types)
* coinaddress
=> https://github.com/Tmpod/coinaddress CoinAddress
* A Gemini server, such as Jetforce.
=> https://github.com/michael-lazar/jetforce Jetforce server
=> gemini://simonvolpert.com/gmipay/buy Download the executable
SHA1 sum: %SHA1%
Place the executable in your capsule's /cgi-bin/ directory and give it execution permissions. Run the script once to create the configuration and state directory. The script will look for it in one of the following locations:
* /etc/gmipay
* $HOME/.config/gmipay
* The current working directory
* /tmp/gmipay
Place the files you would like to put behind the paywall in a directory inaccessible from your capsule (outside the document root) and edit the configuration file, named "paywall.conf" to your needs. The configuration file is well-commented and mostly self-explanatory; In particular, you will need to provide an extended public key (xPub) from your wallet, which will be used to generate fresh receiving addresses for each payment.
Development is done via git. You can clone this repository by executing the following command:
> git clone https://simonvolpert.com/gmipay/
=> gemini://simonvolpert.com/cgi-bin/buy/gmipay-demo.gmi Fully-refunding live demo
## Usage
To place a file behind a paywall, add a link to it in the form of "/cgi-bin/buy/FILENAME". You are done.
The buyer will be offered to send a sum of Bitcoin Cash (defined by the "default_price" key in "paywall.conf") to a receiving address derived from the xPub you provided, and then reload the page. Buyers are identified by the hash of their client certificate. The creation of a client certificate varies from client to client; refer to your Gemini client's specific instructions. By default, the purchase will remain valid (and, therefore, transparently downloadable) as long as the buyer has their client certificate, regardless of its expiry date. To implement a subscription-like system, simply set the "unlock_time" key to something other than 0. To have a setup in which a single payment blanket unlocks access to all paywalled files, set the "global_unlock" key to "yes". Client certificate handover (to preserve access to files even when the certificate was replaced or rotated) is as simple as renaming the state file from the old certificate hash to the new one.
No price conversion is done; This is by design. You should review the "default_price" setting from time to time to make sure it approximately matches the typical price you might be expected to pay for the sort of content you are offering.
A minimal log of significant operations is written to "paywall.log" in the state directory. It can be parsed to set up notifications of incoming payments if necessary.
Care should be taken when changing access settings post-fact, for example, from permanent unlocks to timed subscriptions, or from all access to specific files only. People who pay for your content do so on specific terms, outlined on the payment request page, and changing those terms under them is viewed as a violation of an implicit contract.²
## Security Considerations
Avoid setting your file directory to your state directory, as it will allow anyone to view your configuration, logs and, with some persistence and luck, your buyers' state files. Using a subdirectory under the state directory is fine.
If no location except /tmp/gmipay is writable, settings, purchase states and access permissions will be transient and will be wiped on the next reboot.
It is worth noting that the CGI script is going to be executed as the user running the Gemini server, and will have all of the server's permissions; Running your server as root is therefore seen as extremely unwise. Make sure to only run the server as an unprivileged user to mitigate the risk.
¹ In fact, in line with Gemini's stated design goals, the bulk of the script's code for interacting with the Bitcoin Cash network was written over the course of a single evening.
² If you really must change the terms of access from unlimited to subscription-like, at least have the decency to go through every existing state file and change the year in the timestamp field to 9999 to preserve their existing access rights.
## Known Issues
If you cannot get a payment request page and the error indicates an HTTP 430 error, it means you have been blocked by the default block explorer API due to being a bit too popular. Version 1.3 of the script contains an alternative block explorer with more permissive limits. To resolve the error, recreate your configuration file with the new values.