-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtransaction.py
152 lines (112 loc) · 4.72 KB
/
transaction.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import json
import ssl
import urllib.request
class Transaction:
"""A transaction is returned with completion or failure info"""
OK = "Ok"
FAILURE = 'Failure'
APPROVED = 'Approved'
CODE = 'code'
code_ref_url = 'https://developer.authorize.net/api/'\
'reference/dist/json/responseCodes.json'
def __init__(self, response):
"""Pass the response to initialize the Transaction object"""
super().__init__()
# default SSL used b/c the certificate is only 128 bit, which throws
# this exception if relying on the Authorize.net certificate
# urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY
# _FAILED] certificate verify failed (_ssl.c:748)>
# with Python 3.6.5
ssl._create_default_https_context = ssl._create_unverified_context
with urllib.request.urlopen(self.code_ref_url) as url:
data = json.loads(url.read().decode())
approval_dict = list(filter(
lambda x: x['code'] == '1', data))
if response is not None:
self.transaction_response = TransactionResponse(response)
response_code = self.transaction_response.response_code
self.approval_code = int(approval_dict[0][self.CODE])
if response_code == self.approval_code:
self.result = self.APPROVED
else:
self.result = self.FAILURE
print('Declined with response code ' + str(response_code))
print('result is', self.result)
else:
self.error_code = None
self.error_text = 'Null response from Authorize.net'
class TransactionResponse:
"""TransactionResponse is a more details view of a Transaction.
Although the details are related to a Transaction, a design decision
was made to follow the organization of the Authorize.net API,
even though it could be improved"""
# fields are the expected attributes on the response object passed
# to __init__
fields = {
'responseCode': 'response_code',
'authCode': 'auth_code',
'avsResultCode': 'avs_result_code',
'cvvResultCode': 'cvv_result_code',
'cavv_result_code': 'cavv_result_code',
'transId': 'transaction_id',
'refTransID': 'reference_transaction_id',
'transHash': 'transaction_hash',
'testRequest': 'test_request',
'accountNumber': 'account_number',
'accountType': 'account_type',
'transHashSha2': 'transaction_hash_sha2',
}
def __init__(self, response):
"""Pass the response to initialize the TransactionResponse object"""
super().__init__()
tr = response.transactionResponse
for k, v in self.fields.items():
if hasattr(tr, k):
setattr(self, v, getattr(tr, k))
if hasattr(tr, 'errors'):
self.errors = [Error(an_error) for an_error in tr.errors]
else:
self.errors = None
if hasattr(tr, 'profile'):
self.profile = Profile(response)
else:
self.profile = None
class Error:
"""The organization of the HTML response for errors is messy. The Error
class organizes the information to make it easier to manipulate"""
# fields are the expected attributes on the response object passed
# to __init__
fields = {
'errorCode': 'error_code',
'errorText': 'error_text'
}
def __init__(self, an_error):
"""Convert the response into a defined object"""
for k, v in self.fields.items():
if hasattr(an_error, k):
setattr(self, v, getattr(an_error, k))
class Profile:
"""Pass a resonse variable to pre-load the
customer and payment profile info related to a Transaction"""
# fields are the expected attributes on the response object passed
# to __init__
fields = {
'customerProfileId': 'customer_profile_id',
'customer_payment_profile_id': 'customer_payment_profile_id',
'avsResultCode': 'avs_result_code',
'cvvResultCode': 'cvv_result_code',
'cavv_result_code': 'cavv_result_code',
'transId': 'transaction_id',
'refTransID': 'reference_transaction_id',
'transHash': 'transaction_hash',
'testRequest': 'test_request',
'accountNumber': 'account_number',
'accountType': 'account_type',
'transHashSha2': 'transaction_hash_sha2',
}
def __init__(self, response):
"""Convert response properties into properties on this object"""
profile = response.transactionResponse.profile
for k, v in self.fields.items():
if hasattr(profile, k):
setattr(self, v, getattr(profile, k))