Completed
Push — master ( 894137...9ad265 )
by
unknown
02:31 queued 01:13
created

APIOperationBase   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 185
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
wmc 33
c 5
b 0
f 0
dl 0
loc 185
rs 9.3999

19 Methods

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