move coinify vendor stuff to a submodule
This commit is contained in:
parent
8956c5300f
commit
5ef381f973
|
@ -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__)
|
||||
|
|
0
src/vendor/__init__.py
vendored
0
src/vendor/__init__.py
vendored
1
src/vendor/coinify
vendored
1
src/vendor/coinify
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit abc76101756a95e59abc8dd13e50a45d26855ccb
|
268
src/vendor/coinify_api.py
vendored
268
src/vendor/coinify_api.py
vendored
|
@ -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
|
||||
|
23
src/vendor/coinify_callback.py
vendored
23
src/vendor/coinify_callback.py
vendored
|
@ -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()
|
||||
|
Loading…
Reference in a new issue