shop.balmet.com

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

worldpay.php (16832B)


      1 <?php
      2 
      3 class ModelExtensionPaymentWorldpay extends Model {
      4 
      5 	public function getMethod($address, $total) {
      6 		$this->load->language('extension/payment/worldpay');
      7 
      8 		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$this->config->get('worldpay_geo_zone_id') . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");
      9 
     10 		if ($this->config->get('payment_worldpay_total') > 0 && $this->config->get('payment_worldpay_total') > $total) {
     11 			$status = false;
     12 		} elseif (!$this->config->get('worldpay_geo_zone_id')) {
     13 			$status = true;
     14 		} elseif ($query->num_rows) {
     15 			$status = true;
     16 		} else {
     17 			$status = false;
     18 		}
     19 
     20 		$method_data = array();
     21 
     22 		if ($status) {
     23 			$method_data = array(
     24 				'code' => 'worldpay',
     25 				'title' => $this->language->get('text_title'),
     26 				'terms' => '',
     27 				'sort_order' => $this->config->get('worldpay_sort_order')
     28 			);
     29 		}
     30 
     31 		return $method_data;
     32 	}
     33 
     34 	public function getCards($customer_id) {
     35 
     36 		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "worldpay_card WHERE customer_id = '" . (int)$customer_id . "'");
     37 
     38 		$card_data = array();
     39 
     40 		$this->load->model('account/address');
     41 
     42 		foreach ($query->rows as $row) {
     43 
     44 			$card_data[] = array(
     45 				'card_id' => $row['card_id'],
     46 				'customer_id' => $row['customer_id'],
     47 				'token' => $row['token'],
     48 				'digits' => $row['digits'],
     49 				'expiry' => $row['expiry'],
     50 				'type' => $row['type'],
     51 			);
     52 		}
     53 		return $card_data;
     54 	}
     55 
     56 	public function addCard($order_id, $card_data) {
     57 		$this->db->query("INSERT into " . DB_PREFIX . "worldpay_card SET customer_id = '" . $this->db->escape($card_data['customer_id']) . "', order_id = '" . $this->db->escape($order_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']) . "'");
     58 	}
     59 
     60 	public function deleteCard($token) {
     61 		$this->db->query("DELETE FROM " . DB_PREFIX . "worldpay_card WHERE customer_id = '" . $this->customer->isLogged() . "' AND token = '" . $this->db->escape($token) . "'");
     62 
     63 		if ($this->db->countAffected() > 0) {
     64 			return true;
     65 		} else {
     66 			return false;
     67 		}
     68 	}
     69 
     70 	public function addOrder($order_info, $order_code) {
     71 		$this->db->query("INSERT INTO `" . DB_PREFIX . "worldpay_order` SET `order_id` = '" . (int)$order_info['order_id'] . "', `order_code` = '" . $this->db->escape($order_code) . "', `date_added` = now(), `date_modified` = now(), `currency_code` = '" . $this->db->escape($order_info['currency_code']) . "', `total` = '" . $this->currency->format($order_info['total'], $order_info['currency_code'], false, false) . "'");
     72 
     73 		return $this->db->getLastId();
     74 	}
     75 
     76 	public function getOrder($order_id) {
     77 		$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "worldpay_order` WHERE `order_id` = '" . (int)$order_id . "' LIMIT 1");
     78 
     79 		if ($qry->num_rows) {
     80 			$order = $qry->row;
     81 			$order['transactions'] = $this->getTransactions($order['worldpay_order_id']);
     82 
     83 			return $order;
     84 		} else {
     85 			return false;
     86 		}
     87 	}
     88 
     89 	public function addTransaction($worldpay_order_id, $type, $order_info) {
     90 		$this->db->query("INSERT INTO `" . DB_PREFIX . "worldpay_order_transaction` SET `worldpay_order_id` = '" . (int)$worldpay_order_id . "', `date_added` = now(), `type` = '" . $this->db->escape($type) . "', `amount` = '" . $this->currency->format($order_info['total'], $order_info['currency_code'], false, false) . "'");
     91 	}
     92 
     93 	public function getTransactions($worldpay_order_id) {
     94 		$qry = $this->db->query("SELECT * FROM `" . DB_PREFIX . "worldpay_order_transaction` WHERE `worldpay_order_id` = '" . (int)$worldpay_order_id . "'");
     95 
     96 		if ($qry->num_rows) {
     97 			return $qry->rows;
     98 		} else {
     99 			return false;
    100 		}
    101 	}
    102 
    103 	public function recurringPayment($item, $order_id_rand, $token) {
    104 
    105 		$this->load->model('checkout/recurring');
    106 		$this->load->model('extension/payment/worldpay');
    107 		//trial information
    108 		if ($item['recurring']['trial'] == 1) {
    109 			$price = $item['recurring']['trial_price'];
    110 			$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'];
    111 			$trial_text = sprintf($this->language->get('text_trial'), $trial_amt, $item['recurring']['trial_cycle'], $item['recurring']['trial_frequency'], $item['recurring']['trial_duration']);
    112 		} else {
    113 			$price = $item['recurring']['price'];
    114 			$trial_text = '';
    115 		}
    116 
    117 		$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'];
    118 		$recurring_description = $trial_text . sprintf($this->language->get('text_recurring'), $recurring_amt, $item['recurring']['cycle'], $item['recurring']['frequency']);
    119 
    120 		if ($item['recurring']['duration'] > 0) {
    121 			$recurring_description .= sprintf($this->language->get('text_length'), $item['recurring']['duration']);
    122 		}
    123 
    124 		$order_recurring_id = $this->model_checkout_recurring->addRecurring($this->session->data['order_id'], $recurring_description, $item['recurring']);
    125 		
    126 		$this->model_checkout_recurring->editReference($order_recurring_id, $order_id_rand);
    127 
    128 		$order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
    129 
    130 		$order = array(
    131 			"token" => $token,
    132 			"orderType" => 'RECURRING',
    133 			"amount" => (int)($price * 100),
    134 			"currencyCode" => $order_info['currency_code'],
    135 			"name" => $order_info['firstname'] . ' ' . $order_info['lastname'],
    136 			"orderDescription" => $order_info['store_name'] . ' - ' . date('Y-m-d H:i:s'),
    137 			"customerOrderCode" => 'orderRecurring-' . $order_recurring_id
    138 		);
    139 
    140 		$this->model_extension_payment_worldpay->logger($order);
    141 
    142 		$response_data = $this->model_extension_payment_worldpay->sendCurl('orders', $order);
    143 
    144 		$this->model_extension_payment_worldpay->logger($response_data);
    145 
    146 		$next_payment = new DateTime('now');
    147 		$trial_end = new DateTime('now');
    148 		$subscription_end = new DateTime('now');
    149 
    150 		if ($item['recurring']['trial'] == 1 && $item['recurring']['trial_duration'] != 0) {
    151 			$next_payment = $this->calculateSchedule($item['recurring']['trial_frequency'], $next_payment, $item['recurring']['trial_cycle']);
    152 			$trial_end = $this->calculateSchedule($item['recurring']['trial_frequency'], $trial_end, $item['recurring']['trial_cycle'] * $item['recurring']['trial_duration']);
    153 		} elseif ($item['recurring']['trial'] == 1) {
    154 			$next_payment = $this->calculateSchedule($item['recurring']['trial_frequency'], $next_payment, $item['recurring']['trial_cycle']);
    155 			$trial_end = new DateTime('0000-00-00');
    156 		}
    157 
    158 		if ($trial_end > $subscription_end && $item['recurring']['duration'] != 0) {
    159 			$subscription_end = new DateTime(date_format($trial_end, 'Y-m-d H:i:s'));
    160 			$subscription_end = $this->calculateSchedule($item['recurring']['frequency'], $subscription_end, $item['recurring']['cycle'] * $item['recurring']['duration']);
    161 		} elseif ($trial_end == $subscription_end && $item['recurring']['duration'] != 0) {
    162 			$next_payment = $this->calculateSchedule($item['recurring']['frequency'], $next_payment, $item['recurring']['cycle']);
    163 			$subscription_end = $this->calculateSchedule($item['recurring']['frequency'], $subscription_end, $item['recurring']['cycle'] * $item['recurring']['duration']);
    164 		} elseif ($trial_end > $subscription_end && $item['recurring']['duration'] == 0) {
    165 			$subscription_end = new DateTime('0000-00-00');
    166 		} elseif ($trial_end == $subscription_end && $item['recurring']['duration'] == 0) {
    167 			$next_payment = $this->calculateSchedule($item['recurring']['frequency'], $next_payment, $item['recurring']['cycle']);
    168 			$subscription_end = new DateTime('0000-00-00');
    169 		}
    170 
    171 		if (isset($response_data->paymentStatus) && $response_data->paymentStatus == 'SUCCESS') {
    172 			$this->addRecurringOrder($order_info, $response_data->orderCode, $token, $price, $order_recurring_id, date_format($trial_end, 'Y-m-d H:i:s'), date_format($subscription_end, 'Y-m-d H:i:s'));
    173 
    174 			$this->updateRecurringOrder($order_recurring_id, date_format($next_payment, 'Y-m-d H:i:s'));
    175 
    176 			$this->addProfileTransaction($order_recurring_id, $response_data->orderCode, $price, 1);
    177 		} else {
    178 			$this->addProfileTransaction($order_recurring_id, '', $price, 4);
    179 		}
    180 	}
    181 
    182 	public function cronPayment() {
    183 
    184 		$this->load->model('account/order');
    185 		$this->load->model('checkout/order');
    186 		$profiles = $this->getProfiles();
    187 		$cron_data = array();
    188 		$i = 1;
    189 		foreach ($profiles as $profile) {
    190 			$recurring_order = $this->getRecurringOrder($profile['order_recurring_id']);
    191 
    192 			$today = new DateTime('now');
    193 			$unlimited = new DateTime('0000-00-00');
    194 			$next_payment = new DateTime($recurring_order['next_payment']);
    195 			$trial_end = new DateTime($recurring_order['trial_end']);
    196 			$subscription_end = new DateTime($recurring_order['subscription_end']);
    197 
    198 			$order_info = $this->model_checkout_order->getOrder($profile['order_id']);
    199 
    200 			if (($today > $next_payment) && ($trial_end > $today || $trial_end == $unlimited)) {
    201 				$price = $this->currency->format($profile['trial_price'], $order_info['currency_code'], false, false);
    202 				$frequency = $profile['trial_frequency'];
    203 				$cycle = $profile['trial_cycle'];
    204 			} elseif (($today > $next_payment) && ($subscription_end > $today || $subscription_end == $unlimited)) {
    205 				$price = $this->currency->format($profile['recurring_price'], $order_info['currency_code'], false, false);
    206 				$frequency = $profile['recurring_frequency'];
    207 				$cycle = $profile['recurring_cycle'];
    208 			} else {
    209 				continue;
    210 			}
    211 
    212 			$order = array(
    213 				"token" => $recurring_order['token'],
    214 				"orderType" => 'RECURRING',
    215 				"amount" => (int)($price * 100),
    216 				"currencyCode" => $order_info['currency_code'],
    217 				"name" => $order_info['firstname'] . ' ' . $order_info['lastname'],
    218 				"orderDescription" => $order_info['store_name'] . ' - ' . date('Y-m-d H:i:s'),
    219 				"customerOrderCode" => 'orderRecurring-' . $profile['order_recurring_id'] . '-repeat-' . $i++
    220 			);
    221 
    222 			$this->model_extension_payment_worldpay->logger($order);
    223 
    224 			$response_data = $this->model_extension_payment_worldpay->sendCurl('orders', $order);
    225 
    226 			$this->model_extension_payment_worldpay->logger($response_data);
    227 
    228 			$cron_data[] = $response_data;
    229 
    230 			if (isset($response_data->paymentStatus) && $response_data->paymentStatus == 'SUCCESS') {
    231 				$this->addProfileTransaction($profile['order_recurring_id'], $response_data->orderCode, $price, 1);
    232 				$next_payment = $this->calculateSchedule($frequency, $next_payment, $cycle);
    233 				$next_payment = date_format($next_payment, 'Y-m-d H:i:s');
    234 				$this->updateRecurringOrder($profile['order_recurring_id'], $next_payment);
    235 			} else {
    236 				$this->addProfileTransaction($profile['order_recurring_id'], '', $price, 4);
    237 			}
    238 		}
    239 		$log = new Log('worldpay_recurring_orders.log');
    240 		$log->write(print_r($cron_data, 1));
    241 		return $cron_data;
    242 	}
    243 
    244 	private function calculateSchedule($frequency, $next_payment, $cycle) {
    245 		if ($frequency == 'semi_month') {
    246 			$day = date_format($next_payment, 'd');
    247 			$value = 15 - $day;
    248 			$isEven = false;
    249 			if ($cycle % 2 == 0) {
    250 				$isEven = true;
    251 			}
    252 
    253 			$odd = ($cycle + 1) / 2;
    254 			$plus_even = ($cycle / 2) + 1;
    255 			$minus_even = $cycle / 2;
    256 
    257 			if ($day == 1) {
    258 				$odd = $odd - 1;
    259 				$plus_even = $plus_even - 1;
    260 				$day = 16;
    261 			}
    262 
    263 			if ($day <= 15 && $isEven) {
    264 				$next_payment->modify('+' . $value . ' day');
    265 				$next_payment->modify('+' . $minus_even . ' month');
    266 			} elseif ($day <= 15) {
    267 				$next_payment->modify('first day of this month');
    268 				$next_payment->modify('+' . $odd . ' month');
    269 			} elseif ($day > 15 && $isEven) {
    270 				$next_payment->modify('first day of this month');
    271 				$next_payment->modify('+' . $plus_even . ' month');
    272 			} elseif ($day > 15) {
    273 				$next_payment->modify('+' . $value . ' day');
    274 				$next_payment->modify('+' . $odd . ' month');
    275 			}
    276 		} else {
    277 			$next_payment->modify('+' . $cycle . ' ' . $frequency);
    278 		}
    279 		return $next_payment;
    280 	}
    281 
    282 	private function addRecurringOrder($order_info, $order_code, $token, $price, $order_recurring_id, $trial_end, $subscription_end) {
    283 		$this->db->query("INSERT INTO `" . DB_PREFIX . "worldpay_order_recurring` SET `order_id` = '" . (int)$order_info['order_id'] . "', `order_recurring_id` = '" . (int)$order_recurring_id . "', `order_code` = '" . $this->db->escape($order_code) . "', `token` = '" . $this->db->escape($token) . "', `date_added` = now(), `date_modified` = now(), `next_payment` = now(), `trial_end` = '" . $trial_end . "', `subscription_end` = '" . $subscription_end . "', `currency_code` = '" . $this->db->escape($order_info['currency_code']) . "', `total` = '" . $this->currency->format($price, $order_info['currency_code'], false, false) . "'");
    284 	}
    285 
    286 	private function updateRecurringOrder($order_recurring_id, $next_payment) {
    287 		$this->db->query("UPDATE `" . DB_PREFIX . "worldpay_order_recurring` SET `next_payment` = '" . $next_payment . "', `date_modified` = now() WHERE `order_recurring_id` = '" . (int)$order_recurring_id . "'");
    288 	}
    289 
    290 	private function getRecurringOrder($order_recurring_id) {
    291 		$qry = $this->db->query("SELECT * FROM " . DB_PREFIX . "worldpay_order_recurring WHERE order_recurring_id = '" . (int)$order_recurring_id . "'");
    292 		return $qry->row;
    293 	}
    294 
    295 	private function addProfileTransaction($order_recurring_id, $order_code, $price, $type) {
    296 		$this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$order_recurring_id . "', `date_added` = NOW(), `amount` = '" . (float)$price . "', `type` = '" . (int)$type . "', `reference` = '" . $this->db->escape($order_code) . "'");
    297 	}
    298 
    299 	private function getProfiles() {
    300 		$sql = "
    301 			SELECT `or`.order_recurring_id
    302 			FROM `" . DB_PREFIX . "order_recurring` `or`
    303 			JOIN `" . DB_PREFIX . "order` `o` USING(`order_id`)
    304 			WHERE o.payment_code = 'worldpay'";
    305 
    306 		$qry = $this->db->query($sql);
    307 
    308 		$order_recurring = array();
    309 
    310 		foreach ($qry->rows as $profile) {
    311 			$order_recurring[] = $this->getProfile($profile['order_recurring_id']);
    312 		}
    313 		return $order_recurring;
    314 	}
    315 
    316 	private function getProfile($order_recurring_id) {
    317 		$qry = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_recurring WHERE order_recurring_id = " . (int)$order_recurring_id);
    318 		return $qry->row;
    319 	}
    320 
    321 	public function getWorldpayOrder($worldpay_order_id) {
    322 		$qry = $this->db->query("SELECT * FROM " . DB_PREFIX . "worldpay_order WHERE order_code = " . (int)$worldpay_order_id);
    323 		return $qry->row;
    324 	}
    325 
    326 	public function updateCronJobRunTime() {
    327 		$this->db->query("DELETE FROM `" . DB_PREFIX . "setting` WHERE `code` = 'worldpay' AND `key` = 'worldpay_last_cron_job_run'");
    328 		$this->db->query("INSERT INTO `" . DB_PREFIX . "setting` (`store_id`, `code`, `key`, `value`, `serialized`) VALUES (0, 'worldpay', 'worldpay_last_cron_job_run', NOW(), 0)");
    329 	}
    330 
    331 	public function sendCurl($url, $order = null) {
    332 		$curl = curl_init();
    333 		curl_setopt($curl, CURLOPT_URL, 'https://api.worldpay.com/v1/' . $url);
    334 		$content_length = 0;
    335 		if ($order) {
    336 			$json = json_encode($order);
    337 			$content_length = strlen($json);
    338 			curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
    339 			curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
    340 		}
    341 		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    342 		curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 0);
    343 		curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    344 		curl_setopt($curl, CURLOPT_TIMEOUT, 10);
    345 		curl_setopt(
    346 				$curl, CURLOPT_HTTPHEADER, array(
    347 			"Authorization: " . $this->config->get('payment_worldpay_service_key'),
    348 			"Content-Type: application/json",
    349 			"Content-Length: " . $content_length
    350 				)
    351 		);
    352 
    353 		$result = json_decode(curl_exec($curl));
    354 		curl_close($curl);
    355 		return $result;
    356 	}
    357 
    358 	public function logger($data) {
    359 		if ($this->config->get('worldpay_debug')) {
    360 			$log = new Log('worldpay_debug.log');
    361 			$backtrace = debug_backtrace();
    362 			$log->write($backtrace[6]['class'] . '::' . $backtrace[6]['function'] . ' Data:  ' . print_r($data, 1));
    363 		}
    364 	}
    365 
    366 	public function recurringPayments() {
    367 		/*
    368 		 * Used by the checkout to state the module
    369 		 * supports recurring profiles.
    370 		 */
    371 		return true;
    372 	}
    373 
    374 }