Ingenico Direct Support Site

Results for

icon-search-large No search results yet
Enter your search query above

Introduction

To understand how to use this SDK it is best to read the following documentation:

  • Server Introduction
    First read the Server Introduction to familiarize yourself with the various concepts.
  • Server API Reference
    This Server SDK wraps the Server API and (amongst other things) exposes the responses of the webservice calls as PHP objects. Understanding the Server API will help you understanding these SDK objects as well.
  • This current document will help you understand the global flow when interacting with the Ingenico Direct platform using the PHP SDK.

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

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

Initialization of the SDK

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

To initialize the PHP SDK, create an instance of the Client class. This class facilitates methods to communicate with the Ingenico Direct Server API.

The Client constructor requires an instance of a Communicator, which contains all the logic to transform a request object to a HTTP request and a HTTP response to a response object. This class requires an instance of Connection for performing actual HTTP requests and an instance of CommunicationConfiguration for holding configuration values. Connection is an interface performing the actual HTTP requests, a default implementation is provided by the class DefaultConnection. CommunicationConfiguration is a class whose constructor has the following required parameters:

  • $apiKeyId: the API key (can be obtained from the Back Office)
  • $apiSecret: the API secret (can be obtained from the Back Office)
  • $apiEndpoint: the API endpoint URI including scheme. See API endpoints for the possible values
  • $integrator: the name of the integrator, e.g. your company name

In code:

SDK: PHP
$communicatorConfiguration =
    new CommunicatorConfiguration($apiKeyId, $apiSecret, $apiEndpoint, $integrator);
$connection = new DefaultConnection();
$communicator = new Communicator($connection, $communicatorConfiguration);

$client = new Client($communicator);

Client meta information

The PHP SDK supports sending client meta information to the server for business intelligence and fraud prevention purposes. Client meta information can be added using the constructor of a Client or the method setClientMetaInfo on a Client object. The information must be provided in JSON format.

The following code exemplifies the addition of client meta information:

SDK: PHP
$communicatorConfiguration = new CommunicatorConfiguration(...);
$connection = new DefaultConnection();
$communicator = new Communicator($connection, $communicatorConfiguration);

$client = new Client($communicator, "consumer specific JSON meta info");

Do not use this consumer specific instance for API calls for other consumers.

Payments

As a merchant, your core interaction with Ingenico Direct typically starts when your customer clicks the checkout button in your application. The payment process usually has the following steps:

  1. Payment Product selection
  2. Setting of available information needed for selected payment product (e.g. amount of the order)
  3. Collection of missing customer information needed for selected payment product (e.g. creditcard number)
  4. Submitting the payment request to Ingenico Direct
  5. Handling the response to the payment request (e.g. payment unsuccessful)

Ingenico Direct offers the following ways of handling this payment process:

In the next couple of paragraphs, we discuss each of these options in more detail.

Use a hosted payment through Ingenico Direct Hosted Payment Page

