shop.balmet.com

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

sagepay_server.php (20261B)


      1 <?php
      2 class ControllerExtensionPaymentSagepayServer extends Controller {
      3 	public function index() {
      4 		$this->load->language('extension/payment/sagepay_server');
      5 		$data['text_credit_card'] = $this->language->get('text_credit_card');
      6 		$data['text_card_name'] = $this->language->get('text_card_name');
      7 		$data['text_card_type'] = $this->language->get('text_card_type');
      8 		$data['text_card_digits'] = $this->language->get('text_card_digits');
      9 		$data['text_card_expiry'] = $this->language->get('text_card_expiry');
     10 		$data['text_loading'] = $this->language->get('text_loading');
     11 		$data['text_confirm_delete'] = $this->language->get('text_confirm_delete');
     12 
     13 		$data['entry_card'] = $this->language->get('entry_card');
     14 		$data['entry_card_existing'] = $this->language->get('entry_card_existing');
     15 		$data['entry_card_new'] = $this->language->get('entry_card_new');
     16 		$data['entry_card_save'] = $this->language->get('entry_card_save');
     17 		$data['entry_cc_choice'] = $this->language->get('entry_cc_choice');
     18 
     19 		$data['button_confirm'] = $this->language->get('button_confirm');
     20 		$data['button_delete_card'] = $this->language->get('button_delete_card');
     21 
     22 		$data['action'] = $this->url->link('extension/payment/sagepay_server/send', '', true);
     23 
     24 		if ($this->config->get('payment_sagepay_server_card') == '1') {
     25 			$data['sagepay_server_card'] = true;
     26 		} else {
     27 			$data['sagepay_server_card'] = false;
     28 		}
     29 
     30 		$data['cards'] = array();
     31 
     32 		if ($this->customer->isLogged() && $data['sagepay_server_card']) {
     33 			$this->load->model('extension/payment/sagepay_server');
     34 
     35 			$data['cards'] = $this->model_extension_payment_sagepay_server->getCards($this->customer->getId());
     36 		}
     37 
     38 		return $this->load->view('extension/payment/sagepay_server', $data);
     39 	}
     40 
     41 	public function send() {
     42 
     43 		$payment_data = array();
     44 
     45 		if ($this->config->get('payment_sagepay_server_test') == 'live') {
     46 			$url = 'https://live.sagepay.com/gateway/service/vspserver-register.vsp';
     47 
     48 			$payment_data['VPSProtocol'] = '3.00';
     49 		} elseif ($this->config->get('payment_sagepay_server_test') == 'test') {
     50 			$url = 'https://test.sagepay.com/gateway/service/vspserver-register.vsp';
     51 
     52 			$payment_data['VPSProtocol'] = '3.00';
     53 		} elseif ($this->config->get('payment_sagepay_server_test') == 'sim') {
     54 			$url = 'https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRegisterTx';
     55 
     56 			$payment_data['VPSProtocol'] = '2.23';
     57 		}
     58 
     59 		$this->load->model('checkout/order');
     60 		$this->load->model('extension/payment/sagepay_server');
     61 
     62 		$order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']);
     63 
     64 		$payment_data['ReferrerID'] = 'E511AF91-E4A0-42DE-80B0-09C981A3FB61';
     65 		$payment_data['Vendor'] = $this->config->get('payment_sagepay_server_vendor');
     66 		$payment_data['VendorTxCode'] = $this->session->data['order_id'] . 'T' . strftime("%Y%m%d%H%M%S") . mt_rand(1, 999);
     67 		$payment_data['Amount'] = $this->currency->format($order_info['total'], $order_info['currency_code'], false, false);
     68 		$payment_data['Currency'] = $this->session->data['currency'];
     69 		$payment_data['Description'] = substr($this->config->get('config_name'), 0, 100);
     70 		$payment_data['NotificationURL'] = $this->url->link('extension/payment/sagepay_server/callback', '', true);
     71 		$payment_data['TxType'] = $this->config->get('payment_sagepay_server_transaction');
     72 
     73 		$payment_data['BillingSurname'] = substr($order_info['payment_lastname'], 0, 20);
     74 		$payment_data['BillingFirstnames'] = substr($order_info['payment_firstname'], 0, 20);
     75 		$payment_data['BillingAddress1'] = substr($order_info['payment_address_1'], 0, 100);
     76 
     77 		if ($order_info['payment_address_2']) {
     78 			$payment_data['BillingAddress2'] = $order_info['payment_address_2'];
     79 		}
     80 
     81 		$payment_data['BillingCity'] = substr($order_info['payment_city'], 0, 40);
     82 		$payment_data['BillingPostCode'] = substr($order_info['payment_postcode'], 0, 10);
     83 		$payment_data['BillingCountry'] = $order_info['payment_iso_code_2'];
     84 
     85 		if ($order_info['payment_iso_code_2'] == 'US') {
     86 			$payment_data['BillingState'] = $order_info['payment_zone_code'];
     87 		}
     88 
     89 		$payment_data['BillingPhone'] = substr($order_info['telephone'], 0, 20);
     90 
     91 		if ($this->cart->hasShipping()) {
     92 			$payment_data['DeliverySurname'] = substr($order_info['shipping_lastname'], 0, 20);
     93 			$payment_data['DeliveryFirstnames'] = substr($order_info['shipping_firstname'], 0, 20);
     94 			$payment_data['DeliveryAddress1'] = substr($order_info['shipping_address_1'], 0, 100);
     95 
     96 			if ($order_info['shipping_address_2']) {
     97 				$payment_data['DeliveryAddress2'] = $order_info['shipping_address_2'];
     98 			}
     99 
    100 			$payment_data['DeliveryCity'] = substr($order_info['shipping_city'], 0, 40);
    101 			$payment_data['DeliveryPostCode'] = substr($order_info['shipping_postcode'], 0, 10);
    102 			$payment_data['DeliveryCountry'] = $order_info['shipping_iso_code_2'];
    103 
    104 			if ($order_info['shipping_iso_code_2'] == 'US') {
    105 				$payment_data['DeliveryState'] = $order_info['shipping_zone_code'];
    106 			}
    107 
    108 			$payment_data['CustomerName'] = substr($order_info['firstname'] . ' ' . $order_info['lastname'], 0, 100);
    109 			$payment_data['DeliveryPhone'] = substr($order_info['telephone'], 0, 20);
    110 		} else {
    111 			$payment_data['DeliveryFirstnames'] = $order_info['payment_firstname'];
    112 			$payment_data['DeliverySurname'] = $order_info['payment_lastname'];
    113 			$payment_data['DeliveryAddress1'] = $order_info['payment_address_1'];
    114 
    115 			if ($order_info['payment_address_2']) {
    116 				$payment_data['DeliveryAddress2'] = $order_info['payment_address_2'];
    117 			}
    118 
    119 			$payment_data['DeliveryCity'] = $order_info['payment_city'];
    120 			$payment_data['DeliveryPostCode'] = $order_info['payment_postcode'];
    121 			$payment_data['DeliveryCountry'] = $order_info['payment_iso_code_2'];
    122 
    123 			if ($order_info['payment_iso_code_2'] == 'US') {
    124 				$payment_data['DeliveryState'] = $order_info['payment_zone_code'];
    125 			}
    126 
    127 			$payment_data['DeliveryPhone'] = $order_info['telephone'];
    128 		}
    129 
    130 		$order_products = $this->model_checkout_order->getOrderProducts($this->session->data['order_id']);
    131 		$cart_rows = 0;
    132 		$str_basket = "";
    133 		foreach ($order_products as $product) {
    134 			$str_basket .=
    135 					":" . str_replace(":", " ", $product['name'] . " " . $product['model']) .
    136 					":" . $product['quantity'] .
    137 					":" . $this->currency->format($product['price'], $order_info['currency_code'], false, false) .
    138 					":" . $this->currency->format($product['tax'], $order_info['currency_code'], false, false) .
    139 					":" . $this->currency->format(($product['price'] + $product['tax']), $order_info['currency_code'], false, false) .
    140 					":" . $this->currency->format(($product['price'] + $product['tax']) * $product['quantity'], $order_info['currency_code'], false, false);
    141 			$cart_rows++;
    142 		}
    143 
    144 		$order_totals = $this->model_checkout_order->getOrderTotals($this->session->data['order_id']);
    145 		
    146 		foreach ($order_totals as $total) {
    147 			$str_basket .= ":" . str_replace(":", " ", $total['title']) . ":::::" . $this->currency->format($total['value'], $order_info['currency_code'], false, false);
    148 			$cart_rows++;
    149 		}
    150 		
    151 		$str_basket = $cart_rows . $str_basket;
    152 
    153 		$payment_data['Basket'] = $str_basket;
    154 
    155 		$payment_data['CustomerEMail'] = substr($order_info['email'], 0, 255);
    156 		$payment_data['Apply3DSecure'] = '0';
    157 
    158 		if (isset($this->request->post['CreateToken'])) {
    159 			$payment_data['CreateToken'] = $this->request->post['CreateToken'];
    160 			$payment_data['StoreToken'] = 1;
    161 		}
    162 
    163 		if (isset($this->request->post['Token'])) {
    164 			$payment_data['Token'] = $this->request->post['Token'];
    165 			$payment_data['StoreToken'] = 1;
    166 		}
    167 
    168 		$response_data = $this->model_extension_payment_sagepay_server->sendCurl($url, $payment_data);
    169 
    170 		$json = array();
    171 
    172 		if ((substr($response_data['Status'], 0, 2) == "OK") || $response_data['Status'] == 'AUTHENTICATED' || $response_data['Status'] == 'REGISTERED') {
    173 			$json['redirect'] = $response_data['NextURL'];
    174 			$json['Status'] = $response_data['Status'];
    175 			$json['StatusDetail'] = $response_data['StatusDetail'];
    176 
    177 			$response_data['order_id'] = $this->session->data['order_id'];
    178 			$response_data['VendorTxCode'] = $payment_data['VendorTxCode'];
    179 
    180 			$order_info = array_merge($order_info, $response_data);
    181 
    182 			$this->model_extension_payment_sagepay_server->addOrder($order_info);
    183 
    184 			if ($this->config->get('payment_sagepay_server_transaction') == 'PAYMENT') {
    185 				$recurring_products = $this->cart->getRecurringProducts();
    186 
    187 				//loop through any products that are recurring items
    188 				foreach ($recurring_products as $item) {
    189 					$this->model_extension_payment_sagepay_server->addRecurringPayment($item, $payment_data['VendorTxCode']);
    190 				}
    191 			}
    192 		} else {
    193 			$json['error'] = $response_data['StatusDetail'];
    194 		}
    195 
    196 		$this->response->addHeader('Content-Type: application/json');
    197 		$this->response->setOutput(json_encode($json));
    198 	}
    199 
    200 	public function callback() {
    201 		$this->load->model('checkout/order');
    202 		$this->load->model('extension/payment/sagepay_server');
    203 
    204 		$success_page = $this->url->link('extension/payment/sagepay_server/success', '', true);
    205 		$error_page = $this->url->link('extension/payment/sagepay_server/failure', '', true);
    206 		$end_ln = chr(13) . chr(10);
    207 
    208 		if (isset($this->request->post['VendorTxCode'])) {
    209 			$vendor_tx_code = $this->request->post['VendorTxCode'];
    210 			$order_id_parts = explode('T', $this->request->post['VendorTxCode']);
    211 			$order_id = (int)$order_id_parts[0];
    212 		} else {
    213 			$vendor_tx_code = '';
    214 			$order_id = '';
    215 		}
    216 
    217 		if (isset($this->request->post['Status'])) {
    218 			$str_status = $this->request->post['Status'];
    219 		} else {
    220 			$str_status = '';
    221 		}
    222 
    223 		if (isset($this->request->post['VPSSignature'])) {
    224 			$str_vps_signature = $this->request->post['VPSSignature'];
    225 		} else {
    226 			$str_vps_signature = '';
    227 		}
    228 		if (isset($this->request->post['StatusDetail'])) {
    229 			$str_status_detail = $this->request->post['StatusDetail'];
    230 		} else {
    231 			$str_status_detail = '';
    232 		}
    233 
    234 		if (isset($this->request->post['VPSTxId'])) {
    235 			$str_vps_tx_id = $this->request->post['VPSTxId'];
    236 		} else {
    237 			$str_vps_tx_id = '';
    238 		}
    239 
    240 		if (isset($this->request->post['TxAuthNo'])) {
    241 			$str_tx_auth_no = $this->request->post['TxAuthNo'];
    242 		} else {
    243 			$str_tx_auth_no = '';
    244 		}
    245 
    246 		if (isset($this->request->post['AVSCV2'])) {
    247 			$str_avs_cv2 = $this->request->post['AVSCV2'];
    248 		} else {
    249 			$str_avs_cv2 = '';
    250 		}
    251 
    252 		if (isset($this->request->post['AddressResult'])) {
    253 			$str_address_result = $this->request->post['AddressResult'];
    254 		} else {
    255 			$str_address_result = '';
    256 		}
    257 
    258 		if (isset($this->request->post['PostCodeResult'])) {
    259 			$str_postcode_result = $this->request->post['PostCodeResult'];
    260 		} else {
    261 			$str_postcode_result = '';
    262 		}
    263 
    264 		if (isset($this->request->post['CV2Result'])) {
    265 			$str_cv2_result = $this->request->post['CV2Result'];
    266 		} else {
    267 			$str_cv2_result = '';
    268 		}
    269 
    270 		if (isset($this->request->post['GiftAid'])) {
    271 			$str_gift_aid = $this->request->post['GiftAid'];
    272 		} else {
    273 			$str_gift_aid = '';
    274 		}
    275 
    276 		if (isset($this->request->post['3DSecureStatus'])) {
    277 			$str_3d_secure_status = $this->request->post['3DSecureStatus'];
    278 		} else {
    279 			$str_3d_secure_status = '';
    280 		}
    281 
    282 		if (isset($this->request->post['CAVV'])) {
    283 			$str_cavv = $this->request->post['CAVV'];
    284 		} else {
    285 			$str_cavv = '';
    286 		}
    287 
    288 		if (isset($this->request->post['AddressStatus'])) {
    289 			$str_address_status = $this->request->post['AddressStatus'];
    290 		} else {
    291 			$str_address_status = '';
    292 		}
    293 
    294 		if (isset($this->request->post['PayerStatus'])) {
    295 			$str_payer_status = $this->request->post['PayerStatus'];
    296 		} else {
    297 			$str_payer_status = '';
    298 		}
    299 
    300 		if (isset($this->request->post['CardType'])) {
    301 			$str_card_type = $this->request->post['CardType'];
    302 		} else {
    303 			$str_card_type = '';
    304 		}
    305 
    306 		if (isset($this->request->post['Last4Digits'])) {
    307 			$str_last_4_digits = $this->request->post['Last4Digits'];
    308 		} else {
    309 			$str_last_4_digits = '';
    310 		}
    311 
    312 		if (isset($this->request->post['ExpiryDate'])) {
    313 			$str_expiry_date = $this->request->post['ExpiryDate'];
    314 		} else {
    315 			$str_expiry_date = '';
    316 		}
    317 
    318 		if (isset($this->request->post['Token'])) {
    319 			$str_token = $this->request->post['Token'];
    320 		} else {
    321 			$str_token = '';
    322 		}
    323 
    324 		if (isset($this->request->post['DeclineCode'])) {
    325 			$str_decline_code = $this->request->post['DeclineCode'];
    326 		} else {
    327 			$str_decline_code = '';
    328 		}
    329 
    330 		if (isset($this->request->post['BankAuthCode'])) {
    331 			$str_bank_auth_code = $this->request->post['BankAuthCode'];
    332 		} else {
    333 			$str_bank_auth_code = '';
    334 		}
    335 
    336 		$order_info = $this->model_checkout_order->getOrder($order_id);
    337 
    338 		$transaction_info = $this->model_extension_payment_sagepay_server->getOrder($order_id);
    339 
    340 		$this->model_extension_payment_sagepay_server->logger('$order_id', $order_id);
    341 		$this->model_extension_payment_sagepay_server->logger('$order_info', $order_info);
    342 		$this->model_extension_payment_sagepay_server->logger('$transaction_info', $transaction_info);
    343 		$this->model_extension_payment_sagepay_server->logger('$strStatus', $str_status);
    344 
    345 		//Check if order we have saved in database maches with callback sagepay does
    346 		if (!isset($transaction_info['order_id']) || $transaction_info['order_id'] != $order_id) {
    347 			echo "Status=INVALID" . $end_ln;
    348 			echo "StatusDetail= Order IDs could not be matched. Order might be tampered with." . $end_ln;
    349 			echo "RedirectURL=" . $error_page . $end_ln;
    350 
    351 			$this->model_extension_payment_sagepay_server->logger('StatusDetail', 'Order IDs could not be matched. Order might be tampered with');
    352 
    353 			exit;
    354 		}
    355 
    356 		if (isset($transaction_info['SecurityKey'])) {
    357 			$str_security_key = $transaction_info['SecurityKey'];
    358 		} else {
    359 			$str_security_key = '';
    360 		}
    361 
    362 		/** Now we rebuilt the POST message, including our security key, and use the MD5 Hash **
    363 		 * * component that is included to create our own signature to compare with **
    364 		 * * the contents of the VPSSignature field in the POST.  Check the Sage Pay Server protocol **
    365 		 * * if you need clarification on this process * */
    366 		$str_message = $str_vps_tx_id . $vendor_tx_code . $str_status . $str_tx_auth_no . $this->config->get('payment_sagepay_server_vendor') . urldecode($str_avs_cv2) . $str_security_key
    367 				. $str_address_result . $str_postcode_result . $str_cv2_result . $str_gift_aid . $str_3d_secure_status . $str_cavv
    368 				. $str_address_status . $str_payer_status . $str_card_type . $str_last_4_digits . $str_decline_code . $str_expiry_date . $str_bank_auth_code;
    369 
    370 		$str_my_signature = strtoupper(md5($str_message));
    371 
    372 		/** We can now compare our MD5 Hash signature with that from Sage Pay Server * */
    373 		if ($str_my_signature != $str_vps_signature) {
    374 			$this->model_extension_payment_sagepay_server->deleteOrder($order_id);
    375 
    376 			echo "Status=INVALID" . $end_ln;
    377 			echo "StatusDetail= Cannot match the MD5 Hash. Order might be tampered with." . $end_ln;
    378 			echo "RedirectURL=" . $error_page . $end_ln;
    379 
    380 			$this->model_extension_payment_sagepay_server->logger('StatusDetail', 'Cannot match the MD5 Hash. Order might be tampered with');
    381 			exit;
    382 		}
    383 
    384 		if (($str_status != "OK" && $str_status != "REGISTERED" && $str_status != "AUTHENTICATED") || !$order_info) {
    385 			$this->model_extension_payment_sagepay_server->deleteOrder($order_id);
    386 
    387 			echo "Status=INVALID" . $end_ln;
    388 			echo "StatusDetail= Either status invalid or order info was not found.";
    389 			echo "RedirectURL=" . $error_page . $end_ln;
    390 
    391 			$this->model_extension_payment_sagepay_server->logger('StatusDetail', 'Either status invalid or order info was not found');
    392 			exit;
    393 		}
    394 
    395 		$comment = "Paid with Sagepay Server<br><br>";
    396 		$comment .= "<b>Transaction details</b><br>";
    397 		$comment .= "Status: " . $str_status . "<br>";
    398 		$comment .= "AVS and CV2 checks: " . $str_avs_cv2 . "<br>";
    399 		$comment .= "3D Secure checks: " . $str_3d_secure_status . "<br>";
    400 		$comment .= "Card type: " . $str_card_type . "<br>";
    401 
    402 		if ($str_card_type == "PAYPAL") {
    403 			$comment .= "Paypal address status: " . $str_address_status . "<br>";
    404 			$comment .= "Paypal payer status: " . $str_payer_status . "<br>";
    405 		}
    406 		$comment .= "Last 4 digits: " . $str_last_4_digits . "<br>";
    407 
    408 		$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('payment_sagepay_server_order_status_id'), $comment);
    409 
    410 		$this->model_extension_payment_sagepay_server->updateOrder($order_info, $str_vps_tx_id, $str_tx_auth_no);
    411 
    412 		$this->model_extension_payment_sagepay_server->addTransaction($transaction_info['sagepay_server_order_id'], $this->config->get('payment_sagepay_server_transaction'), $order_info);
    413 
    414 		if (!empty($str_token)) {
    415 			$data['customer_id'] = $order_info['customer_id'];
    416 			$data['ExpiryDate'] = substr($str_expiry_date, -4, 2) . '/' . substr($str_expiry_date, 2);
    417 			$data['Token'] = $str_token;
    418 			$data['CardType'] = $str_card_type;
    419 			$data['Last4Digits'] = $str_last_4_digits;
    420 
    421 			$this->model_extension_payment_sagepay_server->addCard($data);
    422 		}
    423 
    424 		echo "Status=OK" . $end_ln;
    425 		echo "RedirectURL=" . $success_page . $end_ln;
    426 	}
    427 
    428 	public function success() {
    429 		$this->load->model('checkout/order');
    430 		$this->load->model('extension/payment/sagepay_server');
    431 		$this->load->model('checkout/recurring');
    432 
    433 		if (isset($this->session->data['order_id'])) {
    434 			$order_details = $this->model_extension_payment_sagepay_server->getOrder($this->session->data['order_id']);
    435 
    436 			if ($this->config->get('payment_sagepay_server_transaction') == 'PAYMENT') {
    437 				$recurring_products = $this->model_extension_payment_sagepay_server->getRecurringOrders($this->session->data['order_id']);
    438 
    439 				//loop through any products that are recurring items
    440 				foreach ($recurring_products as $item) {
    441 					$this->model_extension_payment_sagepay_server->updateRecurringPayment($item, $order_details);
    442 				}
    443 			}
    444 
    445 			$this->response->redirect($this->url->link('checkout/success', '', true));
    446 		} else {
    447 			$this->response->redirect($this->url->link('account/login', '', true));
    448 		}
    449 	}
    450 
    451 	public function failure() {
    452 		$this->load->language('extension/payment/sagepay_server');
    453 
    454 		$this->session->data['error'] = $this->language->get('text_generic_error');
    455 
    456 		$this->response->redirect($this->url->link('checkout/checkout', '', true));
    457 	}
    458 
    459 	public function delete() {
    460 		$this->load->language('account/sagepay_server_cards');
    461 
    462 		$this->load->model('extension/payment/sagepay_server');
    463 
    464 		$card = $this->model_extension_payment_sagepay_server->getCard(false, $this->request->post['Token']);
    465 
    466 		if (!empty($card['token'])) {
    467 			if ($this->config->get('payment_sagepay_server_test') == 'live') {
    468 				$url = 'https://live.sagepay.com/gateway/service/removetoken.vsp';
    469 			} else {
    470 				$url = 'https://test.sagepay.com/gateway/service/removetoken.vsp';
    471 			}
    472 			$payment_data['VPSProtocol'] = '3.00';
    473 			$payment_data['Vendor'] = $this->config->get('payment_sagepay_server_vendor');
    474 			$payment_data['TxType'] = 'REMOVETOKEN';
    475 			$payment_data['Token'] = $card['token'];
    476 
    477 			$response_data = $this->model_extension_payment_sagepay_server->sendCurl($url, $payment_data);
    478 			if ($response_data['Status'] == 'OK') {
    479 				$this->model_extension_payment_sagepay_server->deleteCard($card['card_id']);
    480 				$this->session->data['success'] = $this->language->get('text_success_card');
    481 				$json['success'] = true;
    482 			} else {
    483 				$json['error'] = $this->language->get('text_fail_card');
    484 			}
    485 		} else {
    486 			$json['error'] = $this->language->get('text_fail_card');
    487 		}
    488 		$this->response->setOutput(json_encode($json));
    489 	}
    490 
    491 	public function cron() {
    492 		if (isset($this->request->get['token']) && hash_equals($this->config->get('payment_sagepay_server_cron_job_token'), $this->request->get['token'])) {
    493 			$this->load->model('extension/payment/sagepay_server');
    494 
    495 			$orders = $this->model_extension_payment_sagepay_server->cronPayment();
    496 
    497 			$this->model_extension_payment_sagepay_server->updateCronJobRunTime();
    498 
    499 			$this->model_extension_payment_sagepay_server->logger('Repeat Orders', $orders);
    500 		}
    501 	}
    502 
    503 }