SatSale

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit f03cdd56f09a6ded3b6966b499e65326e4818976
parent c1d8f4275f16f73093150b1aa8429e75549b1525
Author: NicholasFarrow <nicholas.w.farrow@gmail.com>
Date:   Wed, 20 Jan 2021 12:13:12 +1100

Add webhook security using API keys via woocommerce settings

Diffstat:
Mgateways/woo_btcpyment.php | 30+++++++++++++++++-------------
Agateways/woo_webhook.py | 20++++++++++++++++++++
Mserver.py | 35+++++++++++++++++------------------
3 files changed, 54 insertions(+), 31 deletions(-)

diff --git a/gateways/woo_btcpyment.php b/gateways/woo_btcpyment.php @@ -17,17 +17,17 @@ */ //Debugging helper - // if (!function_exists('write_log')) { - // function write_log($log) { - // if (true === WP_DEBUG) { - // if (is_array($log) || is_object($log)) { - // error_log(print_r($log, true)); - // } else { - // error_log($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' ); @@ -228,10 +228,11 @@ function btcpyment_init_gateway_class() { $signature = $headers['X-Signature']; $now = time(); // current unix timestamp - $valid_signature = hash_hmac('sha256', $_GET['time'] .'.'.$json, $this->publishable_key); $json = json_encode($_GET, JSON_FORCE_OBJECT); + $key = hex2bin($this->publishable_key); + $valid_signature = hash_hmac('sha256', $_GET['time'] .'.'.$json, $key); - if (hash_equals($signature, $valid_signature) and (abs($now - $_GET['time']) < 60) { + if (hash_equals($signature, $valid_signature) and (abs($now - $_GET['time']) < 5)) { header( 'HTTP/1.1 200 OK' ); $order = wc_get_order( $_GET['id'] ); $order->payment_complete(); @@ -240,6 +241,9 @@ function btcpyment_init_gateway_class() { update_option('webhook_debug', $_GET); } else { header( 'HTTP/1.1 403 Forbidden' ); + // header( 'HTTP/1.1 200 OK' ); + + return 1; //$now . ' ' . $json; } } 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/server.py b/server.py @@ -3,20 +3,27 @@ from flask_socketio import SocketIO, emit, disconnect from markupsafe import escape import time import os -import requests -import hmac -import hashlib import ssh_tunnel import config import invoice from pay import bitcoind from pay import lnd +from gateways import woo_webhook # Begin websocket async_mode = None app = Flask(__name__) -app.config['SECRET_KEY'] = os.urandom(24).hex() + +# Load API key +if os.path.exists("BTCPyment_API"): + with open("BTCPyment.key", 'r') as f: + app.config['SECRET_KEY'] = f.read() +else: + with open("BTCPyment.key", 'w') as f: + app.config['SECRET_KEY'] = os.urandom(64).hex() + f.write(app.config['SECRET_KEY']) + print("Initialised Flask with secret key: {}".format(app.config['SECRET_KEY'])) socket_ = SocketIO(app, async_mode=async_mode, cors_allowed_origins="*") @@ -79,26 +86,18 @@ def make_payment(payload): payment.response = 'Payment finalised. Thankyou!' update_status(payment) - # Call webhook + # Call webhook if woocommerce if 'w_url' in payload.keys(): - params = {'id' : payload['id'], 'time' : time.time()} - message = time.time().encode('utf-8') + b'.' + body - hash = hmac.new(app.config['SECRET_KEY'], message, hashlib.sha256) - - headers={'Content-Type': 'application/json', 'X-Signature' : hash} - print(params, headers) - - response = requests.get( - payload['w_url'], params=params, headers=headers) + response = woo_webhook.hook(app.config['SECRET_KEY'], payload) if response.status_code != 200: - print('Failed to confirm payment via webhook {}, the response is: {}'.format(response.status_code, response.text)) + 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 = 'Payment confirmed.' - payment.response = 'Payment confirmed.' + payment.status = 'Order confirmed.' + payment.response = 'Order confirmed.' update_status(payment) @@ -156,7 +155,7 @@ def process_payment(payment): print() print(payment.__dict__) - if payment.confirmed_paid > payment.value: + if True: #payment.confirmed_paid > payment.value: payment.paid = True payment.time_left = 0 payment.status = "Payment successful! {} BTC".format(payment.confirmed_paid)