1
|
|
|
''' |
2
|
|
|
Created on Nov 1, 2015 |
3
|
|
|
|
4
|
|
|
@author: krgupta |
5
|
|
|
''' |
6
|
|
|
import abc |
7
|
|
|
import logging |
8
|
|
|
import xml.dom.minidom |
9
|
|
|
from pip._vendor import requests |
10
|
|
|
from _pyio import __metaclass__ |
11
|
|
|
|
12
|
|
|
from authorizenet.constants import constants |
13
|
|
|
from authorizenet import apicontractsv1 |
14
|
|
|
from authorizenet import utility |
15
|
|
|
''' |
16
|
|
|
from authorizenet.apicontractsv1 import merchantAuthenticationType |
17
|
|
|
from authorizenet.apicontractsv1 import ANetApiRequest |
18
|
|
|
from authorizenet.apicontractsv1 import ANetApiResponse |
19
|
|
|
''' |
20
|
|
|
class APIOperationBaseInterface(object): |
21
|
|
|
|
22
|
|
|
__metaclass__ = abc.ABCMeta |
23
|
|
|
|
24
|
|
|
@abc.abstractmethod |
25
|
|
|
def execute(self): |
26
|
|
|
''' |
27
|
|
|
Makes a http-post call. |
28
|
|
|
Uses request xml and response class type to check that the response was of correct type |
29
|
|
|
''' |
30
|
|
|
pass |
31
|
|
|
|
32
|
|
|
@abc.abstractmethod |
33
|
|
|
def getresponseclass(self): |
34
|
|
|
''' Returns the response class ''' |
35
|
|
|
pass |
36
|
|
|
|
37
|
|
|
@abc.abstractmethod |
38
|
|
|
def getrequesttype(self): |
39
|
|
|
''' Returns the request class ''' |
40
|
|
|
pass |
41
|
|
|
|
42
|
|
|
@abc.abstractmethod |
43
|
|
|
def getresponse(self): |
44
|
|
|
''' Returns the de-serialized response''' |
45
|
|
|
pass |
46
|
|
|
|
47
|
|
|
@abc.abstractmethod |
48
|
|
|
def getresultcode(self): |
49
|
|
|
''' Returns the result code from the response ''' |
50
|
|
|
pass |
51
|
|
|
|
52
|
|
|
@abc.abstractmethod |
53
|
|
|
def getmessagetype(self): |
54
|
|
|
''' Returns the message type enum from the response ''' |
55
|
|
|
pass |
56
|
|
|
|
57
|
|
|
@abc.abstractmethod |
58
|
|
|
def afterexecute(self): |
59
|
|
|
'''Returns the message received from binding after processing request''' |
60
|
|
|
pass |
61
|
|
|
|
62
|
|
|
@abc.abstractmethod |
63
|
|
|
def beforeexecute(self): |
64
|
|
|
'''TODO''' |
65
|
|
|
pass |
66
|
|
|
|
67
|
|
|
class APIOperationBase(APIOperationBaseInterface): |
68
|
|
|
__metaclass__ = abc.ABCMeta |
69
|
|
|
|
70
|
|
|
__initialized = False |
71
|
|
|
__merchantauthentication = "null" |
72
|
|
|
__environment = "null" |
73
|
|
|
|
74
|
|
|
@staticmethod |
75
|
|
|
def __classinitialized(): |
76
|
|
|
return APIOperationBase.__initialized |
77
|
|
|
|
78
|
|
|
@abc.abstractmethod |
79
|
|
|
def validaterequest(self): |
80
|
|
|
return |
81
|
|
|
|
82
|
|
|
def validate(self): |
83
|
|
|
anetapirequest = self._getrequest() |
84
|
|
|
self.validateandsetmerchantauthentication() |
85
|
|
|
self.validaterequest() |
86
|
|
|
|
87
|
|
|
return |
88
|
|
|
|
89
|
|
|
def _getrequest(self): #protected method |
90
|
|
|
return self._request |
91
|
|
|
|
92
|
|
|
def buildrequest(self): |
93
|
|
|
logging.debug('building request..') |
94
|
|
|
|
95
|
|
|
xmlRequest = self._request.toxml(encoding=constants.xml_encoding, element_name=self.getrequesttype()) |
96
|
|
|
#remove namespaces that toxml() generates |
97
|
|
|
xmlRequest = xmlRequest.replace(constants.nsNamespace1, '') |
98
|
|
|
xmlRequest = xmlRequest.replace(constants.nsNamespace2, '') |
99
|
|
|
|
100
|
|
|
return xmlRequest |
101
|
|
|
|
102
|
|
|
def getprettyxmlrequest(self): |
103
|
|
|
xmlRequest = self.buildrequest() |
104
|
|
|
requestDom = xml.dom.minidom.parseString(xmlRequest) |
105
|
|
|
logging.debug('Request is: %s' % requestDom.toprettyxml()) |
106
|
|
|
|
107
|
|
|
return requestDom |
108
|
|
|
|
109
|
|
|
def execute(self): |
110
|
|
|
|
111
|
|
|
self.endpoint = APIOperationBase.__environment |
112
|
|
|
|
113
|
|
|
logging.debug('Executing http post to url: %s', self.endpoint) |
114
|
|
|
|
115
|
|
|
self.beforeexecute() |
116
|
|
|
|
117
|
|
|
proxyDictionary = {'http' : utility.helper.getproperty("http"), |
118
|
|
|
'https' : utility.helper.getproperty("https"), |
119
|
|
|
'ftp' : utility.helper.getproperty("ftp")} |
120
|
|
|
|
121
|
|
|
#requests is http request |
122
|
|
|
|
123
|
|
|
try: |
124
|
|
|
xmlRequest = self.buildrequest() |
125
|
|
|
self._httpResponse = requests.post(self.endpoint, data=xmlRequest, headers=constants.headers, proxies=proxyDictionary) |
126
|
|
|
except Exception as httpException: |
127
|
|
|
logging.error( 'Error retrieving http response from: %s for request: %s', self.endpoint, self.getprettyxmlrequest()) |
128
|
|
|
logging.error( 'Exception: %s, %s', type(httpException), httpException.args ) |
129
|
|
|
|
130
|
|
|
|
131
|
|
|
if self._httpResponse: |
132
|
|
|
#encoding of response should be changed to retrieve text of response |
133
|
|
|
self._httpResponse.encoding = constants.response_encoding |
134
|
|
|
self._httpResponse = self._httpResponse.text[3:] #strip BOM |
135
|
|
|
self.afterexecute() |
136
|
|
|
try: |
137
|
|
|
self._response = apicontractsv1.CreateFromDocument(self._httpResponse) |
138
|
|
|
except Exception as createfromdocumentexception: |
139
|
|
|
logging.error( 'Create Document Exception: %s, %s', type(createfromdocumentexception), createfromdocumentexception.args ) |
140
|
|
|
else: |
141
|
|
|
if type(self.getresponseclass()) == type(self._response): |
142
|
|
|
if self._response.messages.resultCode == "Error": |
143
|
|
|
print "Response error" |
144
|
|
|
|
145
|
|
|
domResponse = xml.dom.minidom.parseString(self._httpResponse) |
146
|
|
|
logging.debug('Received response: %s' % domResponse.toprettyxml()) |
147
|
|
|
else: |
148
|
|
|
#Need to handle ErrorResponse |
149
|
|
|
logging.debug('Error retrieving response for request: %s' % self._request) |
150
|
|
|
else: |
151
|
|
|
print "Did not receive http response" |
152
|
|
|
return |
153
|
|
|
|
154
|
|
|
def getresponse(self): |
155
|
|
|
return self._response |
156
|
|
|
|
157
|
|
|
def getresultcode(self): |
158
|
|
|
resultcode = 'null' |
159
|
|
|
if self._response: |
160
|
|
|
resultcode = self._response.resultCode |
161
|
|
|
return resultcode |
162
|
|
|
|
163
|
|
|
def getmessagetype(self): |
164
|
|
|
message = 'null' |
165
|
|
|
if self._response: |
166
|
|
|
message = self._response.message |
167
|
|
|
return message |
168
|
|
|
|
169
|
|
|
def afterexecute(self ): |
170
|
|
|
return |
171
|
|
|
|
172
|
|
|
def beforeexecute(self): |
173
|
|
|
return |
174
|
|
|
|
175
|
|
|
@staticmethod |
176
|
|
|
def getmerchantauthentication(self): |
177
|
|
|
return self.__merchantauthentication |
178
|
|
|
|
179
|
|
|
@staticmethod |
180
|
|
|
def setmerchantauthentication(merchantauthentication): |
181
|
|
|
APIOperationBase.__merchantauthentication = merchantauthentication |
182
|
|
|
return |
183
|
|
|
|
184
|
|
|
def validateandsetmerchantauthentication(self): |
185
|
|
|
anetapirequest = apicontractsv1.ANetApiRequest() |
186
|
|
|
if (anetapirequest.merchantAuthentication == "null"): |
187
|
|
|
if (self.getmerchantauthentication() != "null"): |
188
|
|
|
anetapirequest.merchantAuthentication = self.getmerchantauthentication() |
189
|
|
|
else: |
190
|
|
|
raise ValueError('Merchant Authentication can not be null') |
191
|
|
|
return |
192
|
|
|
|
193
|
|
|
@staticmethod |
194
|
|
|
def getenvironment(self): |
195
|
|
|
return APIOperationBase.__environment |
196
|
|
|
|
197
|
|
|
|
198
|
|
|
@staticmethod |
199
|
|
|
def setenvironment(userenvironment): |
200
|
|
|
APIOperationBase.__environment = userenvironment |
201
|
|
|
return |
202
|
|
|
|
203
|
|
|
def __init__(self, apiRequest): |
204
|
|
|
self._httpResponse = None |
205
|
|
|
self._request = None |
206
|
|
|
self._response = None |
207
|
|
|
|
208
|
|
|
if None == apiRequest: |
209
|
|
|
raise ValueError('Input request cannot be null') |
210
|
|
|
|
211
|
|
|
self._request = apiRequest |
212
|
|
|
__merchantauthentication = apicontractsv1.merchantAuthenticationType() |
213
|
|
|
APIOperationBase.__environment = constants.SANDBOX_TESTMODE |
214
|
|
|
|
215
|
|
|
APIOperationBase.setmerchantauthentication(__merchantauthentication) |
216
|
|
|
|
217
|
|
|
if ( False == APIOperationBase.__classinitialized()): |
218
|
|
|
loggingfilename = utility.helper.getproperty(constants.propertiesloggingfilename) |
219
|
|
|
logginglevel = utility.helper.getproperty(constants.propertiesexecutionlogginglevel) |
220
|
|
|
|
221
|
|
|
if (None == loggingfilename): |
222
|
|
|
loggingfilename = constants.defaultLogFileName |
223
|
|
|
if (None == logginglevel): |
224
|
|
|
logginglevel = constants.defaultLoggingLevel |
225
|
|
|
|
226
|
|
|
logging.basicConfig(filename=loggingfilename, level=logginglevel, format=constants.defaultlogformat) |
227
|
|
|
__initialized = True |
228
|
|
|
|
229
|
|
|
self.validate() |
230
|
|
|
|
231
|
|
|
return |
232
|
|
|
|