Files
ExtraNetwork e5c4b6aa13 first commit
2026-05-12 17:04:54 +03:00

1237 lines
52 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Core\Service\ChannelManager;
use App\Core\Mail\LogMail;
use App\Core\Service\ChannelManagerMappingService;
use App\Core\Service\ChannelManagerPropertyMappingService;
use App\Exceptions\ApiErrorException;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Exception;
class Reseliva
{
private $statusMapping;
private $paymentTypeMapping;
private $channelManagerId;
private $channelManagerName;
private $mailer;
public function __construct(
Client $restClient,
Mailer $mailer,
ChannelManagerPropertyMappingService $channelManagerPropertyMappingService,
ChannelManagerMappingService $channelManagerMappingService
)
{
$this->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('<?xml version="1.0" encoding="UTF-8"?><request></request>');
$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('<?xml version="1.0" encoding="UTF-8"?><request></request>');
$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' => '<pre>' . print_r($roomAvailability, true) . '</pre>'
];
//$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' => '<pre>' . print_r(array_merge($request, $channelManagerProperty), true) . '</pre>'
];
$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('<?xml version="1.0" encoding="UTF-8"?><request></request>');
$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' => '<pre>' . print_r($roomRatePrice, true) . '</pre>'
];
//$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' => '<pre>' . print_r($request, true) . '</pre>'
];
$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('<?xml version="1.0" encoding="UTF-8"?><request></request>');
$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('<?xml version="1.0" encoding="UTF-8"?><request></request>');
$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('<?xml version="1.0" encoding="UTF-8"?><' . $serviceRequestName . 'RS></' . $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;
}
}