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