У меня есть простое Django веб-приложение, которое я использую для регистрации личных расходов. Я начал писать новое представление, которое создаст веб-крючок для приема транзакций от моего банка Monzo. Поэтому каждый раз, когда на моем счете появляется новая транзакция, Monzo отправляет JSON с подробностями на указанный мной URL-адрес. И мое приложение должно сохранить эту транзакцию.
Поскольку это все, что происходит, всего лишь один веб-крючок, я решил не использовать каркас Django REST и просто создать представление, которое получает JSON от Банк и сохраняет транзакцию.
Банк повторно отправляет каждую транзакцию два раза. Один раз, когда транзакция впервые попадает на счет, а затем, как правило, второй раз, как только транзакция была рассчитана (выполнена). Так что мой взгляд проверит, существует ли транзакция, и затем либо создаст новую запись, либо обновит существующую.
До сих пор я написал только несколько строк кода и подтвердил, что JSON получен и можно получить в представлении.
Мой вопрос касается проверки. Какую проверку следует выполнить, чтобы убедиться, что JSON не содержит ничего опасного и безопасно для обработки с моей точки зрения?
Пример транзакции, которую банк отправит на мой webhook.
{
"type": "transaction.created",
"data": {
"account_id": "acc_00008gju41AHyfLUzBUk8A",
"amount": -350,
"created": "2015-09-04T14:28:40Z",
"currency": "GBP",
"description": "Ozone Coffee Roasters",
"id": "tx_00008zjky19HyFLAzlUk7t",
"category": "eating_out",
"is_load": false,
"settled": "2015-09-05T14:28:40Z",
"merchant": {
"address": {
"address": "98 Southgate Road",
"city": "London",
"country": "GB",
"latitude": 51.54151,
"longitude": -0.08482400000002599,
"postcode": "N1 3JD",
"region": "Greater London"
},
"created": "2015-08-22T12:20:18Z",
"group_id": "grp_00008zIcpbBOaAr7TTP3sv",
"id": "merch_00008zIcpbAKe8shBxXUtl",
"logo": "https://pbs.twimg.com/profile_images/527043602623389696/68_SgUWJ.jpeg",
"emoji": "?",
"name": "The De Beauvoir Deli Co.",
"category": "eating_out"
}
}
}
Это то, как далеко я продвинулся сегодня утром с моим кодом, так что не далеко, но вы можете видеть, куда я иду с этим.
@csrf_exempt
def index(request):
data = json.loads(request.body)
# Check if transaction already exists and if so then update.
if Transaction.objects.filter(monzo_id=data['data']['id']).exists()
transaction = Transaction.objects.filter(monzo_id=data['data']['id']) # Do I need to check there's only one record?
transaction.data = data
transaction.updated = datetime.datetime.now()
transaction.settled = data['data']['settled']
transaction.save()
else:
transaction = Transaction(
created = datetime.datetime.now(),
monzo_id = data['data']['settled']
.... #More will go here...
)
transaction.save()
#logger.warning(data['type'])
#logger.warning(data['data']['merchant']['address']['city'])
#logger.warning(data['data'])
return render(request, 'template.html', {'content': data}) # Sending data to view just for debugging purposes
Мои модели.py:
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=250, null=False, blank=False)
class Merchant(models.Model):
monzo_id = models.CharField(max_length=250)
name = models.CharField(max_length=250, null=False, blank=False)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
logo = models.URLField(max_length=250, null=True, blank=True) # Should this be URL field?
data = models.TextField(blank = False, null=False)
class Transaction(models.Model):
created = models.DateTimeField(null=False, blank=False)
updated = models.DateTimeField(null=True, blank=True)
account = # To be completed
monzo_id = models.CharField(max_length=250)
datetime = models.DateTimeField(null=False, blank=False)
settled = models.DateTimeField(null=True, blank=True)
amount = models.DecimalField(max_digits=8, decimal_places=2, null=False, blank=False)
currency = models.CharField(max_length=3, null=False, blank=False)
description = models.CharField(max_length=250, null=False, blank=False)
is_load = models.BooleanField(default=False, null=True, blank=True)
merchant_id = models.ForeignKey(Merchant, on_delete=models.PROTECT)
data = models.TextField(blank = False, null=False)