浏览代码

Added XML generation for all transaction methods

master
David Winterbottom 14 年前
父节点
当前提交
c84c0e54cd
共有 2 个文件被更改,包括 244 次插入98 次删除
  1. 84
    64
      oscar/apps/payment/datacash/utils.py
  2. 160
    34
      oscar/apps/payment/tests/datacash.py

+ 84
- 64
oscar/apps/payment/datacash/utils.py 查看文件

@@ -13,78 +13,98 @@ class Gateway(object):
13 13
     def do_request(self, request_xml):
14 14
         pass
15 15
 
16
-    def create_xml_doc(self):
17
-        
18
-        
19
-        return doc
20
-
21
-    def auth(self, card_number, expiry_date, amount, currency, merchant_reference, start_date=None):
16
+    def _initial_transaction(self, method_name, **kwargs):
17
+        """
18
+        Builds the XML for a 'initial' transaction
19
+        """
22 20
         doc = Document()
23
-        req = doc.createElement('Request')
24
-        doc.appendChild(req)
21
+        req = self._create_element(doc, doc, 'Request')
25 22
         
26
-        auth = doc.createElement('Authentication')
27
-        req.appendChild(auth)
28
-        
29
-        client = doc.createElement('client')
30
-        auth.appendChild(client)
31
-        client_text = doc.createTextNode(self._client)
32
-        client.appendChild(client_text)
33
-        
34
-        pw = doc.createElement('password')
35
-        auth.appendChild(pw)
36
-        pw_text = doc.createTextNode(self._password)
37
-        pw.appendChild(pw_text)
23
+        # Authentication
24
+        auth = self._create_element(doc, req, 'Authentication')
25
+        self._create_element(doc, auth, 'client', self._client)
26
+        self._create_element(doc, auth, 'password', self._password)
38 27
             
39
-        txn = doc.createElement('Transaction')
40
-        req.appendChild(txn)
41
-        card_txn = doc.createElement('CardTxn')
42
-        txn.appendChild(card_txn)
43
-        card = doc.createElement('Card')
44
-        card_txn.appendChild(card)
45
-        
46
-        pan = doc.createElement('pan')
47
-        card.appendChild(pan)
48
-        pan_text = doc.createTextNode(card_number)
49
-        pan.appendChild(pan_text)
50
-        
51
-        expiry = doc.createElement('expirydate')
52
-        card.appendChild(expiry)
53
-        expiry_text = doc.createTextNode(expiry_date)
54
-        expiry.appendChild(expiry_text)
55
-        
56
-        if start_date:
57
-            start = doc.createElement('startdate')
58
-            card.appendChild(start)
59
-            start_text = doc.createTextNode(start_date)
60
-            start.appendChild(start_text)
61
-        
62
-        txn_details = doc.createElement('TxnDetails')
63
-        txn.appendChild(txn_details)
64
-        
65
-        merchant = doc.createElement('merchantreference')
66
-        txn_details.appendChild(merchant)
67
-        merchant_text = doc.createTextNode(merchant_reference)
68
-        merchant.appendChild(merchant_text)
69
-        
70
-        amount_ele = doc.createElement('amount')
71
-        txn_details.appendChild(amount_ele)
72
-        amount_text = doc.createTextNode(str(amount))
73
-        amount_ele.appendChild(amount_text)
74
-        amount_ele.setAttribute('currency', currency)
28
+        # Transaction    
29
+        txn = self._create_element(doc, req, 'Transaction') 
75 30
         
