'Ls ', 'EUR' => 'Eur ', ]; private $paymentMethod = [ self::PMET_CARDS => self::PMET_CARDS_E, self::PMET_SWEDB => self::PMET_SWEDB_E, self::PMET_OTHER => self::PMET_OTHER_E, self::PMET_SWEDBANKLINK => self::PMET_SWEDBANKLINK_E, self::PMET_FIRST_DATA_CARDS => self::PMET_FIRST_DATA_CARDS_E, ]; private $templates = [ '1' => 'steps/step-1.tpl', '2' => 'steps/step-2.tpl', '3' => 'steps/step-3.tpl', '4' => 'steps/step-4.tpl', '5' => 'steps/step-otherpayment.tpl', '6' => 'pay/payment-await.tpl', ]; public $loadDeliveries = [ 'd5', // Pasta stacija 'd6', // Post24 'd7', // Pasta stacija 'd8', // Post24 ]; public function __construct($uriData, $dir, $name) { $this->dir = $dir; $this->name = $name; parent:: __construct($uriData); $this->module = new pubBuyModule(); $this->oView->setTemplateDir($this->dir . "/tmpl/"); $this->oView->STEP_1_URL_KEY = pubBuyController::STEP_1_URL_KEY; $this->oView->STEP_2_URL_KEY = pubBuyController::STEP_2_URL_KEY; if (!$this->oView->cacheUsed()) { $this->oView->setJs(getCurrentFolder($this->dir) . '/js/' . $this->name . '.js'); $this->oView->setCss(getCurrentFolder($this->dir) . '/css/' . $this->name . '.css'); } $this->oView->setAsJSON(cCore::JS_MOD, ucfirst($name)); $this->cart = new cSession('cart'); } public function run(){} private function getCartCounter($cartContent = []): int { if (!is_array($cartContent) || empty($cartContent)) { return 0; } if (isset($cartContent['total']) && is_numeric($cartContent['total'])) { return (int)$cartContent['total']; } $counter = 0; if (!empty($cartContent['cat']) && is_array($cartContent['cat'])) { foreach ($cartContent['cat'] as $products) { if (empty($products) || !is_array($products)) { continue; } foreach ($products as $item) { if (!empty($item['count'])) { $counter += (int)$item['count']; } } } } return $counter; } private function renderCartItemsTable($cartContent = []): string { $cartContent = (is_array($cartContent) ? $cartContent : []); $this->oView->cart = $cartContent; $this->oView->CART = $cartContent; return $this->oView->genHelperView('pub/cart-items-table'); } private function renderCartViewItems($cartContent = []): string { $cartContent = (is_array($cartContent) ? $cartContent : []); $this->oView->cart = $cartContent; $this->oView->CART = $cartContent; return $this->oView->genHelperView('/include/cart/view_items'); } private function renderEmptyCart(): array { $this->oView->cart = []; return ['empty_html' => $this->oView->genHelperView('pub/includes/cart/empty')]; } private function renderCartDrawer($cartContent = []): string { $cartContent = (is_array($cartContent) ? $cartContent : []); $this->oView->cart = $cartContent; $this->oView->CART = $cartContent; $this->oView->cart_counter = $this->getCartCounter($cartContent); return $this->oView->genHelperView('pub/drawers'); } private function buildCartAjaxResponse($cartContent = [], array $extra = [], bool $fullRefresh = true): array { $cartContent = (is_array($cartContent) ? $cartContent : []); $counter = $this->getCartCounter($cartContent); $payload = [ 'counter' => $counter, 'total' => $counter, 'subtotal' => number_format((float)($cartContent['subtotal'] ?? 0), 2, '.', ' '), ]; if ($fullRefresh) { $payload['html'] = $this->renderCartDrawer($cartContent); } else { // Return both drawer and view cart formats for AJAX optimization $payload['cart_items_html'] = $this->renderCartItemsTable($cartContent); $payload['cart_view_items_html'] = $this->renderCartViewItems($cartContent); } return $extra ? array_merge($payload, $extra) : $payload; } /** * Function to add to cart product from actions or catalog * * @category APP pubBuy * @author Mareks Keišs * @returns array true or redirect to error */ const GUDRIEM = 10; const KURPIRKT = 11; public function addToCart() { $validAjaxPost = $this->is_post && $this->chkAjaxCode(true, false); if (!$validAjaxPost) { cJSON::sendError($this->gM("There was an error when adding product to cart!")); } $cry = new cDefuseCrypto(); $uid = getG('uid'); if (strlen($uid)) $uid = substr($uid, 0, 2); $prodKey = getP('p'); $prodId = $cry->decrypt($prodKey); if (!$prodId && is_numeric($prodKey)) { $prodId = (int)$prodKey; } $d1 = (int)getP('d1', 0); $d2 = (int)getP('d2', 0); $count = (int)getP('count'); $buyNow = (int)getP('buyNow'); $productExists = $count && $this->module->chkProdExists($prodId); if (!$productExists) { cJSON::sendError($this->gM('The product does not exist!')); } //------------------------------------------------------------ // Add product to cart session //------------------------------------------------------------ // Resolve selected product variant $itemRows = $this->module->getAddedProdData($prodId, $this->langId, $d1, $d2); if (empty($itemRows)) { cJSON::senderror($this->gM('Failed to get product data! Please select product options.')); } $variants = []; foreach ($itemRows as $row) { if (empty($row['r_id'])) { continue; } $variants[$row['r_id']] = $row; } if (empty($variants)) { cJSON::senderror($this->gM('Failed to get product data! Please select product options.')); } $variantCount = count($variants); if ($variantCount > 1) { cJSON::senderror($this->gM('Please select product options before adding to cart.')); } $itemData = reset($variants); $resolvedD1 = (int)($itemData['cl1'] ?? 0); $resolvedD2 = (int)($itemData['cl2'] ?? 0); $sTypes = "{$resolvedD1},{$resolvedD2}"; // Get product discount and calculate price $discount = $itemData['prod_discount'] == 1 ? $itemData['prod_discount_value'] : 0; $price = $itemData['price']; if ($discount > 0) $price = round($itemData['price'] * ((100 - $discount) / 100), 2); // Get all data $cartContent = $this->cart->data; $refCnt = &$cartContent['cat']; $added = false; if (!!$refCnt && isset($refCnt[$prodId][$sTypes])){ $added = true; $refCnt[$prodId][$sTypes]['count'] += $count; if (empty($refCnt[$prodId][$sTypes]['type'])) $refCnt[$prodId][$sTypes]['type'] = $uid; } if (!$added) { if ($itemData['img']) { $parts = pathinfo($itemData['img']); $itemData['img'] = "{$parts['dirname']}/list/{$parts['basename']}"; // Check if img exists if (!file_exists(__MDIR__ . $itemData['img']) || !is_file(__MDIR__ . $itemData['img'])) { $itemData['img'] = '/img/assets/cart/cart-1.jpg'; } } else { $itemData['img'] = '/img/assets/cart/cart-1.jpg'; } $refCnt[$prodId][$sTypes] = [ 'rid' => $itemData['r_id'], 't' => $itemData['t'], 'u' => $this->oUrl->rmSlashesIndex($itemData['u']), 'i' => $itemData['img'], 'count' => $count, 'p' => $price, 'c1' => ($itemData['c1'] ?: ''), 'c2' => ($itemData['c2'] ?: ''), 'cID' => $cry->encrypt("{$prodId}|%|{$sTypes}"), 'type' => $uid, // Type like gudriem/kur pirkt ]; } //pr($cartContent); unset($v, $refCnt); // Save cart content data to session $this->cart->data = $cartContent; $this->cart->enabled_step_level = 1; $this->cart->reload = true; $this->cart->reloadPayments = true; $this->cart->reloadDelivery = true; $this->oView->CART = $cartContent = $this->recalculateCartSubtotals(); $extra = []; if ($buyNow) { $extra['checkoutUrl'] = $this->gL(self::CART_URI_ID, 'a:' . self::STEP_2_CHECKOUT); } return $this->buildCartAjaxResponse($cartContent, $extra); } /** * Function to show cart * * @category APP pubBuy * @author Mareks Keišs * @param bool|int $STEP - payment step to process * @returns bool true or redirect to error */ public function cart($STEP = false){ //---------------------------------------------------------- // Generate document //---------------------------------------------------------- if(getG('a') == 'save'){ $this->throwDocument(); die(); } if(getG('a') == $this->gM(self::PAYMENT_URL_KEY) && $key = $this->module->db->prepData(getG('nr'))){ $this->compPaymentRedirect($key); die(); } //---------------------------------------------------------- // Check if any incoming payment status //---------------------------------------------------------- //$this->chkServerResponse(); //---------------------------------------------------------- // Check form submit & redirect - disabling resubmit //---------------------------------------------------------- $p = false; if(isset($_POST['data']) && count($_POST)){ $this->cart->post = cJSON::decode($_POST['data'], true); redirectToUri(); } if($this->cart->post){ $p = $this->cart->post; $this->cart->post = false; } // Setup cart base data if(!is_array($this->cart->errors)) $this->cart->errors = array(); //---------------------------------------------------------- // Force data reload on lang switch //---------------------------------------------------------- if($this->cart->language && $this->cart->language != $this->langId){ $this->cart->reloadPayments = true; // $this->reloadCartDataArrayAccordingToLanguage(); } $this->cart->language = $this->langId; //---------------------------------------------------------- // Get all cart data //---------------------------------------------------------- $this->setCartDataConfiguration($STEP, $p); $cartContent = $this->cart->data; if(!!$cartContent){ $this->oView->CURR = self::CURRENCY; // Prepare progress data for display $progress = $this->reformatProgressLine($this->getProgressLineCfg()); // Setup variables switch ($STEP){ // BASE CART DATA STEP case self::STEP_1_CART_DATA: $this->oView->prod = $this->cart->products; $this->oView->total = $this->cart->subtotal; break; // DELIVERY STEP case self::STEP_2_DELIVERY: $this->oView->INP = $this->module->db->prepData($this->cart->formInput); //$this->oView->payments = $this->cart->payments; $this->oView->setAsJSON('gM', $this->getJsTranslations()); $this->oView->setAsJSON('vCfg', $this->getCheckoutAddressValCfg()); break; // PAYMENT STEP case self::STEP_3_PAYMENT: $this->oView->T = $this->cart->t; $this->oView->IDATA = $this->cart->itemData; $this->oView->PAYMENTS = $this->cart->payments; $this->oView->DELIVERIES = $this->cart->deliveries; $this->recalculateCartSubtotals(); $this->oView->INP = $this->module->db->prepData($this->cart->formInput); break; // BILL DOWNLOAD STEP case self::STEP_4_BILL_DL: // Auto setup & display - wont reach here die(); break; } // Setup all variables to view $this->oView->cart = $cartContent; $this->oView->PROGRESS = $progress; $this->oView->tplId = $this->cart->tplId; $this->oView->templates = $this->templates; $this->oView->ERR = $this->cart->errors; if($this->cart->formErrors){ $this->oView->setAsJSON('errors', $this->cart->formErrors); $this->cart->formErrors = false; } }else{ if(getV('a') || getV('receipt')) die(redirectToUri($this->gL(self::CART_URI_ID))); // Preserver bill download for session time $this->cart->destroy(array('billDL')); $this->oView->NODATA = true; } // Category sub menu $this->oView->SUB_CAT = indexController::loadCategoryButtonMenu($this); $this->oView->shopCart = true; $this->oView->HEADER = ['t' => $this->gM("Cart")]; $this->oView->setAsJSON('gM', $this->getTranslations()); $this->oView->setAsJSON('cCfg', $this->getCheckoutAddressValCfg()); $this->oView->display('pubBuy', 'BODY'); } private function prefillCheckoutFromAccount(): void { $formInput = (is_array($this->cart->formInput) ? $this->cart->formInput : []); $sessionUser = new cSession(pubUsersController::USER_SESSION_KEY); $userId = (int)($sessionUser->id ?? 0); if (!$userId) { return; } $userModule = new pubUsersModule(); $userData = $userModule->getUserByLoginData(['id' => $userId, 'user_deleted' => 0]); if (empty($userData)) { return; } $shippingDefaults = [ 'checkout_first_name' => (string)($userData['user_name'] ?? ''), 'checkout_last_name' => (string)($userData['user_surname'] ?? ''), 'checkout_email' => (string)($userData['user_email'] ?? ''), 'checkout_phone' => (string)($userData['user_phone'] ?? ''), 'checkout_address1' => '', 'checkout_address2' => '', 'checkout_country' => '', 'checkout_city' => '', 'checkout_zip' => '', ]; $billingDefaults = []; $cfgRaw = $userModule->getUserCfg($userId); $cfg = (@unserialize((string)$cfgRaw) ?: []); $valuesAdv = (is_array($cfg['values_adv'] ?? null) ? $cfg['values_adv'] : []); $addressBook = (is_array($valuesAdv[pubUsersController::ADDRESS_BOOK_CFG_KEY] ?? null) ? $valuesAdv[pubUsersController::ADDRESS_BOOK_CFG_KEY] : []); foreach ($addressBook as $address) { if (!is_array($address)) { continue; } $mapped = [ 'checkout_first_name' => (string)($address['first_name'] ?? ''), 'checkout_last_name' => (string)($address['last_name'] ?? ''), 'checkout_email' => (string)($userData['user_email'] ?? ''), 'checkout_phone' => (string)($address['phone'] ?? ($userData['user_phone'] ?? '')), 'checkout_address1' => (string)($address['address1'] ?? ''), 'checkout_address2' => (string)($address['address2'] ?? ''), 'checkout_country' => (string)($address['country'] ?? ''), 'checkout_city' => (string)($address['city'] ?? ''), 'checkout_zip' => (string)($address['zip'] ?? ''), ]; if (empty($shippingDefaults['checkout_address1']) && !empty($address['is_default_shipping'])) { $shippingDefaults = array_merge($shippingDefaults, $mapped); } if (empty($billingDefaults) && !empty($address['is_default_billing'])) { $billingDefaults = $mapped; } } $formInput['shipping_address'] = $this->mergeCheckoutAddressData( (is_array($formInput['shipping_address'] ?? null) ? $formInput['shipping_address'] : []), $shippingDefaults, ); $formInput['customer_info']['checkout_email'] = (string)($formInput['shipping_address']['checkout_email'] ?? $shippingDefaults['checkout_email']); if (!empty($billingDefaults)) { $formInput['delivery_same_as_bill'] = 0; $formInput['delivery_info'] = $this->mergeCheckoutAddressData( (is_array($formInput['delivery_info'] ?? null) ? $formInput['delivery_info'] : []), $billingDefaults, ); } else { $formInput['delivery_same_as_bill'] = (!isset($formInput['delivery_same_as_bill']) ? 1 : $formInput['delivery_same_as_bill']); if (empty($formInput['delivery_info']) || !is_array($formInput['delivery_info'])) { $formInput['delivery_info'] = $formInput['shipping_address']; } } $this->cart->formInput = $formInput; } private function mergeCheckoutAddressData(array $current, array $defaults): array { foreach ($defaults as $key => $value) { if (!isset($current[$key]) || trim((string)$current[$key]) === '') { $current[$key] = $value; } } return $current; } public function checkout() { $cartData = $this->cart->data; if (!is_array($cartData) || empty($cartData['cat']) || !is_array($cartData['cat'])) { redirectToUri($this->gL(self::CART_URI_ID)); } if (getV('checkout_reset')) { $this->cart->formInput = false; $this->cart->formErrors = false; redirectToUri($this->gL(false, 'a:' . self::STEP_2_CHECKOUT)); } $hasShippingInput = (is_array($this->cart->formInput) && !empty($this->cart->formInput['shipping_address'])); if (!$this->is_post || !$hasShippingInput) { $this->prefillCheckoutFromAccount(); } // Load available shipping/payment options through existing core flow. if (empty($this->cart->enabled_step_level) || (int)$this->cart->enabled_step_level < 3) { $this->cart->enabled_step_level = 3; } $this->setCartDataConfiguration(self::STEP_3_PAYMENT, false, true); if ($this->is_post && getV('checkout_action')) { if (!$this->chkAjaxCode(true, false)) { return; } $action = (string)getV('checkout_action'); if ($action === 'section-save') { $result = $this->saveCheckoutSection($_POST); if (!empty($result['errors'])) { cJSON::sendError($result['errors']); } cJSON::sendOk($result); } if ($action === 'section-reset') { $result = $this->resetCheckoutSection($_POST); if (!empty($result['errors'])) { cJSON::sendError($result['errors']); } cJSON::sendOk($result); } if ($action === 'place-order') { $submitResult = $this->processCheckoutFormSubmit($_POST); $url = $this->gL(false, 'a:' . self::STEP_3_ORDER_COMPLETE . '/nr:' . $submitResult['order_nr']); if (!empty($submitResult['errors'])) { cJSON::sendError($submitResult['errors']); } if (!empty($submitResult['order_nr'])) { cJSON::sendOk([ 'order_id' => $submitResult['order_id'], 'order_nr' => $submitResult['order_nr'], 'order_key' => $submitResult['order_key'], 'order_complete_url' => $url, ]); } cJSON::sendError(['checkout' => $this->gM('Unable to place order. Please try again.')]); } } $formErrors = []; if ($this->is_post && !empty($_POST)) { $submitResult = $this->processCheckoutFormSubmit($_POST); $url = $this->gL(false, 'a:' . self::STEP_3_ORDER_COMPLETE . '/nr:' . $submitResult['order_nr']); if (!empty($submitResult['errors'])) { $formErrors = $submitResult['errors']; } elseif (!empty($submitResult['order_nr'])) { redirectToUri($url); } } $cartData = $this->cart->data; $this->oView->CURR = self::CURRENCY; $this->oView->cart = $cartData; $this->oView->T = $this->cart->t; $this->oView->PAYMENTS = $this->cart->payments; $this->oView->DELIVERIES = $this->cart->deliveries; $this->oView->INP = $this->module->db->prepData($this->cart->formInput); $this->oView->FORM_ERRORS = $formErrors; $this->oView->SUB_CAT = indexController::loadCategoryButtonMenu($this); $this->oView->shopCart = true; $this->oView->setAsJSON('gM', $this->getTranslations()); $this->oView->setAsJSON('cCfg', $this->getCheckoutAddressValCfg()); if (!empty($formErrors)) { $this->oView->setAsJSON('errors', $formErrors); } $this->oView->HEADER = ['t' => $this->gM("Checkout")]; $this->oView->display('checkout', 'BODY'); } private function processCheckoutFormSubmit(array $post): array { $shipping = (isset($post['shipping_address']) && is_array($post['shipping_address']) ? $post['shipping_address'] : []); $delivery = (isset($post['delivery_info']) && is_array($post['delivery_info']) ? $post['delivery_info'] : []); $step2Post = [ 'shipping_address' => $shipping, 'delivery_info' => $delivery, ]; if (!empty($step2Post['delivery_info']['billing_address']) && $this->isSameAsBillingAddress($step2Post['delivery_info']['billing_address'])) { $step2Post['delivery_info'] = $step2Post['shipping_address']; $step2Post['delivery_same_as_bill'] = true; } else { $ddData = $step2Post['delivery_info']; $step2Post['delivery_info'] = []; foreach ($ddData as $k => $v) { $step2Post['delivery_info'][str_replace('checkout_bill_', 'checkout_', $k)] = $v; } } $step2Post['customer_info'] = [ 'checkout_email' => (string)($step2Post['shipping_address']['checkout_email'] ?? ''), ]; $inp = (is_array($this->cart->formInput) ? $this->cart->formInput : []); $this->cart->formInput = $step2Post + $inp; $valid = new cValidator($this); $errors = $valid->checkArrayAdvance($step2Post, $this->getCheckoutAddressValCfg()); if (!empty($errors)) { $this->cart->formErrors = $errors; return ['errors' => $this->flattenValidationErrors($errors)]; } if (empty($this->cart->enabled_step_level) || (int)$this->cart->enabled_step_level < 3) { $this->cart->enabled_step_level = 3; } $step3Post = [ 'sh_and_py' => (isset($post['sh_and_py']) && is_array($post['sh_and_py']) ? $post['sh_and_py'] : []), 'confirmation' => (isset($post['confirmation']) && is_array($post['confirmation']) ? $post['confirmation'] : []), 'customer_info' => [ 'checkout_email' => (string)($step2Post['shipping_address']['checkout_email'] ?? ''), ], ]; $cartInput = $step3Post + (is_array($this->cart->formInput) ? $this->cart->formInput : []); if (array_key_exists('check-note', $post)) { $cartInput['check-note'] = (string)$post['check-note']; } if (empty($step3Post['sh_and_py']['shipping_method']) || empty($step3Post['sh_and_py']['payment_method'])) { return ['errors' => ['sh_and_py' => $this->gM('Please select shipping and payment method!')]]; } if (empty($step3Post['confirmation']['agree_to_terms'])) { return ['errors' => ['confirmation' => ['agree_to_terms' => $this->gM('Please agree to terms!')]]]; } foreach ($step3Post['sh_and_py'] as &$v) { $v = (int)substr((string)$v, 1); } unset($v); $cartInput['sh_and_py'] = $step3Post['sh_and_py']; $this->cart->formInput = $cartInput; if (!in_array($step3Post['sh_and_py']['payment_method'], $this->cart->payments) || !in_array($step3Post['sh_and_py']['shipping_method'], $this->cart->deliveries)) { return ['errors' => ['checkout' => $this->gM('Unable to place order with selected shipping/payment options.')]]; } $bDataIsValid = true; if ($step3Post['sh_and_py']['shipping_method'] == self::DELIVERY_OMNIVA && !empty($step3Post['sh_and_py']['a_omniva'])) { if (!$omniva_data = $this->oApc->check('OMNIVA_DATA')) { $omniva_data = $this->module->getClassificatorDataById(self::DELIVERY_OMNIVA_GR); $this->oApc->store('OMNIVA_DATA', $omniva_data); } if (!isset($omniva_data[$step3Post['sh_and_py']['a_omniva']])) { $bDataIsValid = false; } } if (!$bDataIsValid) { return ['errors' => ['checkout' => $this->gM('Unable to place order with selected shipping/payment options.')]]; } $cry = new cDefuseCrypto(); $cNum = new cNumbers(); $recNr = $this->module->getNextDeletedOrderNr(); $reservedOrderNr = true; if (!strlen($recNr)) { $recNr = $cNum->getProductBillNumber(); $reservedOrderNr = false; } $orderId = $this->module->insertDataIntoDbTable(pubBuyModule::TABLE_ORDERS, [[ 'o_nr' => $recNr, 'o_date' => time(), 'o_user' => $this->resolveCheckoutUserId((string)($step3Post['customer_info']['checkout_email'] ?? '')), 'o_mail' => (string)($step3Post['customer_info']['checkout_email'] ?? ''), 'o_payment_met' => $step3Post['sh_and_py']['payment_method'], 'o_delivery_met' => $step3Post['sh_and_py']['shipping_method'], 'o_input_data' => cJSON::encode($this->cart->formInput), 'o_modified' => time(), 'o_deleted' => 0, ]]); $orderId = $this->normalizeInsertedId($orderId); if (!$orderId) { if ($reservedOrderNr && strlen($recNr)) { $this->module->deleteReservedOrderNr($recNr); } return ['errors' => ['checkout' => $this->gM('Unable to place order. Please try again.')]]; } if ($reservedOrderNr && strlen($recNr)) { $this->module->deleteReservedOrderNr($recNr); } $this->persistCheckoutOrderDetails($orderId, $this->cart->formInput, $this->cart->data); $this->cart->orderId = $orderId; $this->clearCartAfterOrderSubmit(); return [ 'order_id' => $orderId, 'order_nr' => $recNr, 'order_key' => $cry->encrypt((string)$orderId), ]; } private function normalizeInsertedId($value): int { if (is_array($value)) { $value = reset($value); } return (int)$value; } private function resolveCheckoutUserId(string $email = ''): int { $oPubUser = new cSession(pubUsersController::USER_SESSION_KEY); if (!empty($oPubUser->id)) { return (int)$oPubUser->id; } $email = trim($email); if (!strlen($email)) { return 0; } $user = (new pubUsersModule())->getUserByLoginData(['user_email' => $email, 'user_deleted' => 0]); if (!empty($user['id']) && empty($user['user_blocked'])) { return (int)$user['id']; } return 0; } private function flattenValidationErrors(array $errors): array { $flat = []; foreach ($errors as $key => $value) { if (is_array($value)) { $flat += $this->flattenValidationErrors($value); continue; } $flat[$key] = $value; } return $flat; } private function persistCheckoutOrderDetails($orderId, array $formInput, array $cartContent): void { if (!$orderId || empty($formInput) || empty($cartContent['cat']) || !is_array($cartContent['cat'])) { return; } $shipping = (is_array($formInput['shipping_address'] ?? null) ? $formInput['shipping_address'] : []); $delivery = (is_array($formInput['delivery_info'] ?? null) ? $formInput['delivery_info'] : []); $addressData = []; foreach ([$shipping, $delivery] as $i => $address) { if (empty($address) || !is_array($address)) { continue; } $addressData[] = [ 'o_id' => $orderId, 'o_type' => $i, 'o_addr_name' => (string)($address['checkout_first_name'] ?? ''), 'o_addr_lastname' => (string)($address['checkout_last_name'] ?? ''), 'o_addr_address' => trim((string)($address['checkout_address1'] ?? '') . ' ' . (string)($address['checkout_address2'] ?? '')), 'o_addr_city' => (string)($address['checkout_city'] ?? ''), 'o_addr_country' => (string)($address['checkout_country'] ?? ''), 'o_addr_zip' => (string)($address['checkout_zip'] ?? ''), 'o_addr_phone' => (string)($address['checkout_phone'] ?? ''), ]; } if (!empty($addressData)) { $this->module->insertDataIntoDbTable(pubBuyModule::TABLE_ORDERS_ADDRESSES, $addressData); } $orderItems = []; $lastType = 0; foreach ($cartContent['cat'] as $prodId => $pTypes) { if (empty($pTypes) || !is_array($pTypes)) { continue; } foreach ($pTypes as $typeKey => $type) { if (empty($type) || !is_array($type)) { continue; } $typeParts = explode(',', (string)$typeKey); $orderItems[] = [ 'o_id' => $orderId, 'p_id' => $prodId, 'p_row_id' => $type['rid'] ?? 0, 'p_price' => $type['p'] ?? 0, 'p_count' => $type['count'] ?? 0, 'p_type1' => (int)($typeParts[0] ?? 0), 'p_type2' => (int)($typeParts[1] ?? 0), ]; if (!empty($type['type'])) { $lastType = (int)$type['type']; } } } if (!empty($orderItems)) { $this->module->insertDataIntoDbTable(pubBuyModule::TABLE_ORDERS_DATA, $orderItems); } if ($lastType) { $this->module->updateOrdersData($orderId, ['o_type' => $lastType]); } } private function saveCheckoutSection(array $post): array { $section = (string)getV('checkout_section'); $formInput = (is_array($this->cart->formInput) ? $this->cart->formInput : []); if ($section === 'address') { $shipping = (isset($post['shipping_address']) && is_array($post['shipping_address']) ? $post['shipping_address'] : []); $delivery = (isset($post['delivery_info']) && is_array($post['delivery_info']) ? $post['delivery_info'] : []); $step2Post = [ 'shipping_address' => $shipping, 'delivery_info' => $delivery, ]; if (!empty($step2Post['delivery_info']['billing_address']) && $this->isSameAsBillingAddress($step2Post['delivery_info']['billing_address'])) { $step2Post['delivery_info'] = $step2Post['shipping_address']; $step2Post['delivery_same_as_bill'] = true; } else { $ddData = $step2Post['delivery_info']; $step2Post['delivery_info'] = []; foreach ($ddData as $k => $v) { $step2Post['delivery_info'][str_replace('checkout_bill_', 'checkout_', $k)] = $v; } } $valid = new cValidator($this); $errors = $valid->checkArrayAdvance($step2Post, $this->getCheckoutAddressValCfg()); if (!empty($errors)) { return ['errors' => $this->flattenValidationErrors($errors)]; } $formInput['shipping_address'] = $step2Post['shipping_address']; $formInput['delivery_info'] = $step2Post['delivery_info']; $formInput['delivery_same_as_bill'] = !empty($step2Post['delivery_same_as_bill']); $formInput['customer_info'] = [ 'checkout_email' => (string)($step2Post['shipping_address']['checkout_email'] ?? ''), ]; $this->cart->enabled_step_level = max((int)$this->cart->enabled_step_level, 2); $this->cart->formInput = $formInput; return ['section' => $section, 'saved' => true]; } if ($section === 'shipping') { $shippingMethod = (string)($post['sh_and_py']['shipping_method'] ?? ''); if (!$shippingMethod) { return ['errors' => ['shipping_method' => $this->gM('Please select shipping method!')]]; } if (!in_array((int)substr($shippingMethod, 1), $this->cart->deliveries)) { return ['errors' => ['shipping_method' => $this->gM('Invalid shipping method selected!')]]; } $formInput['sh_and_py']['shipping_method'] = $shippingMethod; $this->cart->enabled_step_level = max((int)$this->cart->enabled_step_level, 3); $this->cart->formInput = $formInput; return ['section' => $section, 'saved' => true]; } if ($section === 'payment') { $paymentMethod = (string)($post['sh_and_py']['payment_method'] ?? ''); if (!$paymentMethod) { return ['errors' => ['payment_method' => $this->gM('Please select payment method!')]]; } if (!in_array((int)substr($paymentMethod, 1), $this->cart->payments)) { return ['errors' => ['payment_method' => $this->gM('Invalid payment method selected!')]]; } $formInput['sh_and_py']['payment_method'] = $paymentMethod; $this->cart->enabled_step_level = max((int)$this->cart->enabled_step_level, 3); $this->cart->formInput = $formInput; return ['section' => $section, 'saved' => true]; } if ($section === 'notes') { $formInput['check-note'] = (string)($post['check-note'] ?? ''); $this->cart->formInput = $formInput; return ['section' => $section, 'saved' => true]; } return ['errors' => ['checkout' => $this->gM('Unknown checkout section!')]]; } private function resetCheckoutSection(array $post): array { $section = (string)getV('checkout_section'); $formInput = (is_array($this->cart->formInput) ? $this->cart->formInput : []); if ($section === 'address') { unset($formInput['shipping_address'], $formInput['delivery_info'], $formInput['delivery_same_as_bill'], $formInput['customer_info']); $this->cart->enabled_step_level = max((int)$this->cart->enabled_step_level, 1); $this->cart->formInput = $formInput; $this->prefillCheckoutFromAccount(); return [ 'section' => $section, 'reset' => true, 'prefill' => (is_array($this->cart->formInput) ? $this->cart->formInput : []), ]; } if ($section === 'shipping') { unset($formInput['sh_and_py']['shipping_method']); if (empty($formInput['sh_and_py'])) { unset($formInput['sh_and_py']); } $this->cart->formInput = $formInput; return ['section' => $section, 'reset' => true]; } if ($section === 'payment') { unset($formInput['sh_and_py']['payment_method']); if (empty($formInput['sh_and_py'])) { unset($formInput['sh_and_py']); } $this->cart->formInput = $formInput; return ['section' => $section, 'reset' => true]; } if ($section === 'notes') { unset($formInput['check-note']); $this->cart->formInput = $formInput; return ['section' => $section, 'reset' => true]; } return ['errors' => ['checkout' => $this->gM('Unknown checkout section!')]]; } private function clearCartAfterOrderSubmit(): void { $this->cart->data = false; $this->cart->products = false; $this->cart->countDivision = false; $this->cart->countries = false; $this->cart->payments = false; $this->cart->formInput = false; $this->cart->itemData = false; $this->cart->subtotal = false; $this->cart->enabled_step_level = 1; $this->cart->formErrors = false; unset($_SESSION['order_key']); } private function isSameAsBillingAddress($value): bool { return in_array((string)$value, ['same_as_bill', '1', 'true', 'on'], true); } public function orderComplete() { $this->oView->ORDER_NR = prepForDisplayHtml((string)getG('nr')); $this->oView->ORDER_DATE = date($this->timeDateFormat); $this->oView->HEADER = ['t' => $this->gM("Order Complete")]; $this->oView->display('order_complete', 'BODY'); } /** * Function to get js translations for view * * @category APP pubBuy * @author Mareks Keišs * @return array of data */ public function getTranslations() { return [ 'chkComp' => $this->gM('Please fill in the field!'), 'chkEmail' => $this->gM('Not a valid email address specified!'), 'chkDigit' => $this->gM('Only digits allowed!'), 'chkNum' => $this->gM('Not a valid number specified!'), //'chkIp' => $this->gM('Not a valid ip address specified!'), //'chkDate' => $this->gM('Invalid date specified!'), 'chkPhone' => $this->gM('Invalid telephone specified!'), //'chkUrlSegm' => $this->gM('Invalid url segment specified!'), //'chkAbsUrl' => $this->gM('Invalid url specified!'), //'chkIsSize' => $this->gM('Invalid size specified!'), //'chkEqual' => $this->gM('Fields do not match!'), //'chkMinLen' => $this->gM('Min value lenght is %s!'), ]; } /** * Function to check & analyse server payment response * * @category APP pubBuy * @author Mareks Keišs * @returns bool true or redir to error */ public function chkServerResponse(){ $recNr = false; $sendMail = false; $redirect = false; $cry = new cDefuseCrypto(); //---------------------------------------------------------- // CPS payment system //---------------------------------------------------------- if(getP('responseXml') || getV('demus')){ // TODO: kas šī par klasi? $cps = new cps(); $data = $cps->getResponse(); if($cps->validateSignature($data)){ // Continue normal case $receipt = array( 'rec_status' => 0, 'rec_reference_id' => $data['base']['referenceId'], 'rec_result_code' => $data['result']['resultCode'], 'rec_result_message' => $data['result']['resultMessage'], 'rec_result_data' => '', 'rec_result_time' => time(), ); $recNr = $data['base']['orderId']; // Validate payment - ok? // TODO: kas šī par klasi? if($data['result']['resultMessage'] == cps::STATUS_CAPTURED){ $sendMail = true; $receipt['rec_status'] = 1; $receipt['rec_value'] = $data['base']['value']; $receipt['rec_currency'] = $data['base']['currency']; // Update order reservation $this->module->updOrderReservationById($recNr); } $this->module->updReceiptByReceiptNr($recNr, $receipt); $redirect = true; } } //---------------------------------------------------------- // FirstData payment system //---------------------------------------------------------- if($trId = getP('trans_id')){ // TODO: kas šī par klasi? $fd = new firstData(); $data = $fd->updateTransactionStatus(false, $trId); if($data['receipt_id']){ // Continue normal case $receipt = array( 'rec_status' => 0, 'rec_reference_id' => $data['ref_id'], 'rec_result_code' => $data['result_code'], 'rec_result_message' => (isset($fd->statuses[$data['result']])?$fd->statuses[$data['result']]:''), 'rec_result_data' => $data['response'], 'rec_result_time' => time(), ); $recNr = $data['receipt_id']; // Validate payment - ok? if($data['result'] == firstData::STATUS_OK){ $sendMail = true; $receipt['rec_status'] = 1; // Update order reservation $this->module->updOrderReservationById($recNr); } $this->module->updReceiptByReceiptNr($recNr, $receipt); $redirect = true; // Imitate get receipt id $_GET['receipt'] = $cry->encrypt($recNr); // Imitate language selection $lang = new sysLanguagesModule(); if($langId = $lang->getLangIdByCode($data['language'])) $this->uri_data['p_lang_id'] = $this->langId = $langId; } } //---------------------------------------------------------- // SWEDBANK banklink payment system //---------------------------------------------------------- if(getV('VK_SERVICE')){ $swed = new swedbank(); $data = $swed->getResponse(); if($swed->validateSignature($data)){ $recNr = $data['VK_REF']; // Payment successful if($data['VK_SERVICE'] == swedbank::SERVICE_OK) { $rec = $this->module->getReceiptByNr($recNr); if(!$rec['rec_status']){ $sendMail = true; // Continue normal case $receipt = array( 'rec_status' => 1, 'rec_currency' => $data['VK_CURR'], 'rec_value' => floatval($data['VK_AMOUNT'])*100, 'rec_reference_id' => $data['VK_REF'], 'rec_result_code' => $data['VK_SERVICE'], 'rec_result_message' => swedbank::STATUS_CAPTURED, 'rec_result_data' => $swed->implodeToStr($data), 'rec_result_time' => time(), ); // Update order reservation $this->module->updReceiptByReceiptNr($recNr, $receipt); $this->module->updOrderReservationById($recNr); } if($data['VK_AUTO'] == swedbank::VK_AUTO){ $redirect = false; }else{ $redirect = true; } // Payment unsuccessful }else{ if ($data['VK_AUTO'] != swedbank::VK_AUTO) { $receipt = array( 'rec_status' => 0, 'rec_result_message' => swedbank::STATUS_ERROR, 'rec_result_data' => $swed->implodeToStr($data), 'rec_result_time' => time(), ); $this->module->updReceiptByReceiptNr($recNr, $receipt); $redirect = true; } } } } //---------------------------------------------------------- // DEMO USER AUTO PAYMENT ACCEPT //---------------------------------------------------------- if(0 && in_array($this->oUser->suser->id, $this->demoUsers)){ $id = $cry->decrypt(getG('receipt')); if($rec = $this->module->getReceiptByNr($id)){ $recNr = $rec['rec_nr']; // Continue normal case $receipt = array( 'rec_status' => 1, 'rec_currency' => 'LVL', 'rec_value' => $rec['rec_value'], 'rec_reference_id' => '111111', 'rec_result_code' => '000', 'rec_result_message' => pubBuyController::STATUS_CAPTURED, 'rec_result_data' => '', 'rec_result_time' => time(), ); // Update order reservation $this->module->updOrderReservationById($recNr); $this->module->updReceiptByReceiptNr($recNr, $receipt); $sendMail = true; $redirect = true; } } //---------------------------------------------------------- // Send mail & redirect to cart receipt print //---------------------------------------------------------- if($sendMail){ $mm = new cMail(); if(!!($qData = $this->module->getOrderDataForReceiptMail($recNr))){ if(!$mm->isMailSent($qData['email'], $recNr)){ $PDFFile = 'URL:' . $cry->encrypt($recNr); $mm->addMail( $qData['email'], false, cMail::MAIL_SERVER_LORETA_LV, 0, //cMail::MAIL_7_AUCTION_PROD, $this->langId, [ 'Prod-name' => '', 'Prod-pickup-days' => self::PICKUP_DAYS, ], $PDFFile, false, 1, $recNr, ); } } } if($redirect){ die(redirectToUri($this->getFullLinkForID(self::CART_URI_ID, 'a:invoice-print/receipt:' . getG('receipt')))); } return false; } /** * Function to set product data for cart * * @category APP pubBuy * @author Mareks Keišs * @param string $STEP - step to setup * @param bool $post - submitted data form * @param bool $loadOnly - load only data without setting up steps * @return bool true or redirect to error */ public function setCartDataConfiguration($STEP, $post = false, $loadOnly = false){ switch ($STEP){ //********************************************************** // BASE CART DATA //********************************************************** case self::STEP_1_CART_DATA: // If reload cart data if($this->cart->reload || !$this->cart->products){ $this->cart->reload = false; // Load delivery data //$this->setCartDataConfiguration(self::STEP_2_DELIVERY, false, true); } // If data submitted - analyse & redirect if($post && count($post)){ if($this->cart->enabled_step_level < 2) $this->cart->enabled_step_level = 2; die(redirectToUri($this->gL(self::CART_URI_ID, 'a' . $this->gL(self::STEP_2_URL_KEY)))); } //---------------------------------------------------------- // Recalculate all data - for cart //---------------------------------------------------------- $this->recalculateCartSubtotals(); // Reset each time if(!$loadOnly){ $this->cart->STEP_ID = 'product'; if(!$this->cart->enabled_step_level) $this->cart->enabled_step_level = 1; $this->cart->tplId = '1'; } break; //********************************************************** // CART DELIVERY DATA //********************************************************** case self::STEP_2_DELIVERY: // If data submitted - analyse & redirect if($post && count($post)){ // Get all input data $inp = $this->cart->formInput; // Rewrite billing to delivery if(!empty($post['delivery_info']['billing_address']) && $this->isSameAsBillingAddress($post['delivery_info']['billing_address'])){ if(!!$post['shipping_address'] && count($post['shipping_address'])){ $post['delivery_info'] = $post['shipping_address']; $post['delivery_same_as_bill'] = true; } // Reset delivery keys }else{ $ddData = $post['delivery_info']; $post['delivery_info'] = array(); foreach($ddData as $k=>$v) $post['delivery_info'][str_replace('checkout_bill_', 'checkout_', $k)] = $v; unset($inp['delivery_same_as_bill']); } // Update user input data $this->cart->formInput = $post + (!!$inp && is_array($inp) ? $inp : array()); // Validate submitted form $valid = new cValidator($this); $errors = $valid->checkArrayAdvance($post, $this->getCheckoutAddressValCfg()); // TODO BRS Aivars: tur bija fn kas vairs neeksistē, nezinu vai šī ir pareiza!! /*if(empty($post['payment_method']) || !empty($post['payment_method']) && !isset($this->cart->payments[$post['payment_method']])){ $errors['payment_method'] = $this->gM('No payment method selected!'); } if(empty($post['i_country']) || !empty($post['i_country']) &&!isset($this->cart->countries[$post['i_country']])) $errors['i_country'] = $this->gM('Please choose country!'); if(empty($post['d_country']) || !empty($post['d_country']) &&!isset($this->cart->countries[$post['d_country']])) $errors['d_country'] = $this->gM('Please choose country!'); */ if(!!$errors){ $this->cart->formErrors = $errors; }else{ // Check level if(!$this->cart->enabled_step_level || $this->cart->enabled_step_level < 2) die(redirectToUri($this->gL(self::CART_URI_ID, 'a:' . $this->gM(self::STEP_2_URL_KEY)))); $this->cart->enabled_step_level = 3; die(redirectToUri($this->gL(self::CART_URI_ID, 'a:' . $this->gM(self::STEP_3_URL_KEY)))); } } //---------------------------------------------------------- // Enable level 2 immediately //---------------------------------------------------------- if($this->cart->enabled_step_level < 2) $this->cart->enabled_step_level = 2; // Check level if(!$loadOnly) if(!$this->cart->enabled_step_level || $this->cart->enabled_step_level < 2) die(redirectToUri($this->gL(self::CART_URI_ID))); // If reload cart data if($this->cart->reloadDelivery || !$this->cart->delivery){ $this->cart->reloadDelivery = false; if($ids = $this->cart->ids){ $this->cart->delivery = false; //$this->cart->countries = $this->module->getCountryData(); } } // Default user input data $this->chkInpFormDataIsFilled(); // Reset each time if(!$loadOnly){ $this->recalculateCartSubtotals(); $this->cart->STEP_ID = 'delivery'; if($this->cart->enabled_step_level < 2) $this->cart->enabled_step_level = 2; $this->cart->tplId = '2'; } break; //********************************************************** // CART PAYMENT DATA //********************************************************** case self::STEP_3_PAYMENT: // Check level if(!$this->cart->enabled_step_level || $this->cart->enabled_step_level < 3) die(redirectToUri($this->gL(self::CART_URI_ID, 'a:' . $this->gM(self::STEP_2_URL_KEY)))); // Do the final data check here if($post && count($post)){ // Chk terms & setup redirect to payment window // Send back with error if not found if(!empty($post['sh_and_py']['shipping_method']) && !empty($post['sh_and_py']['payment_method']) && isset($post['confirmation']['agree_to_terms']) && $post['confirmation']['agree_to_terms']){ foreach($post['sh_and_py'] as &$v) $v = intval(substr($v, 1)); unset($v); // Check if existing keys if(in_array($post['sh_and_py']['payment_method'], $this->cart->payments) && in_array($post['sh_and_py']['shipping_method'], $this->cart->deliveries)){ $bDataIsValid = true; // Omniva selection check if($post['sh_and_py']['shipping_method'] == self::DELIVERY_OMNIVA && !empty($post['sh_and_py']['a_omniva'])){ // Load additional data if(!$omniva_data = $this->oApc->check("OMNIVA_DATA")){ $omniva_data = $this->module->getClassificatorDataById(self::DELIVERY_OMNIVA_GR); // Omniva type $this->oApc->store('OMNIVA_DATA', $omniva_data); } if(!isset($omniva_data[$post['sh_and_py']['a_omniva']])) $bDataIsValid = false; } // Additional checks // If all checks passed - send an e-mail if($bDataIsValid){ $cry = new cDefuseCrypto(); // Update user input data $inp = $this->cart->formInput; $this->cart->formInput = $post + (!!$inp && is_array($inp) ? $inp : array()); // If checked for subscription add to db record if(!empty($post['confirmation']['subscribe']) && !empty($inp['customer_info']['checkout_email'])){ $cIndex = new indexController(false, false, false, false); $cIndex->addUserToSubscriptionList(array('sub_email' => $inp['customer_info']['checkout_email'])); } $cNum = new cNumbers(); $nNr = $cry->encrypt($_SESSION['order_key'] = $cNum->getRandomChString(20)); // Get bill nr without procedure //$nNr = $cry->encrypt($this->module->getProductBillNumber()); // Redirect & insert data into db & send e-mails to both parties die(redirectToUri($this->gL(self::CART_URI_ID, "a:" . $this->gM(self::PAYMENT_URL_KEY) . "/nr:{$nNr}"))); } } } } // If reload cart data if($this->cart->reloadPayments || !$this->cart->payments){ $this->cart->reloadPayments = false; // Payments / deliveries classifier group types from CMS $tpToCheck = array( cmsClassificatorsModule::CT_TYPE_PAYMENTS, cmsClassificatorsModule::CT_TYPE_DELIVERY, ); $clData = array('t'=> array()); $cartContent = $this->cart->data; // Get cart payment options $prodClData = $this->module->getCartPaymentAndDeliveryOptions((!empty($cartContent['cat']) ? array_keys($cartContent['cat']) : array())); // Loop each product and get all overlapping cl ids if(!!$prodClData){ foreach($prodClData as $types){ if(!!$types){ foreach($tpToCheck as $tk){ // CMS payment / delivery method groups if(!empty($types[$tk])){ if(!!$types[$tk] && !!$tk){ $clData['t'] += $types[$tk]; if(!isset($clData[$tk])){ $clData[$tk] = array_keys($types[$tk]); continue; } // Overlapping cl ids $clData[$tk] = array_intersect($clData[$tk], array_keys($types[$tk])); } }else{ $clData[$tk] = array(); } } } } } // Set default checked values - if not selected already $inp = $this->cart->formInput; if(empty($inp['sh_and_py']['shipping_method'])) $inp['sh_and_py']['shipping_method'] = self::SHIPPING_INTERNATIONAL_SHIP; if(empty($inp['sh_and_py']['payment_method'])) $inp['sh_and_py']['payment_method'] = self::PAYMENT_BANK_TRANSFER; // Overwrite data $this->cart->formInput = $inp; $this->cart->t = $clData['t']; $this->cart->payments = (isset($clData[cmsClassificatorsModule::CT_TYPE_PAYMENTS]) ? $clData[cmsClassificatorsModule::CT_TYPE_PAYMENTS] : array()); $this->cart->deliveries = (isset($clData[cmsClassificatorsModule::CT_TYPE_DELIVERY]) ? $clData[cmsClassificatorsModule::CT_TYPE_DELIVERY] : array()); $itemToData = array( self::DELIVERY_OMNIVA => array( 'k' => self::DELIVERY_OMNIVA_GR, 'd' => 'sub_data/omniva.tpl' ), ); // Load additional data if(!$omniva_data = $this->oApc->check("OMNIVA_DATA")){ $omniva_data = $this->module->getClassificatorDataById(self::DELIVERY_OMNIVA_GR); // Omniva type $this->oApc->store('OMNIVA_DATA', $omniva_data); } $this->oView->INP = $inp; $this->oView->omniva = $omniva_data; if(!!$itemToData){ foreach($itemToData as &$v){ $v['d'] = $this->oView->genTemplate($v['d']); } unset($v); } $this->cart->itemData = $itemToData; unset($prodClData, $prodClData, $tpToCheck, $clData, $omniva_data); } // Reset each time if(!$loadOnly){ $this->recalculateCartSubtotals(); $this->cart->STEP_ID = 'payment'; $this->cart->enabled_step_level = 3; $this->cart->tplId = '3'; } break; //********************************************************** // CART BILL DATA //********************************************************** case self::STEP_4_BILL_DL: if(getG('a') != $this->gM(self::ORDER_RECEIVED_URL_KEY) && !getG('nr')) redirectToUri($this->gL()); $this->cart->tplId = 5; // Set template id - for other-payment-met $this->cart->orderId = false; // Rewrite id $this->cart->STEP_ID = 'receipt'; // Set cart line selected item $this->oView->tplId = $this->cart->tplId; $this->oView->templates = $this->templates; // Category sub menu $this->oView->SUB_CAT = indexController::loadCategoryButtonMenu($this); $this->oView->PROGRESS = $this->reformatProgressLine($this->getProgressLineCfg(), 'receipt', 4, true);; //$this->oView->PRE_BODY = $this->oView->genHelperView('pub/preBodyContent'); die($this->oView->display('pubBuy', 'BODY')); /*$tplId = ''; if(!($receiptNr = getG('receipt'))) redirectToUri($this->gL(self::CART_URI_ID)); $paymentStatus = $this->checkProdPaid(); // Reset basic cart data if(!isset($this->cart->billDL[$receiptNr])){ //if($paymentStatus) //$this->setupViewTrackingArrays($receiptNr, $paymentStatus); $this->cart->data = false; $this->cart->formInput = false; } switch($paymentStatus){ case self::PMET_OTHER_E: $tplId = '5'; $this->oView->DOC_SAVE_URL = $this->gL(self::CART_URI_ID, "a:save/receipt:{$receiptNr}"); break; case self::PMET_SWEDB_E: case self::PMET_SWEDBANKLINK_E: case self::PMET_CARDS_E: case self::PMET_FIRST_DATA_CARDS_E: $tplId = '4'; $this->oView->DOC_SAVE_URL = $this->gL(self::CART_URI_ID, "a:save/receipt:{$receiptNr}"); break; default: $this->oView->REC_ID = $receiptNr; die($this->oView->display($this->templates['6'], 'BODY')); break; } // Reset each time if(!$loadOnly){ $progress = array(); // Preserve & load progress for bill download if(isset($this->cart->billDL[$receiptNr])){ $progress = $this->cart->billDL[$receiptNr]; }elseif(!!($progress = $this->reformatProgressLine($this->getProgressLineCfg(), 'receipt', 4, true))){ if(!!!$this->cart->billDL) $this->cart->billDL = array(); if(!isset($this->cart->billDL[$receiptNr])) $this->cart->billDL[$receiptNr] = $progress; }else{ redirectToUri($this->gL(self::CART_URI_ID)); } // Show this view separately - not to interfere with new ongoing payment $this->oView->cart = false; $this->oView->tplId = $tplId; $this->oView->templates = $this->templates; $this->oView->PROGRESS = $progress; die($this->oView->display('pubBuy', 'BODY')); }*/ break; } } /** * Function to get first drop-down match * * @category APP pubBuy * @author Mareks Keišs * @returns bool */ public function getFirstDDKeyMatch(&$data){ if(count($data)){ foreach($data as $k=>$el){ if(isset($el['e']) && $el['e']){ unset($data[$k]); return $k; } } } } /** * Function to check if input data is filled, or if some field is missing * * @category APP pubBuy * @author Mareks Keišs * @returns bool */ public function chkInpFormDataIsFilled(){ if(!!!$this->cart->formInput) $this->cart->formInput = array(); return false; if($this->oUser->isLogined()){ // Get input form data $uMod = new pubUsersModule(); $inp = $this->cart->formInput; if(!$inp) $inp = array(); // Get user data if no data found if(!$inp || empty($inp['email']) || empty($inp['name'])){ $user = $uMod->getUserDataById($this->oUser->getUser()); $inp['email'] = $user['user_email']; $inp['name'] = "{$user['user_name']} {$user['user_surname']}"; } // Get address data if address fields not filled if(!$inp || empty($inp['paddress']) || empty($inp['townCity']) || empty($inp['country']) || empty($inp['telephone'])){ $uData = $uMod->getUserAddressData($this->oUser->getUser()); $inp['name'] = $uData['name']; $inp['paddress'] = $uData['address']; $inp['paddress2'] = $uData['address2']; $inp['townCity'] = $uData['city']; $inp['country'] = $uData['country']; $inp['pcode'] = $uData['pcode']; $inp['telephone'] = $uData['telephone']; } $this->cart->formInput = $inp; } return true; } /** * Function to get first drop-down match * * @category APP pubBuy * @author Mareks Keišs * @returns bool */ public function getProgressLineCfg(){ // Set steps progress return $progress = array( 'product' => array( 'lbl' => $this->gM('Shopping cart'), 'step' => 1, 'href' => $this->gL(self::CART_URI_ID, 'a:' . $this->gM(self::STEP_1_URL_KEY)), ), 'delivery' => array( 'lbl' => $this->gM('Customer information'), 'step' => 2, 'href' => $this->gL(self::CART_URI_ID, 'a:' . $this->gM(self::STEP_2_URL_KEY)), ), 'payment' => array( 'lbl' => $this->gM('Shipping & Payment method'), 'step' => 3, 'href' => $this->gL(self::CART_URI_ID, 'a:' . $this->gM(self::STEP_3_URL_KEY)), ), 'receipt' => array( 'lbl' => $this->gM('Order complete'), 'step' => 4 ), ); } /** * Function to recalculate cart subtotal values * * @category APP pubBuy * @author Mareks Keišs * @returns bool */ public function recalculateCartSubtotals(){ $cartContent = $this->cart->data; if(!!$cartContent){ $cartContent['vat'] = 0; $cartContent['total'] = 0; $cartContent['subtotal'] = 0; foreach($cartContent as $tkey=>$type){ if(!!$type && is_array($type)){ foreach($type as $pkey=>$prod) { if(!!$prod && is_array($prod)){ // Loop each product variation foreach($prod as $t => $v){ $cartContent[$tkey][$pkey][$t]['sum'] = $v['count'] * $v['p']; $cartContent['total'] += $v['count']; $cartContent['subtotal'] += $cartContent[$tkey][$pkey][$t]['sum']; } } } } } $cartContent['vat'] = $cartContent['subtotal'] - $cartContent['subtotal'] * 100 / (100 + self::VAT); //pr($cartContent); $this->cart->data = $cartContent; return $cartContent; } } /** * Function to add count for specific cart item * * @category APP pubBuy * @author Mareks Keišs * @returns bool */ public function incDecCartItemCount(){ $type = 'cat'; $id = getP('item'); $count = getP('count'); if(strlen($id)){ $cry = new cDefuseCrypto(); $sid = explode('|%|',$cry->decrypt($id)); // Check if all params present if(count($sid)>1 && $sid[0] && $sid[1]){ $id = $sid[0]; $sid = $sid[1]; if($id && $count && is_numeric($count)){ $cartContent = $this->cart->data; if(!!$cartContent && $id){ if(isset($cartContent[$type][$id][$sid])){ $item = &$cartContent[$type][$id][$sid]; $item['count'] = $count; $item['sum'] = $count * $item['p']; $this->cart->data = $cartContent; $subtotal = $this->recalculateCartSubtotals(); cJSON::sendok($this->buildCartAjaxResponse($subtotal ?: $cartContent, [ 'c' => $count, 'sum' => number_format($item['sum'], 2, '.', ' '), 'item' => $id, ], false)); } } } } } cJSON::senderror(array('msg' => $this->gM('Something went wrong while trying to update cart!'))); } /** * Function to check if cart content is available - if not add notice * * @category APP pubBuy * @author Mareks Keišs * @param int | bool $id - product id to check for availability * @param string | bool $type - product type to check * @param string | bool $div - product division to check for availability * @return bool */ public function checkAmountAvailable($id = false, $type = false, $div = false){ $count = 0; $errNotifications = ($id ? $this->cart->errMsg : array()); $cartContent = $this->cart->data; if(!!$cartContent){ // Check for specific ID if($id){ if(isset($cartContent[$type][$id])){ foreach($cartContent[$type][$id] as $v){ if($v['t'] == $div || !$v['t'] && !$div){ $count = $v['count']; break; } } } if($count){ $pCount = $this->module->getProdCount(array($type => array($id))); if($pCount && count($pCount)){ $div = ($div?$div:'0,0'); $tArray = explode(',', $div); if(count($tArray) == 1) $tArray[] = 0; foreach($pCount[$type][$id] as $v){ $even = array_intersect($tArray, $nArray = explode(',', $v['division'])); if(count($even) == count($nArray)){ if($v['prod_available'] - $v['prod_count'] - $count < 0){ $errNotifications[$type][$id][$div] = $this->gM('Unfortunately, chosen quantity is not available at the moment. Reduce the amount of the ordered goods or choose another product.'); }else{ if(isset($errNotifications[$type][$id][$div])) unset($errNotifications[$type][$id][$div]); if(isset($errNotifications[$type][$id]) && !!!$errNotifications[$type][$id]) unset($errNotifications[$type][$id]); if(isset($errNotifications[$type]) && !!!$errNotifications[$type]) unset($errNotifications[$type]); } break; } } } } // Check all items in cart }else{ $ids = $this->cart->ids; $pCount = $this->module->getProdCount($ids); foreach($cartContent as $tkey=>$type){ if(!!$type && is_array($type)){ foreach ($type as $pkey => $prod) { if($prod && is_array($prod)){ foreach ($prod as $v) { $div = ($v['t']?$v['t']:'0,0'); $tArray = explode(',', $div); if(count($tArray) == 1) $tArray[] = 0; foreach($pCount[$tkey][$pkey] as $vv){ $even = array_intersect($tArray, $nArray = explode(',', $vv['division'])); if(count($even) == count($nArray)){ if($vv['prod_available'] - $vv['prod_count'] - $v['count'] < 0){ $errNotifications[$tkey][$pkey][$div] = $this->gM('Unfortunately, chosen quantity is not available at the moment. Reduce the amount of the ordered goods or choose another product.'); }else{ if(isset($errNotifications[$tkey][$pkey][$div])) unset($errNotifications[$tkey][$pkey][$div]); if(isset($errNotifications[$tkey][$pkey]) && !!!$errNotifications[$tkey][$pkey]) unset($errNotifications[$tkey][$pkey]); if(isset($errNotifications[$tkey]) && !!!$errNotifications[$tkey]) unset($errNotifications[$tkey]); } break; } } } } } } } } } $this->cart->errMsg = $errNotifications; if($id && isset($errNotifications[$type][$id][$div]) || !$id && !!$errNotifications) return false; return true; } /** * Function to remove item from cart * * @category APP pubBuy * @author Mareks Keišs * @param int | bool $id - product row id to remove * @param string | bool $type - product type * @return bool */ public function removeItemFromCart($id = false, $type = false){ // Clear cart if(getP('delAll')){ $this->cart->destroy(); cJSON::sendok($this->buildCartAjaxResponse([], $this->renderEmptyCart())); } if(strlen($id)){ $cry = new cDefuseCrypto(); $sid = explode('|%|',$cry->decrypt($id)); // Check if all params present if(count($sid)>1 && $sid[0] && $sid[1]){ $id = $sid[0]; $sid = $sid[1]; if($id){ $cartContent = $this->cart->data; if(!!$cartContent && $id){ if(isset($cartContent[$type][$id][$sid])){ unset($cartContent[$type][$id][$sid]); if(!count($cartContent[$type][$id])) unset($cartContent[$type][$id]); // Last removed - destroy cart content if(count($cartContent[$type]) == 0){ $this->cart->destroy(); cJSON::sendok($this->buildCartAjaxResponse([], $this->renderEmptyCart())); } $this->cart->data = $cartContent; $subtotal = $this->recalculateCartSubtotals(); cJSON::sendok($this->buildCartAjaxResponse($subtotal ?: $cartContent, [ 'subtotal' => number_format((float)($subtotal['subtotal'] ?? 0), 2, '.', ' '), 'item' => $id, ], false)); } } } } } cJSON::senderror(array('msg' => $this->gM('Something went wrong while trying to update cart!'))); // Clear one shop item if($id && $type){ $cry = new cDefuseCrypto(); $sid = explode('-',$cry->decrypt(substr($id, 1))); if(count($sid)>1 && $sid[0] && $sid[1]){ $id = $sid[0]; $sid = $sid[1]; $cartContent = $this->cart->data; $divErrors = $this->cart->errMsg; $this->recalculateCartSubtotals(); if(isset($cartContent[$type][$id][$sid])){ $cartContent['total'] -= $cartContent[$type][$id][$sid]['count']; unset($divErrors[$type][$id][$cartContent[$type][$id][$sid]['t']], $cartContent[$type][$id][$sid]); if(count($cartContent[$type][$id])==0){ unset($cartContent[$type][$id], $divErrors[$type][$id]); if(count($cartContent[$type])==0){ unset($cartContent[$type], $divErrors[$type]); if($cartContent['total'] == 0) $cartContent = $divErrors = array(); } } $this->cart->data = $cartContent; $this->cart->errMsg = $divErrors; $this->cart->reload = true; $this->cart->reloadPayments = true; $this->cart->reloadDelivery = true; $subtotal = $this->recalculateCartSubtotals(); if(!!!$cartContent) return array('reaod' => true); return array( 'tu' => $cartContent['total'], 't' => number_format($subtotal['total'], 2, '.', ' '), 'tp' => number_format($subtotal['total_pay'], 2, '.', ' ') ); } } } return false; } public function getCheckoutAddressValCfg(): array { return [ 'cfg' => [ 'sBindAttrTitle' => 'data-validator', ], /* CHECKOUT SHIPPING ADDRESS*/ 'checkout_email' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::CHK_EMAIL], ], 'checkout_first_name' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_last_name' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_address1' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_address2' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 0, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_city' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_country' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_zip' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_phone' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::CHK_PHONE], ], /* CHECKOUT BILLING ADDRESS*/ 'checkout_bill_first_name' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_bill_last_name' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_bill_address1' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_bill_address2' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 0, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_bill_city' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_bill_country' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_bill_zip' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::TY_STR], ], 'checkout_bill_phone' => [ cValidator::P_TYPE => cValidator::TY_STR, cValidator::P_COMP => 1, cValidator::P_TEST => [cValidator::CHK_PHONE], ], ]; } /** * Function to get input field translations * * @category APP pubBuy * @author Mareks Keišs * @returns bool true or redir to error */ public function getJsTranslations(){ return array( 'chkPhone' => $this->gM('Invalid telephone specified!'), 'chkComp' => $this->gM('Please fill in the field!'), 'chkEmail' => $this->gM('Not a valid email address specified!'), ); } /** * Function to get list of objects for delivery selection * * @category APP pubBuy * @author Mareks Keišs * @returns bool true or redir to error */ CONST TYPE_P_STACIJAS = 'pastaStacijas'; CONST TYPE_P_POST24 = 'post24Stacijas'; public function getListForSelect($type, $return = false){ $data = false; if(!($data = $this->oApc->check("{$type}_{$this->langId}"))){ switch($type){ // PastaStacijas case self::TYPE_P_STACIJAS: $json = file_get_contents("http://klients.pastastacija.lv/api/terminals.json"); if($result = json_decode($json, true)){ $data = array( 't' => $this->gM('- Chose PastaStacija -'), 'd' => array() ); if(count($result)){ foreach($result as $k=>$v){ $data['d'][$k] = $v['name']; } } } unset($result); break; // Post 24 case self::TYPE_P_POST24: $cl = new cmsClassificatorsModule(); $data = array( 't' => $this->gM('- Chose Post24 station -'), 'd' => array() ); $temp = $cl->getClGroupsTranslationsById(cmsClassificatorsModule::POST_24_ADRESES, false, true); if(count($temp[cmsClassificatorsModule::POST_24_ADRESES])) foreach($temp[cmsClassificatorsModule::POST_24_ADRESES] as $k=>$v) $data['d'][$k] = $v['title']; unset($temp); break; } } if(!$data && !$return) cJSON::senderror(); if(!!$data) $this->oApc->store("{$type}_{$this->langId}", $data, 60*60*12); return $data; } /** * Function to compose payment redirect document * * @category APP pubBuy * @author Mareks Keišs * @returns mixed bool / redirect to page next */ public function compPaymentRedirect($key){ $cry = new cDefuseCrypto(); $key = $cry->decrypt($key); $order = $this->cart->formInput; $cartContent = $this->cart->data; $classificatorTitles = $this->cart->t; // Check active purchase if(!!$cartContent && !!$order && isset($_SESSION['order_key']) && $_SESSION['order_key'] == $key){ // Get bill number $recNr = $this->module->getNextDeletedOrderNr(); if(!strlen($recNr)){ $cNum = new cNumbers(); $recNr = $cNum->getProductBillNumber(); } // Place order $this->cart->orderId = $this->module->insertDataIntoDbTable(pubBuyModule::TABLE_ORDERS, array(array( 'o_nr' => $recNr, 'o_date' => time(), 'o_mail' => $order['customer_info']['checkout_email'], 'o_payment_met' => $order['sh_and_py']['payment_method'], 'o_delivery_met' => $order['sh_and_py']['shipping_method'], 'o_input_data' => cJSON::encode($this->cart->formInput), 'o_modified' => time(), 'o_deleted' => 0, ))); // Delete reserved order number $this->module->deleteReservedOrderNr($recNr); // Save order address data $addressData = array(); $shipping = &$order['shipping_address']; $delivery = &$order['delivery_info']; foreach(array($shipping, $delivery) as $k=>$v){ $addressData[] = array( 'o_id' => $this->cart->orderId, 'o_type' => $k, 'o_addr_name' => $v['checkout_first_name'], 'o_addr_lastname' => $v['checkout_last_name'], 'o_addr_address' => $v['checkout_address1'] . ' ' . $v['checkout_address2'], 'o_addr_city' => $v['checkout_city'], 'o_addr_country' => $v['checkout_country'], 'o_addr_zip' => $v['checkout_zip'], 'o_addr_phone' => $v['checkout_phone'], ); } if(!!$addressData) $this->module->insertDataIntoDbTable(pubBuyModule::TABLE_ORDERS_ADDRESSES, $addressData); // Prepare all input data for view $shipping = $this->module->db->prepData($shipping); $delivery = $this->module->db->prepData($delivery); // Handle products if(!!$cartContent['cat'] && is_array($cartContent['cat'])){ $iType = 0; $data = array(); $tableD = array(); // Gen data array foreach($cartContent['cat'] as $prodId=>$pTypes){ if(!!$pTypes && is_array($pTypes)){ foreach($pTypes as $tyKey=>$type){ $ty = explode(',', $tyKey); // Add data for insertion into db $data[] = array( 'o_id' => $this->cart->orderId, 'p_id' => $prodId, 'p_row_id' => $type['rid'], 'p_price' => $type['p'], 'p_count' => $type['count'], 'p_type1' => @$ty[0], 'p_type2' => @$ty[1], ); // Prepare data for view $type['t'] = $this->module->db->prepData($type['t']); $type['c1'] = $this->module->db->prepData($type['c1']); $type['c2'] = $this->module->db->prepData($type['c2']); $div = '{SIZE}'; $img = '{TITLE}'; // Add data for e-mail array $tableD[] = array( 'item_img' => (!empty($type['i']) ? str_replace(array( '{SRC}', '{TITLE}' ), array( "http{$this->oUrl->_sslS}://{$_SERVER['SERVER_NAME']}{$type['i']}", $type['t'] ), $img) : ''), 'item_name' => $type['t'], 'item_data' => (!empty($type['c1']) ? str_replace('{SIZE}', $type['c1'], $div) : '') . (!empty($type['c2']) ? str_replace('{SIZE}', $type['c2'], $div) : ''), 'item_value' => number_format($type['p'], 2, '.', ' ') . ' ' . self::CURRENCY, 'item_count' => $type['count'], 'Item_count_value' => number_format($type['sum'], 2, '.', ' ') . ' ' . self::CURRENCY, ); if(!empty($type['type'])) $iType = $type['type']; } } } // Insert order data $this->module->insertDataIntoDbTable(pubBuyModule::TABLE_ORDERS_DATA, $data); if($iType){ $this->module->updateOrdersData($this->cart->orderId, array('o_type' => $iType)); } } // Before redirecting compose outgoing mail $mm = new cMail(); // Send payment mail for other mail type if(!empty($order['customer_info']['checkout_email'])){ $shippingHtml = '-'; if(!empty($classificatorTitles[$order['sh_and_py']['shipping_method']])){ $shippingHtml = $this->gM($classificatorTitles[$order['sh_and_py']['shipping_method']]); // Check if Omniva selected - add pickup place if($order['sh_and_py']['shipping_method'] == self::DELIVERY_OMNIVA && !empty($order['sh_and_py']['a_omniva'])){ // Load additional data if(!$omniva_data = $this->oApc->check("OMNIVA_DATA")){ $omniva_data = $this->module->getClassificatorDataById(self::DELIVERY_OMNIVA_GR); // Omniva type $this->oApc->store('OMNIVA_DATA', $omniva_data); } if(!empty($omniva_data[$order['sh_and_py']['a_omniva']])) $shippingHtml .= " - {$omniva_data[$order['sh_and_py']['a_omniva']]['n']}"; } } $email_href = "http{$this->oUrl->_sslS}://{$_SERVER['SERVER_NAME']}" . $this->gL(self::EMAIL_READ_URL, "v:" . $cry->encrypt($recNr)); $sShipFlatSep = ''; $sDelivFlatSep = ''; if(strlen($shipping['checkout_address2'])) $sShipFlatSep = (is_numeric(substr($shipping['checkout_address1'], -1)) ? '-' : ' '); if(strlen($delivery['checkout_address2'])) $sDelivFlatSep = (is_numeric(substr($delivery['checkout_address1'], -1)) ? '-' : ' '); $mailData = array( 'order_nr' => $recNr, /*'order_pname' => $order['i_name'], 'order_phone' => $order['i_telephone'],*/ 'order_mail' => $order['customer_info']['checkout_email'], 'order_i_email' => $order['customer_info']['checkout_email'], 'order_i_fname' => ($shipping['checkout_first_name'] ? $shipping['checkout_first_name'] . ' ' . $shipping['checkout_last_name'] . ' (' . $this->gM('Telephone') . ': ' . $shipping['checkout_phone'] . ')' : '-'), 'order_i_faddress' => ($shipping['checkout_address1'] ? $shipping['checkout_address1'] . $sShipFlatSep . $shipping['checkout_address2'] : '-'), 'order_i_city_zip' => ($shipping['checkout_city'] ? $shipping['checkout_city'] . ', ' . $shipping['checkout_zip'] : '-'), 'order_i_country' => ($shipping['checkout_country'] ? $shipping['checkout_country'] : '-'), 'order_d_fname' => ($delivery['checkout_first_name'] ? $delivery['checkout_first_name'] . ' ' . $delivery['checkout_last_name'] . ' (' . $this->gM('Telephone') . ': ' . $delivery['checkout_phone'] . ')' : '-'), 'order_d_faddress' => ($delivery['checkout_address1'] ? $delivery['checkout_address1'] . $sDelivFlatSep . $delivery['checkout_address2'] : '-'), 'order_d_city_zip' => ($delivery['checkout_city'] ? $delivery['checkout_city'] . ', ' . $delivery['checkout_zip'] : '-'), 'order_d_country' => ($delivery['checkout_country'] ? $delivery['checkout_country'] : '-'), 'item_open_link' => (strlen($email_href) ? $this->gM("Can't see the images?") . ' ' . $this->gM('Click here.') . '' : ""), 'delivery_met' => $shippingHtml, 'payment_met' => (!empty($classificatorTitles[$order['sh_and_py']['payment_method']]) ? $this->gM($classificatorTitles[$order['sh_and_py']['payment_method']]) : '-'), 'order_delivery' => (!empty($order['delivery_cost']) ? number_format($order['delivery_cost'], 2, '.', '') . self::CURRENCY : '-'), 'order_delivery_msg' => (empty($order['delivery_cost']) ? $this->gM('msg_addition_delivery_costs') : ''), 'tr' => array( 'class' => 'sample', 'data' => $tableD ), 'vat' => number_format($cartContent['vat'], 2, '.', ' ') . ' ' . self::CURRENCY, 'subtotal' => number_format($cartContent['subtotal'] + (!empty($order['delivery_cost']) ? $order['delivery_cost'] : 0), 2, '.', ' ') . ' ' . self::CURRENCY, ); // Send mail to customer $mId = $mm->addMail( $order['customer_info']['checkout_email'], false, cMail::MAIL_SERVER_LORETA_LV, cMail::MAIL_1_ORDER_CONFIRMATION, $this->langId, $mailData, '', false, ); // Update mail link id if ($mId > 0 || $mId < 0) $this->module->updOrderById($this->cart->orderId, ['o_mid' => $mId]); // Send mail to info $mm->addMail(cMail::SENDER, cMail::CC_SHOP_OWNER, cMail::MAIL_SERVER_LORETA_LV, cMail::MAIL_1_ORDER_CONFIRMATION, $this->langId, $mailData, '', false); } // Kill cart session $this->cart->data = false; $this->cart->products = false; $this->cart->countDivision = false; $this->cart->countries = false; $this->cart->payments = false; $this->cart->formInput = false; $this->cart->itemData = false; $this->cart->subtotal = false; unset($_SESSION['order_key']); redirectToUri($this->gL(false, "a:" . $this->gM(self::ORDER_RECEIVED_URL_KEY) . "/nr:{$key}")); die(); } redirectToUri($this->gL()); die(); // Check active purchase if(!!$cartContent && !!$order){ $sessionUserId = $this->oUser->getUser(); $order['order_reserved'] = true; $order['order_nr'] = $recNr; $order['rec_sum'] = $order['order_sum'] = $this->cart->subtotal['total_pay'] * 100; $order['order_delivery'] = $this->cart->subtotal['delivery'] * 100; // Reset demo user 1 cent payment if($sessionUserId && in_array($sessionUserId, $this->demoUsersSant)){ $order['order_sum'] = 1; } // Get user data $uData = array( 'ind_name' => (isset($order['name']) && $order['name'] ? $order['name'] : $order['company']), 'ind_tel' => $order['telephone'], 'ind_email' => $order['email'], ); if(isset($order['send-spam'])) $uData['ind_news'] = $order['send-spam']; $user = $this->getUserForOrder($uData); $this->oUser->module->updateUserAddressData($user['id'], array( 'user_id' => $user['id'], 'name' => $order['name'], 'address' => $order['paddress'], 'address2' => $order['paddress2'], 'city' => $order['townCity'], 'country' => $order['country'], 'pcode' => $order['pcode'], 'telephone' => $order['telephone'], )); // Die in case if no user retrieved if(!($user && count($user))){ $this->cart->enabled_step_level = 1; $this->oView->display('pay/payment-false', 'BODY'); } // Delivery setup $delId = 0; if(isset($order['del']['id']) && $delId = substr($order['del']['id'], 1)) $delivery = $delivery[$delId]; // Place new order with reservation time $orderId = ($this->cart->order_id ? $this->cart->order_id : 0); $prodCount = array('cnt' => 0, 't' => ''); // Diff. prod count $this->cart->orderId = $this->module->reserveProduct( // Order id by ref $orderId, // Base order data array( 'user_id' => $user['id'], 'order_date' => time(), 'order_res' => 1, 'order_res_till' => time() + self::RESERV_TIME, // Reservation time 'order_delivered' => 0, 'order_returned' => 0, 'order_deleted' => 0, ), // Delivery array( 'order_id' => &$orderId, 'prod_delivery' => round($order['order_delivery'], 2), 'prod_delivery_type' => $delId, 'prod_delivery_title' => (isset($delivery['shop_rec_title']) && $delivery['shop_rec_title'] ? $delivery['shop_rec_title'] : (isset($delivery['shop_stitle'])?$delivery['shop_stitle']:'')), 'prod_delivery_text' => (isset($delivery['shop_rec_description']) ? $delivery['shop_rec_description'] : ''), 'prod_delivery_json' => cJSON::encode($this->cart->formInput), ), // Receipt array( 'order_id' => &$orderId, 'rec_nr' => $order['order_nr'], 'rec_status' => 0, 'rec_value' => round($order['order_sum'], 2), 'rec_currency' => 'EUR', // self::CURRENCY_CODE, 'rec_reference_id' => 0, 'rec_result_code' => '', 'rec_result_message' => '', 'rec_result_time' => time(), 'rec_user_ip' => @$_SERVER['REMOTE_ADDR'], 'rec_inc_delivery' => (isset($order['order_delivery']) && $order['order_delivery'] > 0 ? 1 : 0), 'rec_type' => (isset($this->paymentMethod[$key])?$this->paymentMethod[$key]:0), ), // Order product data $this->createOrderDataArray($orderId, $this->cart->products, $this->cart->data, $prodCount) ); // In case bought single product if($prodCount['cnt'] == 1) $order['prod_sname'] = str_replace(array('&', '\'', '"'), ' ', $prodCount['t']); // Preserve data & kill cart session $this->cart->destroy(array('billDL')); // Redirect to payment module $this->redirectToPayment($key, $order['order_nr'], $order); }elseif($recNr){ // Redirect to payment module $this->redirectToPayment($key, $recNr); } $this->oView->display('pay/payment-false', 'BODY'); return false; } /** * Function to setup payment redirect data & payment form * * @category APP pubBuy * @author Mareks Keišs * @returns int user id */ public function redirectToPayment($key, $recId, $order = false){ // Load Order data for payment if(!$order && $recId){ $order = $this->module->getPageBackPaymentData($recId); if($this->paymentMethod[$key] != $order['rec_type']){ foreach($this->paymentMethod as $k=>$v) if($v == $order['rec_type']){ $key = $k; break; } } } if($key && !!$order){ $cry = new cDefuseCrypto(); $sessionUserId = $this->oUser->getUser(); switch ($key) { // CPS cards case self::PMET_CARDS: $this->cart->enabled_step_level = 1; $this->oView->display('pay/payment-false', 'BODY'); /*$data = array( 'orderNumber' => $order['order_nr'], 'firstName' => $user['user_name'], 'lastName' => $user['user_surname'], 'email' => $prod['ind_email'], 'country' => 'LV', 'value' => $order['order_sum'], 'currency' => 'LVL', 'productName' => $prod['prod_sname'], 'productUrl' => $prod['prod_full_url'], ); $this->oView->ORDER_ID = $orderId; $cps = new cps(); $this->oView->CPS_CARDS = $cps->getSendForAuthXML($data, true, $this->getFullLinkForID(self::CART_URI_ID, 'receipt:' . $cry->encrypt($order['order_nr'])));*/ break; // FIRST DATA CARDS case self::PMET_FIRST_DATA_CARDS: $data = array( 'post_amount' => $order['order_sum'], 'post_ip' => @$_SERVER['REMOTE_ADDR'], 'post_description' => 'PIRKUMS ELIXIRVAULT.LV / ' . $order['order_nr'] . (isset($order['prod_sname']) ? ' / ' . trim($order['prod_sname']) : ''), 'post_language' => $this->uri_data['lang_code'], 'receipt_id' => $order['order_nr'], ); $fd = new firstData(); if(!$fd->startSMSTransaction($data)){ die(redirectToUri($this->gL(self::CART_URI_ID, 'a:transaction-error/receipt:' . $cry->encrypt($order['order_nr'])))); } die(); break; // DIRECT SWEDBANK BANKLINK case self::PMET_SWEDBANKLINK: $data = array( 'VL_LANG' => 'LAT', 'VK_CURR' => self::CURRENCY_CODE, 'VK_REF' => $order['order_nr'], 'VK_STAMP' => $order['order_nr'], 'VK_AMOUNT' => number_format($order['order_sum']/100, 2, '.', ''), 'VK_MSG' => 'PIRKUMS ELIXIRVAULT.LV / ' . $order['order_nr'] . (isset($order['prod_sname']) ? ' / ' . trim($order['prod_sname']) : ''), ); $banklink = new swedbank(); die($banklink->getBanklinkData($data, $this->getFullLinkForID(self::CART_URI_ID, 'a:invoice-print/receipt:' . $cry->encrypt($order['order_nr'])))); break; // CPS Swedbank gen case self::PMET_SWEDB: $this->cart->enabled_step_level = 1; $this->oView->display('pay/payment-false', 'BODY'); /*$data = array( 'orderNumber' => $order['order_nr'], 'firstName' => $user['user_name'], 'lastName' => $user['user_surname'], 'email' => $prod['ind_email'], 'country' => 'LV', 'value' => $order['order_sum'], 'currency' => 'LVL', 'productName' => 'PIRKUMS LORETASECRET.lv/' . trim($prod['prod_sname']), 'productUrl' => $prod['prod_full_url'], ); $this->oView->ORDER_ID = $orderId; $cps = new cps(); $this->oView->CPS_SWED = $cps->getSendForAuthSwedXML($data, true, $this->getFullLinkForID(self::CART_URI_ID, 'receipt:' . $cry->encrypt($order['order_nr'])));*/ break; // GEN RECEIPT case self::PMET_OTHER: // Before redirecting compose outgoing mail $mm = new cMail(); $PDFFile = 'URL:' . $cry->encrypt($order['order_nr']); // Send payment mail for other mail type if(isset($order['email'])) $mm->addMail( $order['email'], false, 0, //cMail::MAIL_13_OTHER_PAYMENT_RECEIPT, $this->langId, array('Prod-name' => (isset($order['prod_sname']) ? $order['prod_sname'] : '')), $PDFFile ); die(redirectToUri($this->getFullLinkForID(self::CART_URI_ID, 'a:invoice/receipt:' . $cry->encrypt($order['order_nr'])))); break; } if(!$sessionUserId || $sessionUserId && !in_array($sessionUserId, $this->demoUsers)){ $this->oView->display('pay/payment-redirect', 'BODY'); return true; }else{ redirectToUri($this->getFullLinkForID(self::CART_URI_ID, 'a:invoice-print/demus:1/receipt:' . $cry->encrypt($order['order_nr']))); die(); } } } /** * Function to get user to link order data to * * @category APP pubBuy * @author Mareks Keišs * @returns int user id */ public function getUserForOrder($prod){ //$prod['aType'] = pubUsersController::US_ORDER; return null; //$this->oUser->getUserForLinks($prod); } /** * Function to create order product data array prep for inset * * @category APP pubBuy * @author Mareks Keišs * @param int $order_id - order id * @param array $p - product data * @param array $o - order data * @param array $prodCount - different product count * @return array of data */ public function createOrderDataArray(&$order_id, $p, $o, &$prodCount){ $data = array(); if(!!$p && !!$o){ foreach ($o as $tkey=>$type) { if(!!$type && is_array($type)){ foreach ($type as $pkey=>$prod) { if(!!$prod){ foreach ($prod as $v) { // Add product if(isset($p[$tkey][$pkey])){ $tp = $p[$tkey][$pkey]; $cl = explode(',', (!!$v['t'] ? $v['t'] : '0,0')); $data[] = array( 'order_id' => &$order_id, 'prod_type' => ($tkey == 'act' ? 0 : 1), 'prod_id' => $tp['id'], 'prod_price' => round((isset($tp['prod_new_price']) && $tp['prod_new_price'] > 0 ? $tp['prod_new_price'] : $tp['prod_price']), 2) * 100, 'prod_vat' => $tp['prod_vat'], 'prod_count' => $v['count'], 'prod_cl_id' => $cl[0], 'prod_cl_id_2' => (isset($cl[1]) ? $cl[1] : 0), ); } } $prodCount['cnt']++; $prodCount['t'] = $p[$tkey][$pkey]['prod_name']; } } } } } return $data; } /** * Function to get order status * * @category APP pubBuy * @author Mareks Keišs * @returns bool true/false */ public function checkProdPaid(){ $cry = new cDefuseCrypto(); if($id = $cry->decrypt(getG('receipt'))){ if($rec = $this->module->getRowDataByTable(pubBuyModule::TABLE_ORDERS_RECEIPTS, array('rec_nr' => $id))){ if($rec['rec_result_message'] == self::STATUS_CAPTURED){ return $rec['rec_type']; }elseif($rec['rec_type'] == self::PMET_OTHER_E){ return self::PMET_OTHER_E; } } } return false; } /** * Function to throw .pdf generated document * * @category APP pubBuy * @author Mareks Keišs * @returns bool */ public function throwDocument($save = false, &$prod = array()){ // Increase memory limit ini_set('memory_limit', '64M'); if($rec_id = getG('receipt')){ $cry = new cDefuseCrypto(); $rec_id = $cry->decrypt($rec_id); // Set to default language /*$defLang = getDefaultAppLang(); $this->uri_data['p_lang_id'] = $this->langId = $defLang['id']; $this->initLocale((isset($defLang['lang_code']) && $defLang['lang_code']?$defLang['lang_code']:false), false, false);*/ if($rec_id && $order = $this->module->getOrderDataForReceipt($this->module->db->prepData($rec_id), $this->langId)){ $order['order']['order_date'] = date($this->PUBDateFormat, $order['order']['order_date']); $order['receipt']['rec_result_time'] = date($this->PUBDateFormat, $order['receipt']['rec_result_time']); $order['delivery']['prod_delivery'] = ($order['delivery']['prod_delivery']? number_format($order['delivery']['prod_delivery'] /= 100, 2, '.', ' ') : false); $order['delivery']['prod_delivery_text'] = prepForDisplayHtml($order['delivery']['prod_delivery_text']); //$numWords = cNumbers::translateWords($this); $order['receipt']['prod_summ'] = number_format($order['receipt']['rec_value']/= 100, '2', '.', ' '); $order['receipt']['prod_summ_words'] = cNumbers::num2words($this, str_replace(' ', '', $order['receipt']['rec_value'])); // Fill data from user profile in case if no other data specified $order['input'] = $this->module->db->prepData(json_decode($order['delivery']['prod_delivery_json'], true)); // Set country from id $ccMod = new cmsClassificatorsModule(); $countries = $ccMod->getClGroupsTranslationsById(cmsClassificatorsModule::CT_COUNTRIES, $this->langId, true); $order['input']['country'] = $countries[cmsClassificatorsModule::CT_COUNTRIES][$order['input']['country']]['title']; // Handle each product if(!!$order['products']){ $order['vat'] = array('lvl' => array()); $order['receipt']['prod_price_exvat'] = 0; foreach($order['products'] as &$v){ // EUR $v['prod_price'] /= 100; $order['receipt']['prod_price_exvat'] += ($exvat = $v['prod_price'] * 100 / (100 + $v['prod_vat'])) * $v['prod_count']; if(!isset($order['vat']['lvl'][$v['prod_vat']])) $order['vat']['lvl'][$v['prod_vat']] = 0; $order['vat']['lvl'][$v['prod_vat']] += ($v['prod_price'] - $exvat) * $v['prod_count']; $v['prod_sum'] = number_format($v['prod_price'] * $v['prod_count'], '2', '.', ' '); $v['prod_price'] = number_format($v['prod_price'], '2', '.', ' '); if($v['cl_1'] || $v['cl_2']) $v['prod_name'] .= " (" . trim("{$v['cl_1']} {$v['cl_2']}") . ")"; } unset($v); $order['receipt']['prod_price_exvat'] = number_format($order['receipt']['prod_price_exvat'], '2', '.', ' '); if(!!$order['vat']['lvl']){ foreach($order['vat']['lvl'] as &$v) $v = number_format($v, '2', '.', ' '); unset($v); } // Replace sub station if one has been chosen if(in_array($order['input']['del']['id'], $this->loadDeliveries) && isset($order['input']['del']['sub']) && $order['input']['del']['sub']){ if(!!($select = $this->getListForSelect((in_array($order['input']['del']['id'], array('d5', 'd7')) ? self::TYPE_P_STACIJAS : self::TYPE_P_POST24), true))){ if(isset($select['d'][$order['input']['del']['sub']])) $order['delivery']['prod_delivery_text'] = str_replace(self::TERMINAL_STR_KEY, $select['d'][$order['input']['del']['sub']], $order['delivery']['prod_delivery_text']); } $order['delivery']['prod_delivery_text'] = str_replace(self::TERMINAL_STR_KEY, '', $order['delivery']['prod_delivery_text']); } } $order['receipt']['rec_payment'] = (in_array($order['receipt']['rec_type'], array(self::PMET_CARDS_E, self::PMET_FIRST_DATA_CARDS_E)) ? $this->gM('msg_VISA_card'):$this->gM('msg_bank_transfer')); //pr($order); die(); $p = new cPdfFromHTML(); $this->oView->O = $order; //pr($this->oView->genTemplate('print_pdf')); die(); return $p->renderPdf($this->oView->genTemplate('print_pdf'), !$save, 'document'); } } return false; } /** * Function to reformat cart steps level * * @category APP pubBuy * @author Mareks Keišs * @param array $progCfg - progress config array * @param string|bool $stpID - progress step key * @param int|bool $stpLevel - progress enabled steps * @param bool $stpLock - progress steps lock * @return mixed */ public function reformatProgressLine($progCfg, $stpID = false, $stpLevel = false, $stpLock = false){ if(!!$progCfg){ $stpLevel = ($stpLevel ? $stpLevel : $this->cart->enabled_step_level); $stpLock = ($stpLock ? $stpLock : $this->cart->steps_lock); $stpID = ($stpID ? $stpID : $this->cart->STEP_ID); if($stpLevel){ $i = 1; foreach($progCfg as $k=>&$v){ if($k == $stpID) $v['active'] = true; if($stpLock) unset($v['href']); if($i <= $stpLevel){ $v['enb'] = true; $i++; }else{ unset($v['href']); } } unset($v); } return $progCfg; } return false; } /** * Function to setup view ordering tracking codes * * @category APP pubBuy * @author Mareks Keišs * @param string $receiptNr - payment receipt nr * @param int $paymentType - payment type id * @return mixed */ public function setupViewTrackingArrays($receiptNr, $paymentType){ $cry = new cDefuseCrypto(); $receiptNr = $cry->decrypt($receiptNr); if($receiptNr){ $defLang = getDefaultAppLang(); $order = $this->module->getOrderDataForReceipt($this->module->db->prepData($receiptNr), $defLang['id']); if(!!$order){ // Fill data from user profile in case if no other data specified $order['input'] = $this->module->db->prepData(json_decode($order['delivery']['prod_delivery_json'], true)); // Setup google e-commerce tracking $orderInfo = array( 'order_id' => $receiptNr, 'store' => 'elixirvault.lv', 'subtotal' => number_format($order['receipt']['rec_value'] / 100, 2, '.', ''), 'legaplp' => (isset($order['input']['type_chk']) && $order['input']['type_chk'] == 'person' ? 0 : 1), // Distinguish legal person 'pickup_type' => $paymentType, 'products' => array() ); if(!!$order['products'] && is_array($order['products'])){ foreach ($order['products'] as $p){ $orderInfo['products'][$p['prod_id']] = array( 'prod_nr' => $p['prod_nr'], 'prod_title' => $p['prod_name'], 'prod_category' => ($p['prod_type'] ? 'kataloga prece' : 'akcijas prece'), 'prod_u_price' => number_format($p['prod_price'] / 100, 2, '.', ''), 'prod_count' => $p['prod_count'], ); } } unset($order); switch($paymentType){ case self::PMET_OTHER_E: $this->oView->DOAFFILIATE = $orderInfo; break; case self::PMET_SWEDB_E: case self::PMET_SWEDBANKLINK_E: case self::PMET_CARDS_E: case self::PMET_FIRST_DATA_CARDS_E: $this->oView->GECOMERCE = $orderInfo; $this->oView->DOAFFILIATE = $orderInfo; break; } } } return false; } /** * Function to setup view ordering tracking codes * * @category APP pubBuy * @author Mareks Keišs * @param string $receiptNr - payment receipt nr * @return mixed */ public function retryPayment($receiptNr){ $cry = new cDefuseCrypto(); if($receiptNr = $cry->decrypt($receiptNr)){ if($order_id = $this->module->chkOrderFailed($receiptNr)){ if(!!($data = $this->module->reloadCartContentByRecId($order_id))){ // Update reservation to false $this->module->db->query("UPDATE mod_orders SET order_res_till = unix_timestamp() - 1"); $this->cart->enabled_step_level = 3; $this->cart->reload = true; $this->cart->reloadPayments = true; $this->cart->reloadDeliveryAndSetup = true; $this->cart->order_id = $order_id; // Recount all data for cart if(!!$data['cart']){ $data['cart']['total'] = 0; foreach ($data['cart'] as $typeK=>&$typeD){ if(!!$typeD && is_array($typeD)){ foreach ($typeD as $prodK=>&$prod) { if(!!$prod){ foreach ($prod as &$v) { if($v['count']) $data['cart']['total'] += $v['count']; if($v['t'] == '0,0') $v['t'] = ''; unset($v['typeK'], $v['prod_id']); } } } } } unset($typeD, $prod, $v); } $this->cart->data = $data['cart']; $this->cart->formInput = $data['inp']; $this->setCartDataConfiguration(pubBuyController::STEP_1_CART_DATA, false, true); $this->cart->reloadDelivery = true; $this->setCartDataConfiguration(pubBuyController::STEP_2_DELIVERY, false, true); // Redirect to payment redirectToUri($this->gL(self::CART_URI_ID, 'a:payment')); } } } // Go to cart main view $this->cart(pubBuyController::STEP_1_CART_DATA); } public function clearCart(): bool { $this->cart->destroy(); return true; } }