The high-level flow of a hosted payment is described below, followed by a more detailed look at each of the steps.

  1. At this point, your customer has provided all relevant information regarding the order, e.g. a shopping cart of items and a shipping address.
  2. See the section on initialization. Create an instance of Client if you hadn't done so yet, and set the meta data that you've collected about the client of the customer.
  3. Create a CreateHostedCheckoutRequest body and populate at least its Order. See the relevant section of the full API reference for more details. You can specify an optional returnUrl, which is used to redirect your customer back to your website in step 9.
  4. The create hosted checkout SDK call returns a CreateHostedCheckoutResponse response. Store the hostedCheckoutId and RETURNMAC it contains, as well as any other relevant order information. You will need these when your customer returns from our hosted payment pages, or when the customer fails to return in a reasonable amount of time. This response also contains a partialRedirectURL. You have to concatenate the base URL https://payment. with partialRedirectURL according to the formula https://payment. + partialRedirectURL and perform a redirection of your customer to this URL.
  5. After completing the interactive payment process in the RPP, your customer is redirected back to the URL you provided in step 3 as body->getHostedCheckoutSpecificInput()->getReturnUrl(). The hostedCheckoutId and RETURNMAC you stored in step 5 are added to this URL as query parameters. Specifying a returnUrl is optional, however. As a result, your customer is only redirected back if you've provided a URL in step 3.
  6. If you cannot identify the customer based on e.g. the HTTP session, you can use the hostedCheckoutId for this purpose. If you do, you must check that the hostedCheckoutId and RETURNMAC from the returnUrl match those that you stored in step 3. Note that the RETURNMAC is used as a shared secret between Ingenico Direct and your system that is specific for this hosted checkout.
  7. Retrieve the results of the customer's interaction with Ingenico Direct.
  8. Check the GetHostedCheckoutResponse response returned in step 13. If response->getStatus() equals PAYMENT_CREATED, then the customer attempted a payment, the details of which can be found in response->getCreatedPaymentOutput(). Depending on the payment product chosen and the status of the payment you can "deliver the goods" immediately, or set up a regular poll of the created payment to wait for the status. Such a poll is done using the SDK call client->merchant("merchantId")->payments()->getPayment(paymentId), where paymentId is response->getCreatedPaymentOutput()->getPayment()->getId(). For details on the various payment products and their statuses, see Payment Products.

Additionally, it may be the case that the customer does not return in time (or at all), for example because the browser is closed or because you didn't provide a returnUrl. In this case, you need to retrieve the status of the hosted checkout (step 12 of the image above) before the hosted checkout times out, which happens after 2 hours, and follow step 14 of the image above as well.

Use a Server SDK to build a payment flow hosted on your server

The high-level flow of a payment performed from pages hosted on your server is described below, followed by a more detailed look at each of the steps. First, we describe the flow for payment products that do not require a redirect to a payment method hosted by a third party. Afterwards, the flow for payment methods that require a redirect is described.

  1. At this point, your customer has provided all relevant information regarding the order, e.g. a shopping cart of items and a shipping address.
  2. See the section on initialization. Create an instance of Client if you hadn't done so yet, and set the meta data that you've collected about the client of the customer.
  3. Create GetPaymentProductsParams queryParams and request a list of relevant payment products. See the relevant section of the full API reference for more details.
  4. Show the relevant payment products to the customer such that they can select one.
  5. The customer selects one of the available payment products.
  6. Once the customer has decided which payment product should be used, you request the fields of this payment product. See the relevant section of the full API reference for more details.
  7. Based on the information retrieved in the previous step, you render a form that the customer can use to enter all relevant information for the selected payment product.
  8. The customer submits the form.
  9. Create a CreatePaymentRequest body, populate its Order and other properties depending on the selected payment product, and submit it. See the relevant section of the full API reference for more details. Do not store the information provided by the customer. The paymentProductId can be used to determine whether this payment involves a redirect to a third party. For this flow, we assume that we're dealing with a payment that doesn't require a redirect.
  10. The create payment SDK call returns a CreatePaymentResponse response. The status of the payment is accessible via response->getPayment()->getStatus(). Depending on the payment product chosen and the status of the payment you can "deliver the goods" immediately, or set up a regular poll of the created payment to wait for the status. Such a poll is done using the SDK call client->merchant("merchantId")->payments()->getPayment(paymentId), where paymentId is response->getPayment()->getId(). For details on the various payment products and their statuses, see Payment Products.