76
-        method = doc.createElement('method')
77
-        card_txn.appendChild(method)
78
-        method_text = doc.createTextNode('auth')
79
-        method.appendChild(method_text)
31
+        # CardTxn
32
+        if 'card_number' in kwargs:
33
+            card_txn = self._create_element(doc, txn, 'CardTxn')
34
+            self._create_element(doc, card_txn, 'method', method_name)
35
+            
36
+            card = self._create_element(doc, card_txn, 'Card')
37
+            self._create_element(doc, card, 'pan', kwargs['card_number'])
38
+            self._create_element(doc, card, 'expirydate', kwargs['expiry_date'])
39
+            
40
+            if 'start_date' in kwargs:
41
+                self._create_element(doc, card, 'startdate', kwargs['start_date'])
42
+            
43
+            if 'issue_number' in kwargs:
44
+                self._create_element(doc, card, 'issuenumber', kwargs['issue_number'])
45
+          
46
+            if 'auth_code' in kwargs:
47
+                self._create_element(doc, card, 'authcode', kwargs['auth_code'])
48
+        
49
+        # HistoricTxn
50
+        if 'txn_reference' in kwargs:
51
+            historic_txn = self._create_element(doc, txn, 'HistoricTxn')
52
+            self._create_element(doc, historic_txn, 'reference', kwargs['txn_reference'])
53
+            self._create_element(doc, historic_txn, 'method', method_name)
54
+            if 'auth_code' in kwargs:
55
+                self._create_element(doc, historic_txn, 'authcode', kwargs['auth_code'])
56
+        
57
+        # TxnDetails
58
+        if 'amount' in kwargs:
59
+            txn_details = self._create_element(doc, txn, 'TxnDetails')
60
+            if 'merchant_reference' in kwargs:
61
+                self._create_element(doc, txn_details, 'merchantreference', kwargs['merchant_reference'])
62
+            self._create_element(doc, txn_details, 'amount', str(kwargs['amount']), {'currency': kwargs['currency']})
80 63
         
81 64
         self.do_request(doc.toxml())
82 65
 
83
-    def pre(self, request):
84
-        pass
66
+    def _create_element(self, doc, parent, tag, value=None, attributes=None):
67
+        ele = doc.createElement(tag)
68
+        parent.appendChild(ele)
69
+        if value:
70
+            text = doc.createTextNode(value)
71
+            ele.appendChild(text)
72
+        if attributes:
73
+            [ele.setAttribute(k, v) for k,v in attributes.items()]
74
+        return ele
85 75
 
86
-    def refund(self, request):
87
-        pass
76
+    def auth(self, **kwargs):
77
+        """
78
+        Performs an 'auth' request, which is to debit the money immediately
79
+        as a one-off transaction.
80
+        
81
+        Note that currency should be ISO 4217 Alphabetic format.
82
+        """ 
83
+        return self._initial_transaction('auth', **kwargs)
84
+        
85
+    def pre(self, **kwargs):
86
+        """
87
+        Performs an 'pre' request, which is to ring-fence the requested money
88
+        so it can be fulfilled at a later time.
89
+        """ 
90
+        return self._initial_transaction('pre', **kwargs)
91
+
92
+    def refund(self, **kwargs):
93
+        return self._initial_transaction('refund', **kwargs)
94
+        
95
+    def erp(self, **kwargs):
96
+        return self._initial_transaction('erp', **kwargs)
97
+        
98
+    # "Historic" transaction types    
99
+        
100
+    def cancel(self, txn_reference): 
101
+        return self._initial_transaction('cancel', txn_reference=txn_reference)
102
+    
103
+    def fulfil(self, **kwargs):
104
+        return self._initial_transaction('fulfil', **kwargs) 
105
+    
106
+    def txn_refund(self, **kwargs):
107
+        return self._initial_transaction('txn_refund', **kwargs) 
88 108
 
89 109
 
90 110
 class Adapter(object):

+ 160
- 34
oscar/apps/payment/tests/datacash.py 查看文件

@@ -7,9 +7,9 @@ from django.test import TestCase
7 7
 from oscar.apps.payment.datacash.utils import Gateway
8 8
 
9 9
 
10
-class AuthTransactionTests(TestCase):
10
+class TransactionMixin(object):
11 11
     
12
-    def setUp(self):
12
+    def init_gateway(self):
13 13
         self.gateway = Gateway(client="DUMMY", password="123456")
14 14
         self.transport = mock.Mock()
15 15
         self.gateway.do_request = self.transport
@@ -22,6 +22,12 @@ class AuthTransactionTests(TestCase):
22 22
             self.assertEquals(value, tag.firstChild.data)
23 23
         except IndexError:
24 24
             self.fail("Tag '%s' not found\n%s" % (tag_name, request_xml))
