1515 AdyenInvalidRequestError ,
1616 AdyenAPIInvalidFormat ,
1717 AdyenAPIInvalidAmount ,
18- )
18+ AdyenEndpointInvalidFormat )
1919from . import settings
2020
2121
@@ -66,15 +66,16 @@ class AdyenClient(object):
6666 hmac (str, optional): Hmac key that is used for signature calculation.
6767 """
6868
69- def __init__ (self , username = None , password = None ,
69+ def __init__ (self , username = None , password = None , xapikey = None ,
7070 review_payout_username = None , review_payout_password = None ,
7171 store_payout_username = None , store_payout_password = None ,
7272 platform = "test" , merchant_account = None ,
7373 merchant_specific_url = None , skin_code = None ,
7474 hmac = None , app_name = None ,
75- http_force = None ):
75+ http_force = None , live_endpoint_prefix = None ):
7676 self .username = username
7777 self .password = password
78+ self .xapikey = xapikey
7879 self .review_payout_username = review_payout_username
7980 self .review_payout_password = review_payout_password
8081 self .store_payout_username = store_payout_username
@@ -86,10 +87,11 @@ def __init__(self, username=None, password=None,
8687 self .skin_code = skin_code
8788 self .psp_list = []
8889 self .app_name = app_name
89- self .LIB_VERSION = "1.3 .0"
90+ self .LIB_VERSION = "1.4 .0"
9091 self .USER_AGENT_SUFFIX = "adyen-python-api-library/"
9192 self .http_init = False
9293 self .http_force = http_force
94+ self .live_endpoint_prefix = live_endpoint_prefix
9395
9496 def _determine_api_url (self , platform , service , action ):
9597 """This returns the Adyen API endpoint based on the provided platform,
@@ -103,8 +105,10 @@ def _determine_api_url(self, platform, service, action):
103105 base_uri = settings .BASE_PAL_URL .format (platform )
104106 if service == "Recurring" :
105107 api_version = settings .API_RECURRING_VERSION
108+ elif service == "Payout" :
109+ api_version = settings .API_PAYOUT_VERSION
106110 else :
107- api_version = settings .API_VERSION
111+ api_version = settings .API_PAYMENT_VERSION
108112 return '/' .join ([base_uri , service , api_version , action ])
109113
110114 def _determine_hpp_url (self , platform , action ):
@@ -121,6 +125,34 @@ def _determine_hpp_url(self, platform, action):
121125 result = '/' .join ([base_uri , service ])
122126 return result
123127
128+ def _determine_checkout_url (self , platform , action ):
129+ """This returns the Adyen API endpoint based on the provided platform,
130+ service and action.
131+
132+ Args:
133+ platform (str): Adyen platform, ie 'live' or 'test'.
134+ action (str): the API action to perform.
135+ """
136+ api_version = settings .API_CHECKOUT_VERSION
137+ if platform == "test" :
138+ base_uri = settings .ENDPOINT_CHECKOUT_TEST
139+ elif self .live_endpoint_prefix is not None and platform == "live" :
140+ base_uri = settings .ENDPOINT_CHECKOUT_LIVE_SUFFIX .format (
141+ self .live_endpoint_prefix )
142+ elif self .live_endpoint_prefix is None and platform == "live" :
143+ errorstring = """Please set your live suffix. You can set it
144+ by running 'settings.
145+ ENDPOINT_CHECKOUT_LIVE_SUFFIX = 'Your live suffix'"""
146+ raise AdyenEndpointInvalidFormat (errorstring )
147+ if action == "paymentsDetails" :
148+ action = "payments/details"
149+ if action == "paymentsResult" :
150+ action = "payments/result"
151+ if action == "originKeys" :
152+ api_version = settings .API_CHECKOUT_UTILITY_VERSION
153+
154+ return '/' .join ([base_uri , api_version , action ])
155+
124156 def _review_payout_username (self , ** kwargs ):
125157 if 'username' in kwargs :
126158 return kwargs ['username' ]
@@ -190,35 +222,47 @@ def call_api(self, request_data, service, action, idempotency=False,
190222
191223 # username at self object has highest priority. fallback to root module
192224 # and ensure that it is set.
225+ if self .xapikey :
226+ xapikey = self .xapikey
227+ elif 'xapikey' in kwargs :
228+ xapikey = kwargs .pop ("xapikey" )
229+
193230 if self .username :
194231 username = self .username
195232 elif 'username' in kwargs :
196233 username = kwargs .pop ("username" )
197234 elif service == "Payout" :
198- if any (substring in action for substring in ["store" , "submit" ]):
235+ if any (substring in action for substring in
236+ ["store" , "submit" ]):
199237 username = self ._store_payout_username (** kwargs )
200238 else :
201239 username = self ._review_payout_username (** kwargs )
202240 if not username :
203241 errorstring = """Please set your webservice username.
204- You can do this by running 'Adyen.username = 'Your username'"""
242+ You can do this by running
243+ 'Adyen.username = 'Your username'"""
205244 raise AdyenInvalidRequestError (errorstring )
206-
207- # password at self object has highest priority. fallback to root module
208- # and ensure that it is set.
245+ # password at self object has highest priority.
246+ # fallback to root module
247+ # and ensure that it is set.
209248 if self .password :
210249 password = self .password
211250 elif 'password' in kwargs :
212251 password = kwargs .pop ("password" )
213252 elif service == "Payout" :
214- if any (substring in action for substring in ["store" , "submit" ]):
253+ if any (substring in action for substring in
254+ ["store" , "submit" ]):
215255 password = self ._store_payout_pass (** kwargs )
216256 else :
217257 password = self ._review_payout_pass (** kwargs )
218258 if not password :
219259 errorstring = """Please set your webservice password.
220- You can do this by running 'Adyen.password = 'Your password'"""
260+ You can do this by running
261+ 'Adyen.password = 'Your password'"""
221262 raise AdyenInvalidRequestError (errorstring )
263+ # xapikey at self object has highest priority.
264+ # fallback to root module
265+ # and ensure that it is set.
222266
223267 # platform at self object has highest priority. fallback to root module
224268 # and ensure that it is set to either 'live' or 'test'.
@@ -331,6 +375,73 @@ class instance.
331375 status_code , headers , message )
332376 return adyen_result
333377
378+ def call_checkout_api (self , request_data , action , ** kwargs ):
379+ """This will call the checkout adyen api. xapi key merchant_account,
380+ and platform are pulled from root module level and or self object.
381+ AdyenResult will be returned on 200 response. Otherwise, an exception
382+ is raised.
383+
384+ Args:
385+ request_data (dict): The dictionary of the request to place. This
386+ should be in the structure of the Adyen API.
387+ https://docs.adyen.com/developers/checkout/api-integration
388+ service (str): This is the API service to be called.
389+ action (str): The specific action of the API service to be called
390+ """
391+ if not self .http_init :
392+ self .http_client = HTTPClient (self .app_name ,
393+ self .USER_AGENT_SUFFIX ,
394+ self .LIB_VERSION ,
395+ self .http_force )
396+ self .http_init = True
397+
398+ # xapi at self object has highest priority. fallback to root module
399+ # and ensure that it is set.
400+ if self .xapikey :
401+ xapikey = self .xapikey
402+ elif 'xapikey' in kwargs :
403+ xapikey = kwargs .pop ("xapikey" )
404+
405+ if not xapikey :
406+ errorstring = """Please set your webservice xapikey.
407+ You can do this by running 'Adyen.xapikey = 'Your xapikey'"""
408+ raise AdyenInvalidRequestError (errorstring )
409+
410+ # platform at self object has highest priority. fallback to root module
411+ # and ensure that it is set to either 'live' or 'test'.
412+ if self .platform :
413+ platform = self .platform
414+ elif 'platform' in kwargs :
415+ platform = kwargs .pop ('platform' )
416+
417+ if not isinstance (platform , str ):
418+ errorstring = "'platform' value must be type of string"
419+ raise TypeError (errorstring )
420+ elif platform .lower () not in ['live' , 'test' ]:
421+ errorstring = "'platform' must be the value of 'live' or 'test'"
422+ raise ValueError (errorstring )
423+
424+ if not request_data .get ('merchantAccount' ):
425+ request_data ['merchantAccount' ] = self .merchant_account
426+
427+ # Adyen requires this header to be set and uses the combination of
428+ # merchant account and merchant reference to determine uniqueness.
429+ headers = {}
430+
431+ url = self ._determine_checkout_url (platform , action )
432+
433+ raw_response , raw_request , status_code , headers = \
434+ self .http_client .request (url , json = request_data ,
435+ xapikey = xapikey , headers = headers ,
436+ ** kwargs )
437+
438+ # Creates AdyenResponse if request was successful, raises error if not.
439+ adyen_result = self ._handle_response (url , raw_response , raw_request ,
440+ status_code , headers ,
441+ request_data )
442+
443+ return adyen_result
444+
334445 def hpp_payment (self , request_data , action , hmac_key = "" , ** kwargs ):
335446
336447 if not self .http_init :
@@ -386,7 +497,6 @@ def _handle_response(self, url, raw_response, raw_request,
386497 Returns:
387498 AdyenResult: Result object if successful.
388499 """
389-
390500 if status_code != 200 :
391501 response = {}
392502 # If the result can't be parsed into json, most likely is raw html.
@@ -405,9 +515,10 @@ def _handle_response(self, url, raw_response, raw_request,
405515 "Unexpected error while communicating with Adyen."
406516 " Received the response data:'{}', HTTP Code:'{}'. "
407517 "Please reach out to support@adyen.com if the "
408- "problem persists with the psp:{}"
409- .format (raw_response , status_code ,
410- headers .get ('pspReference' )),
518+ "problem persists with the psp:{}" .format (
519+ raw_response ,
520+ status_code ,
521+ headers .get ('pspReference' )),
411522 status_code = status_code ,
412523 raw_request = raw_request ,
413524 raw_response = raw_response ,
0 commit comments