From 5ef381f9736aa5b4c1c809c74873c9c42071ac1f Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Fri, 24 Mar 2017 01:58:04 +0100 Subject: [PATCH] move coinify vendor stuff to a submodule --- src/shop/views.py | 4 +- src/vendor/__init__.py | 0 src/vendor/coinify | 1 - src/vendor/coinify_api.py | 268 --------------------------------- src/vendor/coinify_callback.py | 23 --- 5 files changed, 2 insertions(+), 294 deletions(-) delete mode 100644 src/vendor/__init__.py delete mode 160000 src/vendor/coinify delete mode 100644 src/vendor/coinify_api.py delete mode 100644 src/vendor/coinify_callback.py diff --git a/src/shop/views.py b/src/shop/views.py index 24c3b434..bd6c785e 100644 --- a/src/shop/views.py +++ b/src/shop/views.py @@ -35,8 +35,8 @@ from shop.models import ( from .forms import AddToOrderForm from .epay import calculate_epay_hash, validate_epay_callback from collections import OrderedDict -from vendor.coinify_api import CoinifyAPI -from vendor.coinify_callback import CoinifyCallback +from vendor.coinify.coinify_api import CoinifyAPI +from vendor.coinify.coinify_callback import CoinifyCallback import json, time import logging logger = logging.getLogger("bornhack.%s" % __name__) diff --git a/src/vendor/__init__.py b/src/vendor/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/vendor/coinify b/src/vendor/coinify deleted file mode 160000 index abc76101..00000000 --- a/src/vendor/coinify +++ /dev/null @@ -1 +0,0 @@ -Subproject commit abc76101756a95e59abc8dd13e50a45d26855ccb diff --git a/src/vendor/coinify_api.py b/src/vendor/coinify_api.py deleted file mode 100644 index 4241e48a..00000000 --- a/src/vendor/coinify_api.py +++ /dev/null @@ -1,268 +0,0 @@ -import requests, json, time, hashlib, hmac - - -class CoinifyAPI: - api_key = None - """Coinify API key. Get yours at https://www.coinify.com/merchant/api""" - - api_secret = None - """Coinify API secret. Get yours at https://www.coinify.com/merchant/api""" - - api_base_url = None - """Base URL to the Coinify API""" - - API_DEFAULT_BASE_URL = "https://api.coinify.com" - - def __init__(self, api_key=None, api_secret=None, api_base_url=None): - """ - Create an instance of the CoinifyAPI class. - Provide your API key and API secret. - - Set api_base_url to None to use default - """ - self.api_key = api_key - self.api_secret = api_secret - self.api_base_url = api_base_url or self.API_DEFAULT_BASE_URL - - def invoices_list(self, limit=None, offset=None, include_expired=None): - """ - Returns an array of your Coinify invoices - - See https://www.coinify.com/docs/api/#list-all-invoices - """ - query_params = {} - - if limit is not None: - query_params['limit'] = limit - if offset is not None: - query_params['offset'] = offset - if include_expired is not None: - query_params['include_expired'] = include_expired - - return self.call_api_authenticated('/v3/invoices', query_params=query_params) - - def invoice_create(self, amount, currency, plugin_name, plugin_version, - description=None, custom=None, callback_url=None, callback_email=None, - return_url=None, cancel_url=None, input_currency=None, input_return_address=None): - - """ - Create a new invoice. - - See https://www.coinify.com/docs/api/#create-an-invoice - """ - params = { - 'amount': amount, - 'currency': currency, - 'plugin_name': plugin_name, - 'plugin_version': plugin_version - } - - if description is not None: - params['description'] = description - if custom is not None: - params['custom'] = custom - if callback_url is not None: - params['callback_url'] = callback_url - if callback_email is not None: - params['callback_email'] = callback_email - if return_url is not None: - params['return_url'] = return_url - if cancel_url is not None: - params['cancel_url'] = cancel_url - if input_currency is not None: - params['input_currency'] = input_currency - if input_return_address is not None: - params['input_return_address'] = input_return_address - - return self.call_api_authenticated('/v3/invoices', 'POST', params) - - def invoice_get(self, invoice_id): - """ - Get a specific invoice - - See https://www.coinify.com/docs/api/#get-a-specific-invoice - """ - path = '/v3/invoices/%d' % (invoice_id,) - - return self.call_api_authenticated(path) - - def invoice_update(self, invoice_id, description=None, custom=None): - """ - Update the description and custom data of an invoice - - See https://www.coinify.com/docs/api/#update-an-invoice - """ - params = {} - - if description is not None: - params['description'] = description - if custom is not None: - params['custom'] = custom - - path = '/v3/invoices/%d' % (invoice_id,) - - return self.call_api_authenticated(path, 'PUT', params) - - def invoice_input_create(self, invoice_id, currency, return_address): - """ - Request for an invoice to be paid with another input currency. - - See https://www.coinify.com/docs/api/#pay-with-another-input-currency - """ - params = { - 'currency': currency, - 'return_address': return_address - } - - path = '/v3/invoices/%d/inputs' % (invoice_id,) - - return self.call_api_authenticated(path, 'POST', params) - - def buy_orders_list(self, limit=None, offset=None, include_cancelled=None): - """ - Returns an array of your Coinify buy orders - - See https://www.coinify.com/docs/api/#list-all-buy-orders - """ - - query_params = {} - - if limit is not None: - query_params['limit'] = limit - if offset is not None: - query_params['offset'] = offset - if include_cancelled is not None: - query_params['include_cancelled'] = include_cancelled - - return self.call_api_authenticated('/v3/buys', query_params=query_params) - - def buy_order_create(self, amount, currency, btc_address, instant_order=None, - callback_url=None, callback_email=None): - """ - Create a new buy order - - See https://www.coinify.com/docs/api/#create-a-buy-order - """ - params = { - 'amount': amount, - 'currency': currency, - 'btc_address': btc_address - } - - if instant_order is not None: - params['instant_order'] = instant_order - if callback_url is not None: - params['callback_url'] = callback_url - if callback_email is not None: - params['callback_email'] = callback_email - - return self.call_api_authenticated('/v3/buys', 'POST', params) - - def buy_order_confirm(self, buy_order_id): - """ - Confirm a buy order - - See https://www.coinify.com/docs/api/#buy-order-confirm - """ - path = '/v3/buys/%d/actions/confirm' % (buy_order_id,) - - return self.call_api_authenticated(path, 'PUT') - - def buy_order_get(self, buy_order_id): - """ - Get a specific buy order - - See https://www.coinify.com/docs/api/#get-a-specific-buy-order - """ - path = '/v3/buys/%d' % (buy_order_id,) - - return self.call_api_authenticated(path) - - def rates_get(self, currency=None): - """ - Return buy and sell rates for all available currencies or for the specified currency. - :param self: - :param currency|None: A 3-char currency code - :return: - """ - if currency is None: - path = '/v3/rates' - else: - path = '/v3/rates/%s' % (currency,) - - return self.call_api_authenticated(path) - - def balance_get(self): - """ - Get the balance of a merchant - :param path: - :return: An array as described in https://www.coinify.com/docs/api/#check-account-balance . If success, - then the 'data' value contains the balance in BTC and fiat currency and also the base currency - of the merchant that requests it. - """ - path = '/v3/balance' - return self.call_api_authenticated(path) - - def input_currencies_list(self): - """ - Receive a list of supported input currencies - """ - - return self.call_api('/v3/input-currencies') - - def call_api_authenticated(self, path, method='GET', params={}, query_params={}): - """ - Perform an authenticated API call, using the - API key and secret provided in the constructor. - - path: API path, WITH a leading slash, e.g. '/v3/invoices' - params: dict with parameters to send with the API call - - Returns a dict as described in https://www.coinify.com/docs/api/#response-format, - or None if the HTTP call couldn't be performed correctly. - """ - extra_headers = { - 'Authorization': self.generate_authorization_header() - } - - return self.call_api(path, method, params, query_params, extra_headers) - - def call_api(self, path, method='GET', params={}, query_params={}, headers={}): - """ - Perform an API call - - path: API path, WITH a leading slash, e.g. '/v3/invoices' - params: dict with parameters to send with the API call - - Returns a dict as described in https://www.coinify.com/docs/api/#response-format, - or None if the HTTP call couldn't be performed correctly. - """ - url = self.api_base_url + path - - headers['Content-Type'] = 'application/json' - - if self.api_key is not None: - headers['Authorization'] = self.generate_authorization_header() - - r = requests.request(method, url, json=params, headers=headers, params=query_params) - return r.json() - - def generate_authorization_header(self): - """ - Generate a nonce and a signature for an API call - and wrap those in a HTTP header - """ - # Generate nonce, based on the current Unix timestamp - nonce = str(int(time.time() * 1000000)) - - # Concatenate nonce and API key - message = nonce + self.api_key - - # Compute signature - signature = hmac.new(self.api_secret, msg=message, digestmod=hashlib.sha256).hexdigest() - - # Construct the header value - header_value = 'Coinify apikey="%s", nonce="%s", signature="%s"' % (self.api_key, nonce, signature) - - return header_value - diff --git a/src/vendor/coinify_callback.py b/src/vendor/coinify_callback.py deleted file mode 100644 index d55e9dba..00000000 --- a/src/vendor/coinify_callback.py +++ /dev/null @@ -1,23 +0,0 @@ -import hashlib, hmac - -class CoinifyCallback: - """ - Class to validate callbacks from Coinfy - """ - - ipn_secret = None - """Coinify IPN callback secret. Get yours at https://www.coinify.com/merchant/ipn""" - - def __init__( self, ipn_secret ): - self.ipn_secret = ipn_secret - - def validate_callback( self, callback_raw, signature ): - """ - Validates a callback and it's signature based on the IPN secret given in the constructor. - - callback_raw must contain the raw JSON POST data sent with the callback (before any JSON decoding) - signature must contain the signature as extracted from the 'X-Coinify-Callback-Signature' header, - which should be a 64-byte hexadecimal string - """ - return signature == hmac.new(self.ipn_secret, msg=callback_raw, digestmod=hashlib.sha256).hexdigest() -