Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: 2
updates:
- package-ecosystem: pip
directory: "/"
schedule:
interval: daily
time: "04:00"
open-pull-requests-limit: 10
51 changes: 51 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: "Code scanning - action"

on:
push:
pull_request:
schedule:
- cron: '0 15 * * 4'

jobs:
CodeQL-Build:

runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2

# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language

#- run: |
# make bootstrap
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
57 changes: 41 additions & 16 deletions Adyen/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,25 @@ class AdyenClient(object):
skin_code (str, optional): skin_code to place directory_lookup requests
and generate hpp signatures with.
hmac (str, optional): Hmac key that is used for signature calculation.
http_timeout (int, optional): The timeout in seconds for HTTP calls,
default 30.
"""

def __init__(self, username=None, password=None, xapikey=None,
review_payout_username=None, review_payout_password=None,
store_payout_username=None, store_payout_password=None,
platform="test", merchant_account=None,
merchant_specific_url=None, skin_code=None,
hmac=None,
http_force=None, live_endpoint_prefix=None):
def __init__(
self,
username=None,
password=None,
xapikey=None,
review_payout_username=None,
review_payout_password=None,
store_payout_username=None, store_payout_password=None,
platform="test", merchant_account=None,
merchant_specific_url=None, skin_code=None,
hmac=None,
http_force=None,
live_endpoint_prefix=None,
http_timeout=30,
):
self.username = username
self.password = password
self.xapikey = xapikey
Expand All @@ -91,9 +101,9 @@ def __init__(self, username=None, password=None, xapikey=None,
self.http_init = False
self.http_force = http_force
self.live_endpoint_prefix = live_endpoint_prefix
self.http_timeout = http_timeout

@staticmethod
def _determine_api_url(platform, service, action):
def _determine_api_url(self, platform, service, action):
"""This returns the Adyen API endpoint based on the provided platform,
service and action.

Expand All @@ -102,7 +112,13 @@ def _determine_api_url(platform, service, action):
service (str): API service to place request through.
action (str): the API action to perform.
"""
base_uri = settings.BASE_PAL_URL.format(platform)
if platform == "live" and self.live_endpoint_prefix:
base_uri = settings.PAL_LIVE_ENDPOINT_URL_TEMPLATE.format(
self.live_endpoint_prefix
)
else:
base_uri = settings.BASE_PAL_URL.format(platform)

if service == "Recurring":
api_version = settings.API_RECURRING_VERSION
elif service == "Payout":
Expand Down Expand Up @@ -199,8 +215,14 @@ def _store_payout_pass(self, **kwargs):
'Adyen.store_payout_password = 'Your payout password'"""
raise AdyenInvalidRequestError(errorstring)

def call_api(self, request_data, service, action, idempotency=False,
**kwargs):
def call_api(
self,
request_data,
service,
action,
idempotency=False,
**kwargs
):
"""This will call the adyen api. username, password, merchant_account,
and platform are pulled from root module level and or self object.
AdyenResult will be returned on 200 response. Otherwise, an exception
Expand All @@ -217,12 +239,15 @@ def call_api(self, request_data, service, action, idempotency=False,
https://docs.adyen.com/manuals/api-manual#apiidempotency
Returns:
AdyenResult: The AdyenResult is returned when a request was
succesful.
successful.
"""
if not self.http_init:
self.http_client = HTTPClient(self.USER_AGENT_SUFFIX,
self.LIB_VERSION,
self.http_force)
self.http_client = HTTPClient(
user_agent_suffix=self.USER_AGENT_SUFFIX,
lib_version=self.LIB_VERSION,
force_request=self.http_force,
timeout=self.http_timeout,
)
self.http_init = True

# username at self object has highest priority. fallback to root module
Expand Down
101 changes: 60 additions & 41 deletions Adyen/httpclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@


class HTTPClient(object):
def __init__(self, user_agent_suffix, lib_version, force_request=None):
def __init__(
self,
user_agent_suffix,
lib_version,
force_request=None,
timeout=None,
):
# Check if requests already available, default to urllib
self.user_agent = user_agent_suffix + lib_version
if not force_request:
Expand All @@ -53,17 +59,20 @@ def __init__(self, user_agent_suffix, lib_version, force_request=None):
else:
self.request = self._urllib_post

def _pycurl_post(self,
url,
json=None,
data=None,
username="",
password="",
xapikey="",
headers=None,
timeout=30):
self.timeout = timeout