The high-level flow of a payment performed from pages on your server is a little different if a redirect is involved. We only describe the steps that differ from the flow without a redirect.

  1. We assume that we're dealing with a payment that involves a redirect. As mentioned above, this can be determined using the paymentProductId. Create a CreatePaymentRequest body and populate at least its Order. Additionally, populate its redirectPaymentMethodSpecificInput by providing at least the desired returnUrl. The returnUrl defines the location to which the customer should be redirected after completing the payment process. See the relevant section of the full API reference for more details.
  2. The create payment SDK call returns a CreatePaymentResponse response. For payments involving a redirect, response->getMerchantAction()->getRedirectData()->getRedirectURL() defines the URL to which the customer should be redirected to complete the payment. You need to store the value of response->getMerchantAction()->getRedirectData()->getRETURNMAC() because it should be compared with the RETURNMAC returned by the third party at a later stage. Additionally, you need to store the value of response->getPayment()->getId(). This paymentId is needed to check the status of the payment after the redirect.
  3. Redirect the customer to the redirectUrl.
  4. After the payment process is completed, your customer is redirected to the returnUrl specified previously. In the flow shown in the figure above we assume that this URL brings the customer back to your server.
  5. Retrieve the RETURNMAC provided by the third party from the returnUrl. You can use the RETURNMAC to identify the customer by comparing it with the one stored previously, and to validate that the customer was redirected to you by our systems.
  6. Use the paymentId stored previously to check the status of the payment. See the relevant section of the full API reference for more details. The retrieve payment SDK call returns a PaymentResponse response. The status of the payment is accessible via response->getPayment()->getStatus(). Use this status to handle the order appropriately, as described above.

Idempotent requests

To execute a request as an idempotent request, you can call the same method as for a non-idempotent request, but with an extra CallContext argument with its idempotenceKey property set. This will make sure the SDK will send an X-GCS-Idempotence-Key header with the idempotence key as its value.

If a subsequent request is sent with the same idempotence key, the response will contain an X-GCS-Idempotence-Request-Timestamp header, and the SDK will set the idempotenceRequestTimestamp property of the CallContext argument. If the first request has not finished yet, the RESTful Server API will return a 409 status code. If this occurs, the SDK will throw an IdempotenceException with the original idempotence key and the idempotence request timestamp.
For example:

SDK: PHP
$callContext = new CallContext();
$callContext->setIdempotenceKey($idempotenceKey);
try {
    $createPaymentResponse = $client->merchant($merchantId)->payments()
        ->createPayment($createPaymentRequest, $callContext);

    $idempotenceRequestTimestamp = $callContext->getIdempotenceRequestTimestamp();
    // idempotenceRequestTimestamp contains the value of the
    // X-GCS-Idempotence-Request-Timestamp header
    // if idempotenceRequestTimestamp is not empty this was not the first request
} catch (IdempotenceException $e) {
    // a request with the same idempotenceKey is still in progress, try again after a short pause
    // $e->getIdempotenceRequestTimestamp() contains the value of the
    // X-GCS-Idempotence-Request-Timestamp header
} catch (ResponseException $e {
    $idempotenceRequestTimestamp = $callContext->getIdempotenceRequestTimestamp();
    // idempotenceRequestTimestamp contains the value of the
    // X-GCS-Idempotence-Request-Timestamp header
    // if idempotenceRequestTimestamp is not empty this was not the first request
}
If an idempotence key is sent for a call that does not support idempotence, the RESTful Server API will ignore the key and treat the request as a first request.

Exceptions

Payment exceptions

If a payment attempt is declined by the RESTful Server API, a DeclinedPaymentException is thrown. This exception contains a reference to the payment result which can be inspected to find the reason why the payment attempt was declined. This payment result can also be used to later retrieve the payment attempt again.
For example:

SDK: PHP
try {
    $createPaymentResponse =
        $client->merchant($merchantId)->payments()->createPayment($createPaymentRequest);
} catch (DeclinedPaymentException $e) {
    $paymentResult = $e->getPaymentResult();
    $paymentId = $paymentResult->getPayment()->getId();
    $paymentStatus = $paymentResult->getPayment()->getStatus();
    $message = 'Payment ' . $paymentId . ' was declined with status ' . $paymentStatus;
    //Do something with $message
}

Unlike direct payments, indirect payments like iDeal and PayPal usually will not cause a DeclinedPaymentException to be thrown, but instead will result in a CreatePaymentResponse return value. To determine if the payment was successfully finished, declined or cancelled, you would need to retrieve the payment status and examine its contents, especially the status field. It is recommended to use shared code for handling errors.
For example:

SDK: PHP
try {
    $createPaymentResponse =
        $client->merchant($merchantId)->payments()->createPayment($createPaymentRequest);
    $paymentId = $createPaymentResponse->getPayment()->getId();
} catch (DeclinedPaymentException $e) {
    $paymentResult = $e->getPaymentResult();
    handlePaymentError($paymentResult->getPayment());
    return;
}
//other code
$payment = $client->merchant($merchantId)->payments()->getPayment($paymentId);
if (isNotSuccessful($payment)) {
    handlePaymentError($payment);
}

Refund exceptions

If a refund attempt is declined by the RESTful Server API, a DeclinedRefundException is thrown. This exception contains a reference to the refund result which can be inspected to find the reason why the refund was declined. This refund result can also be used to later retrieve the refund attempt again.
For example:

SDK: PHP
try {
    $RefundResponse =
        $client->merchant($merchantId)->refunds()->createPayment($createRefundRequest);
} catch (DeclinedRefundException $e) {
    $refundResult = $e->getRefundResult();
    $refundId = $refundResult->getRefund()->getId();
    $refundStatus = $refundResult->getRefund()->getStatus();
    $message = 'Refund ' . $refundId . ' was declined with status ' . $refundStatus;
    //Do something with $message
}

Other exceptions

Besides from the above exceptions, all calls can throw one of the following runtime exceptions:

  • A 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)
  • A 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)
  • A DirectException if something went wrong on our end, we were 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:

SDK: PHP
try {
    $createPaymentResponse =
        $client->merchant($merchantId)->payments()->createPayment($createPaymentRequest);
} catch (DeclinedPaymentException $e) {
    $paymentResult = $e->getPaymentResult();
    $paymentId = $paymentResult->getPayment()->getId();
    $paymentStatus = $paymentResult->getPayment()->getStatus();
    $message = 'Payment ' . $paymentId . ' was declined with status ' . $paymentStatus;
    //Do something with $message
} catch (ValidationException $e) {
    $message = 'Input validation error:' . PHP_EOL;
    foreach ($e->getErrors() as $error) {
        $message .= '- ';
        if (!$error->propertyName) {
            $message .= $error->getPropertyName() . ': ';
        }
        $message .= $error->getMessage() . '(' . $error->getCode() . ')' . PHP_EOL;
    }
    //Do something with $message
} catch (AuthorizationException $e) {
    $message = 'Authorization error:' . PHP_EOL;
    foreach ($e->getErrors() as $error) {
        $message .= '- ' . $error->getMessage() . '(' . $error->getCode() . ')' . PHP_EOL;
    }
    //Do something with $message
}
} catch (ReferenceException $e) {
    $message = 'Incorrect object reference:' . PHP_EOL;
    foreach ($e->getErrors() as $error) {
        $message .= '- ' . $error->getMessage() . '(' . $error->getCode() . ')' . PHP_EOL;
    }
    //Do something with $message
} catch (DirectException $e) {
    $message = 'Error occurred at Ingenico Direct or a downstream partner/acquirer:' . PHP_EOL;
    foreach ($e->getErrors() as $error) {
        $message .= '- ' . $error->getMessage() . '(' . $error->getCode() . ')' . PHP_EOL;
    }
    //Do something with $message
} catch (ApiException $e) {
    $message = 'Unexpected error:' . PHP_EOL;
    foreach ($e->getErrors() as $error) {
        $message .= '- ' . $error->getMessage() . '(' . $error->getCode() . ')' . PHP_EOL;
    }
    //Do something with $message
}

