paypercall
v0.1.4
Published
Charge for HTTP APIs on a pay-per-call basis with Bitcoin and Lightning
Downloads
15
Maintainers
Readme
paypercall
Charge for HTTP APIs on a pay-per-call basis with Bitcoin and Lightning. Available as an express middleware and as a reverse proxy.
Powered by :zap: Lightning Charge.
Install
$ npm install paypercall
Server Setup
As a middleware
paypercall
can be used as an express middleware to charge payments directly in your node.js apps.
Below is an example app that charges 0.1 USD to send out tweets:
app.js
const pay = require('paypercall')({ chargeUrl: ..., chargeToken: ... })
, twt = require('twitter')({ consumer_key: ..., consumer_secret: ..., ... })
, app = require('express')()
app.use(require('body-parser').urlencoded())
app.post('/tweet', pay(0.1, 'USD'), (req, res, next) =>
twt.post('statuses/update', { status: req.body.message })
.then(tweet => res.send(tweet))
.catch(next))
app.listen(4000, _ => console.log('HTTP server running on localhost:4000'))
See ifpaytt
for a more full-fledged application using paypercall
as a middleware.
As a reverse proxy
Alternatively, you can develop your HTTP server with no payments awareness
and use paypercall
as a reverse proxy to handle payments.
An example with a python app:
app.py
from flask import Flask, request
import twitter
app = Flask(__name__)
twt = twitter.Api(consumer_key=..., consumer_secret=..., ...)
@app.route("/tweet", methods=['POST'])
def tweet():
return twt.PostUpdate(request.form['message'])
@app.run(Port=4001)
Run the python app and the paypercall
proxy:
$ FLASK_APP=app.py flask run
* Running on http://localhost:4001/
$ paypercall --charge-token mySecretToken --upstream-url http://localhost:4001 \
--port 4000 --rates-yaml '{ POST /tweet: 0.1 USD }'
HTTP reverse proxy running on http://localhost:4000, proxying to http://localhost:4001
You will now have the python app running on port 4001 (providing API calls free of charge)
and the paypercall
reverse proxy running on port 4000 (charging on a per-call basis).
Paying for API calls
Send an empty request (no body) to the resource to get the BOLT11 payment request and the
X-Token
header:$ curl -i -X POST http://localhost:4000/tweet HTTP/1.1 402 Payment Required Content-Type: application/vnd.lightning.bolt11 X-Token: lmbdmJeoSQ0ZCB5egtnph.af1eupleFBVuhN2vrbRuDLTlsnnUPYRzDWdL5HtWykY lnbcrt8925560p1pdfh7n2pp54g5avyupe70l988h30u0hy8agpj2z7qsveu7ejhys97j98rgez0...
Make the payment:
$ lightning-cli pay lnbcrt8925560p1pdfh7n2pp54g5avyupe70l988h30u0hy8agpj2z7qsveu7ejhys97j98rgez0...
Send the request again, this time with the request body and with the
X-Token
header echoed back:$ curl -i -X POST http://localhost:4000/tweet \ -H 'X-Token: lmbdmJeoSQ0ZCB5egtnph.af1eupleFBVuhN2vrbRuDLTlsnnUPYRzDWdL5HtWykY' \ -d message='I got lightning working and all I got was this tweet' HTTP/1.1 200 OK Content-Type: application/json {"id_str":"123123123","text":"I got lightning working...",...}
Documentation
Middleware
const pay = require('paypercall')(options)
Returns a new payment middleware factory. options
can contain the following fields:
chargeUrl
: Lightning Charge server URL (optional, defaults tohttp://localhost:9112
)chargeToken
: Lightning Charge access token (required)dbPath
: Path to sqlite database (optional, defaults to./paypercall.db
)currency
: Default currency if none is specified (optional, defaults toBTC
)secret
: Secret key used for HMAC tokens (optional, generated based onchargeToken
by default)invoiceExp
: How long should invoices be payable for (optional, defaults to 1 hour)accessExp
: How long should paid access tokens remain valid for (optional, defaults to 1 hour)
const payware = pay(amount[, currency])
Returns an express middleware that requires a payment of amount
units of currency
(or the default currency if none provided) before letting requests pass through.
Can be used as following:
const pay = require('paypercall')({ chargeToken: 'myToken', currency: 'EUR' })
, app = require('express')
// charge requests to a specific route
app.post('/sms', pay(0.15), (req, res) => { /* send SMS */ })
// charge all requests to /paid-apis/*
app.use('/paid-apis', pay(0.25))
// dynamic pricing (should only be based on the method and path)
app.post('/ocr/:type', (req, res, next) => {
pay(getPriceForType(req.params.type))(req, res, (err) => {
if (err) return next(err)
// payment succesfull, run OCR
// (the paid invoice is accessible at `req.invoice`)
})
})
Reverse proxy
$ paypercall --help
Charge for HTTP APIs on a pay-per-call basis with Bitcoin and Lightning
Usage
$ paypercall [options]
Options
-c, --charge-url <url> lightning charge server url [default: http://localhost:9112]
-t, --charge-token <token> lightning charge access token [required]
-u, --upstream-url <url> the upstream server to reverse proxy [required]
-r, --rates-path <path> path to YAML file mapping from endpoints to rates [default: ./rates.yaml]
-y, --rates-yaml <yaml> YAML string to use instead of reading from {rates-path}
-x, --currency <name> default rate currency if none is specified [default: BTC]
-d, --db-path <path> path to store sqlite database [default: ./payperclick.db]
--invoice-expiry <sec> how long should invoices be payable for [default: 1 hour]
--access-expiry <sec> how long should paid access tokens remain valid for [default: 1 hour]
--token-secret <secret> secret key used for HMAC tokens [default: generated based on {charge-token}]
-p, --port <port> http server port [default: 4000]
-i, --host <host> http server listen address [default: 127.0.0.1]
-e, --node-env <env> nodejs environment mode [default: production]
-h, --help output usage information
-v, --version output version number
Example
$ payperclick -t myAccessToken -u http://upstream-server.com/ \
-y '{ POST /tweet: 0.0001 BTC, PUT /page/:id: 0.0002 BTC }'
License
MIT