restClient = $restClient; $this->mailer = $mailer; $this->url = 'https://www.reseliva.net/siteBase/REST/cms/service/'; //$this->url = 'https://api.reseliva.com/pms/service/'; $this->reservationPushUrl = 'https://www.reseliva.net/siteBase/utility/CM/ExtranetWork/notify.php'; $this->statusMapping = [ 'A' => 'Active', 'C' => 'Canceled', 'M' => 'Modified', ]; $this->typeMapping = [ 'Booking' => 'Book', 'Modify' => 'Modify', 'Cancel' => 'Cancel' ]; $this->paymentTypeMapping = [ 'MO' => 'Money Order', 'CC' => 'Credit Card given', 'POS' => 'Payed with payment system', 'PayPal' => 'Payed with PayPal' ]; $this->channelManagerId = 1; $this->channelManagerName = 'Reseliva'; $this->channelManagerPropertyMappingService = $channelManagerPropertyMappingService; $this->channelManagerMappingService = $channelManagerMappingService; } public function requestPost($method, $xmlPayload) { $response = ['status' => false, 'message' => '']; try { $this->restClient = new Client(['http_errors' => false]); $res = $this->restClient->post($this->url . $method, [ 'headers' => [ 'Content-Type' => 'text/xml; charset=UTF8', 'Accept' => 'text/xml' ], 'body' => $xmlPayload, ] ); $getResponseBody = $res->getBody(); $getResponse = $getResponseBody->getContents(); if (empty($getResponse)) { throw new ApiErrorException('Empty XML response'); } $getResponseXml = new \SimpleXMLElement($getResponse, LIBXML_NOCDATA); $getResponse = json_decode(json_encode($getResponseXml), 1); $response = ["status" => true, 'message' => '', "data" => $getResponse]; } catch (ApiErrorException $e) { $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage() . ' ' . $method; Log::error($message); $response['message'] = $e->getMessage(); } catch (Exception $e) { $message = $e->getFile() . " " . $e->getLine() . " " . $e->getMessage() . ' ' . $method; Log::error($message); $response['message'] = $e->getMessage(); } return $response; } public function productList($reselivaPropertyId) { $response = ['status' => false, 'message' => '']; try { $userId = Config::get('app.channelManager.reseliva.userId'); $userPSW = Config::get('app.channelManager.reseliva.userPassword'); $requestParam = new \SimpleXMLElement(''); $Authentication = $requestParam->addChild('Authentication'); $Authentication->addChild('UserID', $userId); $Authentication->addChild('UserPSW', $userPSW); $Authentication->addChild('PropertyID', $reselivaPropertyId); $xmlPayload = $requestParam->asXML(); $request = $this->requestPost('product_list', $xmlPayload); if (!$request['status']) { throw new ApiErrorException($request['message']); } $responseData = []; $responseData['hotelId'] = $request['data']['@attributes']['hotel_id']; $roomType = singleElementXMLArray($request['data']['RoomType']); foreach ($roomType as $room) { $responseData['rooms'][$room['@attributes']['id']] = [ 'id' => $room['@attributes']['id'], 'name' => $room['@attributes']['name'], ]; $room['RatePlan'] = singleElementXMLArray($room['RatePlan']); foreach ($room['RatePlan'] as $rate) { $responseData['rooms'][$room['@attributes']['id']]['rate'][$rate['@attributes']['id']] = [ 'id' => $rate['@attributes']['id'], 'name' => htmlspecialchars_decode($rate['@attributes']['name']), ]; } } $response = [ 'status' => true, 'data' => $responseData ]; } 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(); } return $response; } public function inventoryRoomRateUpdate($xmlPayload) { $response = ['status' => false, 'message' => '']; try { $request = $this->requestPost('inventory', $xmlPayload); if (!$request['status']) { throw new ApiErrorException($request['message']); } if (!isset($request['data']['success'])) { $request['data']['error']['erroritem'] = singleElementXMLArray($request['data']['error']['erroritem']); $errorsCollect = collect($request['data']['error']['erroritem']); throw new ApiErrorException($request['data']['error']['@attributes']['msg'] . '. Errors: ' . implode(', ', $errorsCollect->pluck('@attributes.desc')->toArray())); } $response = [ 'status' => true, 'data' => [ 'confirmId' => $request['data']['rqid'] ] ]; } 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(); } return $response; } /** Pattern Functions */ public function availabilityUpdateRequestMultiParam($propertyId, $params) { $idList = []; $userId = Config::get('app.channelManager.reseliva.userId'); $userPSW = Config::get('app.channelManager.reseliva.userPassword'); $requestParam = new \SimpleXMLElement(''); $Authentication = $requestParam->addChild('Authentication'); $Authentication->addChild('UserID', $userId); $Authentication->addChild('UserPSW', $userPSW); $Authentication->addChild('PropertyID', $propertyId); $inventory = $requestParam->addChild('inventory'); foreach ($params as $updateDate => $rooms) { //foreach $day = $inventory->addChild('day'); $date = $day->addChild('date'); $date->addAttribute('from', $updateDate); $date->addAttribute('to', $updateDate); $roomTypes = $day->addChild('roomtypes'); foreach ($rooms as $roomId => $value) { //foreach $roomType = $roomTypes->addChild('roomtype'); $roomType->addAttribute('reseliva_id', $roomId); $roomType->addAttribute('availability', fillOnUndefined($value, 'availability', 0)); $roomType->addAttribute('stopsale', fillOnUndefined($value, 'stop_sell', 0)); $idList = array_merge($idList, $value['idList']); } } return [ 'idList' => $idList, 'xmlPayload' => $requestParam->asXML() ]; } public function roomAvailabilityPush($propertyId, $bulkQueueData) { $response = ['status' => false, 'message' => '']; $channelManagerPropertyMappingCriteria = [ 'criteria' => [ ['field' => 'status', 'condition' => '=', 'value' => 1], ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId], ['field' => 'channel_manager_id', 'condition' => '=', 'value' => $this->channelManagerId], ['field' => 'channel_manager_property_id', 'condition' => '!=', 'value' => null], ], 'with' => ['channelManagerRoomRate.propertyRoomRateMapping'], 'firstRow' => true, 'orderBy' => [ ['field' => 'id', 'value' => 'ASC'] ] ]; $channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria); $channelManagerPushedIds = []; $channelManagerNoneMappingIds = []; $channelManagerPushConfirmCode = []; if ($channelManagerPropertyMapping['status'] == 'success' && !empty($channelManagerPropertyMapping['data'])) { $channelManagerPropertyMapping = $channelManagerPropertyMapping['data']; $channelManagerPropertyRoomRateMappingCollect = collect($channelManagerPropertyMapping['channel_manager_room_rate']); $roomAvailabilityQueueForUpdate = []; $roomAvailabilityQueueForUpdateIdList = []; $roomAvailabilityQueue = $bulkQueueData; foreach ($roomAvailabilityQueue as $roomAvailability) { //Dates less than today cannot be updated. if (Carbon::parse($roomAvailability['date'])->lessThan(Carbon::now()->toDateString())) { //$logMessage $mailParams = [ 'title' => $this->channelManagerName . ' - RoomAvailabilityPushService Error - Previous Date Problem', 'logMessage' => '
' . print_r($roomAvailability, true) . '
' ]; //$this->mailer->onQueue('logMail', new LogMail($mailParams)); //$logMessage $channelManagerPushedIds[] = $roomAvailability['id']; continue; } $channelManagerRoomRate = $channelManagerPropertyRoomRateMappingCollect->where('property_room_rate_mapping.room_id', $roomAvailability['property_room_id'])->first(); if (empty($channelManagerRoomRate)) { //None Mapping! //$channelManagerPushedIds[] = $roomAvailability['id']; $channelManagerNoneMappingIds[] = $roomAvailability['id']; continue; } $roomAvailabilityQueueForUpdateIdList [$channelManagerPropertyMapping['channel_manager_property_id']] [$roomAvailability['date']][] = $roomAvailability['id']; $roomAvailabilityQueueForUpdate [$channelManagerPropertyMapping['channel_manager_property_id']] [$roomAvailability['date']] [$channelManagerRoomRate['channel_manager_room_id']] = [ 'id' => $roomAvailability['id'], 'idList' => $roomAvailabilityQueueForUpdateIdList[$channelManagerPropertyMapping['channel_manager_property_id']][$roomAvailability['date']], 'date' => $roomAvailability['date'], 'availability' => $roomAvailability['availability'], 'stop_sell' => $roomAvailability['stop_sell'], ]; } foreach ($roomAvailabilityQueueForUpdate as $channelManagerPropertyId => $channelManagerProperty) { try { ksort($channelManagerProperty); $roomAvailabilityUpdateRequestMultiParam = $this->availabilityUpdateRequestMultiParam($channelManagerPropertyId, $channelManagerProperty); $request = $this->inventoryRoomRateUpdate($roomAvailabilityUpdateRequestMultiParam['xmlPayload']); if ($request['status']) { $channelManagerPushedIds = array_merge($channelManagerPushedIds, $roomAvailabilityUpdateRequestMultiParam['idList']); $channelManagerPushConfirmCode[] = $request['data']['confirmId']; } else { //$logMessage $mailParams = [ 'title' => $this->channelManagerName . ' - RoomAvailabilityPushService Error - InventoryRoomRateAvailabilityUpdate Error', 'logMessage' => '
' . print_r(array_merge($request, $channelManagerProperty), true) . '
' ]; $this->mailer->onQueue('logMail', new LogMail($mailParams)); //$logMessage throw new ApiErrorException($request['message']); } } catch (ApiErrorException $e) { $message = $this->channelManagerName . ' - ' . $e->getFile() . " " . $e->getLine() . " " . implode(', ', $e->getMessageArr()); Log::error($message); //$response['message'] = $this->channelManagerName . ' - ' . implode(', ', $e->getMessageArr()); } catch (Exception $e) { $message = $this->channelManagerName . ' - ' . $e->getFile() . " " . $e->getLine() . " " . $e->getMessage(); Log::error($message); //$response['message'] = $e->getMessage(); } } } else { $channelManagerNoneMappingIds = collect($bulkQueueData)->pluck('id')->toArray(); } $channelManagerPushedIds = array_unique($channelManagerPushedIds); asort($channelManagerPushedIds); $channelManagerPushedIds = array_values($channelManagerPushedIds); $response = [ 'status' => true, 'data' => [ 'confirmCode' => $channelManagerPushConfirmCode, 'channelManagerPushedIds' => $channelManagerPushedIds, 'channelManagerNoneMappingIds' => $channelManagerNoneMappingIds ] ]; return $response; } public function roomRateUpdateRequestMultiParam($propertyId, $params) { $idList = []; $userId = Config::get('app.channelManager.reseliva.userId'); $userPSW = Config::get('app.channelManager.reseliva.userPassword'); $requestParam = new \SimpleXMLElement(''); $Authentication = $requestParam->addChild('Authentication'); $Authentication->addChild('UserID', $userId); $Authentication->addChild('UserPSW', $userPSW); $Authentication->addChild('PropertyID', $propertyId); $inventory = $requestParam->addChild('inventory'); foreach ($params as $updateDate => $rooms) { //foreach $day = $inventory->addChild('day'); $date = $day->addChild('date'); $date->addAttribute('from', $updateDate); $date->addAttribute('to', $updateDate); $roomTypes = $day->addChild('roomtypes'); foreach ($rooms as $roomId => $rates) { //foreach $roomType = $roomTypes->addChild('roomtype'); $roomType->addAttribute('reseliva_id', $roomId); //$roomType->addAttribute('stopsale', fillOnUndefined($value, 'stop_sell')); foreach ($rates as $rateId => $value) { //foreach $ratePlan = $roomType->addChild('RatePlan'); $ratePlan->addAttribute('reseliva_id', $rateId); $rate = $ratePlan->addChild('Rate'); $rate->addAttribute('price1', floatval($value['amount'])); $restrictions = $ratePlan->addChild('Restrictions'); $restrictions->addAttribute('closed', fillOnUndefined($value, 'stop_sell', 0)); if (isset($value['min_stay']) && !in_array($value['min_stay'], [0])) { $restrictions->addAttribute('minLOS', fillOnUndefined($value, 'min_stay', 1)); } $idList = array_merge($idList, $value['idList']); } } } return [ 'idList' => $idList, 'xmlPayload' => $requestParam->asXML() ]; } public function roomRatePricePush($propertyId, $bulkQueueData) { $response = ['status' => false, 'message' => '']; try { $channelManagerPropertyMappingCriteria = [ 'criteria' => [ ['field' => 'status', 'condition' => '=', 'value' => 1], ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId], ['field' => 'channel_manager_id', 'condition' => '=', 'value' => $this->channelManagerId], ['field' => 'channel_manager_property_id', 'condition' => '!=', 'value' => null], ], 'with' => ['channelManagerRoomRate.propertyRoomRateMapping'], 'firstRow' => true, 'orderBy' => [ ['field' => 'id', 'value' => 'ASC'] ] ]; $channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria); $channelManagerPushedIds = []; $channelManagerNoneMappingIds = []; $channelManagerPushConfirmCode = null; if ($channelManagerPropertyMapping['status'] == 'success' && !empty($channelManagerPropertyMapping['data'])) { $channelManagerPropertyMapping = $channelManagerPropertyMapping['data']; $channelManagerPropertyRoomRateMappingCollect = collect($channelManagerPropertyMapping['channel_manager_room_rate']); $roomRatePriceQueueForUpdate = []; $roomRatePriceQueueForUpdateIdList = []; $roomRatePriceQueue = $bulkQueueData; foreach ($roomRatePriceQueue as $roomRatePrice) { //Dates less than today cannot be updated. if (Carbon::parse($roomRatePrice['date'])->lessThan(Carbon::now()->toDateString())) { //$logMessage $mailParams = [ 'title' => $this->channelManagerName . ' - RoomAvailabilityPushService Error - Previous Date Problem', 'logMessage' => '
' . print_r($roomRatePrice, true) . '
' ]; //$this->mailer->onQueue('logMail', new LogMail($mailParams)); //$logMessage $channelManagerPushedIds[] = $roomRatePrice['id']; continue; } $channelManagerRoomRate = $channelManagerPropertyRoomRateMappingCollect->where('property_room_rate_mapping_id', $roomRatePrice['room_rate_mapping_id'])->first(); if (empty($channelManagerRoomRate)) { //None Mapping! //$channelManagerPushedIds[] = $roomAvailability['id']; $channelManagerNoneMappingIds[] = $roomRatePrice['id']; continue; } $roomRatePriceQueueForUpdateIdList [$channelManagerPropertyMapping['channel_manager_property_id']] [$roomRatePrice['date']][$channelManagerRoomRate['channel_manager_room_id']] [$channelManagerRoomRate['channel_manager_room_rate_id']][] = $roomRatePrice['id']; $roomRatePriceQueueForUpdate [$channelManagerPropertyMapping['channel_manager_property_id']] [$roomRatePrice['date']] [$channelManagerRoomRate['channel_manager_room_id']] [$channelManagerRoomRate['channel_manager_room_rate_id']] = [ 'id' => $roomRatePrice['id'], 'idList' => $roomRatePriceQueueForUpdateIdList[$channelManagerPropertyMapping['channel_manager_property_id']][$roomRatePrice['date']][$channelManagerRoomRate['channel_manager_room_id']][$channelManagerRoomRate['channel_manager_room_rate_id']], 'date' => $roomRatePrice['date'], 'amount' => $roomRatePrice['amount'], 'currency' => $roomRatePrice['currency'], 'stop_sell' => $roomRatePrice['stop_sell'], 'min_stay' => $roomRatePrice['min_stay'], ]; } foreach ($roomRatePriceQueueForUpdate as $channelManagerPropertyId => $channelManagerProperty) { if (empty($channelManagerProperty)) { throw new ApiErrorException('$channelManagerProperty is Empty!'); } ksort($channelManagerProperty); $roomRateUpdateRequestMultiParam = $this->roomRateUpdateRequestMultiParam($channelManagerPropertyId, $channelManagerProperty); $request = $this->inventoryRoomRateUpdate($roomRateUpdateRequestMultiParam['xmlPayload']); if ($request['status']) { $channelManagerPushedIds = array_merge($channelManagerPushedIds, $roomRateUpdateRequestMultiParam['idList']); $channelManagerPushConfirmCode = $request['data']['confirmId']; } else { //$logMessage $mailParams = [ 'title' => $this->channelManagerName . ' - RoomAvailabilityPushService Error - InventoryRoomRateUpdate Error', 'logMessage' => '
' . print_r($request, true) . '
' ]; $this->mailer->onQueue('logMail', new LogMail($mailParams)); //$logMessage throw new ApiErrorException($request['message']); } } } $channelManagerPushedIds = array_unique($channelManagerPushedIds); asort($channelManagerPushedIds); $channelManagerPushedIds = array_values($channelManagerPushedIds); $response = [ 'status' => true, 'data' => [ 'confirmCode' => $channelManagerPushConfirmCode, 'channelManagerPushedIds' => $channelManagerPushedIds, 'channelManagerNoneMappingIds' => $channelManagerNoneMappingIds ] ]; } catch (ApiErrorException $e) { $response['message'] = $this->channelManagerName . ' - ' . implode(', ', $e->getMessageArr()); } catch (Exception $e) { $message = $this->channelManagerName . ' - ' . $e->getFile() . " " . $e->getLine() . " " . $e->getMessage(); Log::error($message); $response['message'] = $e->getMessage(); } return $response; } public function reservationPullFormattedData($propertyId, $channelManagerPropertyId, $param) { $bookingParam = []; $response = ['status' => false, 'message' => '']; try { $isB2CBooking = false; //Check Channel Manager Mapping $channelManagerMappingCriteria = [ 'criteria' => [ ['field' => 'status', 'condition' => '=', 'value' => 1], ], 'with' => ['propertyChannelManager'], 'orderBy' => [ ['field' => 'id', 'value' => 'ASC'] ] ]; $channelManagerMappingData = $this->channelManagerMappingService->select($channelManagerMappingCriteria); $channelManagerMappingCollect = collect($channelManagerMappingData['data']); $channelManagerMapping = $channelManagerMappingCollect->where('channel_manager_channel_id', $param['otaname'])->first(); //Eğer kanala ait bir otel yok ise devam et if (empty($channelManagerMapping)) { //TODO: hata dönecek //throw new ApiErrorException($request['message']); } //Check Channel Manager Mapping //Check Channel Manager Property Mapping $channelManagerPropertyMappingCriteria = [ 'criteria' => [ ['field' => 'status', 'condition' => '=', 'value' => 1], ['field' => 'channel_manager_id', 'condition' => '=', 'value' => $this->channelManagerId], ['field' => 'property_id', 'condition' => '=', 'value' => $propertyId], ], 'with' => ['channelManagerRoomRate.propertyRoomRateMapping'], 'firstRow' => true ]; $channelManagerPropertyMapping = $this->channelManagerPropertyMappingService->select($channelManagerPropertyMappingCriteria); //Eğer kanala ait bir otel yok ise devam et if ($channelManagerPropertyMapping['status'] != 'success' || empty($channelManagerPropertyMapping['data'])) { ///TODO: hata dönecek /// throw new ApiErrorException($request['message']); } $channelManagerRoomRateCollect = collect($channelManagerPropertyMapping['data']['channel_manager_room_rate']); if (empty(fillOnUndefined($param, 'reservno_ota'))) { $param['reservno_ota'] = null; } $roomRequest = []; foreach ($param['room'] as $room) { $roomRequest[] = [ 'adults' => $room['totalpax'], 'children' => $room['totalchd'], 'age' => [] ]; } $paymentTypeCode = 'HTL'; $paymentSourceCode = null; if (isset($param['cc_token']) && !empty($param['cc_token'])) { $paymentTypeCode = 'CRD'; if (empty($param['prepaid'])) { $paymentSourceCode = 'GST'; } if (!empty($param['prepaid'])) { $paymentSourceCode = 'OTA'; } } //Booking $bookingParam['booking'] = [ 'id' => null, 'booking_code' => null, 'property_id' => $propertyId, 'channel_manager_id' => $this->channelManagerId, 'channel_id' => $channelManagerMapping['property_channel_id'], 'channel_booking_code' => fillOnUndefined($param, 'reservno_ota'), 'search_key' => $param['reservno'], 'checkin_date' => $param['checkinFormatted'], 'checkout_date' => $param['checkoutFormatted'], 'rooms' => json_encode($roomRequest), 'payment_type_code' => $paymentTypeCode, 'room_amount' => $param['paymenttotal'], 'addon_amount' => 0, 'discount_amount' => 0, 'total' => $param['paymenttotal'], 'currency_code' => $param['paymentcurr'], 'channel_token' => null, 'booking_engine_token' => null, 'reservation_time' => $param['restimeUnixFormatted'], 'status' => $param['status'] == 'A' ? 1 : 0 ]; $extraParamBookingContact = []; //Booking Contact $bookingParam['contact'] = [ 'name' => $param['firstname'], 'surname' => !empty($param['lastname']) ? $param['lastname'] : null, 'phone_code' => null, 'phone_number' => fillOnUndefined($param, 'tel'), 'email' => fillOnUndefined($param, 'email'), 'country_code' => fillOnUndefined($param, 'country'), 'note' => !empty($param['note']) ? $param['note'] : null, 'language_code' => fillOnUndefined($param, 'language', 'en'), 'extra_param' => !empty($extraParamBookingContact) ? json_encode($extraParamBookingContact) : null, 'status' => 1 ]; $bookingParam['contact']['language_code'] = mb_substr($bookingParam['contact']['language_code'], 0, 2); $bookingParam['contact']['country_code'] = mb_strtolower($bookingParam['contact']['country_code']); //Booking Room $param['room'] = array_values($param['room']); foreach ($param['room'] as $roomOrder => $room) { //Check Room Rate Mapping $channelManagerRoomRate = $channelManagerRoomRateCollect->where('channel_manager_room_id', $room['roomid'])->where('channel_manager_room_rate_id', $room['rateid'])->first(); if (empty($channelManagerRoomRate)) { $channelManagerRoomRate = $channelManagerRoomRateCollect->where('channel_manager_room_id', $room['roomid'])->first(); } $dailyAmount = []; if (isset($room['price_breakdown']) && !empty($room['price_breakdown'])) { foreach ($room['price_breakdown'] as $roomAmount) { if (isset($roomAmount['@attributes'])) { $dailyAmount[] = [ 'date' => Carbon::parse($roomAmount['@attributes']['date'])->toDateString(), 'amount' => floatval($roomAmount['@attributes']['price']), 'currency_code' => $param['paymentcurr'] ]; } } } $extraParamRoom = []; $bookingParam['room'][] = [ 'room_order_number' => ($roomOrder + 1), 'occupancy_code' => str_repeat('A', $room['totalpax']) . str_repeat('C', $room['totalchd']), 'checkin_date' => $param['checkinFormatted'], //$room['checkin'], 'checkout_date' => $param['checkoutFormatted'],//$room['checkout'], 'rate_key' => null, 'rate_key_code' => null, 'availability_id' => 1, 'availability_code' => 'ROM', 'room_id' => $channelManagerRoomRate['property_room_rate_mapping']['room_id'], 'room_name' => !empty($room['roomtype']) ? html_entity_decode($room['roomtype']) : null, 'room_rate_mapping_id' => $channelManagerRoomRate['property_room_rate_mapping']['id'], 'room_rate_name' => !empty($room['ratename']) ? html_entity_decode($room['ratename']) : null, 'cancellation_policy' => null, 'payment_type_code' => $paymentTypeCode, 'daily_amount' => !empty($dailyAmount) ? json_encode($dailyAmount) : null, 'extra_param' => !empty($extraParamRoom) ? json_encode($extraParamRoom) : null, 'rate_detail' => json_encode($room), 'total' => $room['total_amount'], 'currency_code' => $param['paymentcurr'], 'status' => $param['status'] == 'A' ? 1 : 0 ]; if (!$isB2CBooking && (mb_strpos(html_entity_decode($room['ratename']), 'B2C') || mb_strpos(html_entity_decode($room['ratename']), 'OPAQUE')) ) { $isB2CBooking = true; } } //Booking Payment Data $bookingParam['payment'] = [ 'payment_code' => (isset($param['cc_token']) && !empty($param['cc_token'])) ? fillOnUndefined($param, 'cc_token') : null, 'payment_type_code' => $paymentTypeCode, 'payment_source_code' => $paymentSourceCode, 'extra_param' => json_encode($param), 'total' => $param['paymenttotal'], 'currency_code' => $param['paymentcurr'], 'status' => 2 ]; //Booking Channel Payment Data $bookingParam['payment_channel'] = null; if (isset($param['cc_token']) && !empty($param['cc_token'])) { $bookingParam['payment_channel'] = [ 'type' => 'ch', 'data' => md5($param['reservno'] . $channelManagerPropertyMapping['data']['channel_manager_property_id'] . $param['cc_token']) ]; } //Channel Manager ETC Params $bookingParam['channel_manager'] = [ 'property_id' => $channelManagerPropertyId, 'booking_id' => $param['reservno'], 'sub_channel' => $param['otaname'], 'sub_channel_booking_id' => $param['reservno_ota'], 'sub_channel_source' => $param['source'], ]; $statusType = null; if ($param['status'] == 'A') { $statusType = 'createBooking'; } elseif ($param['status'] == 'C') { $statusType = 'cancelBooking'; } elseif ($param['status'] == 'M') { $statusType = 'modifiedBooking'; } //362: Barın Hotel, 34: Hotelbeds if (in_array($propertyId, [362]) && in_array($bookingParam['booking']['channel_id'], [34])) { if($isB2CBooking) { //312: Hotelbeds B2C $bookingParam['booking']['channel_id'] = 312; } } //$statusType = 'modifiedBooking'; $response['status'] = true; $response['type'] = $statusType; $response['data'] = $bookingParam; } catch (ApiErrorException $e) { $response['message'] = $this->channelManagerName . ' - ' . implode(', ', $e->getMessageArr()); } catch (Exception $e) { $message = $this->channelManagerName . ' - ' . $e->getFile() . " " . $e->getLine() . " " . $e->getMessage(); Log::error($message); $response['message'] = $e->getMessage(); } return $response; } public function reservationListParam($channelManagerPropertyId) { $userId = Config::get('app.channelManager.reseliva.userId'); $userPSW = Config::get('app.channelManager.reseliva.userPassword'); $requestParam = new \SimpleXMLElement(''); $Authentication = $requestParam->addChild('Authentication'); $Authentication->addChild('UserID', $userId); $Authentication->addChild('UserPSW', $userPSW); $Authentication->addChild('PropertyID', $channelManagerPropertyId); $requestParam->addChild('include_price_breakdown', 1); return $requestParam->asXML(); } public function reservationList($xmlPayload) { $response = ['status' => false, 'message' => '']; try { $request = $this->requestPost('reservation_list', $xmlPayload); if (!$request['status']) { throw new ApiErrorException($request['message']); } $responseData = []; $reservationList = isset($request['data']['reservation']) ? singleElementXMLArray($request['data']['reservation']) : []; foreach ($reservationList as $reservation) { if(Carbon::parse($reservation['checkin'])->toDateString() < Carbon::now()->toDateString() && $reservation['status'] == 'A') { continue; } $reservation['paymenttype'] = empty($reservation['paymenttype']) ? null : $reservation['paymenttype']; $responseData[$reservation['reservno']] = [ 'reservno' => $reservation['reservno'], 'firstname' => $reservation['firstname'], 'lastname' => $reservation['lastname'], 'email' => !empty($reservation['email']) ? $reservation['email'] : null, 'tel' => !empty($reservation['tel']) ? $reservation['tel'] : null, 'status' => $reservation['status'], 'statusText' => fillOnUndefined($this->statusMapping, $reservation['status']), 'resdate' => $reservation['resdate'], 'restime' => $reservation['restime'], 'restimeUnixFormatted' => Carbon::parse($reservation['restime'],'UTC')->timestamp, 'resdateFormatted' => Carbon::parse($reservation['resdate'])->toDateString(), 'checkin' => $reservation['checkin'], 'checkinFormatted' => Carbon::parse($reservation['checkin'])->toDateString(), 'checkout' => $reservation['checkout'], 'checkoutFormatted' => Carbon::parse($reservation['checkout'])->toDateString(), 'nation' => !empty($reservation['nation']) ? $reservation['nation'] : null, 'paymentcurr' => $reservation['paymentcurr'], 'paymenttotal' => $reservation['paymenttotal'], 'source' => $reservation['source'], 'otaname' => $reservation['otaname'], 'reservno_ota' => $reservation['reservno_ota'], 'prepaid' => $reservation['prepaid'], 'paymenttype' => $reservation['paymenttype'], 'paymentTypeText' => fillOnUndefined($this->paymentTypeMapping, $reservation['paymenttype']), 'restotalpax' => $reservation['restotalpax'], 'restotalchd' => $reservation['restotalchd'], 'note' => $reservation['note'], 'cc_token' => fillOnUndefined($reservation, 'cc_token'), ]; $roomList = singleElementXMLArray($reservation['rooms']['room']); foreach ($roomList as $room) { $room['rateid'] = !empty($room['rateid']) ? $room['rateid'] : null; $room['ratename'] = !empty($room['ratename']) ? $room['ratename'] : null; $room['price_breakdown'] = !empty($room['price_breakdown']) && isset($room['price_breakdown']['day']) ? singleElementXMLArray($room['price_breakdown']['day']) : null; $responseData[$reservation['reservno']]['room'][] = $room; } } $response = [ 'status' => true, 'data' => $responseData ]; } 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(); } return $response; } public function reservationConfirmParam($propertyId, $channelManagerBookingId, $bookingCode, $param = []) { $userId = Config::get('app.channelManager.reseliva.userId'); $userPSW = Config::get('app.channelManager.reseliva.userPassword'); $requestParam = new \SimpleXMLElement(''); $Authentication = $requestParam->addChild('Authentication'); $Authentication->addChild('UserID', $userId); $Authentication->addChild('UserPSW', $userPSW); $Authentication->addChild('PropertyID', $propertyId); $reservations = $requestParam->addChild('reservations'); $reservation = $reservations->addChild('reservation'); $reservation->addAttribute('reseliva_id', $channelManagerBookingId); $reservation->addAttribute('pms_id', $bookingCode); return $requestParam->asXML(); } public function reservationConfirm($xmlPayload) { $response = ['status' => false, 'message' => '']; try { $request = $this->requestPost('reservation_confirm', $xmlPayload); if (!$request['status']) { throw new ApiErrorException($request['message']); } if (!isset($request['data']['success'])) { $request['data']['error']['erroritem'] = singleElementXMLArray($request['data']['error']['erroritem']); $errorsCollect = collect($request['data']['error']['erroritem']); throw new ApiErrorException($request['data']['error']['@attributes']['msg'] . '. Errors: ' . implode(', ', $errorsCollect->pluck('@attributes.desc')->toArray())); } $response = [ 'status' => true, ]; } 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(); } return $response; } public function requestPostReservationPushParam($propertyId, $bookingId, $type, $param = []) { $bookingDetail = $param['booking_detail']; $type = $this->typeMapping[$type]; $serviceRequestName = 'BookingRetrieval'; $xmlResponse = new \SimpleXMLElement('<' . $serviceRequestName . 'RS>'); if (in_array($bookingDetail['status'], [0, 3])) { $Bookings = $xmlResponse->addChild('Bookings'); $Booking = $Bookings->addChild('Booking'); if (Carbon::createFromTimestamp($param['booking_detail']['created_at'])->lessThan(Carbon::parse('2022-04-01'))) { $Booking->addAttribute('id', $bookingDetail['id']); } else { $Booking->addAttribute('id', $bookingDetail['booking_code']); } $Booking->addAttribute('type', 'Cancel'); $Booking->addAttribute('cancelDateTime', Carbon::createFromTimestamp($bookingDetail['updated_at'])->toISOString()); $Hotel = $Booking->addChild('Hotel'); $Hotel->addAttribute('id', $bookingDetail['property_id']); foreach ($bookingDetail['booking_room'] as $room) { $RoomStay = $Booking->addChild('RoomStay'); $RoomStay->addAttribute('roomTypeID', $room['room_id']); $RoomStay->addAttribute('ratePlanID', $room['room_rate_mapping_id']); $StayDate = $RoomStay->addChild('StayDate'); $StayDate->addAttribute('arrival', $room['checkin_date']); $StayDate->addAttribute('departure', $room['checkout_date']); } } else { $Bookings = $xmlResponse->addChild('Bookings'); $Booking = $Bookings->addChild('Booking'); if (Carbon::createFromTimestamp($param['booking_detail']['created_at'])->lessThan(Carbon::parse('2022-04-01'))) { $Booking->addAttribute('id', $bookingDetail['id']); } else { $Booking->addAttribute('id', $bookingDetail['booking_code']); } //Book ve Modify Aynı olacak, Cancel if ($type == 'Book') { $Booking->addAttribute('type', 'Book'); $Booking->addAttribute('createDateTime', Carbon::createFromTimestamp($bookingDetail['created_at'])->toISOString()); } if ($type == 'Modify') { $Booking->addAttribute('type', 'Modify'); $Booking->addAttribute('modifyDateTime', Carbon::createFromTimestamp($bookingDetail['updated_at'])->toISOString()); } $Hotel = $Booking->addChild('Hotel'); $Hotel->addAttribute('id', $bookingDetail['property_id']); foreach ($bookingDetail['booking_room'] as $room) { $RoomStay = $Booking->addChild('RoomStay'); $RoomStay->addAttribute('roomTypeID', $room['room_id']); $RoomStay->addAttribute('ratePlanID', $room['room_rate_mapping_id']); $StayDate = $RoomStay->addChild('StayDate'); $StayDate->addAttribute('arrival', $room['checkin_date']); $StayDate->addAttribute('departure', $room['checkout_date']); $roomPaxCollect = collect($room['room_pax']); $GuestCount = $RoomStay->addChild('GuestCount'); $GuestCount->addAttribute('adult', $roomPaxCollect->where('type', 'ADT')->count()); $GuestCount->addAttribute('child', $roomPaxCollect->where('type', 'CHD')->count()); if($roomPaxCollect->where('type', 'CHD')->count() > 0) { $roomPaxChild = $roomPaxCollect->where('type', 'CHD')->toArray(); foreach ($roomPaxChild as $child) { $Child = $GuestCount->addChild('Child'); $Child->addAttribute('age',Carbon::now()->diffInYears(Carbon::parse($child['birth_date'])->toDateString())); } } $diffInDays = Carbon::parse($room['checkin_date'])->diffInDays(Carbon::parse($room['checkout_date'])); //dd($room['total'], $diffInDays, $room); $PerDayRates = $RoomStay->addChild('PerDayRates'); $PerDayRates->addAttribute('currency', $room['currency_code']); $baseRateDaily = moneyDoubleFormatDecimal($room['total'] / $diffInDays); $currentDate = $room['checkin_date']; for ($i = 0; $i < $diffInDays; $i++) { $PerDayRate = $PerDayRates->addChild('PerDayRate'); $PerDayRate->addAttribute('stayDate', $currentDate); $PerDayRate->addAttribute('baseRate', $baseRateDaily); $PerDayRate->addAttribute('hotelServiceFees', 0); $currentDate = Carbon::parse($currentDate)->addDay()->toDateString(); } $Total = $RoomStay->addChild('Total'); $Total->addAttribute('amountAfterTaxes', $room['total']); $Total->addAttribute('amountOfTaxes', 0); $Total->addAttribute('currency', $room['currency_code']); $roomNotes['cancellationPolicy'] = 'Cancellation Policy: Refundable'; $cancellationPolicy = json_decode($room['cancellation_policy'], 1); if (!empty($cancellationPolicy) && is_array($cancellationPolicy)) { if (isset($cancellationPolicy['isNonRefundable']) && $cancellationPolicy['isNonRefundable']) { $roomNotes['cancellationPolicy'] = 'Cancellation Policy: NonRefundable'; } } $roomNotes['payment'] = 'Payment: ' . $bookingDetail['booking_payment_type']['name']; $RoomStay->addChild('RoomNotes', implode('. ', $roomNotes)); } $PrimaryGuest = $Booking->addChild('PrimaryGuest'); $Name = $PrimaryGuest->addChild('Name'); $Name->addAttribute('givenName', $bookingDetail['booking_contact']['name']); $Name->addAttribute('surname', $bookingDetail['booking_contact']['surname']); $Phone = $PrimaryGuest->addChild('Phone'); $Phone->addAttribute('countryCode', $bookingDetail['booking_contact']['phone_code']); //$Phone->addAttribute('cityAreaCode'); $Phone->addAttribute('number', $bookingDetail['booking_contact']['phone_number']); $PrimaryGuest->addChild('Email', $bookingDetail['booking_contact']['email']); if(fillOnUndefined($bookingDetail['booking_contact'],'language_code')) { $Booking->addChild('CountryCode', $bookingDetail['booking_contact']['language_code']); } $Total = $Booking->addChild('Total'); $Total->addAttribute('amountAfterTaxes', $bookingDetail['total']); $Total->addAttribute('amountOfTaxes', 0); $Total->addAttribute('currency', $bookingDetail['currency_code']); $Booking->addChild('SpecialRequest'); $Booking->addChild('BookingNotes', htmlspecialchars($bookingDetail['booking_contact']['note'])); } return $xmlResponse->asXML(); } public function requestPostReservationPush($xmlPayload) { $response = ['status' => false, 'message' => '']; //U : uExtranetWork //P : ExtrntWrk21!*22 try { $this->restClient = new Client(['http_errors' => false]); $res = $this->restClient->post($this->reservationPushUrl, [ 'headers' => [ 'Content-Type' => 'text/xml; charset=UTF8', 'Authorization' => 'Basic dUV4dHJhbmV0V29yazpFeHRybnRXcmsyMSEqMjI=', 'Accept' => 'text/xml' ], 'body' => $xmlPayload, ] ); $getResponseBody = $res->getBody(); $getResponseXmlBase = $getResponseBody->getContents(); $getResponseXml = new \SimpleXMLElement($getResponseXmlBase, LIBXML_NOCDATA); $getResponse = json_decode(json_encode($getResponseXml), 1); if ($getResponse['Status'] != 'success') { throw new ApiErrorException('requestPostReservationPush Error channelManagerName: ' . $this->channelManagerName); } $response = ['status' => true, 'message' => '', 'response' => $getResponseXmlBase]; } 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(); } return $response; } }