def _pycurl_post(
self,
url,
json=None,
data=None,
username="",
password="",
xapikey="",
headers=None
):
"""This function will POST to the url endpoint using pycurl. returning
an AdyenResult object on 200 HTTP responce. Either json or data has to
an AdyenResult object on 200 HTTP response. Either json or data has to
be provided. If username and password are provided, basic auth will be
used.

Expand Down Expand Up @@ -129,7 +138,7 @@ def _pycurl_post(self,
raw_request = json_lib.dumps(json) if json else urlencode(data)
curl.setopt(curl.POSTFIELDS, raw_request)

curl.setopt(curl.TIMEOUT, timeout)
curl.setopt(curl.TIMEOUT, self.timeout)
curl.perform()

# Grab the response content
Expand All @@ -143,14 +152,16 @@ def _pycurl_post(self,

return result, raw_request, status_code, response_headers

def _requests_post(self, url,
json=None,
data=None,
username="",
password="",
xapikey="",
headers=None,
timeout=30):
def _requests_post(
self,
url,
json=None,
data=None,
username="",
password="",
xapikey="",
headers=None
):
"""This function will POST to the url endpoint using requests.
Returning an AdyenResult object on 200 HTTP response.
Either json or data has to be provided.
Expand Down Expand Up @@ -191,8 +202,14 @@ def _requests_post(self, url,
# can be identified as coming from the Adyen Python library.
headers['User-Agent'] = self.user_agent

request = requests.post(url, auth=auth, data=data, json=json,
headers=headers, timeout=timeout)
request = requests.post(
url=url,
auth=auth,
data=data,
json=json,
headers=headers,
timeout=self.timeout
)

# Ensure either json or data is returned for raw request
# Updated: Only return regular dict,
Expand All @@ -201,14 +218,16 @@ def _requests_post(self, url,

return request.text, message, request.status_code, request.headers

def _urllib_post(self, url,
json=None,
data=None,
username="",
password="",
xapikey="",
headers=None,
timeout=30):
def _urllib_post(
self,
url,
json=None,
data=None,
username="",
password="",
xapikey="",
headers=None,
):

"""This function will POST to the url endpoint using urllib2. returning
an AdyenResult object on 200 HTTP responce. Either json or data has to
Expand All @@ -228,7 +247,6 @@ def _urllib_post(self, url,
xapikey (str, optional): Adyen API key. Will be used for auth
if username and password are absent.
headers (dict, optional): Key/Value pairs of headers to include
timeout (int, optional): Default 30. Timeout for the request.

Returns:
str: Raw response received
Expand Down Expand Up @@ -279,7 +297,7 @@ def _urllib_post(self, url,

# URLlib raises all non 200 responses as en error.
try:
response = urlopen(url_request, timeout=timeout)
response = urlopen(url_request, timeout=self.timeout)
except HTTPError as e:
raw_response = e.read()

Expand All @@ -293,13 +311,15 @@ def _urllib_post(self, url,
return (raw_response, raw_request,
response.getcode(), dict(response.info()))

def request(self, url,
json="",
data="",
username="",
password="",
headers=None,
timout=30):
def request(
self,
url,
json="",
data="",
username="",
password="",
headers=None,
):
"""This is overridden on module initialization. This function will make
an HTTP POST to a given url. Either json/data will be what is posted to
the end point. he HTTP request needs to be basicAuth when username and
Expand All @@ -313,7 +333,7 @@ def request(self, url,
key/value of request to place as
www-form
username (str, optional): Username for basic auth. Must be
uncluded as part of password.
included as part of password.
password (str, optional): Password for basic auth. Must be
included as part of username.
xapikey (str, optional): Adyen API key. Will be used for auth
Expand All @@ -324,7 +344,6 @@ def request(self, url,
str: Raw response received
int: HTTP status code, eg 200,404,401
dict: Key/Value pairs of the headers received.
:param timout:
"""
raise NotImplementedError('request of HTTPClient should have been '
'overridden on initialization. '
Expand Down
12 changes: 7 additions & 5 deletions Adyen/settings.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# Those constants are used from the library only
BASE_PAL_URL = "https://pal-{}.adyen.com/pal/servlet"
PAL_LIVE_ENDPOINT_URL_TEMPLATE = "https://{}-pal-live" \
".adyenpayments.com/pal/servlet"
BASE_HPP_URL = "https://{}.adyen.com/hpp"
ENDPOINT_CHECKOUT_TEST = "https://checkout-test.adyen.com"
ENDPOINT_CHECKOUT_LIVE_SUFFIX = "https://{}-checkout-live" \
".adyenpayments.com/checkout"
API_BIN_LOOKUP_VERSION = "v50"
API_CHECKOUT_VERSION = "v49"
API_CHECKOUT_VERSION = "v64"
API_CHECKOUT_UTILITY_VERSION = "v1"
API_RECURRING_VERSION = "v25"
API_PAYMENT_VERSION = "v49"
API_PAYOUT_VERSION = "v30"
LIB_VERSION = "3.0.0"
API_RECURRING_VERSION = "v49"
API_PAYMENT_VERSION = "v64"
API_PAYOUT_VERSION = "v64"
LIB_VERSION = "3.1.0"
LIB_NAME = "adyen-python-api-library"
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
setup(
name='Adyen',
packages=['Adyen'],
version='3.0.0',
version='3.1.0',
maintainer='Adyen',
maintainer_email='support@adyen.com',
description='Adyen Python Api',
Expand Down
Loading