bornhack-website/src/shop/coinify.py

132 lines
4.3 KiB
Python

import json
import logging
import requests
from django.conf import settings
from vendor.coinify.coinify_api import CoinifyAPI
from .models import CoinifyAPICallback, CoinifyAPIInvoice, CoinifyAPIRequest
logger = logging.getLogger("bornhack.%s" % __name__)
def process_coinify_invoice_json(invoicejson, order, request):
# create or update the invoice object in our database
coinifyinvoice, created = CoinifyAPIInvoice.objects.update_or_create(
coinify_id=invoicejson["id"], order=order, defaults={"invoicejson": invoicejson}
)
# if the order is paid in full call the mark as paid method now
if invoicejson["state"] == "complete" and not coinifyinvoice.order.paid:
coinifyinvoice.order.mark_as_paid(request=request)
return coinifyinvoice
def save_coinify_callback(request, order):
# first make a dict with all HTTP_ headers
headerdict = {}
for key, value in list(request.META.items()):
if key[:5] == "HTTP_":
headerdict[key[5:]] = value
# now attempt to parse json
try:
parsed = json.loads(request.body.decode("utf-8"))
except Exception:
parsed = ""
# save this callback to db
callbackobject = CoinifyAPICallback.objects.create(
headers=headerdict, body=request.body, payload=parsed, order=order
)
return callbackobject
def coinify_api_request(api_method, order, **kwargs):
# Initiate coinify API
coinifyapi = CoinifyAPI(settings.COINIFY_API_KEY, settings.COINIFY_API_SECRET)
# is this a supported method?
if not hasattr(coinifyapi, api_method):
logger.error("coinify api method not supported" % api_method)
return False
# get and run the API call using the SDK
method = getattr(coinifyapi, api_method)
# catch requests exceptions as described in https://github.com/CoinifySoftware/python-sdk#catching-errors and
# http://docs.python-requests.org/en/latest/user/quickstart/#errors-and-exceptions
try:
response = method(**kwargs)
except requests.exceptions.RequestException as E:
logger.error("requests exception during coinify api request: %s" % E)
return False
# save this API request to the database
req = CoinifyAPIRequest.objects.create(
order=order, method=api_method, payload=kwargs, response=response
)
logger.debug("saved coinify api request %s in db" % req.id)
return req
def handle_coinify_api_response(apireq, order, request):
if apireq.method == "invoice_create" or apireq.method == "invoice_get":
# Parse api response
if apireq.response["success"]:
# save this new coinify invoice to the DB
coinifyinvoice = process_coinify_invoice_json(
invoicejson=apireq.response["data"], order=order, request=request
)
return coinifyinvoice
else:
api_error = apireq.response["error"]
logger.error(
"coinify API error: %s (%s)" % (api_error["message"], api_error["code"])
)
return False
else:
logger.error("coinify api method not supported" % apireq.method)
return False
#################################################################
# API CALLS
def get_coinify_invoice(coinify_invoiceid, order, request):
# put args for API request together
invoicedict = {"invoice_id": coinify_invoiceid}
# perform the api request
apireq = coinify_api_request(api_method="invoice_get", order=order, **invoicedict)
coinifyinvoice = handle_coinify_api_response(apireq, order, request)
return coinifyinvoice
def create_coinify_invoice(order, request):
# put args for API request together
invoicedict = {
"amount": float(order.total),
"currency": "DKK",
"plugin_name": "BornHack webshop",
"plugin_version": "1.0",
"description": "BornHack order id #%s" % order.id,
"callback_url": order.get_coinify_callback_url(request),
"return_url": order.get_coinify_thanks_url(request),
"cancel_url": order.get_cancel_url(request),
}
# perform the API request
apireq = coinify_api_request(
api_method="invoice_create", order=order, **invoicedict
)
coinifyinvoice = handle_coinify_api_response(apireq, order, request)
return coinifyinvoice