worldline

Documentation

Python SDK

Introduction

The Python SDK helps you to communicate with the  Acquiring API . More specifically, it offers a fluent Python API that provides access to all the functionality of the RESTful API. Below, we discuss the following topics in detail.

  • Initialization of the SDK

  • Exceptions

  • Logging

  • Advanced use: Connection pooling

  • Advanced use: Customization of the communication

  • Notes

The source code of the SDK is available on Github . There you can find installation instructions.

The API documentation of the latest version of the SDK is available  here . For a specific major version, replace latest with the actual version in format <major>.x .

Initialization of the Python SDK

All Python code snippets presented in the API Reference assume you have initialized the Python SDK before using them in your Development Environment. This section details the initialization of the Python SDK.

Initializing is simple, and requires only one key task: use our  Factory  class to create an instance of  Client , which contains the actual methods to communicate with the Server API.

The  Factory  needs the following input information to provide you with an initialized  Client

  • A String to the configuration file with your connection configuration.

  • The oauth2_token_uri , oauth2_client_id and oauth2_client_secret .The property file should contain the following keys:

[AcquiringSDK]
acquiring.api.integrator=<your company name>
acquiring.api.endpoint.host=api.preprod.acquiring.worldline-solutions.com
acquiring.api.authorizationType=OAuth2
acquiring.api.oauth2.tokenUri=https://auth-test-eu-west-1.aws.bambora.com/connect/token
acquiring.api.connectTimeout=5 # use -1 for no timeout
acquiring.api.socketTimeout=300 # use -1 for no timeout
acquiring.api.maxConnections=10 # to support 10 concurrent connections

We recommend to keep the timeout values at these values. See  API endpoints  for the possible hosts and token URIs.

If a proxy should be used, the property file should additionally contain the following key(s) under the  [AcquiringSDK]  section:

acquiring.api.proxy.uri=<URL to the proxy host including leading http:// or https://>
# omit the following two lines if no proxy authentication is required
acquiring.api.proxy.username=<username for the proxy>
acquiring.api.proxy.password=<password for the proxy>

You can create an instance of  Client  using the  Factory  with this code snippet:

client = Factory.create_client_from_file(configuration_file_name, "oauth2_client_id", "oauth2_client_secret")

Connection management

Connection pooling is configured with the  max_connections  setting in  CommunicatorConfiguration  or in the configuration file. Its value determines how many connections to the Server API are kept alive for re-use in a connection pool. If there are more requests in progress than this maximum number of connections, then a new connection will be temporarily opened.

Exceptions

All calls can raise one of the following runtime exceptions:

  • ValidationException  if the request was not correct and couldn't be processed (HTTP status code 400)

  • An  AuthorizationException  if the request was not allowed (HTTP status code 403)

  • An  IdempotenceException  if an idempotent request caused a conflict (HTTP status code 409)

  • ReferenceException  if an object was attempted to be referenced that doesn't exist or has been removed, or there was a conflict (HTTP status code 404, 409 or 410)

  • PlatformException  if something went wrong on the Worldline platform. The Worldline platform was unable to process a message from a downstream partner/acquirer, or the service that you're trying to reach is temporary unavailable (HTTP status code 500, 502 or 503)

  • An  ApiException  if the RESTful Server API returned any other error

A payment attempt can now be handled as follows:

try:
    response = client.v1().acquirer(acquirer_id).merchants(merchant_id).payments().process_payment(request)
except ValidationException as e:
    sys.stderr.write("Input validation error: " + e.detail)
except AuthorizationException as e:
    sys.stderr.write("Authorization error: " + e.detail)
except ReferenceException as e:
    sys.stderr.write("Incorrect object reference: " + e.detail)
except PlatformException as e:
    sys.stderr.write("Error occurred at Worldline or a downstream partner/acquirer: " + e.detail)
except ApiException as e:
    sys.stderr.write("Worldline error: " + e.status_code + ", " + e.detail)

Exception overview

The following table is a summary that shows when each of these exceptions will be raised:

HTTP status code

Meaning

Description

Exception Type

200

Successful

Your request was processed correctly

N/A

201

Created

Your request was processed correctly and a new resource was created.
The URI of this created resource is returned in the Location header of the response.

N/A

204

No Content

Your request was processed correctly

N/A

400

Bad Request

Your request is not correct and can't be processed. Please correct the mistake and try again.

ValidationException

403

Not Authorized

You're trying to do something that is not allowed or that you're not authorized to do.

AuthorizationException

404

Not Found

The object you were trying to access could not be found on the server.

ReferenceException

409

Conflict

Your idempotent request resulted in a conflict. The first request has not finished yet.

IdempotenceException

