• Stars
    star
    147
  • Rank 251,347 (Top 5 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 6 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Charge for HTTP APIs on a pay-per-call basis with Bitcoin and Lightning ⚑

paypercall

npm release MIT license Pull Requests Welcome IRC

Charge for HTTP APIs on a pay-per-call basis with Bitcoin and Lightning.

Want to require a payment when users take some programmatic action, such as sending an SMS or running imaging processing? That's what paypercall is for.

Available as an express middleware (where a node.js app makes charges directly) or as a reverse proxy (where a reverse proxy requires payment before providing access to an app).

Powered by ⚑ 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 SMS messages:

app.js

const pay = require('paypercall')({ chargeUrl: ..., chargeToken: ... })
    , twi = require('twilio')(twilioSid, twilioToken)
    , app = require('express')()

app.use(require('body-parser').urlencoded())

app.post('/sms', pay(0.1, 'USD'), (req, res, next) =>
  twi.messages.create({ from: 'paypercall', to: req.body.to, body: req.body.message })
    .then(msg => res.send({ success: true, sid: msg.sid }))
    .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. Below is an example using a python app:

app.py

from flask import Flask, request
from twilio.rest import Client as Twilio

app = Flask(__name__)
twi = Twilio(twilioSid, twilioToken)

@app.route("/sms", methods=['POST'])
def sms():
  msg = twi.messages.create(from='paypercall', to=request.form['to'], body=request.form['message'])
  return { 'success': True, 'sid': msg.sid }

@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 /sms: 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

Users can access paypercall-enabled API endpoints in three steps:

  1. Send an empty request (no body) to the paypercall-enabled endpoint to get the BOLT11 payment request and the X-Token header:

    $ curl -i -X POST http://localhost:4000/sms
    
    HTTP/1.1 402 Payment Required
    Content-Type: application/vnd.lightning.bolt11
    X-Token: lmbdmJeoSQ0ZCB5egtnph.af1eupleFBVuhN2vrbRuDLTlsnnUPYRzDWdL5HtWykY
    
    lnbcrt8925560p1pdfh7n2pp54g5avyupe70l988h30u0hy8agpj2z7qsveu7ejhys97j98rgez0...
  2. Make the payment:

    $ lightning-cli pay lnbcrt8925560p1pdfh7n2pp54g5avyupe70l988h30u0hy8agpj2z7qsveu7ejhys97j98rgez0...
  3. 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/sms \
      -H 'X-Token: lmbdmJeoSQ0ZCB5egtnph.af1eupleFBVuhN2vrbRuDLTlsnnUPYRzDWdL5HtWykY' \
      -t to=+972-789456123 \
      -d message='I got lightning working and all I got was this sms!'
    
    HTTP/1.1 200 OK
    Content-Type: application/json
    
    {"success":true,"sid":"SMf34fe622a8fe7565fc15be3ce8bc437e"}

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 to http://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 to BTC)
  • secret: Secret key used for HMAC tokens (optional, generated based on chargeToken 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 /sms: 0.0001 BTC, PUT /page/:id: 0.0002 BTC }'

License

MIT

More Repositories

1

lightning

Core Lightning β€” Lightning Network implementation focusing on spec compliance and performance
C
2,829
star
2

elements

Open Source implementation of advanced blockchain features extending the Bitcoin protocol
C++
1,044
star
3

lightning-charge

A simple drop-in solution for accepting lightning payments
JavaScript
553
star
4

secp256k1-zkp

Experimental fork of libsecp256k1 with support for pedersen commitments and range proofs.
C
288
star
5

libwally-core

Useful primitives for wallets
C
271
star
6

simplicity

Simplicity is a blockchain programming language designed as an alternative to Bitcoin script.
C
243
star
7

scriptless-scripts

Documentation about scriptless scripts
TeX
130
star
8

filebazaar

Sell digital files with Bitcoin & Lightning ⚑
JavaScript
120
star
9

woocommerce-gateway-lightning

A WooCommerce gateway for lightning payments
PHP
115
star
10

nanopos

A simple Lightning ⚑ point-of-sale system, powered by Lightning Charge
JavaScript
108
star
11

peerswap

Go
96
star
12

elementsproject.org

Source code for the ElementsProject.org website
CSS
90
star
13

nanotip

⚑ Lightning Tip Box ⚑
JavaScript
85
star
14

lightning-charge-client-js

JavaScript client for lightning-charge
JavaScript
64
star
15

ifpaytt

If Pay Then That ⚑ Trigger IFTTT actions with Bitcoin Lightning payments
JavaScript
56
star
16

wordpress-lightning-publisher

⚑ Lightning Publisher for WordPress
PHP
54
star
17

rust-elements

Rust support for Elements transaction/block deserialization
Rust
51
star
18

reserves

Proof-of-Reserves tool for Bitcoin
Rust
46
star
19

confidential-assets-demo

Confidential Assets Demo built on the Elements blockchain platform
Go
36
star
20

cross-input-aggregation

Thoughts on cross-input (signature) aggregation for Bitcoin
Rust
35
star
21

lightning-jukebox

A Lightning powered Jukebox ⚑ Pay with Bitcoin to choose your music.
JavaScript
35
star
22

rust-simplicity

C
34
star
23

elementsproject.github.io

https://elementsproject.org website
HTML
28
star
24

dicemix

Rust
24
star
25

lightning-charge-client-php

PHP client for lightning-charge
PHP
24
star
26

rust-secp256k1-zkp

C
23
star
27

cln-application

Core lightning application on Umbrel
TypeScript
21
star
28

ELIPs

Elements Improvement proposals
12
star
29

elements-miniscript

Rust
11
star
30

glightning

Go
7
star
31

peerswap-spec

7
star
32

borromean-signatures-writeup

TeX
6
star
33

elements-assets-exchange-demo

OTC-style exchange based on atomic swaps using Elements and confidential assets
JavaScript
5
star
34

qa-assets

Elements-related blobs used for quality assurance.
3
star
35

elementsbp-api-reference

[DEPRECATED: Moved to https://github.com/ElementsProject/elements/blob/elements-0.14.1/doc/elements-api.md] API Reference Documentation for the Elements Blockchain Platform
3
star
36

lightning-demos

2
star