25
+    
26
+    def make_request(self, **kwargs):
27
+        """
28
+        Needs to be implemented by subclass.
29
+        """
30
+        pass
25 31
             
26 32
     def assertXmlTagAttributeValue(self, tag_name, attribute, value):
27 33
         request_xml = self.transport.call_args[0][0]
@@ -32,51 +38,171 @@ class AuthTransactionTests(TestCase):
32 38
         except IndexError:
33 39
             self.fail("Tag '%s' not found\n%s" % (tagName, request_xml))
34 40
     
35
-    def make_auth_request(self):
36
-        self.gateway.auth(card_number='1000010000000007', 
37
-                          start_date='01/10',
38
-                          expiry_date='01/12',
39
-                          issue_number='03',
40
-                          merchant_reference='123123',
41
-                          currency='GBP',
42
-                          amount=D('12.99'))
43
-    
44
-    def test_auth_includes_credentials(self):
45
-        self.make_auth_request()
41
+    def test_request_includes_credentials(self):
42
+        self.make_request()
46 43
         self.assertTrue(self.transport.called)
47 44
         self.assertXmlTagValue('client', 'DUMMY')
48 45
         self.assertXmlTagValue('password', '123456')
46
+
47
+
48
+class InitialTransactionMixin(TransactionMixin):
49
+    
50
+    def test_request_includes_merchant_reference(self):   
51
+        self.make_request()
52
+        self.assertXmlTagValue('merchantreference', '123123')
53
+        
54
+    def test_request_includes_amount_and_currency(self):   
55
+        self.make_request()
56
+        self.assertXmlTagValue('amount', '12.99')
57
+        self.assertXmlTagAttributeValue('amount', 'currency', 'GBP')
49 58
         
50
-    def test_auth_includes_card_details(self):   
51
-        self.make_auth_request()
59
+    def test_request_can_include_authcode(self):
60
+        self.make_request(auth_code='334455')    
61
+        self.assertXmlTagValue('authcode', '334455')
62
+    
63
+    def test_request_includes_card_details(self):   
64
+        self.make_request(start_date='01/10')
52 65
         self.assertXmlTagValue('pan', '1000010000000007')
53 66
         self.assertXmlTagValue('startdate', '01/10')
54 67
         self.assertXmlTagValue('expirydate', '01/12')
55 68
         
56
-    def test_auth_includes_merchant_reference(self):   
57
-        self.make_auth_request()
58
-        self.assertXmlTagValue('merchantreference', '123123')
69
+    def test_request_can_include_issue_number(self):
70
+        self.make_request(issue_number='03')    
71
+        self.assertXmlTagValue('issuenumber', '03')    
59 72
         
60
-    def test_auth_includes_amount_and_currency(self):   
61
-        self.make_auth_request()
62
-        self.assertXmlTagValue('amount', '12.99')
63
-        self.assertXmlTagAttributeValue('amount', 'currency', 'GBP')
73
+    def test_request_can_include_authcode(self):
74
+        self.make_request(auth_code='334455')    
75
+        self.assertXmlTagValue('authcode', '334455')
76
+
77
+
78
+class AuthTransactionTests(TestCase, InitialTransactionMixin):
79
+    
80
+    def setUp(self):
81
+        self.init_gateway()
82
+    
83
+    def make_request(self, **kwargs):
84
+        self.gateway.auth(card_number='1000010000000007', 
85
+                          expiry_date='01/12',
86
+                          merchant_reference='123123',
87
+                          currency='GBP',
88
+                          amount=D('12.99'),
89
+                          **kwargs)
64 90
         
65
-    def test_auth_includes_method(self):
66
-        self.make_auth_request()    
91
+    def test_request_includes_method(self):
92
+        self.make_request()    
67 93
         self.assertXmlTagValue('method', 'auth')
68 94
     
69
-
70
-class HistoricTransactionTests(TestCase):
95
+    
96
+class PreTransactionTests(TestCase, InitialTransactionMixin):
71 97
     
72 98
     def setUp(self):
