예제 #1
0
def process_raw_adyen_notification(raw, POST):
	# Process a single raw Adyen notification. Must *not* be called in
	# a transactional context, as it manages it's own.

	# Now open a transaction for actually processing what we get
	with transaction.commit_on_success():
		# Set it to confirmed - if we were unable to process the RAW one,
		# this will be rolled back by the transaction, and that's the only
		# thing that htis flag means. Anything else is handled by the
		# regular notification.
		raw.confirmed = True
		raw.save()

		# Have we already seen this notification before?
		notlist = list(Notification.objects.filter(pspReference=POST['pspReference'], eventCode=POST['eventCode'], merchantAccountCode=POST['merchantAccountCode']))
		if len(notlist) == 1:
			# Found it before!
			notification = notlist[0]

			# According to Adyen integration manual, the only case when
			# we need to process this is when it goes from
			# success=False -> success=True.
			if not notification.success and POST['success'] == 'true':
				# We'll implement this one later, but for now trigger a
				# manual email so we don't loose things.
				send_simple_mail(settings.INVOICE_SENDER_EMAIL,
								 settings.ADYEN_NOTIFICATION_RECEIVER,
								 'Received adyen notification type %s that went from failure to success!' % notification.eventCode,
							 "An Adyen notification that went from failure to success has been received.\nThe system doesn't know how to handle this yet, so you'll need to go take a manual look!\n",
							 )
				AdyenLog(pspReference=notification.pspReference, message='Received success->fail notification of type %s, unhandled' % notification.eventCode, error=True).save()
			else:
				AdyenLog(pspReference=notification.pspReference, message='Received duplicate %s notification' % notification.eventCode).save()
				# Don't actually do any processing here either
		else:
			# Not found, so create
			notification = Notification()
			notification.rawnotification = raw
			notification.eventDate = POST['eventDate']
			notification.eventCode = POST['eventCode']
			notification.live = (POST['live'] == 'true')
			notification.success = (POST['success'] == 'true')
			notification.pspReference = POST['pspReference']
			notification.originalReference = POST['originalReference']
			notification.merchantReference = POST['merchantReference']
			notification.merchantAccountCode = POST['merchantAccountCode']
			notification.paymentMethod = POST['paymentMethod']
			notification.reason = POST['reason']
			try:
				notification.amount = int(POST['value'])/100 # We only deal in whole euros
			except:
				# Invalid amount, set to -1
				AdyenLog(pspReference=notification.pspReference, message='Received invalid amount %s' % POST['value'], error=True).save()
				notification.amount = -1
			if POST['currency'] != settings.CURRENCY_ABBREV:
				# For some reason, *report* notifications specifically get delivered with
				# a hard-coded value of EUR, even though they have no currency inside them.
				if notification.eventCode != 'REPORT_AVAILABLE':
					AdyenLog(pspReference=notification.pspReference, message='Received invalid currency %s' % POST['currency'], error=True).save()
					notification.amount = -2

			# Save this unconfirmed for now
			notification.save()

			# Process this notification, which includes flagging invoices
			# as paid.
			process_one_notification(notification)

			# Log the fact that we received it
			AdyenLog(pspReference=notification.pspReference, message='Processed %s notification for %s' % (notification.eventCode, notification.merchantReference)).save()

	# Return that we've consumed the report outside the transaction, in
	# the unlikely event that the COMMIT is what failed
	return True