Accepting Bitcoin on your website with Python/WSGI and coinfee

in #programming8 years ago

Full disclosure, this uses coinfee.net which I made and earn from. I take 15,000 Satoshis per transaction, which is currently about 11 US cents per transaction. Some of that gets eaten up as transaction fees.

Anyway, let's get started. WSGI is an interface for writing web applications in Python. It's easy to launch a WSGI application with uwsgi. You should have Python and uwsgi installed, and pip install coinfee pyyaml jinja2.

Going off of the example here: https://github.com/coinfee/coinfee-python/tree/master/example

Let's start with wsgi.py for a website where you want to sell your book.

"""
My Bitcoin website for making the Billions.
"""

import warnings
from uuid import uuid4 as random_uuid

import jinja2
import coinfee

ADDRESS = 'YOURADDRESS'

# Price in Satoshis. 10,000 or more.
SATOSHIS = 10000

# See deprecation warnings in logs.
warnings.simplefilter('always')


def render(template, page={}):
    template = jinja2.Environment(
        loader=jinja2.FileSystemLoader('./')
        ).get_template(template)
    return str(template.render(page=page))


def application(env, start_response):
    """
    This is where uwsgi calls us.
    """
    def reply(status, data, headers=[]):
        """
        Need to use this as return reply().
        """
        start_response(str(status), headers)
        return data

    path = env['REQUEST_URI']

    if path == '/purchase':
        # Generate a random ID for payment.
        uuid = str(random_uuid())[:19]
        url = '/purchase/{}'.format(uuid)
        # Redirect to unique buy URL.
        return reply(307, '', [('Location', url)])
    if path.startswith('/purchase/'):
        page = {}
        page['unique'] = path[len('/purchase/'):]
        coinfee_payment = coinfee.payment(ADDRESS,
                                          SATOSHIS,
                                          page['unique'])
        page['paid'] = coinfee_payment.status
        page['address'] = coinfee_payment.address
        page['satoshis'] = coinfee_payment.satoshis
        page['bitcoins'] = "{0:.8f}".format(page['satoshis'] *
                                            0.00000001)

        return reply(200, render('purchase.html', page))
    if path == '/':
        return reply(200, render('index.html'))

return reply(404, 'Not found.'

At the top, we have a docstring inside the """'s. You should learn to use them if you haven't already. I don't use them nearly enough, myself.

You'll want to update ADDRESS to your Bitcoin address. Overall, the code should be mostly self-explanatory. On /purchase, the user will be redirected to /purchase/(random). It will check if already paid. If not, it'll prompt them to pay. The payments are deterministic, and part of that seed is the "unique", which we are using to make unique links for people who have bought your book and those who haven't. Please note that if you change ADDRESS, the payment changes entirely and those who have already paid will not be able to see the "book" again, for better or worse.

Now, we use jinja for templating. Let's look at index.html:

{% include 'header.html' %}

<h2><a href="/purchase">Want to buy an amazing book?</a></h2>


<small><a href="/purchase/aa542872-013a-4fca-">Click here if you want to read it without buying it.</a></small>
{% include 'footer.html' %}

We'll get to the header and footer in just a moment. The link at the bottom demonstrates an example that I already bought. If you used my address as ADDRESS, found in the repository's version of wsgi.py, that link would show up as if it were purchased. This demonstrates how with this model, anyone with the link can view your book for free, after the first purchase. It's just the nature of the beast. You can certainly work around that if you want to, in many different ways. But for now, let's start simple.

Next, purchase.html:

{% include 'header.html' %}

{# jinja doesn't like 'is False'. You have to do == False... #}

{% if page['paid'] == False %}

<script src="https://cdn.rawgit.com/davidshimjs/qrcodejs/master/qrcode.min.js"></script>

<h4>Buy my book! Send {{ page['satoshis'] }} Satoshis to <a href="bitcoin:{{ page['address'] }}?amount={{ page['bitcoins'] }}">{{ page['address'] }}</a>. <a href="https://www.bitcoin.com" target="_blank">Are you new to Bitcoin?</a></h4>
<div id="address_qrcode"></div>
<script type="text/javascript">
new QRCode(document.getElementById("address_qrcode"), "bitcoin:{{ page['address'] }}?amount={{ page['bitcoins'] }}");
</script>
<h4><a href="">Click here or refresh after you've sent payment.</a></h4>
<noscript><blink><h1>QR code generator requires Javascript!</h1></blink></noscript>

{% else %}

<b>Thank you for buying my book! I hope you enjoy it!</b>


<h1>The long lost tales of Lorem Ipsum!</h1>

<pre>Though Lorem was an Ipsum, and Ipsum was a Lorem, he was unhappy.

Until he discovered Bitcoin!

The end.</pre>

<small>PS: Please don't send this link to people, because it doesn't expire and they can have this wonderful novel for free if you do!</small>

{% endif %}
{% include 'footer.html' %}

You can see we are using a QR code generator in Javascript. This is nice because we don't have to do it server-side, and it's very easy to work with. It lets the customer scan it, pay, click a link, and be done. If you wanted, you could have the page automatically refresh with a <meta> tag, so they can save their finger for more important tasks than refreshing.

Lastly, the header and footer.

<html>
<head>
<title>coinfee example</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
</head>
<body>
<h1><a href="/">coinfee example</a></h1>
<i>You probably don't want to buy anything on here, since this is just a test page.</i>
<br/><br/>

And the footer:

</body>
</html>

If you want to spruce up the page, you can give bootstrap a try. Just put something like this in your <head> tag.

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

If you want to have the page nicely margin-ed, you'd wrap the content with a <div class="container">.

Now that you've seen the code, you probably want to see it live. From the folder that you have these files in, run uwsgi --master --wsgi-file wsgi.py --http-socket :8088. If you're doing that from your local machine, just browse to http://localhost:8088/. Hopefully, all went well and you can write up a better book than the one in the example.

Thanks for reading!

Coin Marketplace

STEEM 0.19
TRX 0.13
JST 0.029
BTC 64725.57
ETH 3184.85
USDT 1.00
SBD 2.54