pp_express.php (85094B)
1 <?php 2 class ControllerExtensionPaymentPPExpress extends Controller { 3 public function index() { 4 $this->load->language('extension/payment/pp_express'); 5 6 $data['payment_pp_express_incontext_disable'] = $this->config->get('payment_pp_express_incontext_disable'); 7 8 if ($this->config->get('payment_pp_express_test') == 1) { 9 $data['username'] = $this->config->get('payment_pp_express_sandbox_username'); 10 } else { 11 $data['username'] = $this->config->get('payment_pp_express_username'); 12 } 13 14 $data['continue'] = $this->url->link('extension/payment/pp_express/checkout', '', true); 15 16 unset($this->session->data['paypal']); 17 18 return $this->load->view('extension/payment/pp_express', $data); 19 } 20 21 public function express() { 22 $this->load->model('extension/payment/pp_express'); 23 24 if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) { 25 $this->response->redirect($this->url->link('checkout/cart')); 26 } 27 28 if ($this->customer->isLogged()) { 29 /** 30 * If the customer is already logged in 31 */ 32 $this->session->data['paypal']['guest'] = false; 33 34 unset($this->session->data['guest']); 35 } else { 36 if ($this->config->get('config_checkout_guest') && !$this->config->get('config_customer_price') && !$this->cart->hasDownload() && !$this->cart->hasRecurringProducts()) { 37 /** 38 * If the guest checkout is allowed (config ok, no login for price and doesn't have downloads) 39 */ 40 $this->session->data['paypal']['guest'] = true; 41 } else { 42 /** 43 * If guest checkout disabled or login is required before price or order has downloads 44 * 45 * Send them to the normal checkout flow. 46 */ 47 unset($this->session->data['guest']); 48 49 $this->response->redirect($this->url->link('checkout/checkout', '', true)); 50 } 51 } 52 53 unset($this->session->data['shipping_method']); 54 unset($this->session->data['shipping_methods']); 55 unset($this->session->data['payment_method']); 56 unset($this->session->data['payment_methods']); 57 58 $this->load->model('tool/image'); 59 60 if ($this->cart->hasShipping()) { 61 $shipping = 2; 62 } else { 63 $shipping = 1; 64 } 65 66 $max_amount = $this->cart->getTotal() * 1.5; 67 $max_amount = $this->currency->format($max_amount, $this->session->data['currency'], '', false); 68 69 $data = array( 70 'METHOD' => 'SetExpressCheckout', 71 'MAXAMT' => $max_amount, 72 'RETURNURL' => $this->url->link('extension/payment/pp_express/expressReturn', '', true), 73 'CANCELURL' => $this->url->link('checkout/cart', '', true), 74 'REQCONFIRMSHIPPING' => 0, 75 'NOSHIPPING' => $shipping, 76 'ALLOWNOTE' => $this->config->get('payment_pp_express_allow_note'), 77 'LOCALECODE' => 'EN', 78 'LANDINGPAGE' => 'Login', 79 'HDRIMG' => $this->model_tool_image->resize($this->config->get('payment_pp_express_logo'), 750, 90), 80 'PAYFLOWCOLOR' => $this->config->get('payment_pp_express_colour'), 81 'CHANNELTYPE' => 'Merchant' 82 ); 83 84 if (isset($this->session->data['pp_login']['seamless']['access_token']) && (isset($this->session->data['pp_login']['seamless']['customer_id']) && $this->session->data['pp_login']['seamless']['customer_id'] == $this->customer->getId()) && $this->config->get('module_pp_login_seamless')) { 85 $data['IDENTITYACCESSTOKEN'] = $this->session->data['pp_login']['seamless']['access_token']; 86 } 87 88 $data = array_merge($data, $this->model_extension_payment_pp_express->paymentRequestInfo()); 89 90 $result = $this->model_extension_payment_pp_express->call($data); 91 92 /** 93 * If a failed PayPal setup happens, handle it. 94 */ 95 if (!isset($result['TOKEN'])) { 96 $this->session->data['error'] = $result['L_LONGMESSAGE0']; 97 /** 98 * Unable to add error message to user as the session errors/success are not 99 * used on the cart or checkout pages - need to be added? 100 * If PayPal debug log is off then still log error to normal error log. 101 */ 102 103 $this->log->write('Unable to create PayPal call: ' . json_encode($result)); 104 105 $this->response->redirect($this->url->link('checkout/checkout', '', true)); 106 } 107 108 $this->session->data['paypal']['token'] = $result['TOKEN']; 109 110 if ($this->config->get('payment_pp_express_test') == 1) { 111 header('Location: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $result['TOKEN']); 112 } else { 113 header('Location: https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $result['TOKEN']); 114 } 115 } 116 117 public function expressReturn() { 118 /** 119 * This is the url when PayPal has completed the auth. 120 * 121 * It has no output, instead it sets the data and locates to checkout 122 */ 123 $this->load->model('extension/payment/pp_express'); 124 $data = array( 125 'METHOD' => 'GetExpressCheckoutDetails', 126 'TOKEN' => $this->session->data['paypal']['token'] 127 ); 128 129 $result = $this->model_extension_payment_pp_express->call($data); 130 $this->session->data['paypal']['payerid'] = $result['PAYERID']; 131 $this->session->data['paypal']['result'] = $result; 132 133 $this->session->data['comment'] = ''; 134 if (isset($result['PAYMENTREQUEST_0_NOTETEXT'])) { 135 $this->session->data['comment'] = $result['PAYMENTREQUEST_0_NOTETEXT']; 136 } 137 138 if ($this->session->data['paypal']['guest'] == true) { 139 140 $this->session->data['guest']['customer_group_id'] = $this->config->get('config_customer_group_id'); 141 $this->session->data['guest']['firstname'] = trim($result['FIRSTNAME']); 142 $this->session->data['guest']['lastname'] = trim($result['LASTNAME']); 143 $this->session->data['guest']['email'] = trim($result['EMAIL']); 144 145 if (isset($result['PHONENUM'])) { 146 $this->session->data['guest']['telephone'] = $result['PHONENUM']; 147 } else { 148 $this->session->data['guest']['telephone'] = ''; 149 } 150 151 $this->session->data['guest']['payment']['firstname'] = trim($result['FIRSTNAME']); 152 $this->session->data['guest']['payment']['lastname'] = trim($result['LASTNAME']); 153 154 if (isset($result['BUSINESS'])) { 155 $this->session->data['guest']['payment']['company'] = $result['BUSINESS']; 156 } else { 157 $this->session->data['guest']['payment']['company'] = ''; 158 } 159 160 $this->session->data['guest']['payment']['company_id'] = ''; 161 $this->session->data['guest']['payment']['tax_id'] = ''; 162 163 if ($this->cart->hasShipping()) { 164 $shipping_name = explode(' ', trim($result['PAYMENTREQUEST_0_SHIPTONAME'])); 165 $shipping_first_name = $shipping_name[0]; 166 unset($shipping_name[0]); 167 $shipping_last_name = implode(' ', $shipping_name); 168 169 $this->session->data['guest']['payment']['address_1'] = $result['PAYMENTREQUEST_0_SHIPTOSTREET']; 170 if (isset($result['PAYMENTREQUEST_0_SHIPTOSTREET2'])) { 171 $this->session->data['guest']['payment']['address_2'] = $result['PAYMENTREQUEST_0_SHIPTOSTREET2']; 172 } else { 173 $this->session->data['guest']['payment']['address_2'] = ''; 174 } 175 176 $this->session->data['guest']['payment']['postcode'] = $result['PAYMENTREQUEST_0_SHIPTOZIP']; 177 $this->session->data['guest']['payment']['city'] = $result['PAYMENTREQUEST_0_SHIPTOCITY']; 178 179 $this->session->data['guest']['shipping']['firstname'] = $shipping_first_name; 180 $this->session->data['guest']['shipping']['lastname'] = $shipping_last_name; 181 $this->session->data['guest']['shipping']['company'] = ''; 182 $this->session->data['guest']['shipping']['address_1'] = $result['PAYMENTREQUEST_0_SHIPTOSTREET']; 183 184 if (isset($result['PAYMENTREQUEST_0_SHIPTOSTREET2'])) { 185 $this->session->data['guest']['shipping']['address_2'] = $result['PAYMENTREQUEST_0_SHIPTOSTREET2']; 186 } else { 187 $this->session->data['guest']['shipping']['address_2'] = ''; 188 } 189 190 $this->session->data['guest']['shipping']['postcode'] = $result['PAYMENTREQUEST_0_SHIPTOZIP']; 191 $this->session->data['guest']['shipping']['city'] = $result['PAYMENTREQUEST_0_SHIPTOCITY']; 192 193 $this->session->data['shipping_postcode'] = $result['PAYMENTREQUEST_0_SHIPTOZIP']; 194 195 $country_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "country` WHERE `iso_code_2` = '" . $this->db->escape($result['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE']) . "' AND `status` = '1' LIMIT 1")->row; 196 197 if ($country_info) { 198 $this->session->data['guest']['shipping']['country_id'] = $country_info['country_id']; 199 $this->session->data['guest']['shipping']['country'] = $country_info['name']; 200 $this->session->data['guest']['shipping']['iso_code_2'] = $country_info['iso_code_2']; 201 $this->session->data['guest']['shipping']['iso_code_3'] = $country_info['iso_code_3']; 202 $this->session->data['guest']['shipping']['address_format'] = $country_info['address_format']; 203 $this->session->data['guest']['payment']['country_id'] = $country_info['country_id']; 204 $this->session->data['guest']['payment']['country'] = $country_info['name']; 205 $this->session->data['guest']['payment']['iso_code_2'] = $country_info['iso_code_2']; 206 $this->session->data['guest']['payment']['iso_code_3'] = $country_info['iso_code_3']; 207 $this->session->data['guest']['payment']['address_format'] = $country_info['address_format']; 208 $this->session->data['shipping_country_id'] = $country_info['country_id']; 209 } else { 210 $this->session->data['guest']['shipping']['country_id'] = ''; 211 $this->session->data['guest']['shipping']['country'] = ''; 212 $this->session->data['guest']['shipping']['iso_code_2'] = ''; 213 $this->session->data['guest']['shipping']['iso_code_3'] = ''; 214 $this->session->data['guest']['shipping']['address_format'] = ''; 215 $this->session->data['guest']['payment']['country_id'] = ''; 216 $this->session->data['guest']['payment']['country'] = ''; 217 $this->session->data['guest']['payment']['iso_code_2'] = ''; 218 $this->session->data['guest']['payment']['iso_code_3'] = ''; 219 $this->session->data['guest']['payment']['address_format'] = ''; 220 $this->session->data['shipping_country_id'] = ''; 221 } 222 223 if (isset($result['PAYMENTREQUEST_0_SHIPTOSTATE'])) { 224 $returned_shipping_zone = $result['PAYMENTREQUEST_0_SHIPTOSTATE']; 225 } else { 226 $returned_shipping_zone = ''; 227 } 228 229 $zone_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone` WHERE (`name` = '" . $this->db->escape($returned_shipping_zone) . "' OR `code` = '" . $this->db->escape($returned_shipping_zone) . "') AND `status` = '1' AND `country_id` = '" . (int)$country_info['country_id'] . "' LIMIT 1")->row; 230 231 if ($zone_info) { 232 $this->session->data['guest']['shipping']['zone'] = $zone_info['name']; 233 $this->session->data['guest']['shipping']['zone_code'] = $zone_info['code']; 234 $this->session->data['guest']['shipping']['zone_id'] = $zone_info['zone_id']; 235 $this->session->data['guest']['payment']['zone'] = $zone_info['name']; 236 $this->session->data['guest']['payment']['zone_code'] = $zone_info['code']; 237 $this->session->data['guest']['payment']['zone_id'] = $zone_info['zone_id']; 238 $this->session->data['shipping_zone_id'] = $zone_info['zone_id']; 239 } else { 240 $this->session->data['guest']['shipping']['zone'] = ''; 241 $this->session->data['guest']['shipping']['zone_code'] = ''; 242 $this->session->data['guest']['shipping']['zone_id'] = ''; 243 $this->session->data['guest']['payment']['zone'] = ''; 244 $this->session->data['guest']['payment']['zone_code'] = ''; 245 $this->session->data['guest']['payment']['zone_id'] = ''; 246 $this->session->data['shipping_zone_id'] = ''; 247 } 248 249 $this->session->data['guest']['shipping_address'] = true; 250 } else { 251 $this->session->data['guest']['payment']['address_1'] = ''; 252 $this->session->data['guest']['payment']['address_2'] = ''; 253 $this->session->data['guest']['payment']['postcode'] = ''; 254 $this->session->data['guest']['payment']['city'] = ''; 255 $this->session->data['guest']['payment']['country_id'] = ''; 256 $this->session->data['guest']['payment']['country'] = ''; 257 $this->session->data['guest']['payment']['iso_code_2'] = ''; 258 $this->session->data['guest']['payment']['iso_code_3'] = ''; 259 $this->session->data['guest']['payment']['address_format'] = ''; 260 $this->session->data['guest']['payment']['zone'] = ''; 261 $this->session->data['guest']['payment']['zone_code'] = ''; 262 $this->session->data['guest']['payment']['zone_id'] = ''; 263 $this->session->data['guest']['shipping_address'] = false; 264 } 265 266 $this->session->data['account'] = 'guest'; 267 268 unset($this->session->data['shipping_method']); 269 unset($this->session->data['shipping_methods']); 270 unset($this->session->data['payment_method']); 271 unset($this->session->data['payment_methods']); 272 } else { 273 unset($this->session->data['guest']); 274 /** 275 * if the user is logged in, add the address to the account and set the ID. 276 */ 277 278 if ($this->cart->hasShipping()) { 279 $this->load->model('account/address'); 280 281 $addresses = $this->model_account_address->getAddresses(); 282 283 /** 284 * Compare all of the user addresses and see if there is a match 285 */ 286 $match = false; 287 foreach($addresses as $address) { 288 if (trim(strtolower($address['address_1'])) == trim(strtolower($result['PAYMENTREQUEST_0_SHIPTOSTREET'])) && trim(strtolower($address['postcode'])) == trim(strtolower($result['PAYMENTREQUEST_0_SHIPTOZIP']))) { 289 $match = true; 290 291 $this->session->data['payment_address_id'] = $address['address_id']; 292 $this->session->data['payment_country_id'] = $address['country_id']; 293 $this->session->data['payment_zone_id'] = $address['zone_id']; 294 295 $this->session->data['shipping_address_id'] = $address['address_id']; 296 $this->session->data['shipping_country_id'] = $address['country_id']; 297 $this->session->data['shipping_zone_id'] = $address['zone_id']; 298 $this->session->data['shipping_postcode'] = $address['postcode']; 299 300 break; 301 } 302 } 303 304 /** 305 * If there is no address match add the address and set the info. 306 */ 307 if ($match == false) { 308 309 $shipping_name = explode(' ', trim($result['PAYMENTREQUEST_0_SHIPTONAME'])); 310 $shipping_first_name = $shipping_name[0]; 311 unset($shipping_name[0]); 312 $shipping_last_name = implode(' ', $shipping_name); 313 314 $country_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "country` WHERE `iso_code_2` = '" . $this->db->escape($result['PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE']) . "' AND `status` = '1' LIMIT 1")->row; 315 $zone_info = $this->db->query("SELECT * FROM `" . DB_PREFIX . "zone` WHERE (`name` = '" . $this->db->escape($result['PAYMENTREQUEST_0_SHIPTOSTATE']) . "' OR `code` = '" . $this->db->escape($result['PAYMENTREQUEST_0_SHIPTOSTATE']) . "') AND `status` = '1' AND `country_id` = '" . (int)$country_info['country_id'] . "'")->row; 316 317 $address_data = array( 318 'firstname' => $shipping_first_name, 319 'lastname' => $shipping_last_name, 320 'company' => '', 321 'company_id' => '', 322 'tax_id' => '', 323 'address_1' => $result['PAYMENTREQUEST_0_SHIPTOSTREET'], 324 'address_2' => (isset($result['PAYMENTREQUEST_0_SHIPTOSTREET2']) ? $result['PAYMENTREQUEST_0_SHIPTOSTREET2'] : ''), 325 'postcode' => $result['PAYMENTREQUEST_0_SHIPTOZIP'], 326 'city' => $result['PAYMENTREQUEST_0_SHIPTOCITY'], 327 'zone_id' => (isset($zone_info['zone_id']) ? $zone_info['zone_id'] : 0), 328 'country_id' => (isset($country_info['country_id']) ? $country_info['country_id'] : 0) 329 ); 330 331 $address_id = $this->model_account_address->addAddress($this->customer->getId(), $address_data); 332 333 $this->session->data['payment_address_id'] = $address_id; 334 $this->session->data['payment_country_id'] = $address_data['country_id']; 335 $this->session->data['payment_zone_id'] = $address_data['zone_id']; 336 337 $this->session->data['shipping_address_id'] = $address_id; 338 $this->session->data['shipping_country_id'] = $address_data['country_id']; 339 $this->session->data['shipping_zone_id'] = $address_data['zone_id']; 340 $this->session->data['shipping_postcode'] = $address_data['postcode']; 341 } 342 } else { 343 $this->session->data['payment_address_id'] = ''; 344 $this->session->data['payment_country_id'] = ''; 345 $this->session->data['payment_zone_id'] = ''; 346 } 347 } 348 349 $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true)); 350 } 351 352 public function expressConfirm() { 353 $this->load->language('extension/payment/pp_express'); 354 $this->load->language('checkout/cart'); 355 356 $this->load->model('tool/image'); 357 358 // Coupon 359 if (isset($this->request->post['coupon']) && $this->validateCoupon()) { 360 $this->session->data['coupon'] = $this->request->post['coupon']; 361 362 $this->session->data['success'] = $this->language->get('text_coupon'); 363 364 $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true)); 365 } 366 367 // Voucher 368 if (isset($this->request->post['voucher']) && $this->validateVoucher()) { 369 $this->session->data['voucher'] = $this->request->post['voucher']; 370 371 $this->session->data['success'] = $this->language->get('text_voucher'); 372 373 $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true)); 374 } 375 376 // Reward 377 if (isset($this->request->post['reward']) && $this->validateReward()) { 378 $this->session->data['reward'] = abs($this->request->post['reward']); 379 380 $this->session->data['success'] = $this->language->get('text_reward'); 381 382 $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true)); 383 } 384 385 $this->document->setTitle($this->language->get('express_text_title')); 386 387 $data['breadcrumbs'] = array(); 388 389 $data['breadcrumbs'][] = array( 390 'href' => $this->url->link('common/home'), 391 'text' => $this->language->get('text_home') 392 ); 393 394 $data['breadcrumbs'][] = array( 395 'href' => $this->url->link('extension/payment/pp_express/express'), 396 'text' => $this->language->get('text_title') 397 ); 398 399 $data['breadcrumbs'][] = array( 400 'href' => $this->url->link('extension/payment/pp_express/expressConfirm'), 401 'text' => $this->language->get('express_text_title') 402 ); 403 404 $points = $this->customer->getRewardPoints(); 405 406 $points_total = 0; 407 408 foreach ($this->cart->getProducts() as $product) { 409 if ($product['points']) { 410 $points_total += $product['points']; 411 } 412 } 413 414 $data['button_shipping'] = $this->language->get('button_express_shipping'); 415 $data['button_confirm'] = $this->language->get('button_express_confirm'); 416 417 if (isset($this->request->post['next'])) { 418 $data['next'] = $this->request->post['next']; 419 } else { 420 $data['next'] = ''; 421 } 422 423 $data['action'] = $this->url->link('extension/payment/pp_express/expressConfirm', '', true); 424 425 $this->load->model('tool/upload'); 426 427 $products = $this->cart->getProducts(); 428 429 foreach ($products as $product) { 430 $product_total = 0; 431 432 foreach ($products as $product_2) { 433 if ($product_2['product_id'] == $product['product_id']) { 434 $product_total += $product_2['quantity']; 435 } 436 } 437 438 if ($product['minimum'] > $product_total) { 439 $data['error_warning'] = sprintf($this->language->get('error_minimum'), $product['name'], $product['minimum']); 440 } 441 442 if ($product['image']) { 443 $image = $this->model_tool_image->resize($product['image'], $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_width'), $this->config->get('theme_' . $this->config->get('config_theme') . '_image_cart_height')); 444 } else { 445 $image = ''; 446 } 447 448 $option_data = array(); 449 450 foreach ($product['option'] as $option) { 451 if ($option['type'] != 'file') { 452 $value = $option['value']; 453 } else { 454 $upload_info = $this->model_tool_upload->getUploadByCode($option['value']); 455 456 if ($upload_info) { 457 $value = $upload_info['name']; 458 } else { 459 $value = ''; 460 } 461 } 462 463 $option_data[] = array( 464 'name' => $option['name'], 465 'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value) 466 ); 467 } 468 469 // Display prices 470 if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) { 471 $unit_price = $this->tax->calculate($product['price'], $product['tax_class_id'], $this->config->get('config_tax')); 472 473 $price = $this->currency->format($unit_price, $this->session->data['currency']); 474 $total = $this->currency->format($unit_price * $product['quantity'], $this->session->data['currency']); 475 } else { 476 $price = false; 477 $total = false; 478 } 479 480 $recurring_description = ''; 481 482 if ($product['recurring']) { 483 $frequencies = array( 484 'day' => $this->language->get('text_day'), 485 'week' => $this->language->get('text_week'), 486 'semi_month' => $this->language->get('text_semi_month'), 487 'month' => $this->language->get('text_month'), 488 'year' => $this->language->get('text_year'), 489 ); 490 491 if ($product['recurring']['trial']) { 492 $recurring_price = $this->currency->format($this->tax->calculate($product['recurring']['trial_price'] * $product['quantity'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']); 493 $recurring_description = sprintf($this->language->get('text_trial_description'), $recurring_price, $product['recurring']['trial_cycle'], $frequencies[$product['recurring']['trial_frequency']], $product['recurring']['trial_duration']) . ' '; 494 } 495 496 $recurring_price = $this->currency->format($this->tax->calculate($product['recurring']['price'] * $product['quantity'], $product['tax_class_id'], $this->config->get('config_tax')), $this->session->data['currency']); 497 498 if ($product['recurring']['duration']) { 499 $recurring_description .= sprintf($this->language->get('text_payment_description'), $recurring_price, $product['recurring']['cycle'], $frequencies[$product['recurring']['frequency']], $product['recurring']['duration']); 500 } else { 501 $recurring_description .= sprintf($this->language->get('text_payment_cancel'), $recurring_price, $product['recurring']['cycle'], $frequencies[$product['recurring']['frequency']], $product['recurring']['duration']); 502 } 503 } 504 505 $data['products'][] = array( 506 'cart_id' => $product['cart_id'], 507 'thumb' => $image, 508 'name' => $product['name'], 509 'model' => $product['model'], 510 'option' => $option_data, 511 'quantity' => $product['quantity'], 512 'stock' => $product['stock'] ? true : !(!$this->config->get('config_stock_checkout') || $this->config->get('config_stock_warning')), 513 'reward' => ($product['reward'] ? sprintf($this->language->get('text_points'), $product['reward']) : ''), 514 'price' => $price, 515 'total' => $total, 516 'href' => $this->url->link('product/product', 'product_id=' . $product['product_id']), 517 'remove' => $this->url->link('checkout/cart', 'remove=' . $product['cart_id']), 518 'recurring' => $product['recurring'], 519 'recurring_name' => (isset($product['recurring']['recurring_name']) ? $product['recurring']['recurring_name'] : ''), 520 'recurring_description' => $recurring_description 521 ); 522 } 523 524 $data['vouchers'] = array(); 525 526 if ($this->cart->hasShipping()) { 527 528 $data['has_shipping'] = true; 529 /** 530 * Shipping services 531 */ 532 if ($this->customer->isLogged()) { 533 $this->load->model('account/address'); 534 $shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']); 535 } elseif (isset($this->session->data['guest'])) { 536 $shipping_address = $this->session->data['guest']['shipping']; 537 } 538 539 if (!empty($shipping_address)) { 540 // Shipping Methods 541 $quote_data = array(); 542 543 $this->load->model('setting/extension'); 544 545 $results = $this->model_setting_extension->getExtensions('shipping'); 546 547 if (!empty($results)) { 548 foreach ($results as $result) { 549 if ($this->config->get('shipping_' . $result['code'] . '_status')) { 550 $this->load->model('extension/shipping/' . $result['code']); 551 552 $quote = $this->{'model_extension_shipping_' . $result['code']}->getQuote($shipping_address); 553 554 if ($quote) { 555 $quote_data[$result['code']] = array( 556 'title' => $quote['title'], 557 'quote' => $quote['quote'], 558 'sort_order' => $quote['sort_order'], 559 'error' => $quote['error'] 560 ); 561 } 562 } 563 } 564 565 if (!empty($quote_data)) { 566 $sort_order = array(); 567 568 foreach ($quote_data as $key => $value) { 569 $sort_order[$key] = $value['sort_order']; 570 } 571 572 array_multisort($sort_order, SORT_ASC, $quote_data); 573 574 $this->session->data['shipping_methods'] = $quote_data; 575 $data['shipping_methods'] = $quote_data; 576 577 if (!isset($this->session->data['shipping_method'])) { 578 //default the shipping to the very first option. 579 $key1 = key($quote_data); 580 $key2 = key($quote_data[$key1]['quote']); 581 $this->session->data['shipping_method'] = $quote_data[$key1]['quote'][$key2]; 582 } 583 584 $data['code'] = $this->session->data['shipping_method']['code']; 585 $data['action_shipping'] = $this->url->link('extension/payment/pp_express/shipping', '', true); 586 } else { 587 unset($this->session->data['shipping_methods']); 588 unset($this->session->data['shipping_method']); 589 $data['error_no_shipping'] = $this->language->get('error_no_shipping'); 590 } 591 } else { 592 unset($this->session->data['shipping_methods']); 593 unset($this->session->data['shipping_method']); 594 $data['error_no_shipping'] = $this->language->get('error_no_shipping'); 595 } 596 } 597 } else { 598 $data['has_shipping'] = false; 599 } 600 601 // Totals 602 $this->load->model('setting/extension'); 603 604 $totals = array(); 605 $taxes = $this->cart->getTaxes(); 606 $total = 0; 607 608 // Because __call can not keep var references so we put them into an array. 609 $total_data = array( 610 'totals' => &$totals, 611 'taxes' => &$taxes, 612 'total' => &$total 613 ); 614 615 // Display prices 616 if ($this->customer->isLogged() || !$this->config->get('config_customer_price')) { 617 $sort_order = array(); 618 619 $results = $this->model_setting_extension->getExtensions('total'); 620 621 foreach ($results as $key => $value) { 622 $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order'); 623 } 624 625 array_multisort($sort_order, SORT_ASC, $results); 626 627 foreach ($results as $result) { 628 if ($this->config->get('total_' . $result['code'] . '_status')) { 629 $this->load->model('extension/total/' . $result['code']); 630 631 // We have to put the totals in an array so that they pass by reference. 632 $this->{'model_extension_total_' . $result['code']}->getTotal($total_data); 633 } 634 } 635 636 $sort_order = array(); 637 638 foreach ($totals as $key => $value) { 639 $sort_order[$key] = $value['sort_order']; 640 } 641 642 array_multisort($sort_order, SORT_ASC, $totals); 643 } 644 645 $data['totals'] = array(); 646 647 foreach ($totals as $total) { 648 $data['totals'][] = array( 649 'title' => $total['title'], 650 'text' => $this->currency->format($total['value'], $this->session->data['currency']), 651 ); 652 } 653 654 /** 655 * Payment methods 656 */ 657 if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) { 658 $this->load->model('account/address'); 659 $payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']); 660 } elseif (isset($this->session->data['guest'])) { 661 $payment_address = $this->session->data['guest']['payment']; 662 } 663 664 $method_data = array(); 665 666 $this->load->model('setting/extension'); 667 668 $results = $this->model_setting_extension->getExtensions('payment'); 669 670 foreach ($results as $result) { 671 if ($this->config->get('payment_' . $result['code'] . '_status')) { 672 $this->load->model('extension/payment/' . $result['code']); 673 674 $method = $this->{'model_extension_payment_' . $result['code']}->getMethod($payment_address, $total); 675 676 if ($method) { 677 $method_data[$result['code']] = $method; 678 } 679 } 680 } 681 682 $sort_order = array(); 683 684 foreach ($method_data as $key => $value) { 685 $sort_order[$key] = $value['sort_order']; 686 } 687 688 array_multisort($sort_order, SORT_ASC, $method_data); 689 690 if (!isset($method_data['pp_express'])) { 691 $this->session->data['error_warning'] = $this->language->get('error_unavailable'); 692 $this->response->redirect($this->url->link('checkout/checkout', '', true)); 693 } 694 695 $this->session->data['payment_methods'] = $method_data; 696 $this->session->data['payment_method'] = $method_data['pp_express']; 697 698 $data['action_confirm'] = $this->url->link('extension/payment/pp_express/expressComplete', '', true); 699 700 if (isset($this->session->data['error_warning'])) { 701 $data['error_warning'] = $this->session->data['error_warning']; 702 unset($this->session->data['error_warning']); 703 } else { 704 $data['error_warning'] = ''; 705 } 706 707 if (isset($this->session->data['success'])) { 708 $data['success'] = $this->session->data['success']; 709 unset($this->session->data['success']); 710 } else { 711 $data['success'] = ''; 712 } 713 714 if (isset($this->session->data['attention'])) { 715 $data['attention'] = $this->session->data['attention']; 716 unset($this->session->data['attention']); 717 } else { 718 $data['attention'] = ''; 719 } 720 721 $data['coupon'] = $this->load->controller('extension/total/coupon'); 722 $data['voucher'] = $this->load->controller('extension/total/voucher'); 723 $data['reward'] = $this->load->controller('extension/total/reward'); 724 $data['column_left'] = $this->load->controller('common/column_left'); 725 $data['column_right'] = $this->load->controller('common/column_right'); 726 $data['content_top'] = $this->load->controller('common/content_top'); 727 $data['content_bottom'] = $this->load->controller('common/content_bottom'); 728 $data['footer'] = $this->load->controller('common/footer'); 729 $data['header'] = $this->load->controller('common/header'); 730 731 $this->response->setOutput($this->load->view('extension/payment/pp_express_confirm', $data)); 732 } 733 734 public function expressComplete() { 735 $this->load->language('extension/payment/pp_express'); 736 $redirect = ''; 737 738 if ($this->cart->hasShipping()) { 739 // Validate if shipping address has been set. 740 $this->load->model('account/address'); 741 742 if ($this->customer->isLogged() && isset($this->session->data['shipping_address_id'])) { 743 $shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']); 744 } elseif (isset($this->session->data['guest'])) { 745 $shipping_address = $this->session->data['guest']['shipping']; 746 } 747 748 if (empty($shipping_address)) { 749 $redirect = $this->url->link('checkout/checkout', '', true); 750 } 751 752 // Validate if shipping method has been set. 753 if (!isset($this->session->data['shipping_method'])) { 754 $redirect = $this->url->link('checkout/checkout', '', true); 755 } 756 } else { 757 unset($this->session->data['shipping_method']); 758 unset($this->session->data['shipping_methods']); 759 } 760 761 // Validate if payment address has been set. 762 $this->load->model('account/address'); 763 764 if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) { 765 $payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']); 766 } elseif (isset($this->session->data['guest'])) { 767 $payment_address = $this->session->data['guest']['payment']; 768 } 769 770 // Validate if payment method has been set. 771 if (!isset($this->session->data['payment_method'])) { 772 $redirect = $this->url->link('checkout/checkout', '', true); 773 } 774 775 // Validate cart has products and has stock. 776 if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) { 777 $redirect = $this->url->link('checkout/cart'); 778 } 779 780 // Validate minimum quantity requirements. 781 $products = $this->cart->getProducts(); 782 783 foreach ($products as $product) { 784 $product_total = 0; 785 786 foreach ($products as $product_2) { 787 if ($product_2['product_id'] == $product['product_id']) { 788 $product_total += $product_2['quantity']; 789 } 790 } 791 792 if ($product['minimum'] > $product_total) { 793 $redirect = $this->url->link('checkout/cart'); 794 795 break; 796 } 797 } 798 799 if ($redirect == '') { 800 $totals = array(); 801 $taxes = $this->cart->getTaxes(); 802 $total = 0; 803 804 // Because __call can not keep var references so we put them into an array. 805 $total_data = array( 806 'totals' => &$totals, 807 'taxes' => &$taxes, 808 'total' => &$total 809 ); 810 811 $this->load->model('setting/extension'); 812 813 $sort_order = array(); 814 815 $results = $this->model_setting_extension->getExtensions('total'); 816 817 foreach ($results as $key => $value) { 818 $sort_order[$key] = $this->config->get('total_' . $value['code'] . '_sort_order'); 819 } 820 821 array_multisort($sort_order, SORT_ASC, $results); 822 823 foreach ($results as $result) { 824 if ($this->config->get('total_' . $result['code'] . '_status')) { 825 $this->load->model('extension/total/' . $result['code']); 826 827 // We have to put the totals in an array so that they pass by reference. 828 $this->{'model_extension_total_' . $result['code']}->getTotal($total_data); 829 } 830 } 831 832 $sort_order = array(); 833 834 foreach ($totals as $key => $value) { 835 $sort_order[$key] = $value['sort_order']; 836 } 837 838 array_multisort($sort_order, SORT_ASC, $totals); 839 840 $this->load->language('checkout/checkout'); 841 842 $data = array(); 843 844 $data['invoice_prefix'] = $this->config->get('config_invoice_prefix'); 845 $data['store_id'] = $this->config->get('config_store_id'); 846 $data['store_name'] = $this->config->get('config_name'); 847 848 if ($data['store_id']) { 849 $data['store_url'] = $this->config->get('config_url'); 850 } else { 851 $data['store_url'] = HTTP_SERVER; 852 } 853 854 if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) { 855 $data['customer_id'] = $this->customer->getId(); 856 $data['customer_group_id'] = $this->config->get('config_customer_group_id'); 857 $data['firstname'] = $this->customer->getFirstName(); 858 $data['lastname'] = $this->customer->getLastName(); 859 $data['email'] = $this->customer->getEmail(); 860 $data['telephone'] = $this->customer->getTelephone(); 861 862 $this->load->model('account/address'); 863 864 $payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']); 865 } elseif (isset($this->session->data['guest'])) { 866 $data['customer_id'] = 0; 867 $data['customer_group_id'] = $this->session->data['guest']['customer_group_id']; 868 $data['firstname'] = $this->session->data['guest']['firstname']; 869 $data['lastname'] = $this->session->data['guest']['lastname']; 870 $data['email'] = $this->session->data['guest']['email']; 871 $data['telephone'] = $this->session->data['guest']['telephone']; 872 873 $payment_address = $this->session->data['guest']['payment']; 874 } 875 876 $data['payment_firstname'] = isset($payment_address['firstname']) ? $payment_address['firstname'] : ''; 877 $data['payment_lastname'] = isset($payment_address['lastname']) ? $payment_address['lastname'] : ''; 878 $data['payment_company'] = isset($payment_address['company']) ? $payment_address['company'] : ''; 879 $data['payment_company_id'] = isset($payment_address['company_id']) ? $payment_address['company_id'] : ''; 880 $data['payment_tax_id'] = isset($payment_address['tax_id']) ? $payment_address['tax_id'] : ''; 881 $data['payment_address_1'] = isset($payment_address['address_1']) ? $payment_address['address_1'] : ''; 882 $data['payment_address_2'] = isset($payment_address['address_2']) ? $payment_address['address_2'] : ''; 883 $data['payment_city'] = isset($payment_address['city']) ? $payment_address['city'] : ''; 884 $data['payment_postcode'] = isset($payment_address['postcode']) ? $payment_address['postcode'] : ''; 885 $data['payment_zone'] = isset($payment_address['zone']) ? $payment_address['zone'] : ''; 886 $data['payment_zone_id'] = isset($payment_address['zone_id']) ? $payment_address['zone_id'] : ''; 887 $data['payment_country'] = isset($payment_address['country']) ? $payment_address['country'] : ''; 888 $data['payment_country_id'] = isset($payment_address['country_id']) ? $payment_address['country_id'] : ''; 889 $data['payment_address_format'] = isset($payment_address['address_format']) ? $payment_address['address_format'] : ''; 890 891 $data['payment_method'] = ''; 892 if (isset($this->session->data['payment_method']['title'])) { 893 $data['payment_method'] = $this->session->data['payment_method']['title']; 894 } 895 896 $data['payment_code'] = ''; 897 if (isset($this->session->data['payment_method']['code'])) { 898 $data['payment_code'] = $this->session->data['payment_method']['code']; 899 } 900 901 if ($this->cart->hasShipping()) { 902 if ($this->customer->isLogged()) { 903 $this->load->model('account/address'); 904 905 $shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']); 906 } elseif (isset($this->session->data['guest'])) { 907 $shipping_address = $this->session->data['guest']['shipping']; 908 } 909 910 $data['shipping_firstname'] = $shipping_address['firstname']; 911 $data['shipping_lastname'] = $shipping_address['lastname']; 912 $data['shipping_company'] = $shipping_address['company']; 913 $data['shipping_address_1'] = $shipping_address['address_1']; 914 $data['shipping_address_2'] = $shipping_address['address_2']; 915 $data['shipping_city'] = $shipping_address['city']; 916 $data['shipping_postcode'] = $shipping_address['postcode']; 917 $data['shipping_zone'] = $shipping_address['zone']; 918 $data['shipping_zone_id'] = $shipping_address['zone_id']; 919 $data['shipping_country'] = $shipping_address['country']; 920 $data['shipping_country_id'] = $shipping_address['country_id']; 921 $data['shipping_address_format'] = $shipping_address['address_format']; 922 923 $data['shipping_method'] = ''; 924 if (isset($this->session->data['shipping_method']['title'])) { 925 $data['shipping_method'] = $this->session->data['shipping_method']['title']; 926 } 927 928 $data['shipping_code'] = ''; 929 if (isset($this->session->data['shipping_method']['code'])) { 930 $data['shipping_code'] = $this->session->data['shipping_method']['code']; 931 } 932 } else { 933 $data['shipping_firstname'] = ''; 934 $data['shipping_lastname'] = ''; 935 $data['shipping_company'] = ''; 936 $data['shipping_address_1'] = ''; 937 $data['shipping_address_2'] = ''; 938 $data['shipping_city'] = ''; 939 $data['shipping_postcode'] = ''; 940 $data['shipping_zone'] = ''; 941 $data['shipping_zone_id'] = ''; 942 $data['shipping_country'] = ''; 943 $data['shipping_country_id'] = ''; 944 $data['shipping_address_format'] = ''; 945 $data['shipping_method'] = ''; 946 $data['shipping_code'] = ''; 947 } 948 949 $product_data = array(); 950 951 foreach ($this->cart->getProducts() as $product) { 952 $option_data = array(); 953 954 foreach ($product['option'] as $option) { 955 $option_data[] = array( 956 'product_option_id' => $option['product_option_id'], 957 'product_option_value_id' => $option['product_option_value_id'], 958 'option_id' => $option['option_id'], 959 'option_value_id' => $option['option_value_id'], 960 'name' => $option['name'], 961 'value' => $option['value'], 962 'type' => $option['type'] 963 ); 964 } 965 966 $product_data[] = array( 967 'product_id' => $product['product_id'], 968 'name' => $product['name'], 969 'model' => $product['model'], 970 'option' => $option_data, 971 'download' => $product['download'], 972 'quantity' => $product['quantity'], 973 'subtract' => $product['subtract'], 974 'price' => $product['price'], 975 'total' => $product['total'], 976 'tax' => $this->tax->getTax($product['price'], $product['tax_class_id']), 977 'reward' => $product['reward'] 978 ); 979 } 980 981 // Gift Voucher 982 $voucher_data = array(); 983 984 if (!empty($this->session->data['vouchers'])) { 985 foreach ($this->session->data['vouchers'] as $voucher) { 986 $voucher_data[] = array( 987 'description' => $voucher['description'], 988 'code' => token(10), 989 'to_name' => $voucher['to_name'], 990 'to_email' => $voucher['to_email'], 991 'from_name' => $voucher['from_name'], 992 'from_email' => $voucher['from_email'], 993 'voucher_theme_id' => $voucher['voucher_theme_id'], 994 'message' => $voucher['message'], 995 'amount' => $voucher['amount'] 996 ); 997 } 998 } 999 1000 $data['products'] = $product_data; 1001 $data['vouchers'] = $voucher_data; 1002 $data['totals'] = $totals; 1003 $data['comment'] = $this->session->data['comment']; 1004 $data['total'] = $total; 1005 1006 if (isset($this->request->cookie['tracking'])) { 1007 $data['tracking'] = $this->request->cookie['tracking']; 1008 1009 $subtotal = $this->cart->getSubTotal(); 1010 1011 // Affiliate 1012 $this->load->model('affiliate/affiliate'); 1013 1014 $affiliate_info = $this->model_affiliate_affiliate->getAffiliateByCode($this->request->cookie['tracking']); 1015 1016 if ($affiliate_info) { 1017 $data['affiliate_id'] = $affiliate_info['affiliate_id']; 1018 $data['commission'] = ($subtotal / 100) * $affiliate_info['commission']; 1019 } else { 1020 $data['affiliate_id'] = 0; 1021 $data['commission'] = 0; 1022 } 1023 1024 // Marketing 1025 $this->load->model('checkout/marketing'); 1026 1027 $marketing_info = $this->model_checkout_marketing->getMarketingByCode($this->request->cookie['tracking']); 1028 1029 if ($marketing_info) { 1030 $data['marketing_id'] = $marketing_info['marketing_id']; 1031 } else { 1032 $data['marketing_id'] = 0; 1033 } 1034 } else { 1035 $data['affiliate_id'] = 0; 1036 $data['commission'] = 0; 1037 $data['marketing_id'] = 0; 1038 $data['tracking'] = ''; 1039 } 1040 1041 $data['language_id'] = $this->config->get('config_language_id'); 1042 $data['currency_id'] = $this->currency->getId($this->session->data['currency']); 1043 $data['currency_code'] = $this->session->data['currency']; 1044 $data['currency_value'] = $this->currency->getValue($this->session->data['currency']); 1045 $data['ip'] = $this->request->server['REMOTE_ADDR']; 1046 1047 if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) { 1048 $data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR']; 1049 } elseif (!empty($this->request->server['HTTP_CLIENT_IP'])) { 1050 $data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP']; 1051 } else { 1052 $data['forwarded_ip'] = ''; 1053 } 1054 1055 if (isset($this->request->server['HTTP_USER_AGENT'])) { 1056 $data['user_agent'] = $this->request->server['HTTP_USER_AGENT']; 1057 } else { 1058 $data['user_agent'] = ''; 1059 } 1060 1061 if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) { 1062 $data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE']; 1063 } else { 1064 $data['accept_language'] = ''; 1065 } 1066 1067 $this->load->model('account/custom_field'); 1068 $this->load->model('checkout/order'); 1069 1070 $order_id = $this->model_checkout_order->addOrder($data); 1071 $this->session->data['order_id'] = $order_id; 1072 1073 $this->load->model('extension/payment/pp_express'); 1074 1075 $paypal_data = array( 1076 'TOKEN' => $this->session->data['paypal']['token'], 1077 'PAYERID' => $this->session->data['paypal']['payerid'], 1078 'METHOD' => 'DoExpressCheckoutPayment', 1079 'PAYMENTREQUEST_0_NOTIFYURL' => $this->url->link('extension/payment/pp_express/ipn', '', true), 1080 'RETURNFMFDETAILS' => 1 1081 ); 1082 1083 $paypal_data = array_merge($paypal_data, $this->model_extension_payment_pp_express->paymentRequestInfo()); 1084 1085 $result = $this->model_extension_payment_pp_express->call($paypal_data); 1086 1087 if ($result['ACK'] == 'Success') { 1088 //handle order status 1089 switch($result['PAYMENTINFO_0_PAYMENTSTATUS']) { 1090 case 'Canceled_Reversal': 1091 $order_status_id = $this->config->get('payment_pp_express_canceled_reversal_status_id'); 1092 break; 1093 case 'Completed': 1094 $order_status_id = $this->config->get('payment_pp_express_completed_status_id'); 1095 break; 1096 case 'Denied': 1097 $order_status_id = $this->config->get('payment_pp_express_denied_status_id'); 1098 break; 1099 case 'Expired': 1100 $order_status_id = $this->config->get('payment_pp_express_expired_status_id'); 1101 break; 1102 case 'Failed': 1103 $order_status_id = $this->config->get('payment_pp_express_failed_status_id'); 1104 break; 1105 case 'Pending': 1106 $order_status_id = $this->config->get('payment_pp_express_pending_status_id'); 1107 break; 1108 case 'Processed': 1109 $order_status_id = $this->config->get('payment_pp_express_processed_status_id'); 1110 break; 1111 case 'Refunded': 1112 $order_status_id = $this->config->get('payment_pp_express_refunded_status_id'); 1113 break; 1114 case 'Reversed': 1115 $order_status_id = $this->config->get('payment_pp_express_reversed_status_id'); 1116 break; 1117 case 'Voided': 1118 $order_status_id = $this->config->get('payment_pp_express_voided_status_id'); 1119 break; 1120 } 1121 1122 $this->model_checkout_order->addOrderHistory($order_id, $order_status_id); 1123 1124 //add order to paypal table 1125 $paypal_order_data = array( 1126 'order_id' => $order_id, 1127 'capture_status' => ($this->config->get('payment_pp_express_transaction') == 'Sale' ? 'Complete' : 'NotComplete'), 1128 'currency_code' => $result['PAYMENTINFO_0_CURRENCYCODE'], 1129 'authorization_id' => $result['PAYMENTINFO_0_TRANSACTIONID'], 1130 'total' => $result['PAYMENTINFO_0_AMT'] 1131 ); 1132 1133 $paypal_order_id = $this->model_extension_payment_pp_express->addOrder($paypal_order_data); 1134 1135 //add transaction to paypal transaction table 1136 $paypal_transaction_data = array( 1137 'paypal_order_id' => $paypal_order_id, 1138 'transaction_id' => $result['PAYMENTINFO_0_TRANSACTIONID'], 1139 'parent_id' => '', 1140 'note' => '', 1141 'msgsubid' => '', 1142 'receipt_id' => (isset($result['PAYMENTINFO_0_RECEIPTID']) ? $result['PAYMENTINFO_0_RECEIPTID'] : ''), 1143 'payment_type' => $result['PAYMENTINFO_0_PAYMENTTYPE'], 1144 'payment_status' => $result['PAYMENTINFO_0_PAYMENTSTATUS'], 1145 'pending_reason' => $result['PAYMENTINFO_0_PENDINGREASON'], 1146 'transaction_entity' => ($this->config->get('payment_pp_express_transaction') == 'Sale' ? 'payment' : 'auth'), 1147 'amount' => $result['PAYMENTINFO_0_AMT'], 1148 'debug_data' => json_encode($result) 1149 ); 1150 1151 $this->model_extension_payment_pp_express->addTransaction($paypal_transaction_data); 1152 1153 $recurring_products = $this->cart->getRecurringProducts(); 1154 1155 //loop through any products that are recurring items 1156 if ($recurring_products) { 1157 $this->load->language('extension/payment/pp_express'); 1158 1159 $this->load->model('checkout/recurring'); 1160 1161 $billing_period = array( 1162 'day' => 'Day', 1163 'week' => 'Week', 1164 'semi_month' => 'SemiMonth', 1165 'month' => 'Month', 1166 'year' => 'Year' 1167 ); 1168 1169 foreach($recurring_products as $item) { 1170 $data = array( 1171 'METHOD' => 'CreateRecurringPaymentsProfile', 1172 'TOKEN' => $this->session->data['paypal']['token'], 1173 'PROFILESTARTDATE' => gmdate("Y-m-d\TH:i:s\Z", gmmktime(gmdate("H"), gmdate("i")+5, gmdate("s"), gmdate("m"), gmdate("d"), gmdate("y"))), 1174 'BILLINGPERIOD' => $billing_period[$item['recurring']['frequency']], 1175 'BILLINGFREQUENCY' => $item['recurring']['cycle'], 1176 'TOTALBILLINGCYCLES' => $item['recurring']['duration'], 1177 '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'], 1178 'CURRENCYCODE' => $this->session->data['currency'] 1179 ); 1180 1181 //trial information 1182 if ($item['recurring']['trial']) { 1183 $data_trial = array( 1184 'TRIALBILLINGPERIOD' => $billing_period[$item['recurring']['trial_frequency']], 1185 'TRIALBILLINGFREQUENCY' => $item['recurring']['trial_cycle'], 1186 'TRIALTOTALBILLINGCYCLES' => $item['recurring']['trial_duration'], 1187 'TRIALAMT' => $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'] 1188 ); 1189 1190 $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']; 1191 $trial_text = sprintf($this->language->get('text_trial'), $trial_amt, $item['recurring']['trial_cycle'], $item['recurring']['trial_frequency'], $item['recurring']['trial_duration']); 1192 1193 $data = array_merge($data, $data_trial); 1194 } else { 1195 $trial_text = ''; 1196 } 1197 1198 $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']; 1199 $recurring_description = $trial_text . sprintf($this->language->get('text_recurring'), $recurring_amt, $item['recurring']['cycle'], $item['recurring']['frequency']); 1200 1201 if ($item['recurring']['duration'] > 0) { 1202 $recurring_description .= sprintf($this->language->get('text_length'), $item['recurring']['duration']); 1203 } 1204 1205 //create new recurring and set to pending status as no payment has been made yet. 1206 $recurring_id = $this->model_checkout_recurring->addRecurring($order_id, $recurring_description, $item['recurring']); 1207 1208 $data['PROFILEREFERENCE'] = $recurring_id; 1209 $data['DESC'] = $recurring_description; 1210 1211 $result = $this->model_extension_payment_pp_express->call($data); 1212 1213 if (isset($result['PROFILEID'])) { 1214 $this->model_checkout_recurring->addReference($recurring_id, $result['PROFILEID']); 1215 } else { 1216 // there was an error creating the recurring, need to log and also alert admin / user 1217 1218 } 1219 } 1220 } 1221 1222 $this->response->redirect($this->url->link('checkout/success')); 1223 1224 if (isset($result['REDIRECTREQUIRED']) && $result['REDIRECTREQUIRED'] == true) { 1225 //- handle german redirect here 1226 $this->response->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_complete-express-checkout&token=' . $this->session->data['paypal']['token']); 1227 } 1228 } else { 1229 if ($result['L_ERRORCODE0'] == '10486') { 1230 if (isset($this->session->data['paypal_redirect_count'])) { 1231 1232 if ($this->session->data['paypal_redirect_count'] == 2) { 1233 $this->session->data['paypal_redirect_count'] = 0; 1234 $this->session->data['error'] = $this->language->get('error_too_many_failures'); 1235 $this->response->redirect($this->url->link('checkout/checkout', '', true)); 1236 } else { 1237 $this->session->data['paypal_redirect_count']++; 1238 } 1239 } else { 1240 $this->session->data['paypal_redirect_count'] = 1; 1241 } 1242 1243 if ($this->config->get('payment_pp_express_test') == 1) { 1244 $this->response->redirect('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']); 1245 } else { 1246 $this->response->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']); 1247 } 1248 } 1249 1250 $this->session->data['error_warning'] = $result['L_LONGMESSAGE0']; 1251 $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm', '', true)); 1252 } 1253 } else { 1254 $this->response->redirect($redirect); 1255 } 1256 } 1257 1258 public function checkout() { 1259 if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) { 1260 $this->response->redirect($this->url->link('checkout/cart')); 1261 } 1262 1263 $this->load->model('extension/payment/pp_express'); 1264 $this->load->model('tool/image'); 1265 $this->load->model('checkout/order'); 1266 1267 $order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']); 1268 1269 $max_amount = $this->cart->getTotal() * 1.5; 1270 $max_amount = $this->currency->format($max_amount, $this->session->data['currency'], '', false); 1271 1272 if ($this->cart->hasShipping()) { 1273 $shipping = 0; 1274 1275 // PayPal requires some countries to use zone code (not name) to be sent in SHIPTOSTATE 1276 $ship_to_state_codes = array( 1277 '30', // Brazil 1278 '38', // Canada 1279 '105', // Italy 1280 '138', // Mexico 1281 '223', // USA 1282 ); 1283 1284 if (in_array($order_info['shipping_country_id'], $ship_to_state_codes)) { 1285 $ship_to_state = $order_info['shipping_zone_code']; 1286 } else { 1287 $ship_to_state = $order_info['shipping_zone']; 1288 } 1289 1290 $data_shipping = array( 1291 'PAYMENTREQUEST_0_SHIPTONAME' => html_entity_decode($order_info['shipping_firstname'] . ' ' . $order_info['shipping_lastname'], ENT_QUOTES, 'UTF-8'), 1292 'PAYMENTREQUEST_0_SHIPTOSTREET' => html_entity_decode($order_info['shipping_address_1'], ENT_QUOTES, 'UTF-8'), 1293 'PAYMENTREQUEST_0_SHIPTOSTREET2' => html_entity_decode($order_info['shipping_address_2'], ENT_QUOTES, 'UTF-8'), 1294 'PAYMENTREQUEST_0_SHIPTOCITY' => html_entity_decode($order_info['shipping_city'], ENT_QUOTES, 'UTF-8'), 1295 'PAYMENTREQUEST_0_SHIPTOSTATE' => html_entity_decode($ship_to_state, ENT_QUOTES, 'UTF-8'), 1296 'PAYMENTREQUEST_0_SHIPTOZIP' => html_entity_decode($order_info['shipping_postcode'], ENT_QUOTES, 'UTF-8'), 1297 'PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE' => $order_info['shipping_iso_code_2'], 1298 'ADDROVERRIDE' => 1, 1299 ); 1300 } else { 1301 $shipping = 1; 1302 $data_shipping = array(); 1303 } 1304 1305 $data = array( 1306 'METHOD' => 'SetExpressCheckout', 1307 'MAXAMT' => $max_amount, 1308 'RETURNURL' => $this->url->link('extension/payment/pp_express/checkoutReturn', '', true), 1309 'CANCELURL' => $this->url->link('checkout/checkout', '', true), 1310 'REQCONFIRMSHIPPING' => 0, 1311 'NOSHIPPING' => $shipping, 1312 'LOCALECODE' => 'EN', 1313 'LANDINGPAGE' => 'Login', 1314 'HDRIMG' => $this->model_tool_image->resize($this->config->get('payment_pp_express_logo'), 750, 90), 1315 'PAYFLOWCOLOR' => $this->config->get('payment_pp_express_colour'), 1316 'CHANNELTYPE' => 'Merchant', 1317 'ALLOWNOTE' => $this->config->get('payment_pp_express_allow_note') 1318 ); 1319 1320 $data = array_merge($data, $data_shipping); 1321 1322 if (isset($this->session->data['pp_login']['seamless']['access_token']) && (isset($this->session->data['pp_login']['seamless']['customer_id']) && $this->session->data['pp_login']['seamless']['customer_id'] == $this->customer->getId()) && $this->config->get('module_pp_login_seamless')) { 1323 $data['IDENTITYACCESSTOKEN'] = $this->session->data['pp_login']['seamless']['access_token']; 1324 } 1325 1326 $data = array_merge($data, $this->model_extension_payment_pp_express->paymentRequestInfo()); 1327 1328 $result = $this->model_extension_payment_pp_express->call($data); 1329 1330 /** 1331 * If a failed PayPal setup happens, handle it. 1332 */ 1333 if (!isset($result['TOKEN'])) { 1334 $this->session->data['error'] = $result['L_LONGMESSAGE0']; 1335 /** 1336 * Unable to add error message to user as the session errors/success are not 1337 * used on the cart or checkout pages - need to be added? 1338 * If PayPal debug log is off then still log error to normal error log. 1339 */ 1340 $this->log->write('Unable to create Paypal session' . json_encode($result)); 1341 1342 $this->response->redirect($this->url->link('checkout/checkout', '', true)); 1343 } 1344 1345 $this->session->data['paypal']['token'] = $result['TOKEN']; 1346 1347 if ($this->config->get('payment_pp_express_test') == 1) { 1348 header('Location: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $result['TOKEN'] . '&useraction=commit'); 1349 } else { 1350 header('Location: https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $result['TOKEN'] . '&useraction=commit'); 1351 } 1352 } 1353 1354 public function checkoutReturn() { 1355 $this->load->language('extension/payment/pp_express'); 1356 1357 $this->load->model('extension/payment/pp_express'); 1358 $this->load->model('checkout/order'); 1359 1360 $data = array( 1361 'METHOD' => 'GetExpressCheckoutDetails', 1362 'TOKEN' => $this->session->data['paypal']['token'] 1363 ); 1364 1365 $result = $this->model_extension_payment_pp_express->call($data); 1366 1367 $this->session->data['paypal']['payerid'] = $result['PAYERID']; 1368 $this->session->data['paypal']['result'] = $result; 1369 1370 $order_id = $this->session->data['order_id']; 1371 1372 $paypal_data = array( 1373 'TOKEN' => $this->session->data['paypal']['token'], 1374 'PAYERID' => $this->session->data['paypal']['payerid'], 1375 'METHOD' => 'DoExpressCheckoutPayment', 1376 'PAYMENTREQUEST_0_NOTIFYURL' => $this->url->link('extension/payment/pp_express/ipn', '', true), 1377 'RETURNFMFDETAILS' => 1 1378 ); 1379 1380 $paypal_data = array_merge($paypal_data, $this->model_extension_payment_pp_express->paymentRequestInfo()); 1381 1382 $result = $this->model_extension_payment_pp_express->call($paypal_data); 1383 1384 if ($result['ACK'] == 'Success') { 1385 //handle order status 1386 switch($result['PAYMENTINFO_0_PAYMENTSTATUS']) { 1387 case 'Canceled_Reversal': 1388 $order_status_id = $this->config->get('payment_pp_express_canceled_reversal_status_id'); 1389 break; 1390 case 'Completed': 1391 $order_status_id = $this->config->get('payment_pp_express_completed_status_id'); 1392 break; 1393 case 'Denied': 1394 $order_status_id = $this->config->get('payment_pp_express_denied_status_id'); 1395 break; 1396 case 'Expired': 1397 $order_status_id = $this->config->get('payment_pp_express_expired_status_id'); 1398 break; 1399 case 'Failed': 1400 $order_status_id = $this->config->get('payment_pp_express_failed_status_id'); 1401 break; 1402 case 'Pending': 1403 $order_status_id = $this->config->get('payment_pp_express_pending_status_id'); 1404 break; 1405 case 'Processed': 1406 $order_status_id = $this->config->get('payment_pp_express_processed_status_id'); 1407 break; 1408 case 'Refunded': 1409 $order_status_id = $this->config->get('payment_pp_express_refunded_status_id'); 1410 break; 1411 case 'Reversed': 1412 $order_status_id = $this->config->get('payment_pp_express_reversed_status_id'); 1413 break; 1414 case 'Voided': 1415 $order_status_id = $this->config->get('payment_pp_express_voided_status_id'); 1416 break; 1417 } 1418 1419 $this->model_checkout_order->addOrderHistory($order_id, $order_status_id); 1420 1421 //add order to paypal table 1422 $paypal_order_data = array( 1423 'order_id' => $order_id, 1424 'capture_status' => ($this->config->get('payment_pp_express_transaction') == 'Sale' ? 'Complete' : 'NotComplete'), 1425 'currency_code' => $result['PAYMENTINFO_0_CURRENCYCODE'], 1426 'authorization_id' => $result['PAYMENTINFO_0_TRANSACTIONID'], 1427 'total' => $result['PAYMENTINFO_0_AMT'] 1428 ); 1429 1430 $paypal_order_id = $this->model_extension_payment_pp_express->addOrder($paypal_order_data); 1431 1432 //add transaction to paypal transaction table 1433 $paypal_transaction_data = array( 1434 'paypal_order_id' => $paypal_order_id, 1435 'transaction_id' => $result['PAYMENTINFO_0_TRANSACTIONID'], 1436 'parent_id' => '', 1437 'note' => '', 1438 'msgsubid' => '', 1439 'receipt_id' => (isset($result['PAYMENTINFO_0_RECEIPTID']) ? $result['PAYMENTINFO_0_RECEIPTID'] : ''), 1440 'payment_type' => $result['PAYMENTINFO_0_PAYMENTTYPE'], 1441 'payment_status' => $result['PAYMENTINFO_0_PAYMENTSTATUS'], 1442 'pending_reason' => $result['PAYMENTINFO_0_PENDINGREASON'], 1443 'transaction_entity' => ($this->config->get('payment_pp_express_transaction') == 'Sale' ? 'payment' : 'auth'), 1444 'amount' => $result['PAYMENTINFO_0_AMT'], 1445 'debug_data' => json_encode($result) 1446 ); 1447 $this->model_extension_payment_pp_express->addTransaction($paypal_transaction_data); 1448 1449 $recurring_products = $this->cart->getRecurringProducts(); 1450 1451 //loop through any products that are recurring items 1452 if ($recurring_products) { 1453 $this->load->model('checkout/recurring'); 1454 1455 $billing_period = array( 1456 'day' => 'Day', 1457 'week' => 'Week', 1458 'semi_month' => 'SemiMonth', 1459 'month' => 'Month', 1460 'year' => 'Year' 1461 ); 1462 1463 foreach ($recurring_products as $item) { 1464 $data = array( 1465 'METHOD' => 'CreateRecurringPaymentsProfile', 1466 'TOKEN' => $this->session->data['paypal']['token'], 1467 'PROFILESTARTDATE' => gmdate("Y-m-d\TH:i:s\Z", gmmktime(gmdate('H'), gmdate('i') + 5, gmdate('s'), gmdate('m'), gmdate('d'), gmdate('y'))), 1468 'BILLINGPERIOD' => $billing_period[$item['recurring']['frequency']], 1469 'BILLINGFREQUENCY' => $item['recurring']['cycle'], 1470 'TOTALBILLINGCYCLES' => $item['recurring']['duration'], 1471 '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'], 1472 'CURRENCYCODE' => $this->session->data['currency'] 1473 ); 1474 1475 //trial information 1476 if ($item['recurring']['trial'] == 1) { 1477 $data_trial = array( 1478 'TRIALBILLINGPERIOD' => $billing_period[$item['recurring']['trial_frequency']], 1479 'TRIALBILLINGFREQUENCY' => $item['recurring']['trial_cycle'], 1480 'TRIALTOTALBILLINGCYCLES' => $item['recurring']['trial_duration'], 1481 'TRIALAMT' => $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'] 1482 ); 1483 1484 $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']; 1485 $trial_text = sprintf($this->language->get('text_trial'), $trial_amt, $item['recurring']['trial_cycle'], $item['recurring']['trial_frequency'], $item['recurring']['trial_duration']); 1486 1487 $data = array_merge($data, $data_trial); 1488 } else { 1489 $trial_text = ''; 1490 } 1491 1492 $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']; 1493 $recurring_description = $trial_text . sprintf($this->language->get('text_recurring'), $recurring_amt, $item['recurring']['cycle'], $item['recurring']['frequency']); 1494 1495 if ($item['recurring']['duration'] > 0) { 1496 $recurring_description .= sprintf($this->language->get('text_length'), $item['recurring']['duration']); 1497 } 1498 1499 //create new recurring and set to pending status as no payment has been made yet. 1500 $recurring_id = $this->model_checkout_recurring->addRecurring($order_id, $recurring_description, $item['recurring']); 1501 1502 $data['PROFILEREFERENCE'] = $recurring_id; 1503 $data['DESC'] = $recurring_description; 1504 1505 $result = $this->model_extension_payment_pp_express->call($data); 1506 1507 if (isset($result['PROFILEID'])) { 1508 $this->model_checkout_recurring->editReference($recurring_id, $result['PROFILEID']); 1509 } else { 1510 // there was an error creating the recurring, need to log and also alert admin / user 1511 1512 } 1513 } 1514 } 1515 1516 if (isset($result['REDIRECTREQUIRED']) && $result['REDIRECTREQUIRED'] == true) { 1517 //- handle german redirect here 1518 $this->response->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_complete-express-checkout&token=' . $this->session->data['paypal']['token']); 1519 } else { 1520 $this->response->redirect($this->url->link('checkout/success')); 1521 } 1522 } else { 1523 if ($result['L_ERRORCODE0'] == '10486') { 1524 if (isset($this->session->data['paypal_redirect_count'])) { 1525 1526 if ($this->session->data['paypal_redirect_count'] == 2) { 1527 $this->session->data['paypal_redirect_count'] = 0; 1528 $this->session->data['error'] = $this->language->get('error_too_many_failures'); 1529 1530 $this->response->redirect($this->url->link('checkout/checkout', '', true)); 1531 } else { 1532 $this->session->data['paypal_redirect_count']++; 1533 } 1534 } else { 1535 $this->session->data['paypal_redirect_count'] = 1; 1536 } 1537 1538 if ($this->config->get('payment_pp_express_test') == 1) { 1539 $this->response->redirect('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']); 1540 } else { 1541 $this->response->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']); 1542 } 1543 } 1544 1545 $this->load->language('extension/payment/pp_express'); 1546 1547 $data['breadcrumbs'] = array(); 1548 1549 $data['breadcrumbs'][] = array( 1550 'href' => $this->url->link('common/home'), 1551 'text' => $this->language->get('text_home') 1552 ); 1553 1554 $data['breadcrumbs'][] = array( 1555 'href' => $this->url->link('checkout/cart'), 1556 'text' => $this->language->get('text_cart') 1557 ); 1558 1559 $data['heading_title'] = $this->language->get('error_heading_title'); 1560 1561 $data['text_error'] = '<div class="warning">' . $result['L_ERRORCODE0'] . ' : ' . $result['L_LONGMESSAGE0'] . '</div>'; 1562 1563 $data['button_continue'] = $this->language->get('button_continue'); 1564 1565 $data['continue'] = $this->url->link('checkout/cart'); 1566 1567 unset($this->session->data['success']); 1568 1569 $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . ' 404 Not Found'); 1570 1571 $data['column_left'] = $this->load->controller('common/column_left'); 1572 $data['column_right'] = $this->load->controller('common/column_right'); 1573 $data['content_top'] = $this->load->controller('common/content_top'); 1574 $data['content_bottom'] = $this->load->controller('common/content_bottom'); 1575 $data['footer'] = $this->load->controller('common/footer'); 1576 $data['header'] = $this->load->controller('common/header'); 1577 1578 $this->response->setOutput($this->load->view('error/not_found', $data)); 1579 } 1580 } 1581 1582 public function ipn() { 1583 $this->load->model('extension/payment/pp_express'); 1584 $this->load->model('account/recurring'); 1585 1586 $request = 'cmd=_notify-validate'; 1587 1588 foreach ($_POST as $key => $value) { 1589 $request .= '&' . $key . '=' . urlencode(html_entity_decode($value, ENT_QUOTES, 'UTF-8')); 1590 } 1591 1592 if ($this->config->get('payment_pp_express_test') == 1) { 1593 $curl = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr'); 1594 } else { 1595 $curl = curl_init('https://www.paypal.com/cgi-bin/webscr'); 1596 } 1597 1598 curl_setopt($curl, CURLOPT_POST, true); 1599 curl_setopt($curl, CURLOPT_POSTFIELDS, $request); 1600 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 1601 curl_setopt($curl, CURLOPT_HEADER, false); 1602 curl_setopt($curl, CURLOPT_TIMEOUT, 30); 1603 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 1604 1605 $response = trim(curl_exec($curl)); 1606 1607 if (!$response) { 1608 $this->model_extension_payment_pp_express->log(array('error' => curl_error($curl),'error_no' => curl_errno($curl)), 'Curl failed'); 1609 } 1610 1611 $this->model_extension_payment_pp_express->log(array('request' => $request,'response' => $response), 'IPN data'); 1612 1613 if ((string)$response == "VERIFIED") { 1614 if (isset($this->request->post['transaction_entity'])) { 1615 $this->log->write($this->request->post['transaction_entity']); 1616 } 1617 1618 if (isset($this->request->post['txn_id'])) { 1619 $transaction = $this->model_extension_payment_pp_express->getTransactionRow($this->request->post['txn_id']); 1620 } else { 1621 $transaction = false; 1622 } 1623 1624 if (isset($this->request->post['parent_txn_id'])) { 1625 $parent_transaction = $this->model_extension_payment_pp_express->getTransactionRow($this->request->post['parent_txn_id']); 1626 } else { 1627 $parent_transaction = false; 1628 } 1629 1630 if ($transaction) { 1631 //transaction exists, check for cleared payment or updates etc 1632 $this->model_extension_payment_pp_express->log('Transaction exists', 'IPN data'); 1633 1634 //if the transaction is pending but the new status is completed 1635 if ($transaction['payment_status'] != $this->request->post['payment_status']) { 1636 $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order_transaction` SET `payment_status` = '" . $this->db->escape($this->request->post['payment_status']) . "' WHERE `transaction_id` = '" . $this->db->escape($transaction['transaction_id']) . "' LIMIT 1"); 1637 } elseif ($transaction['payment_status'] == 'Pending' && ($transaction['pending_reason'] != $this->request->post['pending_reason'])) { 1638 //payment is still pending but the pending reason has changed, update it. 1639 $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order_transaction` SET `pending_reason` = '" . $this->db->escape($this->request->post['pending_reason']) . "' WHERE `transaction_id` = '" . $this->db->escape($transaction['transaction_id']) . "' LIMIT 1"); 1640 } 1641 } else { 1642 $this->model_extension_payment_pp_express->log('Transaction does not exist', 'IPN data'); 1643 1644 if ($parent_transaction) { 1645 //parent transaction exists 1646 $this->model_extension_payment_pp_express->log('Parent transaction exists', 'IPN data'); 1647 1648 //add new related transaction 1649 $transaction = array( 1650 'paypal_order_id' => $parent_transaction['paypal_order_id'], 1651 'transaction_id' => $this->request->post['txn_id'], 1652 'parent_id' => $this->request->post['parent_txn_id'], 1653 'note' => '', 1654 'msgsubid' => '', 1655 'receipt_id' => (isset($this->request->post['receipt_id']) ? $this->request->post['receipt_id'] : ''), 1656 'payment_type' => (isset($this->request->post['payment_type']) ? $this->request->post['payment_type'] : ''), 1657 'payment_status' => (isset($this->request->post['payment_status']) ? $this->request->post['payment_status'] : ''), 1658 'pending_reason' => (isset($this->request->post['pending_reason']) ? $this->request->post['pending_reason'] : ''), 1659 'amount' => $this->request->post['mc_gross'], 1660 'debug_data' => json_encode($this->request->post), 1661 'transaction_entity' => (isset($this->request->post['transaction_entity']) ? $this->request->post['transaction_entity'] : '') 1662 ); 1663 1664 $this->model_extension_payment_pp_express->addTransaction($transaction); 1665 1666 /** 1667 * If there has been a refund, log this against the parent transaction. 1668 */ 1669 if (isset($this->request->post['payment_status']) && $this->request->post['payment_status'] == 'Refunded') { 1670 if (($this->request->post['mc_gross'] * -1) == $parent_transaction['amount']) { 1671 $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order_transaction` SET `payment_status` = 'Refunded' WHERE `transaction_id` = '" . $this->db->escape($parent_transaction['transaction_id']) . "' LIMIT 1"); 1672 } else { 1673 $this->db->query("UPDATE `" . DB_PREFIX . "paypal_order_transaction` SET `payment_status` = 'Partially-Refunded' WHERE `transaction_id` = '" . $this->db->escape($parent_transaction['transaction_id']) . "' LIMIT 1"); 1674 } 1675 } 1676 1677 /** 1678 * If the capture payment is now complete 1679 */ 1680 if (isset($this->request->post['auth_status']) && $this->request->post['auth_status'] == 'Completed' && $parent_transaction['payment_status'] == 'Pending') { 1681 $captured = $this->currency->format($this->model_extension_payment_pp_express->getTotalCaptured($parent_transaction['paypal_order_id']), $this->session->data['currency'], false, false); 1682 $refunded = $this->currency->format($this->model_extension_payment_pp_express->getRefundedTotal($parent_transaction['paypal_order_id']), $this->session->data['currency'], false, false); 1683 $remaining = $this->currency->format($parent_transaction['amount'] - $captured + $refunded, $this->session->data['currency'], false, false); 1684 1685 $this->model_extension_payment_pp_express->log('Captured: ' . $captured, 'IPN data'); 1686 $this->model_extension_payment_pp_express->log('Refunded: ' . $refunded, 'IPN data'); 1687 $this->model_extension_payment_pp_express->log('Remaining: ' . $remaining, 'IPN data'); 1688 1689 if ($remaining > 0.00) { 1690 $transaction = array( 1691 'paypal_order_id' => $parent_transaction['paypal_order_id'], 1692 'transaction_id' => '', 1693 'parent_id' => $this->request->post['parent_txn_id'], 1694 'note' => '', 1695 'msgsubid' => '', 1696 'receipt_id' => '', 1697 'payment_type' => '', 1698 'payment_status' => 'Void', 1699 'pending_reason' => '', 1700 'amount' => '', 1701 'debug_data' => 'Voided after capture', 1702 'transaction_entity' => 'auth' 1703 ); 1704 1705 $this->model_extension_payment_pp_express->addTransaction($transaction); 1706 } 1707 1708 $this->model_extension_payment_pp_express->updateOrder('Complete', $parent_transaction['order_id']); 1709 } 1710 1711 } else { 1712 //parent transaction doesn't exists, need to investigate? 1713 $this->model_extension_payment_pp_express->log('Parent transaction not found', 'IPN data'); 1714 } 1715 } 1716 1717 /* 1718 * Subscription payments 1719 * 1720 * recurring ID should always exist if its a recurring payment transaction. 1721 * 1722 * also the reference will match a recurring payment ID 1723 */ 1724 if (isset($this->request->post['txn_type'])) { 1725 $this->model_extension_payment_pp_express->log($this->request->post['txn_type'], 'IPN data'); 1726 1727 //payment 1728 if ($this->request->post['txn_type'] == 'recurring_payment') { 1729 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1730 1731 $this->model_extension_payment_pp_express->log($recurring, 'IPN data'); 1732 1733 if ($recurring != false) { 1734 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `amount` = '" . (float)$this->request->post['amount'] . "', `type` = '1'"); 1735 1736 //as there was a payment the recurring is active, ensure it is set to active (may be been suspended before) 1737 if ($recurring['status'] != 1) { 1738 $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 2 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "'"); 1739 } 1740 } 1741 } 1742 1743 //suspend 1744 if ($this->request->post['txn_type'] == 'recurring_payment_suspended') { 1745 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1746 1747 if ($recurring != false) { 1748 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '6'"); 1749 $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 3 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "' LIMIT 1"); 1750 } 1751 } 1752 1753 //suspend due to max failed 1754 if ($this->request->post['txn_type'] == 'recurring_payment_suspended_due_to_max_failed_payment') { 1755 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1756 1757 if ($recurring != false) { 1758 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '7'"); 1759 $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 3 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "' LIMIT 1"); 1760 } 1761 } 1762 1763 //payment failed 1764 if ($this->request->post['txn_type'] == 'recurring_payment_failed') { 1765 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1766 1767 if ($recurring != false) { 1768 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '4'"); 1769 } 1770 } 1771 1772 //outstanding payment failed 1773 if ($this->request->post['txn_type'] == 'recurring_payment_outstanding_payment_failed') { 1774 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1775 1776 if ($recurring != false) { 1777 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '8'"); 1778 } 1779 } 1780 1781 //outstanding payment 1782 if ($this->request->post['txn_type'] == 'recurring_payment_outstanding_payment') { 1783 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1784 1785 if ($recurring != false) { 1786 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `amount` = '" . (float)$this->request->post['amount'] . "', `type` = '2'"); 1787 1788 //as there was a payment the recurring is active, ensure it is set to active (may be been suspended before) 1789 if ($recurring['status'] != 1) { 1790 $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 2 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "'"); 1791 } 1792 } 1793 } 1794 1795 //date_added 1796 if ($this->request->post['txn_type'] == 'recurring_payment_profile_date_added') { 1797 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1798 1799 if ($recurring != false) { 1800 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '0'"); 1801 1802 if ($recurring['status'] != 1) { 1803 $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 2 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "'"); 1804 } 1805 } 1806 } 1807 1808 //cancelled 1809 if ($this->request->post['txn_type'] == 'recurring_payment_profile_cancel') { 1810 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1811 1812 if ($recurring != false && $recurring['status'] != 3) { 1813 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '5'"); 1814 $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 4 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "' LIMIT 1"); 1815 } 1816 } 1817 1818 //skipped 1819 if ($this->request->post['txn_type'] == 'recurring_payment_skipped') { 1820 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1821 1822 if ($recurring != false) { 1823 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '3'"); 1824 } 1825 } 1826 1827 //expired 1828 if ($this->request->post['txn_type'] == 'recurring_payment_expired') { 1829 $recurring = $this->model_account_recurring->getOrderRecurringByReference($this->request->post['recurring_payment_id']); 1830 1831 if ($recurring != false) { 1832 $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "', `date_added` = NOW(), `type` = '9'"); 1833 $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = 5 WHERE `order_recurring_id` = '" . (int)$recurring['order_recurring_id'] . "' LIMIT 1"); 1834 } 1835 } 1836 } 1837 } elseif ((string)$response == "INVALID") { 1838 $this->model_extension_payment_pp_express->log(array('IPN was invalid'), 'IPN fail'); 1839 } else { 1840 $this->model_extension_payment_pp_express->log('Response string unknown: ' . (string)$response, 'IPN data'); 1841 } 1842 1843 header("HTTP/1.1 200 Ok"); 1844 } 1845 1846 public function shipping() { 1847 $this->shippingValidate($this->request->post['shipping_method']); 1848 1849 $this->response->redirect($this->url->link('extension/payment/pp_express/expressConfirm')); 1850 } 1851 1852 protected function shippingValidate($code) { 1853 $this->load->language('checkout/cart'); 1854 $this->load->language('extension/payment/pp_express'); 1855 1856 if (empty($code)) { 1857 $this->session->data['error_warning'] = $this->language->get('error_shipping'); 1858 return false; 1859 } else { 1860 $shipping = explode('.', $code); 1861 1862 if (!isset($shipping[0]) || !isset($shipping[1]) || !isset($this->session->data['shipping_methods'][$shipping[0]]['quote'][$shipping[1]])) { 1863 $this->session->data['error_warning'] = $this->language->get('error_shipping'); 1864 return false; 1865 } else { 1866 $this->session->data['shipping_method'] = $this->session->data['shipping_methods'][$shipping[0]]['quote'][$shipping[1]]; 1867 $this->session->data['success'] = $this->language->get('text_shipping_updated'); 1868 return true; 1869 } 1870 } 1871 } 1872 1873 protected function validateCoupon() { 1874 $this->load->model('extension/total/coupon'); 1875 1876 $coupon_info = $this->model_extension_total_coupon->getCoupon($this->request->post['coupon']); 1877 1878 if ($coupon_info) { 1879 return true; 1880 } else { 1881 $this->session->data['error_warning'] = $this->language->get('error_coupon'); 1882 return false; 1883 } 1884 } 1885 1886 protected function validateVoucher() { 1887 $this->load->model('extension/total/coupon'); 1888 1889 $voucher_info = $this->model_extension_total_voucher->getVoucher($this->request->post['voucher']); 1890 1891 if ($voucher_info) { 1892 return true; 1893 } else { 1894 $this->session->data['error_warning'] = $this->language->get('error_voucher'); 1895 return false; 1896 } 1897 } 1898 1899 protected function validateReward() { 1900 $points = $this->customer->getRewardPoints(); 1901 1902 $points_total = 0; 1903 1904 foreach ($this->cart->getProducts() as $product) { 1905 if ($product['points']) { 1906 $points_total += $product['points']; 1907 } 1908 } 1909 1910 $error = ''; 1911 1912 if (empty($this->request->post['reward'])) { 1913 $error = $this->language->get('error_reward'); 1914 } 1915 1916 if ($this->request->post['reward'] > $points) { 1917 $error = sprintf($this->language->get('error_points'), $this->request->post['reward']); 1918 } 1919 1920 if ($this->request->post['reward'] > $points_total) { 1921 $error = sprintf($this->language->get('error_maximum'), $points_total); 1922 } 1923 1924 if (!$error) { 1925 return true; 1926 } else { 1927 $this->session->data['error_warning'] = $error; 1928 return false; 1929 } 1930 } 1931 }