73
-        self.gateway = Gateway(client="DUMMY", password="123456")
74
-
75
-    def test_cancel(self):
76
-        self.gateway.auth
99
+        self.init_gateway()
100
+    
101
+    def make_request(self, **kwargs):
102
+        self.gateway.pre(card_number='1000010000000007', 
103
+                         expiry_date='01/12',
104
+                         merchant_reference='123123',
105
+                         currency='GBP',
106
+                         amount=D('12.99'),
107
+                         **kwargs)    
77 108
         
78
-    def test_fulfil(self):
79
-        pass
109
+    def test_request_includes_method(self):
110
+        self.make_request()    
111
+        self.assertXmlTagValue('method', 'pre')
112
+        
113
+        
114
+class RefundTransactionTests(TestCase, InitialTransactionMixin):
80 115
     
81
-    def test_txn_refund(self):
82
-        pass
116
+    def setUp(self):
117
+        self.init_gateway()
118
+    
119
+    def make_request(self, **kwargs):
120
+        self.gateway.refund(card_number='1000010000000007', 
121
+                            expiry_date='01/12',
122
+                            merchant_reference='123123',
123
+                            currency='GBP',
124
+                            amount=D('12.99'),
125
+                            **kwargs)    
126
+        
127
+    def test_request_includes_method(self):
128
+        self.make_request()    
129
+        self.assertXmlTagValue('method', 'refund')
130
+    
131
+    
132
+class ErpTransactionTests(TestCase, InitialTransactionMixin):
133
+    
134
+    def setUp(self):
135
+        self.init_gateway()
136
+    
137
+    def make_request(self, **kwargs):
138
+        self.gateway.erp(card_number='1000010000000007', 
139
+                         expiry_date='01/12',
140
+                         merchant_reference='123123',
141
+                         currency='GBP',
142
+                         amount=D('12.99'),
143
+                         **kwargs)    
144
+        
145
+    def test_request_includes_method(self):
146
+        self.make_request()    
147
+        self.assertXmlTagValue('method', 'erp')    
148
+    
149
+    
150
+class CancelTransactionTests(TestCase, TransactionMixin):
151
+    
152
+    def setUp(self):
153
+        self.init_gateway()
154
+    
155
+    def make_request(self, **kwargs):
156
+        self.gateway.cancel(txn_reference='12312333444')
157
+        
158
+    def test_request_includes_method(self):
159
+        self.make_request()    
160
+        self.assertXmlTagValue('method', 'cancel') 
161
+        
162
+    def test_request_includes_reference(self):
163
+        self.make_request()    
164
+        self.assertXmlTagValue('reference', '12312333444') 
165
+        
166
+        
167
+class FulfilTransactionTests(TestCase, TransactionMixin):
168
+    
169
+    def setUp(self):
170
+        self.init_gateway()
171
+    
172
+    def make_request(self, **kwargs):
173
+        self.gateway.fulfil(currency='GBP',
174
+                            amount=D('12.99'),
175
+                            txn_reference='12312333444',
176
+                            auth_code='123444')
177
+        
178
+    def test_request_includes_method(self):
179
+        self.make_request()    
180
+        self.assertXmlTagValue('method', 'fulfil')   
181
+        
182
+    def test_request_includes_reference(self):
183
+        self.make_request()    
184
+        self.assertXmlTagValue('reference', '12312333444') 
185
+        
186
+    def test_request_includes_authcode(self):
187
+        self.make_request()    
188
+        self.assertXmlTagValue('authcode', '123444') 
189
+        
190
+        
191
+class TxnRefundTransactionTests(TestCase, TransactionMixin):
192
+    
193
+    def setUp(self):
194
+        self.init_gateway()
195
+    
196
+    def make_request(self, **kwargs):
197
+        self.gateway.txn_refund(currency='GBP',
198
+                                amount=D('12.99'),
199
+                                txn_reference='12312333444')
200
+        
201
+    def test_request_includes_method(self):
202
+        self.make_request()    
203
+        self.assertXmlTagValue('method', 'txn_refund')   
204
+        
205
+    def test_request_includes_reference(self):
206
+        self.make_request()    
207
+        self.assertXmlTagValue('reference', '12312333444') 
208
+    

正在加载...
取消
保存