username = 'yandex'; $this->password = 'P8MUQtNP6TkKMz3E'; $this->channelManagerId = 13;//Yandex $this->request = $request; $this->currencyService = $currencyService; $this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService; $this->propertyChannelCouponService = $propertyChannelCouponService; $payload = $this->request->getContent(); parse_str(urldecode($payload), $payloadDecode); $this->param = $payloadDecode; $this->authorization = $request->header('authorization'); $this->tax = 10; $this->mealCodeMapping = [ 10 => 'AI', 11 => 'BB', 13 => 'RO', 14 => 'FB', 15 => 'HB', ]; $this->paymentTypeMapping = [ 'CRD' => 'prepaid', 'HTL' => 'postpaid' ]; } public function checkAuthentication($authorization) { $response = ['status' => false, 'message' => '']; $basicAuth = 'Basic ' . base64_encode($this->username . ':' . $this->password); if ($authorization != $basicAuth) { $response['message'] = 'Your username or password is incorrect.'; } else { $response['status'] = true; } return $response; } public function responseError($errorMessage) { $response = [ 'status' => false, 'message' => $errorMessage, ]; //channelManagerLogService if (!is_null($this->channelManagerLogId)) { $updateDataLog = [ 'response' => json_encode($response), 'status' => 0 ]; if (!is_null($this->channelManagerRequestTime)) { $updateDataLog['response_time'] = microtime(true) - $this->channelManagerRequestTime; } $channelManagerLog = $this->channelManagerLogService->update($this->channelManagerLogId, $updateDataLog); } //channelManagerLogService return response()->json($response); } public function requestParamConverter($requestParam = []) { $searchRequestJson = []; $searchRequestJson['date']['checkIn'] = Carbon::parse($requestParam['Checkin'])->toDateString(); $searchRequestJson['date']['checkOut'] = Carbon::parse($requestParam['Checkin'])->addDays($requestParam['Nights'])->toDateString(); $rooms = []; $rooms[0]['adults'] = (integer)$requestParam['Context']['OccupancyDetails']['NumAdults']; $rooms[0]['children'] = (integer)($requestParam['Context']['Occupancy'] - $requestParam['Context']['OccupancyDetails']['NumAdults']); $rooms[0]['age'] = []; if (isset($requestParam['Context']['OccupancyDetails']['Children']['Child'])) { $requestParam['Context']['OccupancyDetails']['Children']['Child'] = singleElementXMLArray($requestParam['Context']['OccupancyDetails']['Children']['Child']); } else { $requestParam['Context']['OccupancyDetails']['Children']['Child'] = []; } foreach ($requestParam['Context']['OccupancyDetails']['Children']['Child'] as $child) { $rooms[0]['age'][] = $child['@attributes']['age']; } $searchRequestJson['rooms'] = $rooms; if (isset($requestParam['PropertyList']['Property'])) { $requestParam['PropertyList']['Property'] = singleElementXMLArray($requestParam['PropertyList']['Property']); } else { $requestParam['PropertyList']['Property'] = []; } $searchRequestJson['property'] = $requestParam['PropertyList']['Property']; return $searchRequestJson; } public function roomOccupancy($requestParam) { $roomOccupancy = []; foreach ($requestParam as $room) { $adults = str_repeat('A', $room['adults']); $children = []; if ($room['children'] > 0 && !empty($room['age'])) { foreach ($room['age'] as $child) { $children[] = 'C' . $child; } } $roomOccupancy[] = $adults . implode('', $children); } return $roomOccupancy; } public function deepLinkGenerator($token, $requestParam = []) { $deepLink = 'https://be.extranetwork.com/' . $token . '/' . fillOnUndefined($requestParam, 'locale', 'en') . '/search/'; $deepLink .= Carbon::parse($requestParam['date']['checkIn'])->format('Ymd') . '/'; $deepLink .= Carbon::parse($requestParam['date']['checkOut'])->format('Ymd') . '/'; $roomOccupancy = $this->roomOccupancy($requestParam['rooms']); $deepLink .= implode(',', $roomOccupancy);; $deepLink .= '?utm_source=yandex'; return $deepLink; } public function couponCodeCheck($propertyId, $checkIn, $checkOut) { //$propertyChannelCoupon $propertyChannelCouponsCriteria = [ 'criteria' => [ ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId], ['field' => 'channel_id', 'condition' => '=', 'value' => 1], ['field' => 'start_date', 'condition' => '<=', 'value' => Carbon::now()->toDateString()], ['field' => 'end_date', 'condition' => '>=', 'value' => Carbon::now()->toDateString()], ['field' => 'status', 'condition' => '=', 'value' => 1], ], 'orderBy' => [ ['field' => 'id', 'value' => 'DESC'] ], ]; $propertyChannelCoupons = $this->propertyChannelCouponService->select($propertyChannelCouponsCriteria); if ($propertyChannelCoupons['status'] == 'success') { $propertyChannelCoupons = $propertyChannelCoupons['data']; foreach ($propertyChannelCoupons as $propertyChannelCouponKey => $propertyChannelCouponData) { //Reservation Date Check if (!is_null($propertyChannelCouponData['reservation_start_date']) && !is_null($propertyChannelCouponData['reservation_end_date'])) { $reservationDateCheck = Carbon::parse($propertyChannelCouponData['reservation_start_date'])->lessThanOrEqualTo(Carbon::parse($checkIn)) && Carbon::parse($propertyChannelCouponData['reservation_end_date'])->greaterThanOrEqualTo(Carbon::parse($checkOut)); if (!$reservationDateCheck) { unset($propertyChannelCoupons[$propertyChannelCouponKey]); } } } } else { $propertyChannelCoupons = []; } $propertyChannelCoupon = !empty($propertyChannelCoupons) ? reset($propertyChannelCoupons) : null; return $propertyChannelCoupon; } public function hotel(Request $request) { $response = ['status' => true, 'message' => '']; $listings = new \SimpleXMLElement(''); $listings->addChild('language', 'tr'); try { $channelManagerPropertyMappingCriteria['criteria'] = [ ['field' => 'channel_manager_id', 'condition' => '=', 'value' => $this->channelManagerId], ['field' => 'channel_manager_property_id', 'condition' => '=', 'value' => null], ['field' => 'status', 'condition' => '=', 'value' => 1], ]; $channelManagerPropertyMappingCriteria['with'] = [ 'property.propertyType', 'property.propertyContact', 'property.propertyWeb', 'property.country' ]; $channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria); if ($channelManagerPropertyMapping['status'] == 'success' && !empty($channelManagerPropertyMapping['data'])) { foreach ($channelManagerPropertyMapping['data'] as $propertyMapping) { if ($propertyMapping['status'] != 1) { continue; } $metaAddress = json_decode($propertyMapping['property']['property_contact']['meta'], 1); $listing = $listings->addChild('listing'); $listing->addChild('id', $propertyMapping['property']['id']); $listing->addChild('name', htmlspecialchars($propertyMapping['property']['name'], ENT_XML1, 'UTF-8')); $address = $listing->addChild('address'); $address->addAttribute('format', 'simple'); $component = $address->addChild('component', htmlspecialchars(fillOnUndefined($metaAddress, 'street'), ENT_XML1, 'UTF-8')); $component->addAttribute('name', 'addr1'); //$component = $address->addChild('component'); //$component->addAttribute('name', 'addr2'); $component = $address->addChild('component', fillOnUndefined($metaAddress, 'city')); $component->addAttribute('name', 'city'); //$component = $address->addChild('component', $propertyMapping['property']['country']['name']); //$component->addAttribute('name','region'); $component = $address->addChild('component', fillOnUndefined($metaAddress, 'zip_code')); $component->addAttribute('name', 'postal_code'); $listing->addChild('country', $propertyMapping['property']['country']['country_code']); $listing->addChild('latitude', $propertyMapping['property']['property_contact']['latitude']); $listing->addChild('longitude', $propertyMapping['property']['property_contact']['longitude']); $listing->addChild('category', 'hotel'); } } } catch (ApiErrorException $e) { $response['message'] = implode(', ', $e->getMessageArr()); } catch (Exception $e) { $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage(); Log::error($message); $response['message'] = $e->getMessage(); } header('Content-Type: application/xml; charset=UTF-8'); echo $listings->asXML(); exit; } public function availability(Request $request) { $response = ['status' => true, 'message' => '']; $checkAuthentication = $this->checkAuthentication($this->authorization); if (!$checkAuthentication['status']) { return $this->responseError($checkAuthentication['message']); } $searchController = App::make("App\Http\Controllers\BookingEngine\V1\SearchController"); $requestTime = microtime(true); $param = $this->request->getContent(); $paramXML = simplexml_load_string($param); $requestParam = json_decode(json_encode($paramXML), 1); $hotelIdList = collect($requestParam['PropertyList']['Property'])->values(); $hotelIdList = $hotelIdList ? $hotelIdList->toArray() : []; $transaction = new \SimpleXMLElement(''); try { //Hotels Check $channelManagerPropertyList = []; $channelManagerPropertyMappingCriteria['criteria'] = [ ['field' => 'channel_manager_id', 'condition' => '=', 'value' => $this->channelManagerId], ['field' => 'channel_manager_property_id', 'condition' => '=', 'value' => null], ['field' => 'status', 'condition' => '=', 'value' => 1], ]; $channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria); if ($channelManagerPropertyMapping['status'] == 'success' && !empty($channelManagerPropertyMapping['data'])) { $channelManagerPropertyList = pickItemFromArray('property_id', $channelManagerPropertyMapping['data']); } $availableHotelIds = array_intersect($hotelIdList, $channelManagerPropertyList); if (empty($availableHotelIds)) { throw new ApiErrorException('Hotel not found'); } //Hotels Check $searchRequestJson = $this->requestParamConverter($requestParam); $searchRequestJson['isMobile'] = null; $searchRequestJson['noneCacheSearch'] = true; $searchRequestJson['ipAddress'] = $request->getClientIp(); $searchRequestJson['justPriceValues'] = true; $searchRequestJson['locale'] = fillOnUndefined($requestParam, 'Locale') ?? 'tr'; $roomOccupancy = $this->roomOccupancy($searchRequestJson['rooms']); $roomOccupancy = implode(',', $roomOccupancy); $requestCurrency = fillOnUndefined($requestParam, 'Currency') ?? 'TRY'; $cacheKeyParam = $requestCurrency . ':' . $searchRequestJson['date']['checkIn'] . ':' . $searchRequestJson['date']['checkOut'] . ':' . implode(',', $searchRequestJson['property']) . ':' . $roomOccupancy; $cacheKey = 'YND:' . md5($cacheKeyParam); //Cache::forget($cacheKey); if (Cache::has($cacheKey)) { $search = Cache::get($cacheKey); } else { $requestCreate = Request::create(null, null, [], [], [], [], json_encode($searchRequestJson)); $requestCreate->headers->set('channelId', '1'); //$requestCreate->headers->set('bookingEnginePropertyId', null); $requestCreate->headers->set('channelToken', 'ece3ef02-42e7-92b7-f379-08226ed7a0f3');//TODO: from DB $requestCreate->headers->set('bookingEngineToken', null); $search = $searchController->search($requestCreate); Cache::put($cacheKey, $search, 60 * 60);//1 Day 24 * 60 * 60 } $search = json_decode(json_encode($search), 1); if ($search['original']['status'] != 200) { throw new ApiErrorException('Hotel not found'); } $properties = $search['original']['data']['properties']; if (empty($properties)) { throw new ApiErrorException('Hotel not found'); } $hotelCounter = 0; $numberOfStay = Carbon::parse($searchRequestJson['date']['checkIn'])->diffInDays(Carbon::parse($searchRequestJson['date']['checkOut'])); foreach ($properties as $propertyId => $property) { $propertyName = $property['name']; if (!isset($property['currency'])) { continue; } $currencyExchangeRate = 1; if ($requestCurrency != $property['currency']) { $currencyExchangeRate = $this->currencyService->lastExchangeRate($property['currency'], $requestCurrency); if ($currencyExchangeRate['status'] == 'success') { $currencyExchangeRate = $currencyExchangeRate['data']; } } $token = $property['booking_engine_token']; $deepLinkGenerator = $this->deepLinkGenerator($token, $searchRequestJson); $property = reset($property['availabilities']); $propertyRooms = $property['rooms']; //Standard Room Room Only FreeCancellation - Pay at Hotel $requestedRoomPriceGroup = []; foreach ($propertyRooms as $propertyRoomId => $propertyRoom) { foreach ($propertyRoom['rates'] as $propertyRoomRateId => $propertyRoomRate) { foreach ($propertyRoomRate['requestedRoomPrice'] as $occupancyCode => $requestedRoomPrices) { foreach ($requestedRoomPrices['prices'] as $requestedRoomPriceKey => $requestedRoomPrice) { $roomRateKeyName = $occupancyCode . ' ' . $requestedRoomPrice['room']['name'] . ' ' . $requestedRoomPrice['rate']['boardName'] . ' ' . $requestedRoomPrice['name']; $roomRateKeycode = $requestedRoomPrice['rate']['accommodationCode'] . '|' . (isset($requestedRoomPrice['cancellationPolicy']['id']) ? $requestedRoomPrice['cancellationPolicy']['id'] : 0) . '|' . $requestedRoomPrice['bookingPaymentType']['code']; //$requestedRoomPriceGroup[$roomRateKeycode][$occupancyCode][] = $roomRateKeyName . '-' . $requestedRoomPrice['rateKeyCode']; $requestedRoomPrice['dailyAverageDiscount'] = $requestedRoomPrices['dailyAverageDiscount']; $requestedRoomPriceGroup[] = $requestedRoomPrice; } } } } if (!empty($requestedRoomPriceGroup)) { $requestedRoomPriceGroup = collect($requestedRoomPriceGroup)->sortBy('total')->toArray(); } $requestedRoomPrice = reset($requestedRoomPriceGroup); $propertyCouponCodeCheck = $this->couponCodeCheck($propertyId, $searchRequestJson['date']['checkIn'], $searchRequestJson['date']['checkOut']); if ($propertyCouponCodeCheck) { $requestedRoomPrice['totalWithoutPopup'] = $requestedRoomPrice['total']; $couponPercentageValue = (100 - $propertyCouponCodeCheck['value']) / 100; $requestedRoomPrice['total'] = moneyDoubleFormatDecimal($requestedRoomPrice['total'] * $couponPercentageValue); } $transactionResult = $transaction->addChild('Result'); $transactionResult->addChild('Property', $propertyId); $transactionResult->addChild('Checkin', $searchRequestJson['date']['checkIn']); $transactionResult->addChild('Nights', $numberOfStay); $taxValue = $requestedRoomPrice['total'] * ($this->tax / 100); $baseTotalValue = $requestedRoomPrice['total'] - $taxValue; $netTotalValue = ($taxValue + $baseTotalValue); $baseRate = $transactionResult->addChild('Baserate', moneyDoubleFormatDecimal($baseTotalValue * $currencyExchangeRate)); $baseRate->addAttribute('currency', $requestCurrency); $tax = $transactionResult->addChild('Tax', moneyDoubleFormatDecimal($taxValue * $currencyExchangeRate)); $tax->addAttribute('currency', $requestCurrency); $otherFees = $transactionResult->addChild('OtherFees', 0); $otherFees->addAttribute('currency', $requestCurrency); $transactionResult->addChild('Custom1', htmlspecialchars($propertyName, ENT_XML1, 'UTF-8')); $allowablePointsOfSale = $transactionResult->addChild('AllowablePointsOfSale'); $pointOfSale = $allowablePointsOfSale->addChild('PointOfSale'); $pointOfSale->addAttribute('id', 'default'); $pointOfSale->addChild('URL', htmlspecialchars($deepLinkGenerator, ENT_XML1, 'UTF-8')); } } catch (ApiErrorException $e) { $response['message'] = implode(', ', $e->getMessageArr()); } catch (Exception $e) { $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage(); Log::error($message); $response['message'] = $e->getMessage(); } header('Content-Type: application/xml; charset=UTF-8'); echo $transaction->asXML(); exit; } }