$this->language->load('payment/pp_express');
$redirect = '';
if ($this->cart->hasShipping()) {
// Validate if shipping address has been set.
$this->load->model('account/address');
if ($this->customer->isLogged() && isset($this->session->data['shipping_address_id'])) {
$shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']);
} elseif (isset($this->session->data['guest'])) {
$shipping_address = $this->session->data['guest']['shipping'];
}
if (empty($shipping_address)) {
$redirect = $this->url->link('checkout/checkout', '', 'SSL');
}
// Validate if shipping method has been set.
if (!isset($this->session->data['shipping_method'])) {
$redirect = $this->url->link('checkout/checkout', '', 'SSL');
}
} else {
unset($this->session->data['shipping_method']);
unset($this->session->data['shipping_methods']);
}
// Validate if payment address has been set.
$this->load->model('account/address');
if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) {
$payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']);
} elseif (isset($this->session->data['guest'])) {
$payment_address = $this->session->data['guest']['payment'];
}
// Validate if payment method has been set.
if (!isset($this->session->data['payment_method'])) {
$redirect = $this->url->link('checkout/checkout', '', 'SSL');
}
// Validate cart has products and has stock.
if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
$redirect = $this->url->link('checkout/cart');
}
// Validate minimum quantity requirments.
$products = $this->cart->getProducts();
foreach ($products as $product) {
$product_total = 0;
foreach ($products as $product_2) {
if ($product_2['product_id'] == $product['product_id']) {
$product_total += $product_2['quantity'];
}
}
if ($product['minimum'] > $product_total) {
$redirect = $this->url->link('checkout/cart');
break;
}
}
if ($redirect == '') {
$total_data = array();
$total = 0;
$taxes = $this->cart->getTaxes();
$this->load->model('setting/extension');
$sort_order = array();
$results = $this->model_setting_extension->getExtensions('total');
foreach ($results as $key => $value) {
$sort_order[$key] = $this->config->get($value['code'] . '_sort_order');
}
array_multisort($sort_order, SORT_ASC, $results);
foreach ($results as $result) {
if ($this->config->get($result['code'] . '_status')) {
$this->load->model('total/' . $result['code']);
$this->{'model_total_' . $result['code']}->getTotal($total_data, $total, $taxes);
}
}
$sort_order = array();
foreach ($total_data as $key => $value) {
$sort_order[$key] = $value['sort_order'];
}
array_multisort($sort_order, SORT_ASC, $total_data);
$this->language->load('checkout/checkout');
$data = array();
$data['invoice_prefix'] = $this->config->get('config_invoice_prefix');
$data['store_id'] = $this->config->get('config_store_id');
$data['store_name'] = $this->config->get('config_name');
if ($data['store_id']) {
$data['store_url'] = $this->config->get('config_url');
} else {
$data['store_url'] = HTTP_SERVER;
}
if ($this->customer->isLogged() && isset($this->session->data['payment_address_id'])) {
$data['customer_id'] = $this->customer->getId();
$data['customer_group_id'] = $this->customer->getCustomerGroupId();
$data['firstname'] = $this->customer->getFirstName();
$data['lastname'] = $this->customer->getLastName();
$data['email'] = $this->customer->getEmail();
$data['telephone'] = $this->customer->getTelephone();
$data['fax'] = $this->customer->getFax();
$this->load->model('account/address');
$payment_address = $this->model_account_address->getAddress($this->session->data['payment_address_id']);
} elseif (isset($this->session->data['guest'])) {
$data['customer_id'] = 0;
$data['customer_group_id'] = $this->session->data['guest']['customer_group_id'];
$data['firstname'] = $this->session->data['guest']['firstname'];
$data['lastname'] = $this->session->data['guest']['lastname'];
$data['email'] = $this->session->data['guest']['email'];
$data['telephone'] = $this->session->data['guest']['telephone'];
$data['fax'] = $this->session->data['guest']['fax'];
$payment_address = $this->session->data['guest']['payment'];
}
$data['payment_firstname'] = isset($payment_address['firstname']) ? $payment_address['firstname'] : '';
$data['payment_lastname'] = isset($payment_address['lastname']) ? $payment_address['lastname'] : '';
$data['payment_company'] = isset($payment_address['company']) ? $payment_address['company'] : '';
$data['payment_company_id'] = isset($payment_address['company_id']) ? $payment_address['company_id'] : '';
$data['payment_tax_id'] = isset($payment_address['tax_id']) ? $payment_address['tax_id'] : '';
$data['payment_address_1'] = isset($payment_address['address_1']) ? $payment_address['address_1'] : '';
$data['payment_address_2'] = isset($payment_address['address_2']) ? $payment_address['address_2'] : '';
$data['payment_city'] = isset($payment_address['city']) ? $payment_address['city'] : '';
$data['payment_postcode'] = isset($payment_address['postcode']) ? $payment_address['postcode'] : '';
$data['payment_zone'] = isset($payment_address['zone']) ? $payment_address['zone'] : '';
$data['payment_zone_id'] = isset($payment_address['zone_id']) ? $payment_address['zone_id'] : '';
$data['payment_country'] = isset($payment_address['country']) ? $payment_address['country'] : '';
$data['payment_country_id'] = isset($payment_address['country_id']) ? $payment_address['country_id'] : '';
$data['payment_address_format'] = isset($payment_address['address_format']) ? $payment_address['address_format'] : '';
$data['payment_method'] = '';
if (isset($this->session->data['payment_method']['title'])) {
$data['payment_method'] = $this->session->data['payment_method']['title'];
}
$data['payment_code'] = '';
if (isset($this->session->data['payment_method']['code'])) {
$data['payment_code'] = $this->session->data['payment_method']['code'];
}
if ($this->cart->hasShipping()) {
if ($this->customer->isLogged()) {
$this->load->model('account/address');
$shipping_address = $this->model_account_address->getAddress($this->session->data['shipping_address_id']);
} elseif (isset($this->session->data['guest'])) {
$shipping_address = $this->session->data['guest']['shipping'];
}
$data['shipping_firstname'] = $shipping_address['firstname'];
$data['shipping_lastname'] = $shipping_address['lastname'];
$data['shipping_company'] = $shipping_address['company'];
$data['shipping_address_1'] = $shipping_address['address_1'];
$data['shipping_address_2'] = $shipping_address['address_2'];
$data['shipping_city'] = $shipping_address['city'];
$data['shipping_postcode'] = $shipping_address['postcode'];
$data['shipping_zone'] = $shipping_address['zone'];
$data['shipping_zone_id'] = $shipping_address['zone_id'];
$data['shipping_country'] = $shipping_address['country'];
$data['shipping_country_id'] = $shipping_address['country_id'];
$data['shipping_address_format'] = $shipping_address['address_format'];
$data['shipping_method'] = '';
if (isset($this->session->data['shipping_method']['title'])) {
$data['shipping_method'] = $this->session->data['shipping_method']['title'];
}
$data['shipping_code'] = '';
if (isset($this->session->data['shipping_method']['code'])) {
$data['shipping_code'] = $this->session->data['shipping_method']['code'];
}
} else {
$data['shipping_firstname'] = '';
$data['shipping_lastname'] = '';
$data['shipping_company'] = '';
$data['shipping_address_1'] = '';
$data['shipping_address_2'] = '';
$data['shipping_city'] = '';
$data['shipping_postcode'] = '';
$data['shipping_zone'] = '';
$data['shipping_zone_id'] = '';
$data['shipping_country'] = '';
$data['shipping_country_id'] = '';
$data['shipping_address_format'] = '';
$data['shipping_method'] = '';
$data['shipping_code'] = '';
}
$product_data = array();
foreach ($this->cart->getProducts() as $product) {
$option_data = array();
foreach ($product['option'] as $option) {
if ($option['type'] != 'file') {
$value = $option['option_value'];
} else {
$value = $this->encryption->decrypt($option['option_value']);
}
$option_data[] = array(
'product_option_id' => $option['product_option_id'],
'product_option_value_id' => $option['product_option_value_id'],
'option_id' => $option['option_id'],
'option_value_id' => $option['option_value_id'],
'name' => $option['name'],
'value' => $value,
'type' => $option['type']
);
}
$product_data[] = array(
'product_id' => $product['product_id'],
'name' => $product['name'],
'model' => $product['model'],
'option' => $option_data,
'download' => $product['download'],
'quantity' => $product['quantity'],
'subtract' => $product['subtract'],
'price' => $product['price'],
'total' => $product['total'],
'tax' => $this->tax->getTax($product['price'], $product['tax_class_id']),
'reward' => $product['reward']
);
}
// Gift Voucher
$voucher_data = array();
if (!empty($this->session->data['vouchers'])) {
foreach ($this->session->data['vouchers'] as $voucher) {
$voucher_data[] = array(
'description' => $voucher['description'],
'code' => substr(md5(mt_rand()), 0, 10),
'to_name' => $voucher['to_name'],
'to_email' => $voucher['to_email'],
'from_name' => $voucher['from_name'],
'from_email' => $voucher['from_email'],
'voucher_theme_id' => $voucher['voucher_theme_id'],
'message' => $voucher['message'],
'amount' => $voucher['amount']
);
}
}
$data['products'] = $product_data;
$data['vouchers'] = $voucher_data;
$data['totals'] = $total_data;
$data['comment'] = $this->session->data['comment'];
$data['total'] = $total;
if (isset($this->request->cookie['tracking'])) {
$this->load->model('affiliate/affiliate');
$affiliate_info = $this->model_affiliate_affiliate->getAffiliateByCode($this->request->cookie['tracking']);
$subtotal = $this->cart->getSubTotal();
if ($affiliate_info) {
$data['affiliate_id'] = $affiliate_info['affiliate_id'];
$data['commission'] = ($subtotal / 100) * $affiliate_info['commission'];
} else {
$data['affiliate_id'] = 0;
$data['commission'] = 0;
}
} else {
$data['affiliate_id'] = 0;
$data['commission'] = 0;
}
$data['language_id'] = $this->config->get('config_language_id');
$data['currency_id'] = $this->currency->getId();
$data['currency_code'] = $this->currency->getCode();
$data['currency_value'] = $this->currency->getValue($this->currency->getCode());
$data['ip'] = $this->request->server['REMOTE_ADDR'];
if (!empty($this->request->server['HTTP_X_FORWARDED_FOR'])) {
$data['forwarded_ip'] = $this->request->server['HTTP_X_FORWARDED_FOR'];
} elseif(!empty($this->request->server['HTTP_CLIENT_IP'])) {
$data['forwarded_ip'] = $this->request->server['HTTP_CLIENT_IP'];
} else {
$data['forwarded_ip'] = '';
}
if (isset($this->request->server['HTTP_USER_AGENT'])) {
$data['user_agent'] = $this->request->server['HTTP_USER_AGENT'];
} else {
$data['user_agent'] = '';
}
if (isset($this->request->server['HTTP_ACCEPT_LANGUAGE'])) {
$data['accept_language'] = $this->request->server['HTTP_ACCEPT_LANGUAGE'];
} else {
$data['accept_language'] = '';
}
$this->load->model('checkout/order');
$order_id = $this->model_checkout_order->addOrder($data);
$this->session->data['order_id'] = $order_id;
$this->load->model('payment/pp_express');
$paypal_data = array(
'TOKEN' => $this->session->data['paypal']['token'],
'PAYERID' => $this->session->data['paypal']['payerid'],
'METHOD' => 'DoExpressCheckoutPayment',
'PAYMENTREQUEST_0_NOTIFYURL' => $this->url->link('payment/pp_express/ipn', '', 'SSL'),
'RETURNFMFDETAILS' => 1,
);
$paypal_data = array_merge($paypal_data, $this->model_payment_pp_express->paymentRequestInfo());
$result = $this->model_payment_pp_express->call($paypal_data);
if($result['ACK'] == 'Success') {
//handle order status
switch($result['PAYMENTINFO_0_PAYMENTSTATUS']) {
case 'Canceled_Reversal':
$order_status_id = $this->config->get('pp_express_canceled_reversal_status_id');
break;
case 'Completed':
$order_status_id = $this->config->get('pp_express_completed_status_id');
break;
case 'Denied':
$order_status_id = $this->config->get('pp_express_denied_status_id');
break;
case 'Expired':
$order_status_id = $this->config->get('pp_express_expired_status_id');
break;
case 'Failed':
$order_status_id = $this->config->get('pp_express_failed_status_id');
break;
case 'Pending':
$order_status_id = $this->config->get('pp_express_pending_status_id');
break;
case 'Processed':
$order_status_id = $this->config->get('pp_express_processed_status_id');
break;
case 'Refunded':
$order_status_id = $this->config->get('pp_express_refunded_status_id');
break;
case 'Reversed':
$order_status_id = $this->config->get('pp_express_reversed_status_id');
break;
case 'Voided':
$order_status_id = $this->config->get('pp_express_voided_status_id');
break;
}
$this->model_checkout_order->confirm($order_id, $order_status_id);
//add order to paypal table
$paypal_order_data = array(
'order_id' => $order_id,
'capture_status' => ($this->config->get('pp_express_method') == 'Sale' ? 'Complete' : 'NotComplete'),
'currency_code' => $result['PAYMENTINFO_0_CURRENCYCODE'],
'authorization_id' => $result['PAYMENTINFO_0_TRANSACTIONID'],
'total' => $result['PAYMENTINFO_0_AMT'],
);
$paypal_order_id = $this->model_payment_pp_express->addOrder($paypal_order_data);
//add transaction to paypal transaction table
$paypal_transaction_data = array(
'paypal_order_id' => $paypal_order_id,
'transaction_id' => $result['PAYMENTINFO_0_TRANSACTIONID'],
'parent_transaction_id' => '',
'note' => '',
'msgsubid' => '',
'receipt_id' => (isset($result['PAYMENTINFO_0_RECEIPTID']) ? $result['PAYMENTINFO_0_RECEIPTID'] : ''),
'payment_type' => $result['PAYMENTINFO_0_PAYMENTTYPE'],
'payment_status' => $result['PAYMENTINFO_0_PAYMENTSTATUS'],
'pending_reason' => $result['PAYMENTINFO_0_PENDINGREASON'],
'transaction_entity' => ($this->config->get('pp_express_method') == 'Sale' ? 'payment' : 'auth'),
'amount' => $result['PAYMENTINFO_0_AMT'],
'debug_data' => json_encode($result),
);
$this->model_payment_pp_express->addTransaction($paypal_transaction_data);
$recurring_products = $this->cart->getRecurringProducts();
//loop through any products that are recurring items
if(!empty($recurring_products)) {
$this->language->load('payment/pp_express');
$this->load->model('checkout/recurring');
$billing_period = array(
'day' => 'Day',
'week' => 'Week',
'semi_month' => 'SemiMonth',
'month' => 'Month',
'year' => 'Year'
);
foreach($recurring_products as $item) {
$data = array(
'METHOD' => 'CreateRecurringPaymentsProfile',
'TOKEN' => $this->session->data['paypal']['token'],
'PROFILESTARTDATE' => gmdate("Y-m-d\TH:i:s\Z", mktime(gmdate("H"), gmdate("i")+5, gmdate("s"), gmdate("m"), gmdate("d"), gmdate("y"))),
'BILLINGPERIOD' => $billing_period[$item['recurring_frequency']],
'BILLINGFREQUENCY' => $item['recurring_cycle'],
'TOTALBILLINGCYCLES' => $item['recurring_duration'],
'AMT' => $this->currency->format($this->tax->calculate($item['recurring_price'], $item['tax_class_id'], $this->config->get('config_tax')), false, false, false) * $item['quantity'],
'CURRENCYCODE' => $this->currency->getCode(),
);
//trial information
if($item['recurring_trial'] == 1) {
$data_trial = array(
'TRIALBILLINGPERIOD' => $billing_period[$item['recurring_trial_frequency']],
'TRIALBILLINGFREQUENCY' => $item['recurring_trial_cycle'],
'TRIALTOTALBILLINGCYCLES' => $item['recurring_trial_duration'],
'TRIALAMT' => $this->currency->format($this->tax->calculate($item['recurring_trial_price'], $item['tax_class_id'], $this->config->get('config_tax')), false, false, false) * $item['quantity'],
);
$trial_amt = $this->currency->format($this->tax->calculate($item['recurring_trial_price'], $item['tax_class_id'], $this->config->get('config_tax')), false, false, false) * $item['quantity'].' '.$this->currency->getCode();
$trial_text = sprintf($this->language->get('text_trial'), $trial_amt, $item['recurring_trial_cycle'], $item['recurring_trial_frequency'], $item['recurring_trial_duration']);
$data = array_merge($data, $data_trial);
} else {
$trial_text = '';
}
$recurring_amt = $this->currency->format($this->tax->calculate($item['recurring_price'], $item['tax_class_id'], $this->config->get('config_tax')), false, false, false) * $item['quantity'].' '.$this->currency->getCode();
$recurring_description = $trial_text . sprintf($this->language->get('text_recurring'), $recurring_amt, $item['recurring_cycle'], $item['recurring_frequency']);
if($item['recurring_duration'] > 0) {
$recurring_description .= sprintf($this->language->get('text_length'), $item['recurring_duration']);
}
//create new profile and set to pending status as no payment has been made yet.
$recurring_id = $this->model_checkout_recurring->create($item, $order_id, $recurring_description);
$data['PROFILEREFERENCE'] = $recurring_id;
$data['DESC'] = $recurring_description;
$result = $this->model_payment_pp_express->call($data);
if(isset($result['PROFILEID'])) {
$this->model_checkout_recurring->addReference($recurring_id, $result['PROFILEID']);
} else {
// there was an error creating the profile, need to log and also alert admin / user
}
}
}
$this->redirect($this->url->link('checkout/success'));
if(isset($result['REDIRECTREQUIRED']) && $result['REDIRECTREQUIRED'] == true) { //- handle german redirect here
$this->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_complete-express-checkout&token='.$this->session->data['paypal']['token']);
}
} else {
if ($result['L_ERRORCODE0'] == '10486') {
if (isset($this->session->data['paypal_redirect_count'])) {
if ($this->session->data['paypal_redirect_count'] == 2) {
$this->session->data['paypal_redirect_count'] = 0;
$this->session->data['error'] = $this->language->get('error_too_many_failures');
$this->redirect($this->url->link('checkout/checkout', '', 'SSL'));
} else {
$this->session->data['paypal_redirect_count']++;
}
} else {
$this->session->data['paypal_redirect_count'] = 1;
}
if ($this->config->get('pp_express_test') == 1) {
$this->redirect('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']);
} else {
$this->redirect('https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=' . $this->session->data['paypal']['token']);
}
}
$this->session->data['error'] = $result['L_LONGMESSAGE0'];
$this->redirect($this->url->link('payment/pp_express/expressConfirm', '', 'SSL'));
}
} else {
$this->redirect($redirect);
}