iDEAL payments in php

iDEAL is the de facto standard for online payments in The Netherlands. As of August 1st, iDEAL updated its messages to be SEPA compliant. The new version, stated 3.3.1, requires quite some changes in comparison to the earlier versions. The most important change is the switch to the XML Signature Syntax and Processing standard for XML signatures. To ease the use of iDEAL payments in php, I created a library SlmIdealPayment which is up to date with the latest current iDEAL version.

SlmIdealPayment is a Zend Framework 2 module, but can be used standalone in any php project you have. The only requirement is a php installation with at least version 5.3.3.

The principle behind the library is fairly simple: there are three types of requests (a DirectoryRequest, a TransactionRequest and a StatusRequest) and they all map to php objects. You send the request via the iDEAL client and the Response object returns all the available data:

<?php
use SlmIdealPayment\Options\StandardClientOptions;
use SlmIdealPayment\Client\StandardClient;
use SlmIdealPayment\Request\DirectoryRequest;

$options = new StandardClientOptions;
$client  = new StandardClient($options);
$request = new DirectoryRequest;

$response  = $client->send($request);
$countries = $response->getCountries();

foreach ($countries as $country) {
  echo "Country: " . $country->getName() . "\n\n";

  foreach ($country->getIssuers() as $issuer) {
    echo "Issuer " . $issuer->getName() . "\n";
  }
}

The response object is typical for the request you send. Depending on the request object, you get a different response object returned:

  • DirectoryRequest: DirectoryResponse
  • TransactionRequest: TransactioResponse
  • StatusRequest: StatusResponse

Installation

SlmIdealPayment is available via composer. The package is available under the name slm/ideal-payment and currently you have to use the @beta version constraint. If you do not have composer enabled in your application, you can also load SlmIdealPayment from the Github canonical repository.

Configuration

If you use Zend Framework 2, most of the configuration is automatically done for you. There are a few configuration properties left, which are combined into a configuration template file.

Check the file under vendor/slm/ideal-payment/config called slmidealpayment.local.php.dist and copy this file to config/autoload. Mind to remove the .dist extension. Then fill in all the variables in that file.

For various acquires, the module provides a service which returns the client with configured urls and certificates. You can use the service names according to this list:

  • Rabobank: SlmIdealPayment\Client\Standard\Rabobank
  • ING bank: SlmIdealPayment\Client\Standard\Ing
  • ABN Amro: SlmIdealPayment\Client\Standard\AbnAmro

Not using Zend Framework 2?

If you use a different foundation for your php application, you can configure the client manually. There is an Options class where you can fill in all variables:

<?php
use SlmIdealPayment\Options\StandardClientOptions;
use SlmIdealPayment\Client\StandardClient;

$options = new StandardClientOptions;
// Options here

$client  = new StandardClient($options);

The following options are available:

  • setRequestUrl($url): the url requests are made to ( required )
  • setMerchantId($merchant): the merchant id ( required )
  • setSubId($id): the sub id of the merchant ( required )
  • setPublicCertificate($cert): the certificate of the acquirer ( required )
  • setPrivateCertificate($cert): your (self-signed) certificate ( required )
  • setKeyFile($file): the key file for the certificate ( required )
  • setKeyPassword($password): the password for the key file, if you have any
  • setValidationScheme($scheme): if provided, the request and response XML messages will be validated against this scheme

Send a transaction request

As shown above, it is fairly simple to send a so-called DirectoryRequest to request all available issuers. The second step in the iDEAL process it to send a TransactionRequest to start a transaction. Transactions are characterised by these properties:

  • The issuer which is selected by the user
  • The transactional information
  • The URL used to return to after the user completed the transaction

These are all three properties configured inside the request object. The issuer and transaction are modelled by a value object, which require several values to complete the request:

<?php
use SlmIdealPayment\Request\TransactionRequest;
use SlmIdealPayment\Model\Issuer:
use SlmIdealPayment\Model\Transaction;