Exception overview

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

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
various; CreatePaymentResult is present in the response Payment Rejected Your request was rejected either by us or one of our downstream partners/acquirers. DeclinedPaymentException
various; RefundResult is present in the response Refund Rejected Your request was rejected either by us or one of our downstream partners/acquirers. DeclinedRefundException
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
410 Gone The object that you are trying to reach has been removed. ReferenceException
500 Internal Server Error Something went wrong on our end. DirectException
502 Bad Gateway We were unable to process a message from a downstream partner/acquirer. DirectException
503 Service Unavailable The service that you're trying to reach is temporary unavailable.
Please try again later.
DirectException
other Unexpected error An unexpected error has occurred ApiException

Logging

The PHP 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 resources (ResourceLogger) and logging to SplFileObjects (SplFileObjectLogger).

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

When logged messages contain sensitive data, this data is obfuscated.

The following code exemplifies the use of adding a logger:

SDK: PHP
$communicatorConfiguration = new CommunicatorConfiguration(...);
$connection = new DefaultConnection();
$communicator = new Communicator($connection, $communicatorConfiguration);
$client = new Client($communicator);

$logger = new ResourceLogger(STDOUT);
$client->enableLogging($logger);
//... Do some calls
$client->disableLogging();

Advanced use: Connection Pooling

The PHP SDK supports connection pooling by allowing connections to be shared amongst communicators, and by allowing communicators to be shared amongs clients. Pooling is enabled when the same DefaultConnection instance is provided to Communicator instances. The Communicator can in turn be used by different Client instances.

When Communicator instances are shared between different Client instances, connections are shared.

The following example reuses the connections between the different Client instances, since the same DefaultConnection object is used:

SDK: PHP
$communicatorConfiguration1 = new CommunicatorConfiguration(...);
$communicatorConfiguration2 = new CommunicatorConfiguration(...);

$sharedConnection = new DefaultConnection();

$communicator1 = new Communicator($sharedConnection, $communicatorConfiguration1);
$communicator2 = new Communicator($sharedConnection, $communicatorConfiguration2);

client1 = new Client($communicator1);
client2 = new Client($communicator2);

Advanced use: Customization of the communication

A Client uses a Communicator to communicate with the Ingenico Direct RESTful Server API. This Communicator uses a Connection to perform the actual HTTP requests and a ConnectionResponse to hold the HTTP response.

Connection and ConnectionResponse are interfaces. The SDK provides a default implementation via the classes DefaultConnection and DefaultConnectionResponse:

  • DefaultConnection uses cURL via the standard PHP/cURL bindings to implement the get(), delete(), post() and put() methods.
  • DefaultConnectionResponse offers a straightforward implementation of the getHttpStatusCode(), getHeaders(), getHeaderValue and getBody() methods, and is used by DefaultConnection.

If needed, the DefaultConnection class (and optionally the DefaultConnectionResponse class) can be extended or completely replaced. In order to use this class, initialize the client with an instance of this class:

SDK: PHP
$communicatorConfiguration =
    new CommunicatorConfiguration('ApiKeyId', 'ApiSecret', 'BaseUri', 'Integrator');
$connection = new YourConnection();
$communicator = new Communicator($connection, $communicatorConfiguration);

$client = new Client($communicator);

Advanced use: Proxy

The PHP SDK provides basic HTTP proxy support with authentication. Proxy support is enabled by supplying an optional ProxyConfiguration object to the constructor of the CommunicatorConfiguration class.

To exemplify the use of a proxy, consider the following code snippet:

SDK: PHP
$proxyConfiguration = new ProxyConfiguration(
    'proxyHost',
    'proxyPort',
    'proxyUserName',
    'proxyPassword'
);

$communicatorConfiguration = new CommunicatorConfiguration(
    'apiKeyId',
    'apiSecret',
    'baseUri',
    'Integrator',
    $proxyConfiguration
);

$communicator = new Communicator($communicatorConfiguration);
$proxyClient = new Client($communicator);