commit 8581fefc2d34f55650e535ab320352f5ffd1e07e
parent 4b6b4f722acb1747b17437ccf00506e11073f9d9
Author: NicholasFarrow <nicholas.w.farrow@gmail.com>
Date: Fri, 22 Jan 2021 10:50:42 +1100
merge lnd and master
Diffstat:
10 files changed, 494 insertions(+), 61 deletions(-)
diff --git a/README.md b/README.md
@@ -1,24 +1,26 @@
# BTCPyment
Existing non-custodial Bitcoin payment processors are bloated, difficult to install, and not easily customisable. BTCPyment strives to serve as an easily deployable, lightweight Bitcoin payment processor that keeps your coins with your keys by connecting to your own Bitcoin node or Lightning network node.
-## Demo
-[![demo](https://nickfarrow.com/assets/btcpyment.png)](https://node.nickfarrow.com/)
+Donation Button | Bitcoin Payment Gateway
+:-------------------------:|:-------------------------:
+[![Donate demo](https://user-images.githubusercontent.com/24557779/105266776-69775a00-5be5-11eb-81be-c9b8c2d0014d.png)](https://node.nickfarrow.com/) <br />(Click for demo) | [![Donate demo](https://user-images.githubusercontent.com/24557779/105266808-6b411d80-5be5-11eb-83e6-384c4df4da34.png)](https://node.nickfarrow.com/) <br />(Click for demo)
-BTCPyment is early in development and currently only provides donation buttons, but we plan to soon extend BTCPyment to handle payments from common webstores (shopify, woocommerce, etc).
+BTCPyment currently serves as
+1. Donation button for your website
+2. A Bitcoin payment gateway, including a Woocommerce plugin that easily turns ANY Wordpress site into a Bitcoin accepting store.
- BTCPyment makes donation buttons simple; using Python and Javascript to talk to your own Bitcoin node, with an easy iframe embed install. BTCPyment uses RPC to generate new addresses from your Bitcoin node, and monitors the payment status with your own copy of the blockchain. We now support lightning payments also, with a woocommerce plugin under development.
+BTCPyment makes donation buttons simple; with a simple Python backend to talk to your own Bitcoin node. BTCPyment uses RPC to generate new addresses from your Bitcoin node, and monitors the payment status with your own copy of the blockchain.
# Features
-* Lightweight, Python and Javascript talk to your own Bitcoin node via websockets and SSH.
-* Direct peer-to-peer payments without any middleman. No KYC, and greater privacy than donation systems with reused Bitcoin addresses.
-* Recently added support for Lightning network (lnd)!
+* Process payments with your own Bitcoin node via RPC and SSH. Bitcoin core, or any other node software that supports RPC calls.
+* Direct peer-to-peer payments without any middleman. No KYC, and greater privacy than donation systems wher Bitcoin addresses are reused multiple times.
+* Lightweight and highly extendable (for noobs too!)- Python backend with Javascript websockets. Take a [look at the code](server.py)!
* Natively supports all bitcoind node features (e.g. segwit) through RPC.
-* QR codes, you choose the minimum payment confirmations and payment expiry duration.
-* Highly extendable, just take a look at the code! Optional code execution upon payment.
+* QR codes, customizable required payment confirmations and payment expiry time.
* No shitcoin bloat. Bitcoin only.
# Installation (short!)
-BTCPyment requires you to have a server host on, and a connection to a Bitcoin node. If you don't have one, you should [install one](https://bitcoincore.org/en/download/).
+You require a server to host an instance of BTCPyment on, and a connection to a Bitcoin node. If you don't have a Bitcoin node, you should [install one](https://bitcoincore.org/en/download/).
### Install
Clone and install dependencies
```
@@ -41,6 +43,8 @@ Run BTCPyment with
```
gunicorn --worker-class eventlet -w 1 -b 0.0.0.0:8000 server:app
```
+Gunicorn is a lightweight python HTTP server, alternatively you can run with just `python server.py` though this is not recommended for production.
+
That's it! You should now be able to view your BTCPyment server at `http://YOUR_SERVER_IP:8000/`. If running locally, this will be `127.0.0.1:8000`. You might have to allow gunicorn through your firewall with `sudo ufw allow 8000`. You will want to run with nohup so it continues serving in the background:
```
nohup gunicorn --worker-class eventlet -w 1 -b 0.0.0.0:8000 server:app > log.txt 2>&1 &
@@ -52,20 +56,28 @@ Now embed the donation button into your website:
```html
<iframe src="http://YOUR_SERVER_IP:8000/" style="margin: 0 auto;display:block;height:320px;border:none;overflow:hidden;" scrolling="no"></iframe>
```
+Changing `YOUR_SERVER_IP` to the IP address of the machine you're running BTCPyment through. Optionally, you can redirect a domain to that IP and use that instead.
+
+### Using HTTPS & Domains
+Embedded iframes are easy if your site only uses HTTP. But if your site uses HTTPS, then you can see your donation button at `http://YOUR_SERVER_IP:8000/` but will not be able to in an embedded iframe. See [HTTPS instructions](docs/HTTPS.md).
+
+## Payment Gateway (Woocommerce)
+Currently we have a plugin for Woocommerce in Wordpress, [please click here for installation instructions](docs/woocommerce.md) (another easy install!). BTCPyment acts as a custom payment gateway for Woocommerce via the php plugin found in `/gateways`. We have plans to extend to other web stores in the future.
-## Using HTTPS
-Embedded iframes are easy if your site only uses HTTP. But if your site uses HTTPS, then you can likely see your donation button at `http://YOUR_SERVER_IP:8000/` but not in the embeded iframe. See [HTTPS instructions](docs/HTTPS.md).
+## Security
+For maximum security, we recommend hosting on a machine where your node only has access to a **watch-only** wallet.
# Developers
### You only need a little python!
-The main code can be found in `server.py`. The client logic for the donation button sits in `static/server_connection.js`, invoice structure and bitcoind interface in `invoice/`, button appearance in `template/index.html`. Please have ago at implementing some of the things below!
+The main code can be found in [server.py](server.py). The client-side logic for the donation button sits in [static/server_connection.js](static/server_connection.js), invoice structure and bitcoind interface in [invoice/](invoice/), button appearance in [template/index.html](template/index.html), and Woocommerce plugin in [gateways/woo_btcpyment.php](gateways/woo_btcpyment.php). Please have ago at implementing some of the things below!
More documentation will be added in the near future.
# Coming soon:
* Payment API to process payments from any desired point of sale or web shop (woocommerce, shopify)
-* Lightning support
+* Lightning support (almost ready!)
* **Better UI** with more variety of size and theme.
+* Handle unconfirmed payments. RBF?
* More readily customisable donation button (text/color/QR code)
* Database integration for payment invoices
* Multiple choice of price feeds
diff --git a/config.py b/config.py
@@ -1,11 +1,14 @@
# Bitcoin node connection settings
+# Connecting through local host, or via forwarded ssh port
host = "127.0.0.1"
rpcport = "8332"
+# From ~/.bitcoin/bitcoin.conf
username = "bitcoinrpc"
password = "RPAPASSWORD"
# SSH tunnel to node (raspberry pi!)
# Make sure this command works `ssh HOST@IP -q -N -L 8332:localhost:8332`
+# This forwards the ports required to talk to the node via RPC (or gRPC in the case of lightning)
tunnel_host = "HOST@IP"
# Check for payment every xx seconds
@@ -19,3 +22,9 @@ required_confirmations = 2
# Global connection attempts
connection_attempts = 3
+
+# Payment method
+pay_method = "bitcoind"
+# Switch payment_method to lnd if you want to use lightning payments instead. And uncomment lnd_dir.
+#pay_method = "lnd"
+#lnd_dir = "~/.lnd/"
diff --git a/docs/woocommerce.md b/docs/woocommerce.md
@@ -0,0 +1,13 @@
+# Woocommerce Payment Gateway
+To install the woocommerce payment gateway plugin, first copy `/gateways/woo_btcpyment.php` to your Wordpress site in `wp-content/plugins/`.
+
+Next, in your Wordpress admin area, go to the plugins section and activate BTCPyment. Then go to the Woocommerce settings and the "Payments" tab. Enable BTCPyment as a payment gateway.
+![Woocommerce Settings](https://user-images.githubusercontent.com/24557779/104807944-c74b2100-5836-11eb-8dba-dfaf8b5f5e1f.png)
+
+Click 'Manage' and fill out the required fields and point towards your BTCPyment instance. You will need to copy the contents of `BTCPyment/BTCPyment_API_key` into your API key field. This is generated after running BTCPyment for the first time.
+![BTCPyment Settings](https://user-images.githubusercontent.com/24557779/105259537-164ed880-5be0-11eb-9785-9b2208ad04cb.png)
+
+Now you should be able to view BTCPyment as an option in your checkout:
+![BTCPyment in Checkout](https://user-images.githubusercontent.com/24557779/105259742-7776ac00-5be0-11eb-82fd-9d82a7f1316b.png)
+
+That's it! Please reach out if there are some further features you desire in this plugin.
diff --git a/gateways/woo_btcpyment.php b/gateways/woo_btcpyment.php
@@ -0,0 +1,238 @@
+<?php
+/*
+ * Plugin Name: BTCPyment
+ * Plugin URI: https://github.com/nickfarrow/BTCPyment
+ * Description: Take Bitcoin payments on your store.
+ * Author: Nick Farrow
+ * Author URI: https://nickfarrow.com
+ * Version: 1.0.1
+ *
+*/
+
+/* Based.
+* Based on https://rudrastyh.com/woocommerce/payment-gateway-plugin.html */
+
+/*
+ * This action hook registers our PHP class as a WooCommerce payment gateway
+ */
+
+// Debugging helper
+// Writes to wp-content/debug.log
+ if (!function_exists('write_log')) {
+ function write_log($log) {
+ if (true) {
+ if (is_array($log) || is_object($log)) {
+ error_log(print_r($log, true));
+ } else {
+ error_log($log);
+ }
+ }
+ }
+ }
+
+// BTCPyment class
+add_filter( 'woocommerce_payment_gateways', 'btcpyment_add_gateway_class' );
+function btcpyment_add_gateway_class( $gateways ) {
+ $gateways[] = 'WC_Btcpyment_Gateway';
+ return $gateways;
+}
+
+// Extend existing payment gateway
+add_action( 'plugins_loaded', 'btcpyment_init_gateway_class' );
+function btcpyment_init_gateway_class() {
+ class WC_Btcpyment_Gateway extends WC_Payment_Gateway {
+
+ /**
+ * Class constructor
+ */
+ public function __construct() {
+
+ $this->id = 'btcpyment'; // payment gateway plugin ID
+ $this->icon = ''; // URL of the icon that will be displayed on checkout page near your gateway name
+ $this->has_fields = true; // in case you need a custom credit card form
+ $this->method_title = 'BTCPyment Gateway';
+ $this->method_description = 'Description of btcpyment payment gateway'; // will be displayed on the options page
+
+ $this->supports = array(
+ 'products'
+ );
+
+ // Method with all the options fields
+ $this->init_form_fields();
+
+ // Load the settings.
+ $this->init_settings();
+ $this->title = $this->get_option( 'title' );
+ $this->description = $this->get_option( 'description' );
+ $this->enabled = $this->get_option( 'enabled' );
+ $this->btcpyment_server_url = $this->get_option( 'btcpyment_server_url' );
+ // $this->redirect_url = $this->get_option( 'redirect_url' );
+ // $this->testmode = 'yes' === $this->get_option( 'testmode' );
+ $this->BTCPyment_API_Key = $this->get_option( 'BTCPyment_API_Key' );
+
+ $this->callback_URL = str_replace( 'https:', 'http:', add_query_arg( 'wc-api', 'wc_btcpyment_gateway', home_url( '/' ) ) );
+ // $this->callback_URL = home_url( '/' ) . 'wc-api/' . 'WC_Btcpyment_Gateway/';
+
+ // This action hook saves the settings
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
+
+ // We need custom JavaScript to obtain a token
+ // add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
+
+ // You can also register a webhook here
+ add_action( 'woocommerce_api_wc_btcpyment_gateway', array( $this, 'webhook' ) );
+ }
+
+ /**
+ * Plugin options
+ */
+ public function init_form_fields(){
+
+ $this->form_fields = array(
+ 'enabled' => array(
+ 'title' => 'Enable/Disable',
+ 'label' => 'Enable btcpyment Gateway',
+ 'type' => 'checkbox',
+ 'description' => '',
+ 'default' => 'no'
+ ),
+ 'title' => array(
+ 'title' => 'Title',
+ 'type' => 'text',
+ 'description' => 'This controls the title which the user sees during checkout.',
+ 'default' => 'Bitcoin',
+ 'desc_tip' => true,
+ ),
+ 'description' => array(
+ 'title' => 'Description',
+ 'type' => 'textarea',
+ 'description' => 'This controls the description which the user sees during checkout.',
+ 'default' => 'Pay with Bitcoin via BTCPyment',
+ ),
+ 'btcpyment_server_url' => array(
+ 'title' => 'BTCPyment URL',
+ 'type' => 'text',
+ 'description' => 'Points towards your instance of BTCPyment, should be IP or https://SERVER.com',
+ ),
+ // 'redirect_url' => array(
+ // 'title' => 'Redirect URL',
+ // 'type' => 'text',
+ // 'description' => 'URL the user is redirected to after payment.',
+ // ),
+ // 'testmode' => array(
+ // 'title' => 'Test mode',
+ // 'label' => 'Enable Test Mode',
+ // 'type' => 'checkbox',
+ // 'description' => 'Place the payment gateway in test mode using test API keys.',
+ // 'default' => 'yes',
+ // 'desc_tip' => true,
+ // ),
+ // 'test_publishable_key' => array(
+ // 'title' => 'Test Publishable Key',
+ // 'type' => 'text'
+ // ),
+ // 'test_private_key' => array(
+ // 'title' => 'Test Private Key',
+ // 'type' => 'password',
+ // ),
+ 'BTCPyment_API_Key' => array(
+ 'title' => 'BTCPyment_API_Key',
+ 'type' => 'text'
+ )
+ // 'private_key' => array(
+ // 'title' => 'Live Private Key',
+ // 'type' => 'password'
+ // )
+ );
+ }
+
+
+ /*
+ * Custom CSS and JS, in most cases required only when you decided to go with a custom credit card form
+ */
+ public function payment_scripts() {
+
+ // we need JavaScript to process a token only on cart/checkout pages, right?
+ if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) {
+ return;
+ }
+
+ // if our payment gateway is disabled, we do not have to enqueue JS too
+ if ( 'no' === $this->enabled ) {
+ return;
+ }
+
+ // no reason to enqueue JavaScript if API keys are not set
+ if ( empty($this->BTCPyment_API_Key) ) {
+ return;
+ }
+
+
+ // wp_enqueue_script( 'woocommerce_btcpyment' );
+
+ }
+
+
+ /*
+ * Processing the payments
+ */
+ public function process_payment( $order_id ) {
+
+ global $woocommerce;
+
+ // we need it to get any order detailes
+ $order = wc_get_order( $order_id );
+
+ /*
+ * Array with parameters for API interaction
+ */
+ $args = array(
+ 'amount' => $order->get_total(),
+ 'id' => $order->get_id(),
+ 'w_url' => $this->callback_URL );
+ // HASH??? FOR SECURE PAYMENTS?
+
+ $payment_url = add_query_arg(
+ $args,
+ $this->btcpyment_server_url . "/pay"
+ );
+
+ // Redirect to BTCPyment
+ return [
+ 'result' => 'success',
+ 'redirect' => $payment_url
+ ];
+ }
+
+ /*
+ * Webhook to confirm payment
+ */
+ public function webhook() {
+ $headers = getallheaders();
+ # Get supplied signature
+ $signature = $headers['X-Signature'];
+
+ $now = time(); // current unix timestamp
+ $json = json_encode($_GET, JSON_FORCE_OBJECT);
+ $key = hex2bin($this->BTCPyment_API_Key);
+
+ # Calculate expected signature
+ $valid_signature = hash_hmac('sha256', $_GET['time'] .'.'.$json, $key);
+
+ # Compare signature and timestamps
+ if (hash_equals($signature, $valid_signature) and (abs($now - $_GET['time']) < 5)) {
+ header( 'HTTP/1.1 200 OK' );
+ # Complete order
+ $order = wc_get_order( $_GET['id'] );
+ $order->payment_complete();
+ $order->reduce_order_stock();
+ update_option('webhook_debug', $_GET);
+
+ } else {
+ header( 'HTTP/1.1 403 Forbidden' );
+ return 1;
+ }
+
+ }
+ }
+}
diff --git a/gateways/woo_webhook.py b/gateways/woo_webhook.py
@@ -0,0 +1,20 @@
+import hmac
+import hashlib
+import json
+import codecs
+import time
+import requests
+
+def hook(secret, payload):
+ paid_time = int(time.time())
+ params = {"wc-api":"wc_btcpyment_gateway", 'id' : payload['id'], 'time' : str(paid_time)}
+ message = (str(paid_time) + '.' + json.dumps(params, separators=(',', ':'))).encode('utf-8')
+
+ key = codecs.decode(secret, 'hex')
+ hash = hmac.new(key, message, hashlib.sha256).hexdigest()
+ headers={'Content-Type': 'application/json', 'X-Signature' : hash}
+
+ response = requests.get(
+ payload['w_url'], params=params, headers=headers)
+
+ return response
diff --git a/pay/bitcoind.py b/pay/bitcoind.py
@@ -1,7 +1,10 @@
-import config
+import time
import subprocess
+import time
+import config
from invoice.payment_invoice import invoice
+
class btcd(invoice):
def __init__(self, dollar_value, currency, label):
super().__init__(dollar_value, currency, label)
@@ -17,6 +20,7 @@ class btcd(invoice):
try:
self.rpc = AuthServiceProxy(connection_str)
info = self.rpc.getblockchaininfo()
+ print(info)
print("Successfully contacted bitcoind.")
break
diff --git a/server.py b/server.py
@@ -1,4 +1,4 @@
-from flask import Flask, render_template, session
+from flask import Flask, render_template, session, request
from flask_socketio import SocketIO, emit, disconnect
from markupsafe import escape
import time
@@ -9,6 +9,7 @@ import config
import invoice
from pay import bitcoind
from pay import lnd
+from gateways import woo_webhook
# Begin websocket
async_mode = None
@@ -26,28 +27,39 @@ else:
print("Initialised Flask with secret key: {}".format(app.config['SECRET_KEY']))
socket_ = SocketIO(app, async_mode=async_mode, cors_allowed_origins="*")
-# Render html
+# Render index pages
+# To-do, this will be a donation form page that submits to /pay
@app.route('/')
def index():
- return render_template('index.html', async_mode=socket_.async_mode)
+ return render_template('donate.html', async_mode=socket_.async_mode)
+
+@app.route('/pay')
+def payment_page():
+ #
+ # # Label is blank if not supplied
+ # params = {'label':''}
+ # for key, value in dict(request.args).items():
+ # params[key] = value
+ params = dict(request.args)
+ return render_template('index.html', params=params, async_mode=socket_.async_mode)
# Basic return on initialisation
-@socket_.on('initialise', namespace='/pay')
+@socket_.on('initialise')
def test_message(message):
emit('payresponse', {'time_left': -1, 'response': message['data']})
# Main payment method for websocket
# Recieves form amount and initiates invoice and payment processing.
-@socket_.on('payment', namespace='/pay')
+@socket_.on('make_payment')
def make_payment(payload):
- print("Requesting payment for {}".format(payload['amount']))
-
# Check the amount is a float
amount = payload['amount']
try:
amount = float(amount)
except:
- # Give response?
+ payment.status = 'Invalid amount.'
+ payment.response = 'Invalid amount.'
+ update_status(payment)
amount = None
return
@@ -57,12 +69,16 @@ def make_payment(payload):
amount = None
return
- # Need to check this is safe!
- label = payload['label']
+ # Return if label missing
+ if 'id' in payload.keys():
+ label = payload['id']
+ else:
+ label = "noid"
# Initialise this payment
payment = create_invoice(amount, "USD", label)
+ # Wait for amount to be sent to the address
process_payment(payment)
if payment.paid:
@@ -70,17 +86,28 @@ def make_payment(payload):
payment.response = 'Payment finalised. Thankyou!'
update_status(payment)
- invoice.success.success()
-
# Call webhook if woocommerce webhook url has been provided.
if 'w_url' in payload.keys():
response = woo_webhook.hook(app.config['SECRET_KEY'], payload)
- ### DO SOMETHING
- # Depends on config
- # Get redirected?
- # Nothing?
- # Run custom script?
+ if response.status_code != 200:
+ print('Failed to confirm order payment via webhook {}, the response is: {}'.format(response.status_code, response.text))
+ payment.status = response.text
+ payment.response = response.text
+ else:
+ print("Successfully confirmed payment via webhook.")
+ payment.status = 'Order confirmed.'
+ payment.response = 'Order confirmed.'
+
+ update_status(payment)
+
+ ### DO SOMETHING
+ # Depends on config
+ # Get redirected?
+ # Nothing?
+ # Run custom script?
+
+ return
# Initialise the payment via the payment method (bitcoind / lightningc / etc),
# create qr code for the payment.
@@ -116,8 +143,8 @@ def update_status(payment, console_status=True):
# Payment processing function.
# Handle payment logic.
def process_payment(payment):
- payment.status = 'Awaiting payment.'
- payment.response = 'Awaiting payment.'
+ payment.status = 'Payment intialised, awaiting payment.'
+ payment.response = 'Payment intialised, awaiting payment.'
update_status(payment)
# Track start_time for payment timeouts
@@ -145,8 +172,8 @@ def process_payment(payment):
update_status(payment, console_status=False)
socket_.sleep(config.pollrate)
else:
- payment.status = "Awaiting payment...".format(payment.value)
- payment.response = "Awaiting payment...".format(payment.value)
+ payment.status = "Waiting for payment...".format(payment.value)
+ payment.response = "Waiting for payment...".format(payment.value)
update_status(payment)
socket_.sleep(config.pollrate)
else:
diff --git a/static/server_connection.js b/static/server_connection.js
@@ -1,6 +1,6 @@
// Websocket logic, talks to server.py pay
-$(document).ready(function() {
- namespace = '/pay';
+function initiate(payment_data) {
+ namespace = '/';
var socket = io(namespace);
socket.on('connect', function() {
@@ -21,19 +21,17 @@ $(document).ready(function() {
cb();
});
- $('form#pay').submit(function(event) {
- socket.emit('payment', {'amount': $('#pay_data').val(), 'label' : null});
- return false;
- });
-});
+ socket.emit('make_payment', payment_data);
+ return false
+}
// Additional steps to take when giving a response to the webpage
// Update qr code, and hide timer
function conditionalPageLogic(msg) {
if (msg.address != null) {
- document.getElementById('logo').classList.add("qr");
+ // document.getElementById('logo').classList.add("qr");
// document.getElementById('logo').src = "static/qr_codes/" + msg.uuid + ".png";
- document.getElementById('logo').style.display = "none";
+ // document.getElementById('logo').style.display = "none";
document.getElementById('qrImage').style.display = "block";
document.getElementById('qrClick').href = "/static/qr_codes/" + msg.uuid + ".png";
document.getElementById('qrImage').src = "/static/qr_codes/" + msg.uuid + ".png";
diff --git a/templates/donate.html b/templates/donate.html
@@ -0,0 +1,116 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>BTCPyment</title>
+ <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
+
+ <script src="//code.jquery.com/jquery-1.12.4.min.js"></script>
+ <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js"></script>
+ <!-- <script src="{{ url_for('static', filename='server_connection.js') }}"></script> -->
+
+ <style>
+ html, body {
+ display: flex;
+ /* height:auto;
+ width:260px; */
+ }
+ body{
+ background-color: inherit;
+ overflow: hidden;
+ }
+ p {
+ /* display: inline-block; */
+ overflow-wrap: break-word;
+ word-wrap: break-word;
+ margin: 0;
+ padding: 5px;
+ }
+ h1 {
+ font-size: 2em;
+ }
+ #paybox {
+ background-color: #f7931a;
+ border-radius: 25px;
+ padding-left: 30px;
+ padding-right: 30px;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ font-size: 16px
+
+ /* height:auto; */
+ height: 275px;
+ width:220px;
+ }
+ #row {
+ display: flex;
+ }
+ #left {
+ width: 60%;
+ padding: 0 10px 0 0;
+ float: left;
+ }
+ #right {
+ width: 40%;
+ padding: 0 10px 0 0;
+ float: right;
+ }
+ #address {
+ overflow-wrap: break-word;
+ text-align: right;
+ }
+ #about {
+ color:#000;
+ }
+ .qr {
+ transition: transform .2s;
+ object-fit: cover;
+ }
+ .qr:hover {
+ -ms-transform: scale(2.5); /* IE 9 */
+ -webkit-transform: scale(2.5); /* Safari 3-8 */
+ transform: scale(3);
+ }
+ </style>
+
+</head>
+
+
+<body>
+ <div id="paybox">
+ <div id="row" height="50px">
+ <div id="left" style="display:inline-block;" height="75px">
+ <h1>Donate Bitcoin</h>
+ </div>
+ <div id="right">
+ <a id="logo" target="_blank"><img id="logo" style="padding-top:25px;padding-left:30px;" width="65px" src="https://i.pinimg.com/originals/3a/dd/40/3add4023fa9b435e7da3c09156b88015.png"></a>
+ <a id="qrClick" target="_blank"><img class="qr" id="qrImage" style="padding-top:25px;display:none" width="65px" src="https://i.pinimg.com/originals/3a/dd/40/3add4023fa9b435e7da3c09156b88015.png"></a>
+ </div>
+ </div>
+
+ <div id="paymentForm">
+ <center>
+ <form id="pay" action='/pay' style="margin:0;padding0;">
+ <h2 style="margin:0;padding0;">Amount:
+ <input style="display:inline" size="4" type="float" name="amount" id="amount" placeholder="USD">
+ </h2>
+ <br>
+ <input style="width:100%" type="submit" value="Pay" onclick="hideAmountShowPayment()">
+ </form>
+ </center>
+ </div>
+
+ <!-- <div id="paymentDetails" style="display:none; padding: 0;">
+ <p style="padding:0;">Send: <b><span id="amount"></span></b> BTC</p>
+ <p style="padding:0;">To: </p><b><p id="address" onclick="copyTextFromElement('address')"></p></b>
+ <p style="padding:0;"><span id="status"></span></p>
+ <p id="timerContainer" style="padding:0;"><span id="timer"></span> seconds remaining.</p>
+ </div>
+
+ <div id="information" style="text-align: right; padding: 0;">
+ <small><a id="about" href="https://github.com/nickfarrow/BTCPyment" target="_blank">BTCPyment</a></small>
+ </div> -->
+
+ <div id="paybutton"></div>
+ </div>
+</body>
+</html>
diff --git a/templates/index.html b/templates/index.html
@@ -3,11 +3,18 @@
<head>
<title>BTCPyment</title>
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
-
+
<script src="//code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/3.0.4/socket.io.js"></script>
<script src="{{ url_for('static', filename='server_connection.js') }}"></script>
+ <!-- Initate the payment websocket -->
+ <script type="text/javascript">
+ payment_data = {{ params|tojson }};
+ console.log(payment_data);
+ initiate(payment_data);
+ </script>
+
<style>
html, body {
@@ -80,27 +87,16 @@
<div id="paybox">
<div id="row" height="50px">
<div id="left" style="display:inline-block;" height="75px">
- <h1>Donate Bitcoin</h>
+ <h1>Pay Bitcoin</h>
</div>
<div id="right">
- <a id="logo" target="_blank"><img id="logo" style="padding-top:25px;padding-left:30px;" width="65px" src="https://i.pinimg.com/originals/3a/dd/40/3add4023fa9b435e7da3c09156b88015.png"></a>
- <a id="qrClick" target="_blank"><img class="qr" id="qrImage" style="padding-top:25px;display:none" width="65px" src="https://i.pinimg.com/originals/3a/dd/40/3add4023fa9b435e7da3c09156b88015.png"></a>
+ <!-- <a id="logo" target="_blank"><img id="logo" style="padding-top:25px;padding-left:30px;" width="65px" src="https://i.pinimg.com/originals/3a/dd/40/3add4023fa9b435e7da3c09156b88015.png"></a> -->
+ <a id="qrClick" target="_blank"><img class="qr" id="qrImage" style="padding-top:25px;display:block" width="65px" src="https://i.pinimg.com/originals/3a/dd/40/3add4023fa9b435e7da3c09156b88015.png"></a>
</div>
</div>
- <div id="paymentForm">
- <center>
- <form id="pay" method="POST" action='#' style="margin:0;padding0;">
- <h2 style="margin:0;padding0;">Amount:
- <input style="display:inline" size="4" type="float" name="pay_data" id="pay_data" placeholder="USD">
- </h2>
- <br>
- <input style="width:100%" type="submit" value="Pay" onclick="hideAmountShowPayment()">
- </form>
- </center>
- </div>
- <div id="paymentDetails" style="display:none; padding: 0;">
+ <div id="paymentDetails" style="display:block; padding: 0;">
<p style="padding:0;">Send: <b><span id="amount"></span></b> BTC</p>
<p style="padding:0;">To: </p><b><p id="address" onclick="copyTextFromElement('address')"></p></b>
<p style="padding:0;"><span id="status"></span></p>