$issuer = new Issuer;
$issuer->setId('1234'); // id of selected issuer

$transaction = new Transaction;
$transaction->setPurchaseId(1234);
$transaction->setAmount(123.45);
$transaction->setDescription('A test transaction');
$transaction->setEntranceCode('5b93651'); // random

$request = new TransactionRequest;
$request->setIssuer($issuer);
$request->setTransaction($transaction);
$request->setReturnUrl('http://example.com/return')

// $client already configured
$response = $client->send($request);

You can supply the request with more variables, but these all have a default value and are not required to perform the request:

  • Expiration period of the transaction, which defaults to 15 minutes. Set the expiration period via $transaction->setExpirationPeriod(). The value must be formatted as the ISO 8601 describes durations.
  • Language of the iDEAL interface, which is set to Dutch by default. Set the language via $transaction->setLanguage(). The value must be either “nl” for Dutch or “en” for English.
  • Currency of the transaction, which is set to Euro by default. Set the currency via $transaction->setCurrency(). The value, however, can only be “EUR” so setting this to something else makes no sense until iDEAL supports multiple currencies.

The response will be a TransactionResponse and contains information about the transaction and a url the user can be redirected to:

// From above snippet
$response = $client->send($request);

$transaction = $response->getTransaction();
echo sprint(
  "Transaction ID: %s \n\n",
  $transaction->getTransactionId()
);

echo sprintf(
  "Purchase ID: %s \n\n",
  $transaction->getPurchaseId()
);

// Redirect
$location = $response->getAuthenticationUrl();
header('Location: ' . $location);

Send a status request

Similar to the DirectoryRequest and TransactionRequest, a StatusRequest is performed using a request object with the appropriate information.

<?php
use SlmIdealPayment\Request\StatusRequest;
use SlmIdealPayment\Model\Transaction;

$transaction = new Transaction;
$transaction->setTransactionId(1234);

$request = new StatusRequest;
$request->setTransaction($transaction);

// $client already configured
$response = $client->send($request);

The response will contain information about the status of the transaction and, if successful, more information about the consumer:

<?php
use SlmIdealPayment\Model\Transaction;

// From above snippet
$response = $client->send($request);

$transaction = $response->getTransaction();
echo sprintf(
  "Transaction status: %s",
  $transaction->getStatus()
);

$success = Transaction::STATUS_SUCCESS;
if ($success === $transaction->getStatus()) {
    $consumer = $transaction->getConsumer();

    echo sprintf(
        "Name: %s \n\n", $consumer->getName()
    );

    echo sprintf(
        "IBAN: %s \n\n", $consumer->getAccountIBAN()
    );

    echo sprintf(
        "BIC: %s \n\n", $consumer->getAccountBIC()
    );

    echo sprintf(
        "Transaction amount: %s \n\n",
        $transaction->getAmount()
    );

    echo sprintf(
        "Transaction currency: %s \n\n",
        $transaction->getCurrency()
    );
}

The available statuses are (all mapped to constants in the Transaction class):

  • Unknown: Transaction::STATUS_UNKNOWN
  • Open: Transaction::STATUS_OPEN
  • Success: Transaction::STATUS_SUCCESS
  • Failure: Transaction::STATUS_FAILURE
  • Cancelled: Transaction::STATUS_CANCELLED
  • Expired: Transaction::STATUS_EXPIRED

Summary

Many people struggle with iDEAL payments in php, but SlmIdealPayment can help you enormously. It is fairly easy to install when you use a modern development stack with composer. SlmIdealPayment also abstracts everything from the message format into php value objects, so you can use a descriptive API to create your requests.

The advantage of SlmIdealPayment is it’s open source and supported by several developers. If a bug is found, it’s also fixed in your code base. Furthermore, the abstraction makes it possible to keep iDEAL up to date with newer versions, without the need to modify your own application every time.

If you have any trouble using SlmIdealPayment, you found a bug or you want to add something, just create an issue on Github.