Transaction

Start with preparing information required to perform an iDEAL transaction. Provide sale and customer data, specify the payment type to choose a bank and define a back url – customers will be redirected to this website after submitting the payment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$params = array(
    'sale' => array(
        'amount'      => 19.99,
        'currency'    => 'EUR',
        'description' => 'Product #1'
    ),
    'customer' => array(
        'name'    => 'John Doe',
        'email'   => 'john@doe.com',
        'ip'      => '127.0.0.1',
        'address' => array (
            'street_house' => '1600 Pennsylvania Avenue Northwest',
            'city'         => 'Washington',
            'state'        => 'DC',
            'zip'          => '500',
            'country_code' => 'US',
        ),
    ),
    'back_url'     => 'http://example-page.com',
    'bank_code'    => 'INGBNL2A',
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
params = {
    'sale' => {
        'amount'      => 19.99,
        'currency'    => 'EUR',
        'description' => 'Product #1'
    },
    'customer' => {
        'name'    => 'John Doe',
        'email'   => 'john@doe.com',
        'ip'      => '127.0.0.1',
        'address' => {
            'street_house' => '1600 Pennsylvania Avenue Northwest',
            'city'         => 'Washington',
            'state'        => 'DC',
            'zip'          => '500',
            'country_code' => 'US'
        }
    },
    'back_url'  => 'http://example-page.com',
    'bank_code' => 'INGBNL2A'
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
params = {
  'sale' : {
    'amount'      : 19.99,
    'currency'    : 'EUR',
    'description' : 'Product #1'
  },
  'customer' : {
    'name'    : 'John Doe'
    'email'   : 'john@doe.com',
    'ip'      : '127.0.0.1',
    'address' : {
      'street_house' : '1600 Pennsylvania Avenue Northwest',
      'city'         : 'Washington',
      'state'        : 'DC',
      'zip'          : '500'
      'country_code' : 'US'
    },
  },
  'back_url'     : 'http://example.com',
  'bank_code'    : 'INGBNL2A'
}

Payment

Simply call the idealSale method. You can also check whether the sale was performed successfully, retrieve the transaction ID or error details, if anything goes wrong.

If the idealSale method was performed successfully, you can now redirect the customer to the bank’s website, where they’ll perform the payment. Use the URL returned by the idealSale.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
try
{
    $status = $client->idealSale($params);
}
catch (Exception $e)
{
    // handle exception
}

if ($client->isSuccess()) {
    echo "Success, transaction initiated, id_sale: {$status['id_sale']}, \n
           redirect_url: {$status['redirect_url']} \n"
;
} else {
    die("Error ID: {$status['error']['id_error']}, \n".
        "Error number: {$status['error']['error_number']}, \n".
        "Error description: {$status['error']['error_description']}");
}

header('Location: ' . $status['redirect_url']);
die;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
begin
    status = client.ideal_sale(params)
rescue PayLane::ClientError => e
    # handle exception here
end

if client.success?
    puts "Success, transaction initiated, id_sale: #{status["id_sale"]}"\
         "redirect_url: #{status["redirect_url"]}"
else
    puts "Error ID: #{status["error"]["id_error"]}, \n"\
         "Error number: #{status["error"]["error_number"]}, \n"\
         "Error description: #{status["error"]["error_description"]}"
    exit
end

# redirect to url in status['redirect_url']
exit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try:
    status = client.ideal_sale(params)
except Exception, e:
    # handle exception
    print e
    sys.exit()

if client.is_success():
    print 'Success, transaction initiated, id_sale: %s, redirect_url: %s' % \
        (status['id_sale'], status['redirect_url'])
else:
    sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
             'Error number: ' + str(status["error"]["error_number"]) + '\n' \
             'Error description: ' + str(status["error"]["error_description"]))

# redirect to url in status['redirect_url']
sys.exit()

Ruby note:
There is no native function in Ruby to redirect to another website – you either have to use a mechanism provided by the used framework or write a function that will suit you best.
Python note:
There is no native function in Python to redirect to another website – you either have to use a mechanism provided by the used framework or write a function that will suit you best.

For Django, you can use:
1
2
from django.http import HttpResponseRedirect
HttpResponseRedirect(status['redirect_url'])
For Pylons, you can use:
1
2
from pylons.controllers.util import redirect
redirect(status['redirect_url'])

Verification

After submitting the payment on the bank’s website, the customer will be redirected back to your site (the back_url, to be precise). You should now verify the returned information to avoid any fraud attempts and check the transaction’s status.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$salt        = 'YOUR_HASH_SALT';
$status      = $_GET['status'];
$description = $_GET['description'];
$amount      = $_GET['amount'];
$currency    = $_GET['currency'];
$hash        = $_GET['hash'];

$id = '';
if ($status !== 'ERROR') // success, get id_sale
    $id = $_GET['id_sale'];

$calc_hash = sha1("{$salt}|{$status}|{$description}|{$amount}|{$currency}|{$id}");

// check hash salt
if ( $calc_hash !== $hash ) {
    die ("Error, wrong hash");
}

// check transaction status
switch ($status) {
    case 'ERROR':
        die("Error, transaction declined, {$_GET['error_description']}");
        break;

    case 'CLEARED':
        echo "Success, transaction completed, id_sale: {$_GET['id_sale']}";
        break;

    default:
        /* transaction pending:
         * check status regularly using the saleStatus method
         * or wait for notification */

        echo "Transaction pending";
        break;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Simple controller action code in Rails
# it's just an example - most of the logic should be moved to model

salt        = 'YOUR_HASH_SALT'
status      = params['status']
description = params['description']
amount      = params['amount']
currency    = params['currency']
hash        = params['hash']

id = ''
unless status == 'ERROR'
    id = params['id_sale']
else
    # redirect to an index action to correct the payment + simple notice
    # for rails: redirect_to :index, :notice => "Error, transaction declined, #{description}"
end

calc_hash = Digest::SHA1.hexdigest("#{salt}|#{status}|#{description}|#{amount}|#{currency}|#{id}")

unless calc_hash == hash
    # redirect to an index action to correct the payment
    # for rails: redirect_to :index
end

# check transaction status

case status
    when 'ERROR'
        # redirect to an index action to correct the payment + simple notice
        # for rails: redirect_to :index, :notice => "Error, transaction declined, #{response["error"]["error_description"]}"
    when 'CLEARED'
        # redirect to an index action to correct the payment + simple notice
        # for rails: redirect_to :index, :notice => "Success, transaction completed, id_sale: #{id}"
    else
        # redirect to an index action to correct the payment + simple notice
        # for rails: redirect_to :index, :notice => "Transaction pending"
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
salt        = 'YOUR_HASH_SALT'
status      = get_request_param('status')
description = get_request_param('description')
amount      = get_request_param('amount')
currency    = get_request_param('currency')
hash        = get_request_param('hash')
id_sale     = None

# success, get id_sale
if status != 'ERROR':
    id_sale = get_request_param('id_sale')

calc_hash = hashlib.sha1(
    '|'.join([salt, status, description, amount, currency, id_sale])).hexdigest()

# check hash salt
if calc_hash != hash:
    sys.exit('Error, wrong hash')

# check transaction status
if status == 'ERROR':
    sys.exit('Error, transaction declined, %s' % \
        get_request_param('error_description'))
elif status == 'CLEARED':
    print 'Success, transaction completed, id_sale: %s' % id_sale
else:
    # transaction pending: check status regularly using the saleStatus
    # method or wait for notification
    print 'Transaction pending'
Python note:
The get_request_param function is supposed to collect data from GET params. Depending on your framework or any other toolkit, please use a proper function or write one that suits you best.

For Django, you can use:
1
param_from_get = request.GET.get('param_name')
For Pylons, you can use:
1
2
from pylons import request
param_from_get = request.GET.get('param_name')