409

Conflict

Your request resulted in a conflict. Either you submitted a duplicate request or you're trying to create something with a duplicate key.

ReferenceException

500

Internal Server Error

Something went wrong on the Worldline platform.

PlatformException

502

Bad Gateway

The Worldline platform was unable to process a message from a downstream partner/acquirer.

PlatformException

503

Service Unavailable

The service that you're trying to reach is temporary unavailable.
Please try again later.

PlatformException

other

Unexpected error

An unexpected error has occurred

ApiException

Logging

The Python SDK supports logging of requests, responses and exceptions of the API communication.

In order to start using the logging feature, an implementation of the  CommunicatorLogger  interface should be provided. The SDK provides two example implementations for logging to  sys.stdout  ( SysOutCommunicatorLogger ) and logging to a  logger  ( PythonCommunicatorLogger ).

Logging can be enabled by calling the  enable_logging  method on a  Client  object, and providing the logger as an argument. The logger can subsequently be disabled by calling the  disable_logging  method.

The following code exemplifies the use of adding a logger:

client = Factory.create_client_from_file(configuration_file_name, "oauth2_client_id", "oauth2_client_secret")
logger = PythonCommunicatorLogger(logging.get_logger(...), 800)
client.enable_logging(logger)
# ... Do some calls
client.disable_logging()

Advanced use: Connection pooling

Client  created using the  Factory  class from a properties file or  CommunicatorConfiguration  object will use its own connection pool. If multiple clients should share a single connection pool, the  Factory  class should be used to first create a shared  Communicator , then to create  Client  instances that use that  Communicator :

communicator = Factory.create_communicator(configuration_file_name, "oauth2_client_id", "oauth2_client_secret")
client = Factory.create_client_from_communicator(communicator)

Instead of closing these  Client  instances, you should instead close the  Communicator  when it is no longer needed. This will close all  Client  instances that use the  Communicator .

Connection management

Just like  Client Communicator  also has method  close_expired_connections  that can be used to evict expired HTTP connections. You can call this method on the  Communicator  instead of on any of the  Client  instances. The effect will be the same.

Advanced use: Customization of the communication

Client  uses a  Communicator  to communicate with the RESTful Server API. A  Communicator  contains all the logic to transform a request object to an HTTP request and an HTTP response to a response object. If needed, you can extend this class. To instantiate a  Client  that uses your own implementation of  Communicator  you can use the following code snippet:

communicator = YourCommunicator()
client = Factory.create_client_from_communicator(communicator)

However, for most customizations you do not have to extend  Communicator . The functionality of the  Communicator  is built on the following:

  • The RESTful Server API endpoint URI.

  • Connection , which represents one or more HTTP connections to the Worldline server.

  • An  Authenticator , which is used to sign your requests.

  • MetadataProvider , which constructs the header with metadata of your server that is sent in requests for BI and fraud prevention purposes.

  • Marshaller , which is used to marshal and unmarshal request and response objects to and from JSON.

For your convenience, the  Factory.create_communicator_from_configuration , Factory.create_communicator_from_file , Factory.create_client_from_configuration and  Factory.create_client_from_file methods can take optional arguments to set the  Connection Authenticator MetadataProvider  or  Marshaller  components. For example, the following code snippet:

connection = YourConnection()
client = Factory.create_client_from_file(configuration_file_name, "oauth2_client_id", "oauth2_client_secret",
                                         connection = connection)

Connection management

Calling  close_expired_connections  on a  Client  or a  Communicator  object only works if the  Connection  extends  PooledConnection , otherwise these methods do nothing. If you write a custom  Connection  that uses a pool of HTTP connections, extend  PooledConnection  instead.

Logging

To facilitate implementing logging in a custom  Connection , the SDK provides utility classes  RequestLogMessage  and  ResponseLogMessage . These can be used to easily construct request and response messages. For instance:

# In the below code, logger is the CommunicatorLogger set using enable_logging.
# Note that it may be None if enable_logging is not called.
request_id = uuid.uuid4()
request_log_message = RequestLogMessage(request_id, method, uri)
# add request headers to request_log_message
# if present, set the request body on request_log_message
logger.log(request_log_message.get_message())
start_time = time.time() * 1000
# send the request
end_time = time.time() * 1000
duration = end_time - start_time
status_code = ...
# note: duration is optional
response_log_message = ResponseLogMessage(request_id, status_code, duration)
# add response headers to response_log_message
# if present, set the response body on response_log_message
logger.log(response_log_message.get_message())

Notes

Renaming of properties

The Python SDK uses Python naming conventions. As a result, properties have been turned into so-called  Snake case . For example,  cardNumber  is called  card_number .