Skip to content
This repository has been archived by the owner on Jun 15, 2019. It is now read-only.

Commit

Permalink
Add support for form-urlencoded payloads
Browse files Browse the repository at this point in the history
  • Loading branch information
codeinthehole committed Jul 31, 2013
1 parent 6ab2c90 commit 21a84be
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 13 deletions.
36 changes: 26 additions & 10 deletions datacash/models.py
@@ -1,5 +1,6 @@
import re
from xml.dom.minidom import parseString
import urlparse

from django.db import models

Expand Down Expand Up @@ -106,7 +107,7 @@ class Meta:
ordering = ('-date_created',)

@classmethod
def create_from_xml(cls, payload):
def create_from_xml(cls, xml_string):
"""
Create a fraud response instance from an XML payload
"""
Expand All @@ -120,16 +121,31 @@ def tag_text(doc, tag_name):
return ele.firstChild.data
return ''

doc = parseString(payload)
doc = parseString(xml_string)
return cls.create_from_payload(xml_string, doc, tag_text)

@classmethod
def create_from_querystring(cls, query):
"""
Create a fraud response instance from a querystring payload
"""
def extract(data, key):
return data.get(key, [""])[0]

data = urlparse.parse_qs(query)
return cls.create_from_payload(query, data, extract)

@classmethod
def create_from_payload(cls, raw, payload, extract_fn):
response = cls.objects.create(
aggregator_identifier=tag_text(doc, 'aggregator_identifier'),
merchant_identifier=tag_text(doc, 'merchant_identifier'),
merchant_order_ref=tag_text(doc, 'merchant_order_ref'),
t3m_id=tag_text(doc, 't3m_id'),
score=int(tag_text(doc, 'score')),
recommendation=int(tag_text(doc, 'recommendation')),
message_digest=tag_text(doc, 'message_digest'),
raw_response=payload)
aggregator_identifier=extract_fn(payload, 'aggregator_identifier'),
merchant_identifier=extract_fn(payload, 'merchant_identifier'),
merchant_order_ref=extract_fn(payload, 'merchant_order_ref'),
t3m_id=extract_fn(payload, 't3m_id'),
score=int(extract_fn(payload, 'score')),
recommendation=int(extract_fn(payload, 'recommendation')),
message_digest=extract_fn(payload, 'message_digest'),
raw_response=raw)

# Raise signal so other processes can update orders based on this fraud
# response.
Expand Down
6 changes: 5 additions & 1 deletion datacash/the3rdman/views.py
Expand Up @@ -16,11 +16,15 @@ class CallbackView(generic.View):
"""

def post(self, request, *args, **kwargs):
content_type = request.META['CONTENT_TYPE']
try:
# Create a fraud response object. Other processes should listen
# to the post create signal in order to hook fraud processing into
# this order pipeline.
response = models.FraudResponse.create_from_xml(request.body)
if content_type == 'application/x-www-form-urlencoded':
response = models.FraudResponse.create_from_querystring(request.body)
else:
response = models.FraudResponse.create_from_xml(request.body)
except Exception, e:
logger.error("Error raised handling response:\n%s", request.body)
logger.exception(e)
Expand Down
15 changes: 13 additions & 2 deletions tests/the3rdman_model_tests.py
Expand Up @@ -2,7 +2,7 @@

from datacash import models

RESPONSE = """<?xml version="1.0"?>
XML_RESPONSE = """<?xml version="1.0"?>
<RealTimeResponse xmlns="T3MCallback">
<aggregator_identifier/>
<merchant_identifier>5567</merchant_identifier>
Expand All @@ -13,11 +13,15 @@
<message_digest></message_digest>
</RealTimeResponse>"""

QUERY_RESPONSE = "aggregator_identifier=&merchant_identifier=32195&merchant_order_ref=100032&t3m_id=1701673332&score=114&recommendation=2&message_digest=87d81ea49035fe2f8d59ceea3f16b1f43744701c"


def stub_response(score=0, recommendation=0):
return RESPONSE % {
return XML_RESPONSE % {
'score': score,
'recommendation': recommendation}


class TestFraudResponseModel(TestCase):

def test_recognises_release_response(self):
Expand All @@ -34,3 +38,10 @@ def test_recognises_reject_response(self):
xml = stub_response(recommendation=2)
response = models.FraudResponse.create_from_xml(xml)
self.assertTrue(response.rejected)


class TestFormURLEncodedResponse(TestCase):

def test_for_smoke(self):
response = models.FraudResponse.create_from_querystring(QUERY_RESPONSE)
self.assertTrue(response.rejected)

0 comments on commit 21a84be

Please sign in to comment.