shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

sagepay_direct.php (21201B)


      1 <?php
      2 class ModelExtensionPaymentSagePayDirect extends Model {
      3 	public function getMethod($address, $total) {
      4 		$this->load->language('extension/payment/sagepay_direct');
      5 
      6 		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$this->config->get('payment_sagepay_direct_geo_zone_id') . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");
      7 
      8 		if ($this->config->get('sagepay_direct_total') > 0 && $this->config->get('payment_sagepay_direct_total') > $total) {
      9 			$status = false;
     10 		} elseif (!$this->config->get('payment_sagepay_direct_geo_zone_id')) {
     11 			$status = true;
     12 		} elseif ($query->num_rows) {
     13 			$status = true;
     14 		} else {
     15 			$status = false;
     16 		}
     17 
     18 		$method_data = array();
     19 
     20 		if ($status) {
     21 			$method_data = array(
     22 				'code' => 'sagepay_direct',
     23 				'title' => $this->language->get('text_title'),
     24 				'terms' => '',
     25 				'sort_order' => $this->config->get('payment_sagepay_direct_sort_order')
     26 			);
     27 		}
     28 
     29 		return $method_data;
     30 	}
     31 
     32 	public function getCards($customer_id) {
     33 
     34 		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "sagepay_direct_card WHERE customer_id = '" . (int)$customer_id . "' ORDER BY card_id");
     35 
     36 		$card_data = array();
     37 
     38 		$this->load->model('account/address');
     39 
     40 		foreach ($query->rows as $row) {
     41 
     42 			$card_data[] = array(
     43 				'card_id' => $row['card_id'],
     44 				'customer_id' => $row['customer_id'],
     45 				'token' => $row['token'],
     46 				'digits' => '**** ' . $row['digits'],
     47 				'expiry' => $row['expiry'],
     48 				'type' => $row['type'],
     49 			);
     50 		}
     51 		return $card_data;
     52 	}
     53 
     54 	public function addCard($card_data) {
     55 		$this->db->query("INSERT into " . DB_PREFIX . "sagepay_direct_card SET customer_id = '" . $this->db->escape($card_data['customer_id']) . "', digits = '" . $this->db->escape($card_data['Last4Digits']) . "', expiry = '" . $this->db->escape($card_data['ExpiryDate']) . "', type = '" . $this->db->escape($card_data['CardType']) . "', token = '" . $this->db->escape($card_data['Token']) . "'");
     56 
     57 		return $this->db->getLastId();
     58 	}
     59 
     60 	public function updateCard($card_id, $token) {
     61 		$this->db->query("UPDATE " . DB_PREFIX . "sagepay_direct_card SET token = '" . $this->db->escape($token) . "' WHERE card_id = '" . (int)$card_id . "'");
     62 	}
     63 
     64 	public function getCard($card_id, $token) {
     65 		$qry = $this->db->query("SELECT * FROM " . DB_PREFIX . "sagepay_direct_card WHERE (card_id = '" . $this->db->escape($card_id) . "' OR token = '" . $this->db->escape($token) . "') AND customer_id = '" . (int)$this->customer->getId() . "'");
     66 
     67 		if ($qry->num_rows) {
     68 			return $qry->row;
     69 		} else {
     70 			return false;
     71 		}
     72 	}
     73 
     74 	public function deleteCard($card_id) {
     75 		$this->db->query("DELETE FROM " . DB_PREFIX . "sagepay_direct_card WHERE card_id = '" . (int)$card_id . "'");
     76 	}
     77 
     78 	public function addOrder($order_id, $response_data, $payment_data, $card_id) {
     79 		$this->db->query("INSERT INTO `" . DB_PREFIX . "sagepay_direct_order` SET `order_id` = '" . (int)$order_id . "', `VPSTxId` = '" . $this->db->escape($response_data['VPSTxId']) . "', `VendorTxCode` = '" . $this->db->escape($payment_data['VendorTxCode']) . "', `SecurityKey` = '" . $this->db->escape($response_data['SecurityKey']) . "', `TxAuthNo` = '" . $this->db->escape($response_data['TxAuthNo']) . "', `date_added` = now(), `date_modified` = now(), `currency_code` = '" . $this->db->escape($payment_data['Currency']) . "', `total` = '" . $this->currency->format($payment_data['Amount'], $payment_data['Currency'], false, false) . "', `card_id` = '" . $this->db->escape($card_id) . "'");
     80 
     81 		return $this->db->getLastId();
     82 	}
     83 
     84 	public function getOrder($order_id) {
     85 		$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "sagepay_direct_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
     86 
     87 		if ($qry->num_rows) {
     88 			$order = $qry->row;
     89 			$order['transactions'] = $this->getTransactions($order['sagepay_direct_order_id']);
     90 
     91 			return $order;
     92 		} else {
     93 			return false;
     94 		}
     95 	}
     96 
     97 	public function updateOrder($order_info, $data) {
     98 		$this->db->query("UPDATE `" . DB_PREFIX . "sagepay_direct_order` SET `SecurityKey` = '" . $this->db->escape($data['SecurityKey']) . "',  `VPSTxId` = '" . $this->db->escape($data['VPSTxId']) . "', `TxAuthNo` = '" . $this->db->escape($data['TxAuthNo']) . "' WHERE `order_id` = '" . (int)$order_info['order_id'] . "'");
     99 
    100 		return $this->db->getLastId();
    101 	}
    102 
    103 	public function deleteOrder($vendor_tx_code) {
    104 		$this->db->query("DELETE FROM `" . DB_PREFIX . "sagepay_direct_order` WHERE order_id = '" . $vendor_tx_code . "'");
    105 	}
    106 
    107 	public function addTransaction($sagepay_direct_order_id, $type, $order_info) {
    108 		$this->db->query("INSERT INTO `" . DB_PREFIX . "sagepay_direct_order_transaction` SET `sagepay_direct_order_id` = '" . (int)$sagepay_direct_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . $this->currency->format($order_info['total'], $order_info['currency_code'], false, false) . "'");
    109 	}
    110 
    111 	private function getTransactions($sagepay_direct_order_id) {
    112 		$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "sagepay_direct_order_transaction` WHERE `sagepay_direct_order_id` = '" . (int)$sagepay_direct_order_id . "'");
    113 
    114 		if ($qry->num_rows) {
    115 			return $qry->rows;
    116 		} else {
    117 			return false;
    118 		}
    119 	}
    120 
    121 	public function recurringPayment($item, $vendor_tx_code) {
    122 
    123 		$this->load->model('checkout/recurring');
    124 		$this->load->model('extension/payment/sagepay_direct');
    125 		//trial information
    126 		if ($item['recurring']['trial'] == 1) {
    127 			$price = $item['recurring']['trial_price'];
    128 			$trial_amt = $this->currency->format($this->tax->calculate($item['recurring']['trial_price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity'] . ' ' . $this->session->data['currency'];
    129 			$trial_text = sprintf($this->language->get('text_trial'), $trial_amt, $item['recurring']['trial_cycle'], $item['recurring']['trial_frequency'], $item['recurring']['trial_duration']);
    130 		} else {
    131 			$price = $item['recurring']['price'];
    132 			$trial_text = '';
    133 		}
    134 
    135 		$recurring_amt = $this->currency->format($this->tax->calculate($item['recurring']['price'], $item['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency'], false, false) * $item['quantity'] . ' ' . $this->session->data['currency'];
    136 		$recurring_description = $trial_text . sprintf($this->language->get('text_recurring'), $recurring_amt, $item['recurring']['cycle'], $item['recurring']['frequency']);
    137 
    138 		if ($item['recurring']['duration'] > 0) {
    139 			$recurring_description .= sprintf($this->language->get('text_length'), $item['recurring']['duration']);
    140 		}
    141 
    142 		//create new recurring and set to pending status as no payment has been made yet.
    143 		$order_recurring_id = $this->model_checkout_recurring->addRecurring($this->session->data['order_id'], $recurring_description, $item['recurring']);
    144 		
    145 		$this->model_checkout_recurring->addReference($order_recurring_id, $vendor_tx_code);
    146 
    147 		$order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
    148 
    149 		$sagepay_order_info = $this->getOrder($this->session->data['order_id']);
    150 
    151 		$response_data = $this->setPaymentData($order_info, $sagepay_order_info, $price, $order_recurring_id, $item['recurring']['name']);
    152 
    153 		$next_payment = new DateTime('now');
    154 		$trial_end = new DateTime('now');
    155 		$subscription_end = new DateTime('now');
    156 
    157 		if ($item['recurring']['trial'] == 1 && $item['recurring']['trial_duration'] != 0) {
    158 			$next_payment = $this->calculateSchedule($item['recurring']['trial_frequency'], $next_payment, $item['recurring']['trial_cycle']);
    159 			$trial_end = $this->calculateSchedule($item['recurring']['trial_frequency'], $trial_end, $item['recurring']['trial_cycle'] * $item['recurring']['trial_duration']);
    160 		} elseif ($item['recurring_trial'] == 1) {
    161 			$next_payment = $this->calculateSchedule($item['recurring']['trial_frequency'], $next_payment, $item['recurring']['trial_cycle']);
    162 			$trial_end = new DateTime('0000-00-00');
    163 		}
    164 
    165 		if ($trial_end > $subscription_end && $item['recurring']['duration'] != 0) {
    166 			$subscription_end = new DateTime(date_format($trial_end, 'Y-m-d H:i:s'));
    167 			$subscription_end = $this->calculateSchedule($item['recurring']['frequency'], $subscription_end, $item['recurring']['cycle'] * $item['recurring']['duration']);
    168 		} elseif ($trial_end == $subscription_end && $item['recurring']['duration'] != 0) {
    169 			$next_payment = $this->calculateSchedule($item['recurring']['frequency'], $next_payment, $item['recurring']['cycle']);
    170 			$subscription_end = $this->calculateSchedule($item['recurring']['frequency'], $subscription_end, $item['recurring']['cycle'] * $item['recurring']['duration']);
    171 		} elseif ($trial_end > $subscription_end && $item['recurring']['duration'] == 0) {
    172 			$subscription_end = new DateTime('0000-00-00');
    173 		} elseif ($trial_end == $subscription_end && $item['recurring']['duration'] == 0) {
    174 			$next_payment = $this->calculateSchedule($item['recurring']['frequency'], $next_payment, $item['recurring']['cycle']);
    175 			$subscription_end = new DateTime('0000-00-00');
    176 		}
    177 
    178 		$this->addRecurringOrder($this->session->data['order_id'], $response_data, $order_recurring_id, date_format($trial_end, 'Y-m-d H:i:s'), date_format($subscription_end, 'Y-m-d H:i:s'));
    179 
    180 		if ($response_data['Status'] == 'OK') {
    181 			$this->updateRecurringOrder($order_recurring_id, date_format($next_payment, 'Y-m-d H:i:s'));
    182 
    183 			$this->addRecurringTransaction($order_recurring_id, $response_data, 1);
    184 		} else {
    185 			$this->addRecurringTransaction($order_recurring_id, $response_data, 4);
    186 		}
    187 	}
    188 
    189 	private function setPaymentData($order_info, $sagepay_order_info, $price, $order_recurring_id, $recurring_name, $i = null) {
    190 		if ($this->config->get('payment_sagepay_direct_test') == 'live') {
    191 			$url = 'https://live.sagepay.com/gateway/service/repeat.vsp';
    192 			$payment_data['VPSProtocol'] = '3.00';
    193 		} elseif ($this->config->get('payment_sagepay_direct_test') == 'test') {
    194 			$url = 'https://test.sagepay.com/gateway/service/repeat.vsp';
    195 			$payment_data['VPSProtocol'] = '3.00';
    196 		} elseif ($this->config->get('payment_sagepay_direct_test') == 'sim') {
    197 			$url = 'https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRepeatTx';
    198 			$payment_data['VPSProtocol'] = '2.23';
    199 		}
    200 
    201 		$payment_data['TxType'] = 'REPEAT';
    202 		$payment_data['Vendor'] = $this->config->get('payment_sagepay_direct_vendor');
    203 		$payment_data['VendorTxCode'] = $order_recurring_id . 'RSD' . strftime("%Y%m%d%H%M%S") . mt_rand(1, 999);
    204 		$payment_data['Amount'] = $this->currency->format($price, $this->session->data['currency'], false, false);
    205 		$payment_data['Currency'] = $this->session->data['currency'];
    206 		$payment_data['Description'] = substr($recurring_name, 0, 100);
    207 		$payment_data['RelatedVPSTxId'] = trim($sagepay_order_info['VPSTxId'], '{}');
    208 		$payment_data['RelatedVendorTxCode'] = $sagepay_order_info['VendorTxCode'];
    209 		$payment_data['RelatedSecurityKey'] = $sagepay_order_info['SecurityKey'];
    210 		$payment_data['RelatedTxAuthNo'] = $sagepay_order_info['TxAuthNo'];
    211 
    212 		if (!empty($order_info['shipping_lastname'])) {
    213 			$payment_data['DeliverySurname'] = substr($order_info['shipping_lastname'], 0, 20);
    214 			$payment_data['DeliveryFirstnames'] = substr($order_info['shipping_firstname'], 0, 20);
    215 			$payment_data['DeliveryAddress1'] = substr($order_info['shipping_address_1'], 0, 100);
    216 
    217 			if ($order_info['shipping_address_2']) {
    218 				$payment_data['DeliveryAddress2'] = $order_info['shipping_address_2'];
    219 			}
    220 
    221 			$payment_data['DeliveryCity'] = substr($order_info['shipping_city'], 0, 40);
    222 			$payment_data['DeliveryPostCode'] = substr($order_info['shipping_postcode'], 0, 10);
    223 			$payment_data['DeliveryCountry'] = $order_info['shipping_iso_code_2'];
    224 
    225 			if ($order_info['shipping_iso_code_2'] == 'US') {
    226 				$payment_data['DeliveryState'] = $order_info['shipping_zone_code'];
    227 			}
    228 
    229 			$payment_data['CustomerName'] = substr($order_info['firstname'] . ' ' . $order_info['lastname'], 0, 100);
    230 			$payment_data['DeliveryPhone'] = substr($order_info['telephone'], 0, 20);
    231 		} else {
    232 			$payment_data['DeliveryFirstnames'] = $order_info['payment_firstname'];
    233 			$payment_data['DeliverySurname'] = $order_info['payment_lastname'];
    234 			$payment_data['DeliveryAddress1'] = $order_info['payment_address_1'];
    235 
    236 			if ($order_info['payment_address_2']) {
    237 				$payment_data['DeliveryAddress2'] = $order_info['payment_address_2'];
    238 			}
    239 
    240 			$payment_data['DeliveryCity'] = $order_info['payment_city'];
    241 			$payment_data['DeliveryPostCode'] = $order_info['payment_postcode'];
    242 			$payment_data['DeliveryCountry'] = $order_info['payment_iso_code_2'];
    243 
    244 			if ($order_info['payment_iso_code_2'] == 'US') {
    245 				$payment_data['DeliveryState'] = $order_info['payment_zone_code'];
    246 			}
    247 
    248 			$payment_data['DeliveryPhone'] = $order_info['telephone'];
    249 		}
    250 		$response_data = $this->sendCurl($url, $payment_data, $i);
    251 		$response_data['VendorTxCode'] = $payment_data['VendorTxCode'];
    252 		$response_data['Amount'] = $payment_data['Amount'];
    253 		$response_data['Currency'] = $payment_data['Currency'];
    254 
    255 		return $response_data;
    256 	}
    257 
    258 	public function cronPayment() {
    259 
    260 		$this->load->model('account/order');
    261 		$recurrings = $this->getProfiles();
    262 		$cron_data = array();
    263 		$i = 0;
    264 
    265 		foreach ($recurrings as $recurring) {
    266 
    267 			$recurring_order = $this->getRecurringOrder($recurring['order_recurring_id']);
    268 
    269 			$today = new DateTime('now');
    270 			$unlimited = new DateTime('0000-00-00');
    271 			$next_payment = new DateTime($recurring_order['next_payment']);
    272 			$trial_end = new DateTime($recurring_order['trial_end']);
    273 			$subscription_end = new DateTime($recurring_order['subscription_end']);
    274 
    275 			$order_info = $this->model_account_order->getOrder($recurring['order_id']);
    276 
    277 			if (($today > $next_payment) && ($trial_end > $today || $trial_end == $unlimited)) {
    278 				$price = $this->currency->format($recurring['trial_price'], $order_info['currency_code'], false, false);
    279 				$frequency = $recurring['trial_frequency'];
    280 				$cycle = $recurring['trial_cycle'];
    281 			} elseif (($today > $next_payment) && ($subscription_end > $today || $subscription_end == $unlimited)) {
    282 				$price = $this->currency->format($recurring['recurring_price'], $order_info['currency_code'], false, false);
    283 				$frequency = $recurring['recurring_frequency'];
    284 				$cycle = $recurring['recurring_cycle'];
    285 			} else {
    286 				continue;
    287 			}
    288 
    289 			$sagepay_order_info = $this->getOrder($recurring['order_id']);
    290 
    291 			$response_data = $this->setPaymentData($order_info, $sagepay_order_info, $price, $recurring['order_recurring_id'], $recurring['recurring_name'], $i);
    292 
    293 			$cron_data[] = $response_data;
    294 
    295 			if ($response_data['RepeatResponseData_' . $i++]['Status'] == 'OK') {
    296 				$this->addRecurringTransaction($recurring['order_recurring_id'], $response_data, 1);
    297 				$next_payment = $this->calculateSchedule($frequency, $next_payment, $cycle);
    298 				$next_payment = date_format($next_payment, 'Y-m-d H:i:s');
    299 				$this->updateRecurringOrder($recurring['order_recurring_id'], $next_payment);
    300 			} else {
    301 				$this->addRecurringTransaction($recurring['order_recurring_id'], $response_data, 4);
    302 			}
    303 		}
    304 		$log = new Log('sagepay_direct_recurring_orders.log');
    305 		$log->write(print_r($cron_data, 1));
    306 		return $cron_data;
    307 	}
    308 
    309 	private function calculateSchedule($frequency, $next_payment, $cycle) {
    310 		if ($frequency == 'semi_month') {
    311 			$day = date_format($next_payment, 'd');
    312 			$value = 15 - $day;
    313 			$is_even = false;
    314 			if ($cycle % 2 == 0) {
    315 				$is_even = true;
    316 			}
    317 
    318 			$odd = ($cycle + 1) / 2;
    319 			$plus_even = ($cycle / 2) + 1;
    320 			$minus_even = $cycle / 2;
    321 
    322 			if ($day == 1) {
    323 				$odd = $odd - 1;
    324 				$plus_even = $plus_even - 1;
    325 				$day = 16;
    326 			}
    327 
    328 			if ($day <= 15 && $is_even) {
    329 				$next_payment->modify('+' . $value . ' day');
    330 				$next_payment->modify('+' . $minus_even . ' month');
    331 			} elseif ($day <= 15) {
    332 				$next_payment->modify('first day of this month');
    333 				$next_payment->modify('+' . $odd . ' month');
    334 			} elseif ($day > 15 && $is_even) {
    335 				$next_payment->modify('first day of this month');
    336 				$next_payment->modify('+' . $plus_even . ' month');
    337 			} elseif ($day > 15) {
    338 				$next_payment->modify('+' . $value . ' day');
    339 				$next_payment->modify('+' . $odd . ' month');
    340 			}
    341 		} else {
    342 			$next_payment->modify('+' . $cycle . ' ' . $frequency);
    343 		}
    344 		return $next_payment;
    345 	}
    346 
    347 	private function addRecurringOrder($order_id, $response_data, $order_recurring_id, $trial_end, $subscription_end) {
    348 		$this->db->query("INSERT INTO `" . DB_PREFIX . "sagepay_direct_order_recurring` SET `order_id` = '" . (int)$order_id . "', `order_recurring_id` = '" . (int)$order_recurring_id . "', `VPSTxId` = '" . $this->db->escape($response_data['VPSTxId']) . "', `VendorTxCode` = '" . $this->db->escape($response_data['VendorTxCode']) . "', `SecurityKey` = '" . $this->db->escape($response_data['SecurityKey']) . "', `TxAuthNo` = '" . $this->db->escape($response_data['TxAuthNo']) . "', `date_added` = now(), `date_modified` = now(), `next_payment` = now(), `trial_end` = '" . $trial_end . "', `subscription_end` = '" . $subscription_end . "', `currency_code` = '" . $this->db->escape($response_data['Currency']) . "', `total` = '" . $this->currency->format($response_data['Amount'], $response_data['Currency'], false, false) . "'");
    349 	}
    350 
    351 	private function updateRecurringOrder($order_recurring_id, $next_payment) {
    352 		$this->db->query("UPDATE `" . DB_PREFIX . "sagepay_direct_order_recurring` SET `next_payment` = '" . $next_payment . "', `date_modified` = now() WHERE `order_recurring_id` = '" . (int)$order_recurring_id . "'");
    353 	}
    354 
    355 	private function getRecurringOrder($order_recurring_id) {
    356 		$qry = $this->db->query("SELECT * FROM " . DB_PREFIX . "sagepay_direct_order_recurring WHERE order_recurring_id = '" . (int)$order_recurring_id . "'");
    357 		return $qry->row;
    358 	}
    359 
    360 	private function addRecurringTransaction($order_recurring_id, $response_data, $type) {
    361 		$this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$order_recurring_id . "', `date_added` = NOW(), `amount` = '" . (float)$response_data['Amount'] . "', `type` = '" . (int)$type . "', `reference` = '" . $this->db->escape($response_data['VendorTxCode']) . "'");
    362 	}
    363 
    364 	private function getProfiles() {
    365 
    366 		$sql = "
    367 			SELECT `or`.order_recurring_id
    368 			FROM `" . DB_PREFIX . "order_recurring` `or`
    369 			JOIN `" . DB_PREFIX . "order` `o` USING(`order_id`)
    370 			WHERE o.payment_code = 'sagepay_direct'";
    371 
    372 		$qry = $this->db->query($sql);
    373 
    374 		$order_recurring = array();
    375 
    376 		foreach ($qry->rows as $recurring) {
    377 			$order_recurring[] = $this->getProfile($recurring['order_recurring_id']);
    378 		}
    379 		return $order_recurring;
    380 	}
    381 
    382 	private function getProfile($order_recurring_id) {
    383 		$qry = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_recurring WHERE order_recurring_id = " . (int)$order_recurring_id);
    384 		return $qry->row;
    385 	}
    386 
    387 	public function updateCronJobRunTime() {
    388 		$this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `code` = 'sagepay_direct' AND `key` = 'payment_sagepay_direct_last_cron_job_run'");
    389 		$this->db->query("INSERT INTO `" . DB_PREFIX . "setting` (`store_id`, `code`, `key`, `value`, `serialized`) VALUES (0, 'sagepay_direct', 'payment_sagepay_direct_last_cron_job_run', NOW(), 0)");
    390 	}
    391 
    392 	public function sendCurl($url, $payment_data, $i = null) {
    393 		$curl = curl_init($url);
    394 
    395 		curl_setopt($curl, CURLOPT_PORT, 443);
    396 		curl_setopt($curl, CURLOPT_HEADER, 0);
    397 		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
    398 		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    399 		curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
    400 		curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
    401 		curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
    402 		curl_setopt($curl, CURLOPT_POST, 1);
    403 		curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($payment_data));
    404 
    405 		$response = curl_exec($curl);
    406 
    407 		curl_close($curl);
    408 
    409 		$response_info = explode(chr(10), $response);
    410 
    411 		foreach ($response_info as $string) {
    412 			if (strpos($string, '=') && isset($i)) {
    413 				$parts = explode('=', $string, 2);
    414 				$data['RepeatResponseData_' . $i][trim($parts[0])] = trim($parts[1]);
    415 			} elseif (strpos($string, '=')) {
    416 				$parts = explode('=', $string, 2);
    417 				$data[trim($parts[0])] = trim($parts[1]);
    418 			}
    419 		}
    420 		return $data;
    421 	}
    422 
    423 	public function logger($title, $data) {
    424 		if ($this->config->get('payment_sagepay_direct_debug')) {
    425 			$log = new Log('sagepay_direct.log');
    426 			$backtrace = debug_backtrace();
    427 			$log->write($backtrace[6]['class'] . '::' . $backtrace[6]['function'] . ' - ' . $title . ': ' . print_r($data, 1));
    428 		}
    429 	}
    430 
    431 	public function recurringPayments() {
    432 		/*
    433 		 * Used by the checkout to state the module
    434 		 * supports recurring recurrings.
    435 		 */
    436 		return true;
    437 	}
    438 }