improved error handling, always save callback body, various fixes
This commit is contained in:
parent
3be7319dc3
commit
1b98c01f63
26
src/shop/migrations/0039_auto_20170403_1752.py
Normal file
26
src/shop/migrations/0039_auto_20170403_1752.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-04-03 15:52
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import django.contrib.postgres.fields.jsonb
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('shop', '0038_auto_20170323_2021'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='coinifyapicallback',
|
||||||
|
name='body',
|
||||||
|
field=models.TextField(default=''),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='coinifyapicallback',
|
||||||
|
name='payload',
|
||||||
|
field=django.contrib.postgres.fields.jsonb.JSONField(null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -410,7 +410,8 @@ class CoinifyAPIInvoice(CreatedUpdatedModel):
|
||||||
|
|
||||||
class CoinifyAPICallback(CreatedUpdatedModel):
|
class CoinifyAPICallback(CreatedUpdatedModel):
|
||||||
headers = JSONField()
|
headers = JSONField()
|
||||||
payload = JSONField()
|
payload = JSONField(null=True)
|
||||||
|
body = models.TextField(default='')
|
||||||
order = models.ForeignKey('shop.Order')
|
order = models.ForeignKey('shop.Order')
|
||||||
valid = models.BooleanField(default=False)
|
valid = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
|
|
@ -537,7 +537,7 @@ class CoinifyRedirectView(LoginRequiredMixin, EnsureUserOwnsOrderMixin, EnsureUn
|
||||||
# this coinifyinvoice expired, delete it
|
# this coinifyinvoice expired, delete it
|
||||||
logger.warning("deleting expired coinifyinvoice id %s" % order.coinifyapiinvoice.invoicejson['id'])
|
logger.warning("deleting expired coinifyinvoice id %s" % order.coinifyapiinvoice.invoicejson['id'])
|
||||||
order.coinifyapiinvoice.delete()
|
order.coinifyapiinvoice.delete()
|
||||||
order = self.get_object()
|
order.refresh_from_db()
|
||||||
|
|
||||||
# create a new coinify invoice if needed
|
# create a new coinify invoice if needed
|
||||||
if not hasattr(order, 'coinifyapiinvoice'):
|
if not hasattr(order, 'coinifyapiinvoice'):
|
||||||
|
@ -601,38 +601,52 @@ class CoinifyCallbackView(SingleObjectMixin, View):
|
||||||
if key[:5] == 'HTTP_':
|
if key[:5] == 'HTTP_':
|
||||||
headerdict[key[5:]] = value
|
headerdict[key[5:]] = value
|
||||||
|
|
||||||
|
# parse json
|
||||||
|
try:
|
||||||
|
parsed = json.loads(str(request.body))
|
||||||
|
except JSONDecodeError:
|
||||||
|
parsed = None
|
||||||
|
|
||||||
# save callback to db
|
# save callback to db
|
||||||
callbackobject = CoinifyAPICallback.objects.create(
|
callbackobject = CoinifyAPICallback.objects.create(
|
||||||
headers=headerdict,
|
headers=headerdict,
|
||||||
payload=json.loads(str(request.body)),
|
body=request.body,
|
||||||
|
payload=parsed,
|
||||||
order=self.get_object()
|
order=self.get_object()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# do we have a json body?
|
||||||
|
if not parsed:
|
||||||
|
# no, return an error
|
||||||
|
logger.error("unable to parse JSON body in callback for order %s" % callbackobject.order.id)
|
||||||
|
return HttpResponseBadRequest('unable to parse json')
|
||||||
|
|
||||||
|
# attemt to validate the callbackc
|
||||||
if sdk.validate_callback(request.body, signature):
|
if sdk.validate_callback(request.body, signature):
|
||||||
# mark callback as valid in db
|
# mark callback as valid in db
|
||||||
callbackobject.valid=True
|
callbackobject.valid=True
|
||||||
callbackobject.save()
|
callbackobject.save()
|
||||||
|
|
||||||
# parse json
|
if callbackobject.payload['event'] == 'invoice_state_change' or callbackobject.payload['event'] == 'invoice_manual_resend':
|
||||||
callbackjson = json.loads(str(request.body))
|
|
||||||
if callbackjson['event'] == 'invoice_state_change' or callbackjson['event'] == 'invoice_manual_resend':
|
|
||||||
# find coinify invoice in db
|
# find coinify invoice in db
|
||||||
try:
|
try:
|
||||||
coinifyinvoice = CoinifyAPIInvoice.objects.get(invoicejson__id=callbackjson['data']['id'])
|
coinifyinvoice = CoinifyAPIInvoice.objects.get(invoicejson__id=callbackobject.payload['data']['id'])
|
||||||
except CoinifyAPIInvoice.DoesNotExist:
|
except CoinifyAPIInvoice.DoesNotExist:
|
||||||
logger.error("unable to find CoinifyAPIInvoice with id %s" % callbackjson['data']['id'])
|
logger.error("unable to find CoinifyAPIInvoice with id %s" % callbackobject.payload['data']['id'])
|
||||||
return HttpResponseBadRequest('bad coinifyinvoice id')
|
return HttpResponseBadRequest('bad coinifyinvoice id')
|
||||||
|
|
||||||
# save new coinifyinvoice payload
|
# save new coinifyinvoice payload
|
||||||
coinifyinvoice.invoicejson = callbackjson['data']
|
coinifyinvoice.invoicejson = callbackobject.payload['data']
|
||||||
coinifyinvoice.save()
|
coinifyinvoice.save()
|
||||||
|
|
||||||
# so, is the order paid in full now?
|
# so, is the order paid in full now?
|
||||||
if callbackjson['data']['state'] == 'complete':
|
if callbackobject.payload['data']['state'] == 'complete':
|
||||||
coinifyinvoice.order.mark_as_paid()
|
coinifyinvoice.order.mark_as_paid()
|
||||||
|
|
||||||
# return 200 OK
|
# return 200 OK
|
||||||
return HttpResponse('OK')
|
return HttpResponse('OK')
|
||||||
else:
|
else:
|
||||||
|
logger.error("unsupported callback event %s" % callbackobject.payload['event'])
|
||||||
return HttpResponseBadRequest('unsupported event')
|
return HttpResponseBadRequest('unsupported event')
|
||||||
else:
|
else:
|
||||||
logger.error("invalid coinify callback detected")
|
logger.error("invalid coinify callback detected")
|
||||||
|
|
Loading…
Reference in a new issue