Index: ideal.module
===================================================================
--- ideal.module	(revision 140)
+++ ideal.module	(working copy)
@@ -44,6 +44,15 @@
     'weight' => 1,
     'type' => MENU_LOCAL_TASK,
   );
+  $items['admin/settings/ideal/test'] = array(
+    'title' => 'Test',
+    'page callback' => 'ideal_test_payment',
+    'access arguments' => array('administer ideal'),
+    'file' => 'ideal.admin.inc',
+    'file path' => drupal_get_path('module', 'ideal') . '/includes',
+    'weight' => 2,
+    'type' => MENU_LOCAL_TASK,
+    );
   $items['ideal/return'] = array(
     'page callback' => 'ideal_return',
     'access arguments' => array('make ideal payments'),
Index: includes/ideal.admin.inc
===================================================================
--- includes/ideal.admin.inc	(revision 140)
+++ includes/ideal.admin.inc	(working copy)
@@ -198,7 +198,13 @@
 
   $payment = new iDEALPayment(array(
     'amount' => 15,
+    'purchase_id' => '1234567890123456',
+    'description' => '12345678901234567890123456789012'
   ), TRUE);
 
-  return drupal_get_form('ideal_form_payment', $payment, t('Perform test payments with the configured acquirer.'), 'admin/settings/ideal/test', 'admin/settings/ideal/test');
+  return drupal_get_form('ideal_form_payment', $payment
+    , t('Perform test payments with the configured acquirer.')
+    , 'admin/settings/ideal' // success
+    , 'admin/settings/ideal/test' // error
+    );
 }
