order = new Order((int)$id_order); } if (!is_null($id_order_details)) { $this->id_order_details_to_return = $id_order_details; } if (Validate::isLoadedObject($this->order)) { $this->customer = new Customer((int)$this->order->id_customer); $this->product_list = $this->order->getProductsDetail(); $this->address = new Address((int)$this->order->id_address_delivery); $relais = false; if ($this->ps15x && (Module::isEnabled('soflexibilite') || Module::isEnabled('soliberte'))) { $soflexibilite_relays = Configuration::getMultiple(array( 'SOFLEXIBILITE_A2P_ID', 'SOFLEXIBILITE_BPR_ID', 'SOLIBERTE_A2P_ID', 'SOLIBERTE_BPR_ID' )); if (strpos($this->address->alias, 'So Colissimo') !== false && in_array($this->order->id_carrier, $soflexibilite_relays)) { $relais = true; } } if ($this->ps15x && Module::isEnabled('chronopost')) { $chronopost_relais = Configuration::get('CHRONORELAIS_CARRIER_ID'); if (strpos($this->address->alias, 'ChronoRelais') !== false && $this->order->id_carrier == $chronopost_relais) { $relais = true; } } if ($this->ps15x && Module::isEnabled('dpdfrance')) { $relais = (bool)Db::getInstance()->getValue( 'SELECT `relay_id` FROM `'._DB_PREFIX_.'dpdfrance_shipping` WHERE `id_customer` = '.(int)$this->order->id_customer.' AND `id_cart` = '.(int)$this->order->id_cart.' AND `id_carrier` = '.(int)$this->order->id_carrier ); } if ($relais) { // si l'adresse de livraison correspond a un relais on utilise l'adresse de facturation sur l'etiquette $this->address = new Address((int)$this->order->id_address_invoice); } Context::getContext()->shop = new Shop($this->order->id_shop); } parent::__construct(); $this->path = _PS_MODULE_DIR_.'sonice_retour/'; $this->protocol = Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://'; $this->url = $this->protocol.htmlspecialchars($_SERVER['HTTP_HOST'], ENT_COMPAT, 'UTF-8'). __PS_BASE_URI__.'modules/sonice_retour/'; $this->ps15x = version_compare(_PS_VERSION_, '1.5', '>='); if (version_compare(_PS_VERSION_, '1.5', '>=')) { $this->id_lang = (int)Context::getContext()->language->id; $this->context = Context::getContext(); } else { require_once(dirname(__FILE__).'/../backward_compatibility/backward.php'); $this->context = Context::getContext(); $this->id_lang = (int)Context::getContext()->language->id; $this->context->shop->id = null; $this->context->shop->id_shop_group = null; } } public function l($string, $specific = false, $locale = null) { if (!$specific) { $specific = basename(__FILE__, '.php'); } if (class_exists('Translate')) { return Translate::getModuleTranslation(get_parent_class(), $string, $specific); } return parent::l($string, $specific); } /** * Call Coliposte Web Service * * @return bool */ public function callWS($login = null, $pwd = null, $params = null) { if (!$this->webServiceSupervision()) { $this->error = new StdClass(); $this->error->errorID = 'SoNiceRetourPDF line '.__LINE__; $this->error->error = $this->l( 'Network Supervision Failed. The Coliposte web service is currently having some trouble or is in maintenance. Please try again in a moment.' ); return (false); } try { if (is_array($params) && count($params)) { $parameters = $params; } else { $parameters = $this->_getParams(); if ($login && $pwd) { $parameters['letter']['password'] = $pwd; $parameters['letter']['contractNumber'] = $login; } } $this->response = parent::_callWS($parameters); } catch (Exception $e) { $this->error = new StdClass(); $this->error->errorID = 'SoNiceRetourPDF line '.__LINE__; $this->error->error = sprintf('%s : %s', $e->getLine(), $e->getMessage()); return (false); } return (true); } public function getFormattedResponse() { $result = array(); $result['errorID'] = null; $result['error'] = null; $result['PdfUrl'] = null; if (!$this->response instanceof SimpleXMLElement) { $result['errorID'] = 'SoNiceRetourPDF #'.__LINE__; $result['error'] = $this->l('The result does not have an XML format.'); return ($result); } $elements = $this->response->xpath('//Envelope/Body/generateLabelResponse/*'); if (!isset($elements[0]) || !isset($elements[0]->messages)) { $result['errorID'] = 'SoNiceRetourPDF line '.__LINE__; $result['error'] = 'Wrong Message'; if (isset($elements[0]->faultcode) && isset($elements[0]->faultstring)) { echo '
'.print_r($elements, true).'
'; } return ($result); } if ($elements[0]->messages->type == 'ERROR') { $result['errorID'] = $elements[0]->messages->id; $result['error'] = $elements[0]->messages->messageContent; return ($result); } $result['parcelNumber'] = (string)$elements[0]->labelResponse->parcelNumber; if ($this->demo) { $result['parcelNumber'] = '8R'.abs(rand(1000000, 9999999)).abs(rand(100, 999)); } // Download label if ($this->demo) { $result['PdfUrl'] = $this->url.'functions/demo_retour.pdf'; } elseif (isset($elements[0]->labelResponse->pdfUrl) && Tools::strlen((string)$elements[0]->labelResponse->pdfUrl)) { $label = Tools::file_get_contents(str_replace('&', '&', (string)$elements[0]->labelResponse->pdfUrl)); if (file_put_contents($this->path.'download/'.$result['parcelNumber'].'.pdf', $label)) { $result['PdfUrl'] = str_replace('&', '&', (string)$elements[0]->labelResponse->pdfUrl); } } elseif (!isset($elements[0]->labelResponse->pdfUrl)) { $label = $this->raw_response->parse()->getLabelBinary(); if (!file_put_contents($this->path.'download/'.$result['parcelNumber'].'.pdf', $label)) { echo $this->l('ERROR, unable to save label on the server. Please check the access permission of the folder '). _PS_MODULE_DIR_.'sonice_retour/download/'; } } else { $result['errorID'] = 'SoNiceRetourPDF line '.__LINE__; $result['error'] = 'No PDF from Coliposte to download...'; } return ($result); } /** * Fill the parameters for the web service * * @return array */ private function _getParams() { $date_deposite = new DateTime(); if (!Tools::strlen($this->module_conf['ContractNumber']) || !Tools::strlen($this->module_conf['Password']) || !Tools::strlen($this->module_conf['companyName']) || !Tools::strlen($this->module_conf['Line2']) || !Tools::strlen($this->module_conf['PostalCode']) || !Tools::strlen($this->module_conf['City'])) { die($this->l('You need to configure the module with your login and address details.')); } if (Tools::strlen($this->module_conf['deposit_date'])) { $date_deposite->modify('+'.(int)$this->module_conf['deposit_date'].' Day'); } $order_total_weight = (float)$this->order->getTotalWeight(); if (!$order_total_weight || $order_total_weight < 0.01) { $order_total_weight = 0.01; } if ($order_total_weight > 30) { $order_total_weight /= 1000; } $phone_mobile = $this->address->phone_mobile; if (!preg_match('/^((\+|00)([0-9]{1,3})\s?|0)[067]{1,2}(\s?\d{2}){4}$/', $phone_mobile)) { $phone_mobile = $this->address->phone_mobile; } // For senderParcelRef // If no id_return is given then we get the new one that should be created $parcel_ref = (int)Tools::getValue('id_return') ?: (int)Db::getInstance()->getValue( 'SELECT 1 + IFNULL(( SELECT `id_order_return` AS `id_order_return` FROM `'._DB_PREFIX_.'order_return` ORDER BY `id_order_return` DESC LIMIT 1), 0)' ); $this->updateSenderAddress(); $this->updateAddresseeAddress(); $total_shipping_fee = version_compare(_PS_VERSION_, '1.5', '>=') ? $this->order->total_shipping_tax_incl : $this->order->total_shipping; $total_shipping_fee = Tools::ps_round($total_shipping_fee, 2); $params = array( 'contractNumber' => SoNiceEtiquetageValidate::sanitize($this->module_conf['ContractNumber'], 'N6', 'contractNumber'), 'password' => SoNiceEtiquetageValidate::sanitize($this->module_conf['Password'], 'AN6..15', 'password'), 'outputFormat' => array( 'x' => 0, 'y' => 0, 'outputPrintingType' => 'PDF_A4_300dpi', 'returnType' => $this->module_conf['returnType'] ), 'letter' => array( 'service' => array( 'productCode' => (Tools::strtoupper(Country::getIsoById((int)$this->address->id_country)) == 'FR' ? 'CORE' : 'CORI'), 'depositDate' => $date_deposite->format('Y-m-d'), 'transportationAmount' => SoNiceEtiquetageValidate::sanitize($total_shipping_fee * 100, 'N', 'transportationAmount'), 'totalAmount' => SoNiceEtiquetageValidate::sanitize($total_shipping_fee * 100, 'N', 'totalAmount'), // International 'orderNumber' => SoNiceEtiquetageValidate::sanitize($this->order->id, 'N0..30', 'orderNumber'), 'commercialName' => SoNiceEtiquetageValidate::sanitize($this->module_conf['companyName'], 'AN', 'commercialName'), ), 'parcel' => array( 'insuranceValue' => null, 'weight' => SoNiceEtiquetageValidate::sanitize($order_total_weight, 'N', 'weight'), 'nonMachinable' => false, 'instructions' => null, 'pickupLocationId' => null, ), 'customsDeclarations' => $this->getCustomsDeclarations(), 'sender' => array( 'senderParcelRef' => SoNiceEtiquetageValidate::sanitize('RET'.$parcel_ref, 'AN', 'senderParcelRef'), 'address' => array( 'companyName' => SoNiceEtiquetageValidate::sanitize($this->address->company, 'AN0..35', 'sender::companyName'), 'lastName' => SoNiceEtiquetageValidate::sanitize($this->address->lastname, 'A0..35', 'sender::lastname'), 'firstName' => SoNiceEtiquetageValidate::sanitize($this->address->firstname, 'A0..35', 'sender::firstname'), 'line0' => SoNiceEtiquetageValidate::sanitize($this->address->address2, 'AN0..35', 'sender::line0'), // OCARAT utilisation de line1 pour indiquer le nom de l'expediteur si son adresse contient un nom de societe 'line1' => SoNiceEtiquetageValidate::sanitize( (!empty($this->address->company) ? '(' . $this->address->lastname . ' ' . $this->address->firstname . ')' : null ), 'AN0..35', 'sender::line1' ), 'line2' => SoNiceEtiquetageValidate::sanitize($this->address->address1, 'AN1..35', 'sender::line2'), 'line3' => null, 'countryCode' => SoNiceEtiquetageValidate::sanitize(Country::getIsoById((int)$this->address->id_country), 'A2', 'sender::countryCode'), 'city' => SoNiceEtiquetageValidate::sanitize($this->address->city, 'AN1..35', 'sender::city'), 'zipCode' => SoNiceEtiquetageValidate::sanitize($this->address->postcode, 'AN0..9', 'sender::zipCode'), 'phoneNumber' => Tools::strlen($this->address->phone) > 5 ? SoNiceEtiquetageValidate::sanitize($this->address->phone, 'TP0..15', 'sender::phoneNumber', Country::getIsoById((int)$this->address->id_country)) : null, 'mobileNumber' => $phone_mobile ? SoNiceEtiquetageValidate::sanitize($phone_mobile, 'TP0..15', 'sender::mobileNumber', Country::getIsoById((int)$this->address->id_country)) : SoNiceEtiquetageValidate::sanitize($this->address->phone_mobile, 'TP0..15', 'sender::mobileNumber', Country::getIsoById((int)$this->address->id_country)), 'doorCode1' => null, 'doorCode2' => null, 'email' => SoNiceEtiquetageValidate::sanitize($this->customer->email, 'AN0..80', 'sender::email'), 'intercom' => null ) ), 'addressee' => array( 'address' => array( 'companyName' => SoNiceEtiquetageValidate::sanitize($this->module_conf['companyName'], 'AN0..35', 'addressee::companyName'), 'lastName' => SoNiceEtiquetageValidate::sanitize($this->module_conf['Name'], 'A0..35', 'addressee::lastname'), 'firstName' => SoNiceEtiquetageValidate::sanitize($this->module_conf['Surname'], 'A0..29', 'addressee::firstname'), 'line0' => SoNiceEtiquetageValidate::sanitize($this->module_conf['Line0'], 'AN0..35', 'addressee::line0'), 'line1' => null, 'line2' => SoNiceEtiquetageValidate::sanitize($this->module_conf['Line2'], 'AN1..35', 'addressee::line2'), 'line3' => null, 'countryCode' => Country::getIsoById(Configuration::get('PS_SHOP_COUNTRY_ID')) ?: 'FR', 'city' => SoNiceEtiquetageValidate::sanitize($this->module_conf['City'], 'AN1..35', 'addressee::city'), 'zipCode' => SoNiceEtiquetageValidate::sanitize($this->module_conf['PostalCode'], 'AN0..9', 'addressee::zipCode'), 'phoneNumber' => SoNiceEtiquetageValidate::sanitize($this->module_conf['phoneNumber'], 'TP0..15', 'addressee::phoneNumber'), 'mobileNumber' => null, 'doorCode1' => null, 'doorCode2' => null, 'email' => SoNiceEtiquetageValidate::sanitize($this->module_conf['Mail'], 'AN0..80', 'addressee::email'), 'intercom' => null, 'language' => 'FR', ) ) ) ); $this->validateParameters($params); return ($params); } private function updateAddresseeAddress() { $product = (array)$this->order->getProducts(); $product = reset($product); $id_warehouse = array_key_exists('id_warehouse', $product) ? $product['id_warehouse'] : 0; if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $id_warehouse) { $warehouse = new Warehouse($id_warehouse) ; if (Validate::isLoadedObject($warehouse)) { if ($id_address = (int)$warehouse->id_address) { $address = new Address($id_address); if (Validate::isLoadedObject($address)) { $this->module_conf['companyName'] = $warehouse->name; $this->module_conf['Line2'] = $address->address1; $this->module_conf['Line0'] = $address->address2; $this->module_conf['countryCode'] = Country::getIsoById($address->id_country); $this->module_conf['city'] = $address->city; $this->module_conf['zipCode'] = $address->postcode; $this->module_conf['phoneNumber'] = $address->phone; $this->module_conf['mobileNumber'] = $address->phone_mobile; } } } } } private function updateSenderAddress() { $relay = Db::getInstance()->getRow( 'SELECT * FROM `'._DB_PREFIX_.'socolissimo_delivery_info` WHERE `id_cart` = '.(int)$this->order->id_cart.' AND `id_customer` = '.(int)$this->order->id_customer ); if ($relay && count($relay)) { $invoice_address = new Address($this->order->id_address_invoice); if (Validate::isLoadedObject($invoice_address)) { $this->address = $invoice_address; // $this->address->company = $relay['cecompanyname']; // $this->address->firstname = isset($relay['cefirstname']) && $relay['cefirstname'] ? // Tools::ucfirst($relay['cefirstname']) : Tools::ucfirst($relay['prfirstname']); // $this->address->lastname = isset($relay['cename']) && $relay['cename'] ? // Tools::ucfirst($relay['cename']) : Tools::ucfirst($this->address->lastname); // $this->address->address1 = isset($relay['praddress1']) && $relay['praddress1'] ? // Tools::ucfirst($relay['praddress1']) : Tools::ucfirst($this->address->address1); // $this->address->address2 = isset($relay['praddress2']) && $relay['praddress2'] ? // Tools::ucfirst($relay['praddress2']) : Tools::ucfirst($this->address->address2); // $this->address->postcode = isset($relay['przipcode']) && $relay['przipcode'] ? // Tools::ucfirst($relay['przipcode']) : Tools::ucfirst($this->address->postcode); // $this->address->city = isset($relay['prtown']) && $relay['prtown'] ? // Tools::ucfirst($relay['prtown']) : Tools::ucfirst($this->address->city); // // if (isset($relay['cecountry']) && Tools::strlen($relay['cecountry']) == 2) { // $id_country = Country::getByIso($relay['cecountry']); // if ($this->address->id_country !== $id_country) { // $this->address->id_country = $id_country; // $this->address->country = Country::getNameById($this->order->id_lang, $id_country); // } // } } } } private function validateParameters(&$params) { // Lastname missing // Marketplace order for instance if (!isset($params['letter']['sender']['address']['lastName']) || !$params['letter']['sender']['address']['lastName']) { if (strpos($params['letter']['sender']['address']['firstName'], 'co')) { $full_name = explode('co', $params['letter']['sender']['address']['firstName']); $full_name = explode(' ', reset($full_name)); $params['letter']['sender']['address']['firstName'] = array_shift($full_name); $params['letter']['sender']['address']['lastName'] = implode(' ', $full_name); } else { $full_name = explode(' ', $params['letter']['sender']['address']['firstName']); $params['letter']['sender']['address']['firstName'] = array_shift($full_name); $params['letter']['sender']['address']['lastName'] = implode(' ', $full_name); } } // Firstname missing if (!isset($params['letter']['sender']['address']['firstName']) || !$params['letter']['sender']['address']['firstName'] || Tools::strlen($params['letter']['sender']['address']['firstName']) < 2) { if (strpos($params['letter']['sender']['address']['lastName'], ' co ')) { $full_name = explode('co', $params['letter']['sender']['address']['lastName']); $full_name = explode(' ', reset($full_name)); $params['letter']['sender']['address']['lastName'] = array_shift($full_name); $params['letter']['sender']['address']['firstName'] = implode(' ', $full_name); } else { $full_name = explode(' ', $params['letter']['sender']['address']['lastName']); $params['letter']['sender']['address']['lastName'] = array_shift($full_name); $params['letter']['sender']['address']['firstName'] = implode(' ', $full_name); } } // If COLI and no shipping fee then set it to 1EUR if (isset($params['letter']['service']['productCode']) && in_array($params['letter']['service']['productCode'], array('CORI'))) { $params['letter']['service']['transportationAmount'] = max( 100, (int)$params['letter']['service']['transportationAmount'] ); $params['letter']['service']['totalAmount'] = max( 100, (int)$params['letter']['service']['totalAmount'] ); } } private function getCustomsDeclarations() { $customs_declarations = null; $address_country = Tools::strtoupper(Country::getIsoById((int)$this->address->id_country)); $currency = new Currency($this->order->id_currency); if (in_array($address_country, $this->need_cn23)) { return $customs_declarations; } if (!Validate::isLoadedObject($currency)) { $currency = new stdClass(); $currency->iso_code = 'EUR'; } // Invoice number missing fix // In case of external ERP, etc. if (!$this->order->invoice_number) { $this->order->invoice_number = sprintf('%06s', $this->order->id); } $articles = array(); foreach ($this->order->getProducts() as $id_product => $product) { if ($product['product_price'] == 0) { $product['product_price'] = 1; } $articles[$id_product] = array( 'description' => SoNiceEtiquetageValidate::sanitize( Tools::substr(str_replace(',', '', strip_tags($product['product_name'])), 0, 63), 'AN1..64' ), 'quantity' => (int)SoNiceEtiquetageValidate::sanitize($product['product_quantity'], 'N'), 'weight' => ($product['product_weight'] >= 0.01) ? (float)SoNiceEtiquetageValidate::sanitize($product['product_weight'], 'N') : 0.01, 'value' => (float)SoNiceEtiquetageValidate::sanitize($product['product_price'], 'N'), 'hsCode' => 123456, // TODO SoNiceEtiquetageHsCode::getProductHsCode($product['product_id']), 'originCountry' => $address_country, 'currency' => $currency->iso_code, 'artref' => $product['product_reference'], 'originalIdent' => 'A' ); if (isset($this->module_conf['weight_unit']) && $this->module_conf['weight_unit'] == 'g') { $articles[$id_product]['weight'] /= 1000; } } $articles['category'] = array( 'value' => 6 // Retour de marchandise ); $articles['original'] = array( 'originalIdent' => 'A', 'originalInvoiceNumber' => $this->order->invoice_number, 'originalInvoiceDate' => date('Y-m-d', strtotime($this->order->invoice_date)), 'originalParcelNumber' => $this->order->shipping_number ); $invoice_format = '%1$s%2$06d'; if (Configuration::get( 'PS_INVOICE_USE_YEAR', null, $this->context->shop->id_shop_group, $this->context->shop->id )) { $invoice_format = Configuration::get( 'PS_INVOICE_YEAR_POS', null, $this->context->shop->id_shop_group, $this->context->shop->id ) ? '%1$s%3$s/%2$06d' : '%1$s%2$06d/%3$s'; } $customs_declarations = array( 'includeCustomsDeclarations' => true, 'contents' => $articles, 'invoiceNumber' => sprintf( $invoice_format, Configuration::get( 'PS_INVOICE_PREFIX', null, $this->context->shop->id_shop_group, $this->context->shop->id ), $this->order->invoice_number ), 'licenceNumber' => null, 'certificatNumber' => null ); return ($customs_declarations); } public static function getParcelNumberByIdOrder($id_order) { if (!is_int($id_order)) { return (false); } return (Db::getInstance()->getValue('SELECT `parcel_number` FROM '._DB_PREFIX_.self::SCE_TABLE.' WHERE `id_order` = '.(int)$id_order)); } public static function getLabelInformationByIdOrder($id_order) { if (!is_int($id_order)) { return (false); } $data = Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.self::SCE_TABLE.' WHERE `id_order` = '.(int)$id_order); if (!is_array($data) || !count($data) || !$data) { return (false); } return ($data[0]); } public static function getIdOrderByParcelNumber($parcel_number) { if (!$parcel_number) { return (false); } return ((int)Db::getInstance()->getValue('SELECT `id_order` FROM '._DB_PREFIX_.self::SCE_TABLE.' WHERE `parcel_number` = "'.$parcel_number.'"')); } public static function deleteLabelByIdOrder($id_order) { if (!$id_order) { return (false); } return (Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'sonice_etq_label WHERE `id_order` = '.(int)$id_order)); } public static function getIdOrderCarrierByOrderId($id_order) { if (!$id_order) { return (false); } return (Db::getInstance()->getValue('SELECT `id_order_carrier` FROM `'._DB_PREFIX_.'order_carrier` WHERE `id_order` = '.(int)$id_order)); } }