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 }