Index: includes/ideal.payment.inc
===================================================================
--- includes/ideal.payment.inc	(revision 140)
+++ includes/ideal.payment.inc	(working copy)
@@ -15,6 +15,7 @@
 class iDEALPayment {
   public $pid = 0;
   public $amount = 0;
+  public $description = '';
   public $uid = 0;
   public $purchase_id = NULL;
   public $transaction_id = NULL;
@@ -33,11 +34,17 @@
    *   values.
    */
   function __construct(array $properties, $test = FALSE) {
+    global $user;
+    
+    $this->uid = $user->uid;
+    
     foreach ($properties as $property => $value) {
       if (property_exists($this, $property)) {
         $this->$property = $value;
+        //drupal_set_message("$property = $value");
       }
     }
+    
     $this->test = variable_get('ideal_test', TRUE) ? TRUE : $test;
   }
 
@@ -68,8 +75,9 @@
   /**
    * Save this payment to the database.
    */
-  protected function save() {
+  function save() {
     if ($this->pid == 0) {
+      // new payment
       $return = drupal_write_record('ideal_payment', $this);
     }
     else {
@@ -77,8 +85,13 @@
       $return = drupal_write_record('ideal_payment', $this, 'pid');
       db_query("DELETE FROM {ideal_entrance_code} WHERE pid = %d", $this->pid);
     }
-    if (isset($this->acquirer) && !$this->acquirer->entrance_code) {
-      db_query("INSERT INTO {ideal_entrance_code} VALUES (%d, %d)", $this->pid, $this->acquirer->entrance_code);
+    
+    if (isset($this->acquirer)) {
+      $entrance_code = $this->acquirer->entranceCode();
+      if (!empty($entrance_code)) {
+        db_query("INSERT INTO {ideal_entrance_code}(pid, entrance_code) VALUES (%d, %d)"
+          , $this->pid, $entrance_code);
+      }
     }
 
     return $return;
@@ -194,7 +207,6 @@
     if (!$this->entrance_code) {
       $this->entrance_code = md5(mt_rand());
     }
-
     return $this->entrance_code;
   }
 
@@ -228,10 +240,10 @@
     // Prefix the merchant ID with zeroes until it is 9 characters long.
     $merchant_id = str_repeat('0', 9 - strlen($merchant_id)) . $merchant_id;
     $defaults = array(
-      'createdatetimestamp' => $this->datetimestamp,
+      'createDateTimeStamp' => $this->datetimestamp,
       'Merchant' => array(
-        'merchant_id' => $merchant_id,
-        'sub_id' => variable_get('ideal_sub_id', 0),
+        'merchantID' => $merchant_id,
+        'subID' => variable_get('ideal_sub_id', 0),
         'authentication' => 'SHA1_RSA',
         'token' => $this->token(),
         'tokenCode' => $this->tokenCode($token_code_values),
@@ -242,9 +254,11 @@
     $xml .= '<' . $request_type . 'Req xmlns="http://www.idealdesk.com/Message" version="1.1.0">' . "\n";
     $xml .= $this->xml($fields);
     $xml .= '</' . $request_type . 'Req>';
+    watchdog('iDEAL', "XML request: ". htmlentities($xml), NULL, WATCHDOG_DEBUG);
 
     $url = $this->payment->test ? $this->test_url : $this->url;
     $response = drupal_http_request($url, array('content-type' => 'text/xml; charset="UTF-8"'), 'POST', $xml);
+    watchdog('iDEAL', "XML response: ". htmlentities($response->data), NULL, WATCHDOG_DEBUG);
 
     // The HTTP request went wrong.
     if (isset($response->error)) {
@@ -284,7 +298,7 @@
       $dom = simplexml_load_string($xml);
       $issuers = array('Short' => array(), 'Long' => array());
       foreach ($dom->Directory->Issuer as $issuer) {
-        $issuers[(string) $issuer->issuerList][(int) $issuer->issuerID] = (string) $issuer->issuerName;
+        $issuers[(string) $issuer->issuerList][(string) $issuer->issuerID] = (string) $issuer->issuerName;
       }
       return $issuers;
     }
@@ -335,7 +349,12 @@
       $dom = simplexml_load_string($xml);
       $this->payment->transaction_id = (string) $dom->Transaction->transactionID;
       $this->payment->save();
-      drupal_goto((string) $dom->AcquirerTrxRes->issuerAuthenticationURL);
+      
+      //drupal_goto((string) $dom->Issuer->issuerAuthenticationURL);
+      $location_header = 'Location: '. (string) $dom->Issuer->issuerAuthenticationURL;
+      //drupal_set_message('issuerAuthenticationURL: '. $location_header);
+      header($location_header, TRUE, 302);
+      exit();
     }
     return FALSE;
   }
@@ -353,17 +372,17 @@
       return $cache->data;
     }
     else {
-			$issuers = $this->directoryRequest();
-			// Cache issuers for 24h in case of succes. If the request fails, cache
-			// the result for ten minutes to prevent errors from repeatedly popping
-			// up.
-			$lifetime = 86400;
-			if (!$issuers || empty($issuers['Short'])) {
-				$lifetime = 600;
-				watchdog('iDEAL', t('iDEAL could not retrieve the list of issuing banks and will try again in ten minutes.'), NULL, WATCHDOG_ERROR);
-			}
-			cache_set('ideal_issuers', $issuers, 'cache', time() + $lifetime);
-			return $issuers;
+      $issuers = $this->directoryRequest();
+      // Cache issuers for 24h in case of succes. If the request fails, cache
+      // the result for ten minutes to prevent errors from repeatedly popping
+      // up.
+      $lifetime = 86400;
+      if (!$issuers || empty($issuers['Short'])) {
+        $lifetime = 600;
+        watchdog('iDEAL', t('iDEAL could not retrieve the list of issuing banks and will try again in ten minutes.'), NULL, WATCHDOG_ERROR);
+      }
+      cache_set('ideal_issuers', $issuers, 'cache', time() + $lifetime);
+      return $issuers;
     }
   }
 }
@@ -435,6 +454,18 @@
       '#value' => $minimum_amount,
     );
   }
+  else {
+    $form['amount'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Amount'),
+      '#description' => $minimum_amount > 0 ? t('The minimum amount is €!euros.!cents', array('!euros' => $euros, '!cents' => $cents)) : NULL,
+      '#default_value' => $payment->amount,
+      '#size' => 16,
+      '#maxlength' => 16,
+      '#field_prefix' => '€',
+      '#required' => TRUE,
+    );
+  }
   $options = array('ideal_choose' => t('Choose your bank') . '...');
   foreach ($issuers['Short'] as $issuer_id => $issuer_name) {
     $options[$issuer_id] = $issuer_name;
@@ -494,14 +525,18 @@
   // to reimplement it.
   $values = $form_state['values'];
   $payment = $values['payment'];
+  $payment->amount = $values['amount'];
   if (!$payment->acquirer->transactionRequest($values['issuer'])) {
     $form_state['redirect'] = $values['redirect_error'];
   }
+  else {
+    $form_state['redirect'] = $values['redirect_success'];
+  }
 }
 
 /**
  * Process a user who just returned from his issuer's website after a payment.
  */
 function ideal_return() {
-  
-}
\ No newline at end of file
+  return t('Terug uit iDEAL.');
+}
