25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

1075 satır
53 KiB

  1. <?php
  2. namespace backend\modules\hotel\controllers;
  3. use backend\common\Utils;
  4. use backend\modules\hotel\models\CommonOrder;
  5. use backend\modules\hotel\models\CtripOrder;
  6. use backend\modules\hotel\models\CtripRoomInfo;
  7. use backend\modules\hotel\models\HotelRelation;
  8. use backend\modules\hotel\models\OperaHotelRoom;
  9. use backend\modules\hotel\models\OrderChannelInfo;
  10. use backend\modules\hotel\models\OrderMain;
  11. use backend\modules\hotel\models\RoomRelation;
  12. use backend\modules\hotel\models\RunHotelDistrib;
  13. use backend\modules\hotel\models\SoapService;
  14. use common\components\zOfficeWechat;
  15. use Yii;
  16. use yii\base\Module;
  17. use yii\filters\AccessControl;
  18. use yii\helpers\Json;
  19. class CtripController extends HotelController
  20. {
  21. public $enableCsrfValidation = false;
  22. public $startTime = 0;
  23. public $ctripUser;
  24. public $data = [];
  25. public $post = [];
  26. /**
  27. * CtripController constructor.
  28. * @param string $id
  29. * @param Module $module
  30. * @param array $config
  31. */
  32. public function __construct($id, $module, array $config = [])
  33. {
  34. $this->startTime = microtime(TRUE);
  35. libxml_disable_entity_loader(false);
  36. $this->ctripUser = Yii::$app->params['ctrip'];
  37. parent::__construct($id, $module, $config);
  38. }
  39. public function behaviors()
  40. {
  41. return [
  42. 'access' => [
  43. 'class' => AccessControl::className(),
  44. 'except' => ['set-room-price', 'set-room-info', 'update-room-quantity'],
  45. 'rules' => [
  46. [
  47. 'ips' => ['103.48.141.164', '210.13.114.57','114.80.1.*','140.207.218.*','114.80.10.*','140.206.211.*','103.48.141.160','210.13.114.32','45.251.106.192',
  48. '221.130.190.129','101.226.248.*','140.207.228.*' //携程IP访问白名单
  49. , '127.0.0.1', '106.14.56.77', '180.168.4.58', '139.224.30.29' //蜘蛛IP访问白名单
  50. , '116.236.255.166',
  51. '222.65.108.254' //纳格兰临时允许访问,网络环境地址:张江炬芯研发大厦A栋215
  52. ],
  53. 'allow' => true,
  54. ],
  55. ],/*'rules' => [
  56. [
  57. 'ips' => ['101.226.248.76', '101.226.248.77', '101.226.248.78', '101.226.248.79', '140.207.228.76',
  58. '140.207.228.77', '140.207.228.78', '140.207.228.79', '103.48.141.164', '210.13.114.57', '114.80.10.1',
  59. '140.207.218.145', '221.130.190.129','101.226.248.*','140.207.228.*' //携程IP访问白名单
  60. , '127.0.0.1', '106.14.56.77', '180.168.4.58', '139.224.30.29' //蜘蛛IP访问白名单
  61. , '116.236.255.166',
  62. ],
  63. 'allow' => true,
  64. ],
  65. ],*/
  66. ],
  67. ];
  68. }
  69. public function actions()
  70. {
  71. return [
  72. 'service' => [
  73. 'class' => 'subdee\soapserver\SoapAction',
  74. 'serviceVar' => 'WSDL'
  75. // 'serviceUrl' => 'http://cs1.yiireal.com/hotel/ctrip/service?WSDL' 请求示例
  76. ],
  77. ];
  78. }
  79. protected function actionSoap($data_xml, $request_name)
  80. {
  81. $client = Yii::$app->soapClient;
  82. $param = Utils::xml_encode($data_xml, $request_name);
  83. $this->data = $data_xml;
  84. $res = $client->AdapterRequest(['requestXml' => $param]);
  85. return $res->AdapterRequestResult;
  86. }
  87. /**
  88. * User: wangxj
  89. *
  90. * soap 对外接口
  91. *
  92. * @param string $xml
  93. * @param string $Invoketype
  94. *
  95. * @return string
  96. *
  97. * @soap
  98. */
  99. public function Invoke($xml, $Invoketype)
  100. {
  101. $this->writeLog($Invoketype, $xml);
  102. $request = Utils::xml_to_array($xml); //将xml转化成数组
  103. // if($request[''])
  104. $head = $request['HeaderInfo'];
  105. $user = $head['Authentication']['@attributes'];
  106. $soap = Yii::$app->params['ctrip']['soap'];
  107. if ($user['UserName'] == $soap['UserName'] && $user['Password'] == $soap['Password']) {
  108. // $action = $head['RequestType']['@attributes']['Name'];
  109. $body = $request[$Invoketype . 'Request'];
  110. $data['Message'] = '操作成功';
  111. $data['ResultCode'] = 0;
  112. //携程!!!,这个接口大小写不规则,单独处理
  113. $res = $this->$Invoketype($body);
  114. if ($Invoketype == "DomesticCheckRoomAvail") { //可定检查最有最外层的ResultCode,内层没有ReturnCode
  115. $data = $res;
  116. } else {
  117. $data['ResultCode'] = isset($res['ReturnCode']) ? $res['ReturnCode'] : $data['ResultCode'];
  118. $data['Message'] = isset($res['ReturnDescript']) ? $res['ReturnDescript'] : $data['Message'];
  119. if ($Invoketype == 'DomesticCancelHotelOrder') {
  120. $data['DomesticCancelhotelOrderResponse'] = $res;
  121. } else {
  122. $data[$Invoketype . 'Response'] = $res;
  123. }
  124. }
  125. } else {
  126. $data = [
  127. 'Message' => '用户认证或授权错误(程序错误) ',
  128. 'ResultCode' => CtripOrder::RETURN_CODE_AUTH_FAIL,
  129. ];
  130. }
  131. $data = Utils::data_to_xml($data);
  132. $data = Utils::formatResult($data);
  133. $this->writeLog($Invoketype, $data);
  134. return new \SoapVar($data, XSD_STRING);
  135. }
  136. /**
  137. * User:Steven
  138. *
  139. * Desc:DomesticCheckRoomAvail (可定检查)
  140. * 1.接口调用方:携程
  141. * 2.接口返回方:合作方
  142. * 3.调用频率:订单量的10倍以上
  143. * 4.使用说明:携程在给酒店下订单前,调用合作方接口。通过传入客人入住信息,得 到该房型是否可订。该接口响应时间(含网络)需要在3秒以内
  144. * @param array $body
  145. * @return mixed
  146. */
  147. protected function DomesticCheckRoomAvail($body)
  148. {
  149. // $a='{"Hotel":"4386248","Arrival":"2018-07-12T00:00:00","Departure":"2018-07-13T00:00:00","Room":"145386478","RoomNumber":"1","Person":"1","BalanceType":"PP","RoomPrices":{"RoomPrice":{"EffectDate":"2018-07-12T00:00:00","Price":"729","CNYPrice":"0","Cost":"655.4","CNYCost":"0","BreakFast":"0"}},"Currency":"RMB","IsCompensate":"F","TraceLogID":"ChenckAfterOrder_6733588561","OperationType":"New","CheckAvailID":"0","CheckAvailType":"Query"}';
  150. // $body=json_decode($a,true);
  151. $this->writeLog('DomesticCheckRoomAvail', \GuzzleHttp\json_encode($body));
  152. $trip = new CtripOrder(['scenario' => 'check-room-avail']);
  153. if (!$trip->load_valid($body, '') || !$trip->validate()) {
  154. $roomInfo_arr['RequestResponse']['RequestResult'] = array();
  155. $RequestResult['Message'] = '接受失败!缺少必要参数!';
  156. $RequestResult['ResultCode'] = CtripOrder::RETURN_CODE_CHCEK_CANNOT_ANALYZE;
  157. $RequestResult['DomesticCheckRoomAvailResponse'] = [
  158. "IsBookable" => 0,
  159. "ReturnDescript" => CtripOrder::RETURN_CODE_CHCEK_CANNOT_ANALYZE . ":返回无法解析",
  160. ];
  161. $arr = array(
  162. "agentid" => 1000002,
  163. "title" => '【报警】可定检查:',
  164. "msg" => "[{$RequestResult['ResultCode']}]" . $RequestResult['Message'] . "\n" . "请尽快联系技术,核实渠道上接口参数是否正确",
  165. "touser" => $this->_developerList,
  166. );
  167. zOfficeWechat::sendMsg($arr);
  168. return $RequestResult;
  169. }
  170. $res_arr = $trip->CheckRoomAvail();
  171. $roomInfo_arr['RequestResponse']['RequestResult'] = array();
  172. $RequestResult = $roomInfo_arr['RequestResponse']['RequestResult'];
  173. $RequestResult['Message'] = '接受成功!';
  174. $RequestResult['ResultCode'] = 0;
  175. $availInfo['IsBookable'] = isset($res_arr['isBookable']) && $res_arr['isBookable'] === false ? 0 : 1;
  176. $total_price = '';
  177. $date_list = Utils::createDateRangeArray($body['Arrival'], $body['Departure']);
  178. //$roomData = isset($body['RoomPrices']['RoomPrice']['EffectDate']) ? $body['RoomPrices'] : $body['RoomPrices']['RoomPrice'];
  179. $IsBookable = 1; //初始化可订
  180. $ReturnDescript = "";
  181. $ReturnCode = 0;
  182. foreach ($date_list as $value) {
  183. if (empty($res_arr)) {
  184. $IsBookable = 0;
  185. $ReturnCode = CtripOrder::RETURN_CODE_CHCEK_NO_ROOM_STATUS;
  186. $ReturnDescript = '房型信息不存在';
  187. } else {
  188. foreach ($res_arr as $item) {
  189. if (date('Y-m-d', strtotime($value)) == $item['RUN_DATE']) {
  190. if ($item['AUTHORITY_STATUS'] != 1 || $item['IS_ONSALE'] != 1 || $item['CANCEL_FLAG_B'] != 0 || $item['CANCEL_FLAG_C'] != 0 || $item['RUN_STATUS'] == 329) {
  191. //不可订
  192. $availInfo['IsBookable'] = 0;
  193. $ReturnCode = CtripOrder::RETURN_CODE_CHCEK_STOCK_FAIL;
  194. $item['AUTHORITY_STATUS'] != 1 ? $availInfo['ReturnDescript'] = '未授权!' : ($item['IS_ONSALE'] != 1 ? $availInfo['ReturnDescript'] = '已下线' : ($item['RUN_STATUS'] == 329 ? $availInfo['ReturnDescript'] = ' 关房' : ''));
  195. } else {
  196. //*****(重要)注意:携程要求不做库存的校验,即如果库存大于0,那么就返回可订,同时返回可用房量,如果等于0,即不可订
  197. if ($body['IsHoldRoom'] == 'R') { //保留房
  198. if ($item['REMAINING_COUNT'] > 0 && ($item['buyout'] + $item['retain'] + $item['inquiry']) > 0) {
  199. $availInfo['IsBookable'] = 1;
  200. } else {
  201. $IsBookable = 0;//不可定
  202. $ReturnCode = CtripOrder::RETURN_CODE_CHCEK_STOCK_LESS;
  203. $ReturnDescript = $item['REMAINING_COUNT'] <= 0 ? '保留房库存不足!' : '基础房型库存不足!';
  204. }
  205. /* if ($item['REMAINING_COUNT'] < $body['RoomNumber']) {
  206. $availInfo['IsBookable'] = 0;//不可定
  207. $availInfo['ReturnDescript'] = '保留房库存不足!'; //错误描述:
  208. } else {
  209. if ($body['RoomNumber'] > ($item['buyout'] + $item['retain'])) {
  210. $availInfo['IsBookable'] = 0;
  211. $availInfo['ReturnDescript'] = '基础房型库存不足!'; //错误描述:
  212. } else {
  213. $availInfo['IsBookable'] = 1;
  214. }
  215. }*/
  216. } else { //非保留房
  217. if ($item['OVERSELL_FLAG'] == 1) { //开启超卖
  218. if (($item['buyout'] + $item['retain'] + $item['inquiry']) > 0) {
  219. $availInfo['IsBookable'] = 1;
  220. } else {
  221. $IsBookable = 0;//不可定
  222. $ReturnCode = CtripOrder::RETURN_CODE_CHCEK_STOCK_LESS;
  223. $ReturnDescript = '基础房型库存不足!(预订非保留)';
  224. }
  225. } else { //限量售卖
  226. if ($item['REMAINING_COUNT'] > 0 && ($item['buyout'] + $item['retain'] + $item['inquiry']) > 0) {
  227. $availInfo['IsBookable'] = 1;
  228. } else {
  229. $IsBookable = 0;//不可定
  230. $ReturnCode = CtripOrder::RETURN_CODE_CHCEK_STOCK_LESS;
  231. $ReturnDescript = '库存不足!(预订非保留)';
  232. }
  233. }
  234. /*if ($item['OVERSELL_FLAG'] == 1 || $item['REMAINING_COUNT'] >= $body['RoomNumber']) {
  235. if ($body['RoomNumber'] > ($item['buyout'] + $item['retain'] + $item['inquiry'])) {
  236. $availInfo['IsBookable'] = 0;
  237. $availInfo['ReturnDescript'] = '基础房型库存不足!(预订非保留)'; //错误描述:
  238. } else {
  239. //在渠道房量充足的情况下,判断基础房型的房量是否充足
  240. $availInfo['IsBookable'] = 1;
  241. }
  242. } else {
  243. $availInfo['IsBookable'] = 0;
  244. $availInfo['ReturnDescript'] = '限量售卖,库存不足'; //错误描述:
  245. }*/
  246. }
  247. }
  248. $total_price += $body['RoomNumber'] * $item['PROD_PRICE'];
  249. $roomPrice['RoomPrice'] = array();
  250. $roomPrice['RoomPrice']['EffectDate'] = $item['RUN_DATE'] . 'T00:00:00';
  251. $roomPrice['RoomPrice']['Cost'] = $item['PROD_PRICE']; //取分销价
  252. $roomPrice['RoomPrice']['CNYCost'] = $item['PROD_PRICE'];
  253. $roomPrice['RoomPrice']['BreakFast'] = $item['BREAKFAST_INCLUDE'];
  254. $availInfo['RoomPrices'][] = $roomPrice;
  255. $AvailRoomQuantity['AvailRoomQuantity']['EffectDate'] = $item['RUN_DATE'] . 'T00:00:00';
  256. $AvailRoomQuantity['AvailRoomQuantity']['AvailQuantity'] = $item['OVERSELL_FLAG'] == 1 ? 99 : $item['REMAINING_COUNT'];
  257. $availInfo['AvailRoomQuantitys'][] = $AvailRoomQuantity;
  258. }
  259. }
  260. }
  261. }
  262. $availInfo['IsBookable'] = $IsBookable;
  263. $availInfo['ReturnDescript'] = $ReturnDescript;
  264. if ($availInfo['IsBookable'] == 0) {
  265. $opera_hotel_room = new OperaHotelRoom();
  266. $res = $opera_hotel_room->getHotelRoomInfo($body['Room']);
  267. $user = $this->_developerList . "|" . $res[0]['USER_NAME'] . '|yangxt';
  268. $msg = '酒店名称:' . $res[0]['HOTEL_NAME'] . "\n房型名称:" . $res[0]['ROOM_NAME'] . "\n内部标示:" . $res[0]['INNER_IDENTIFY'] . "\n开始日期:" . $body['Arrival'] . "\n结束日期:" . $body['Departure'] . "\n携程房型ID:" . $res[0]['ChannelRoomId'] . "\n原因:" . $availInfo['ReturnDescript'];
  269. $arr = array(
  270. "agentid" => 1000002,
  271. "title" => '可定检查失败:',
  272. "msg" => $msg,
  273. "touser" => $user,
  274. );
  275. zOfficeWechat::sendMsg($arr);
  276. }
  277. $availInfo['Currency'] = 'RMB';
  278. $availInfo['Room'] = $body['Room'];
  279. $availInfo['InterFaceAmount'] = $total_price;//接口订单金额
  280. $availInfos["DomesticCheckRoomAvailResponse"] = $availInfo;
  281. $availInfos["ResultCode"] = $ReturnCode;
  282. $availInfos['Message'] = $ReturnDescript;
  283. return $availInfos;
  284. }
  285. /**
  286. * User:Steven
  287. *
  288. * Desc: DomesticSubmitNewHotelOrder (新订订单)
  289. * 1-1.接口调用方:携程/合作方
  290. * 1-2.接口返回方:合作方/携程
  291. * 1-3.调用频率:频繁
  292. * 1-4.使用说明:通过该接口,提交订单给对方系统
  293. * $user_id,$hotel_id,$room_type,$org_id,$org_num,$room_list,$cus_list,$checkin_time,$if_cancel,$benefit,$total_commission,$order_id
  294. *
  295. * @param array $body
  296. *
  297. * param $OrderID integer 订单号 订单号 Y
  298. * param $InterFaceSendID integer 订单接口发送号 同一订单每次发送编号会不同,接收方需落 地保存 Y
  299. * param $Hotel integer Ctrip 酒店编号 酒店编号 Y
  300. * param $HotelName string 酒店名 酒店名 Y
  301. * param $Arrival string 入住日期 入住日期 Y
  302. * param $Departure string 离店日期 离店日期 Y
  303. * param $EarlyArrivalTime string 最早到店时间 最早到店时间 Y
  304. * param $LastArrivalTime string 最晚到店时间 最晚到店时间 Y
  305. * param $Person INT 实际入住人数 实际入住人数 Y
  306. * param $Notice string 备注 备注 N
  307. * param $IsHoldRoom string 是否保留房 是否保留房(F 或空-否,R-是) N
  308. * param $IsFlashLive string 是否闪住订单 是否闪住(F 或空-否,T-是) N
  309. * param $Guests object 用户集合  $GuestEntity array 单个用户 FirstName LastName ChinesName Y
  310. * param $mobilePhone integer 手机号 Ctrip 客服号码 Y
  311. * param $Currency string 币种 币种 N
  312. * param $Amount float 订单卖价总金额 订单卖价总金额(预付一般不传或传 0) Y
  313. * param $CNYAmount float 订单卖价总金额(人民 币) 订单卖价总金额(人民币),现付一般不传或 者传 0 Y
  314. * param $GuaranteeType string 担保方式 担保方式 Y
  315. * param $BalanceType string 价格类型 支付方式(PP 预付,FG 现付,PKG 包价) Y
  316. * param $Room integer Ctrip 房型编号 房型编号(供应商需要转成自己的对应编号) Y
  317. * param $RoomPerson INT 房型最大入住人数 房型最大入住人数 Y
  318. * param $RoomName string 房型名称 房型名称 Y
  319. * param $Quantity INT 预订间数 预订间数 Y
  320. * param $CostAmount float 订单底价总金额(原币 种) 订单底价金额(原币种),现付一般不传或者 传 0 Y
  321. * param $CNYCostAmount float 订单底价总金额(人民 币) 订单底价金额(人民币),现付一般不传或者 传 0
  322. * param $RoomPrices object RoomPrice<> EffectDate Price 卖价 CNYPrice 订单卖价金额(原币种) Cost 底价 CNYCost 订单底价金额(原币种) BreakFast 早餐数量 ,预付一般不传或者 传 0 Y
  323. * param $AddOptionals array 附加服务   N
  324. * param $InterFaceConfirmNo integer 酒店确认号 酒店确认号 Y
  325. * param $HotelConfirmNo integer 供应商确认号 供应商确认号 Y
  326. * param $InterFaceAmount INT 接口订单金额 接口订单金额,现付产品卖价,预付产品底价 Y
  327. * param $ReturnCode INT 错误代码 错误代码 Y
  328. * param $ReturnDescript string 返回描述 返回描述 Y
  329. * param $OrderStatus INT 订单状态 订单状态(1:待确认;2:失败;3:确认;4:拒绝) Y
  330. * param $FGToPP string 是否现转预订单 是否现转预订单(T:是,F:否) Y
  331. * param $DepositAmount float 押金 默认值 0 Y
  332. * param $IsFreeSale string 是否 FreeSale F 或空-否,T-是 N
  333. * @return mixed
  334. *
  335. * @throws \yii\db\Exception
  336. */
  337. protected function DomesticSubmitNewHotelOrder($body)
  338. {
  339. $trip = new CtripOrder(['scenario' => 'new-order']);
  340. if ($trip->load($body, '') && $trip->validate()) {
  341. $res = $trip->makeOrder();
  342. if ($res == CtripOrder::RETURN_CODE_SUCCESS) {
  343. //保存发送号
  344. $interFace = new OrderChannelInfo();
  345. $interFace->ORDER_ID = $trip->Spider_order_id;
  346. $interFace->InterFaceSendID = $trip->InterFaceSendID;
  347. //先置旧的数据cancel_flag为1
  348. OrderChannelInfo::updateAll(['CANCEL_FLAG' => 1], ['ORDER_ID' => $trip->Spider_order_id]);
  349. $interFace->save();
  350. //需要修改订单的来源类型为对接
  351. //如果是保留房,直接是已确认,返回状态3:已确认
  352. if ($trip->IsHoldRoom == 'R') {
  353. $channel_status = CtripOrder::ORDER_STATUS_ACCEPT;
  354. $orderStatus = 3;
  355. $commonOrder = new CommonOrder();
  356. $commonOrder->setOrderLog($trip->Spider_order_id, $trip->Spider_parent_room_type, $trip->Spider_room_type, "该订单为保留房订单,系统自动接单", Yii::$app->params['ctrip']['base_user_id'], $trip->Spider_hotel);
  357. } else {
  358. $channel_status = CtripOrder::ORDER_STATUS_WAITING;
  359. $orderStatus = 1;
  360. }
  361. $data = [
  362. 'OrderStatus' => $orderStatus,
  363. 'InterFaceConfirmNO' => '',
  364. 'HotelConfirmNo' => $trip->Spider_order_id,
  365. 'InterFaceAmount' => $trip->CNYCostAmount,
  366. 'ReturnCode' => CtripOrder::RETURN_CODE_SUCCESS,
  367. 'ReturnDescript' => '预订成功',
  368. ];
  369. OrderMain::updateAll(['DOCKING_TYPE' => CtripOrder::ORDER_DOCKING_TYPE, 'CHANNEL_ORDER_STATUS' => $channel_status, 'IF_LAST_PROD' => $trip->IF_LAST_PROD, 'UPDATE_TIME' => date('Y-m-d H:i:s', time())],
  370. ['and', ['CANCEL_FLAG' => 0], ['or', ['ORDER_ID' => $trip->Spider_order_id], ['PARENT_ORDER_ID' => $trip->Spider_order_id]]]);
  371. } else {
  372. if ($res == CtripOrder::RETURN_CODE_PROGRAM_FAIL) {
  373. $ctrip_status = 2;
  374. } else {
  375. $ctrip_status = 4;
  376. }
  377. $data = [
  378. 'OrderStatus' => $ctrip_status,
  379. 'InterFaceConfirmNO' => '',
  380. 'HotelConfirmNo' => '',
  381. 'InterFaceAmount' => $trip->CNYCostAmount,
  382. 'ReturnCode' => $res,
  383. 'ReturnDescript' => CtripOrder::RETURN_MSG[$res],
  384. ];
  385. }
  386. } else {
  387. $code = Utils::getModelError($trip);
  388. $data = [
  389. 'OrderStatus' => 4,
  390. 'InterFaceConfirmNO' => '',
  391. 'HotelConfirmNo' => '',
  392. 'InterFaceAmount' => $trip->CNYCostAmount,
  393. 'ReturnCode' => $code,
  394. 'ReturnDescript' => CtripOrder::RETURN_MSG[$code],
  395. ];
  396. }
  397. //OrderStatus==2的情况会走ebk,不在需要人工搬单 为4的情况会直接拒单
  398. if ($data['OrderStatus'] == 2 || $data['OrderStatus'] == 4) {
  399. $msg = $data['OrderStatus'] == 2 ? "订单预定失败,失败原因:{$data['ReturnDescript']},订单已进入携程ebooking,请关注!"
  400. : "订单预定失败,失败原因:{$data['ReturnDescript']},订单已被拒绝,请核实该订单相关房态!";
  401. $msg .= '订单号:' . $trip->OrderID;
  402. $this->sendAliMsgToRtx('【携程直连】新订订单失败:', $msg, 4, self::AGENT_COMMON_HOTEL_ID);
  403. }
  404. //新订单进来,都推送一次房态和数量
  405. $this->post['hotel_id'] = $trip->Spider_hotel;
  406. $this->post['parent_room_type'] = $trip->Spider_parent_room_type;
  407. $this->post['room_type'] = $trip->Spider_room_type;
  408. $this->post['StartDate'] = substr($trip->Arrival, 0, 10);
  409. $this->post['EndDate'] = substr($trip->Departure, 0, 10);
  410. /*$this->actionSetRoomInfo();
  411. $this->actionUpdateRoomQuantity();*/
  412. return $data;
  413. }
  414. /**
  415. * Author:Steven
  416. * User:wangxj
  417. *
  418. * Desc: DomesticCancelHotelOrder (取消订单)
  419. * 1-1.接口调用方:携程/合作方
  420. * 1-2.接口返回方:合作方/携程
  421. * 1-3.调用频率:频繁
  422. * 1-4.使用说明:通过该接口,提交订单给对方系统
  423. *
  424. * @param array $body
  425. * @return array
  426. * @throws \Exception
  427. * @throws \yii\db\Exception
  428. */
  429. protected function DomesticCancelHotelOrder($body)
  430. {
  431. $trip = new CtripOrder(['scenario' => 'cancel-order']);
  432. $trip->load($body, '');
  433. $trip->saveLog($this->ctripUser['base_user_id'], "渠道商申请取消订单:" . $trip->Spider_order_id);
  434. $res = $trip->applyCancel();
  435. if ($res == CtripOrder::RETURN_CODE_SUCCESS) {
  436. //保存发送号
  437. $interFace = new OrderChannelInfo();
  438. $interFace->ORDER_ID = $trip->Spider_order_id;
  439. $interFace->InterFaceSendID = $trip->InterFaceSendID;
  440. //先置旧的数据cancel_flag为1
  441. OrderChannelInfo::updateAll(['CANCEL_FLAG' => 1], ['ORDER_ID' => $trip->Spider_order_id]);
  442. $interFace->save();
  443. $data = [
  444. 'OrderStatus' => 3,
  445. 'OrderID' => $trip->OrderID,
  446. 'InterFaceConfirmNO' => $trip->InterFaceConfirmNO,
  447. 'ReturnCode' => $res,
  448. 'ReturnDescript' => '同意取消',
  449. ];
  450. // $trip->saveLog(2, '同意渠道取消订单');
  451. //取消成功通知客服
  452. /*if (in_array($res['data']->ORDER_STATUS, [OrderMain::ORDER_STATUS_WAITING_CONFIRM, OrderMain::ORDER_STATUS_CONFIRMED])) {
  453. $dict_type = DictType::findOne($res['data']->ORDER_STATUS);
  454. if ($dict_type !== null) {
  455. $extra = '(' . $dict_type->TYPE_NAME . ')';
  456. } else
  457. $extra = '(未知订单状态)';
  458. } else {
  459. $extra = '';
  460. }*/
  461. /*$arr = array(
  462. "agentid" => 1000002,
  463. "title" => '取消订单:',
  464. "msg" => '携程取消订单:' . $trip->Spider_order_id,
  465. "touser" => $this->_messageList,
  466. );
  467. zOfficeWechat::sendMsg($arr);*/
  468. } else {
  469. //渠道接单状态变为取消被拒
  470. $data = [
  471. 'OrderStatus' => 4,
  472. 'OrderID' => $trip->OrderID,
  473. 'InterFaceConfirmNO' => $trip->InterFaceConfirmNO,
  474. 'ReturnCode' => $res,
  475. 'ReturnDescript' => CtripOrder::RETURN_MSG[$res],
  476. ];
  477. }
  478. $notice = $res == CtripOrder::RETURN_CODE_SUCCESS ? "同意取消订单" : "拒绝取消订单";
  479. $this->sendAliMsgToRtx('【携程直连】携程申请取消订单:', "携程申请取消订单【" . $trip->Spider_order_id . "】," . $notice, 4, self::AGENT_COMMON_HOTEL_ID);
  480. return $data;
  481. }
  482. /**
  483. * User:Steven
  484. * Desc:DomesticGetOrderStatus(订单状态查询)
  485. * @param array $body
  486. *
  487. * @return mixed
  488. */
  489. protected function DomesticGetOrderStatus($body)
  490. {
  491. $trip = new CtripOrder(['scenario' => 'order-status']);
  492. $rs['Message'] = '';
  493. $rs['ResultCode'] = 0;
  494. foreach ($body['Orders'] as $item) {
  495. $trip->load($item, '');
  496. $res = $trip->getOrderStatus();
  497. $data['OrderID'] = $item['OrderID'];
  498. $data['InterFaceSendID'] = $item['InterFaceSendID'];
  499. $data['ReturnDescript'] = '接收成功';
  500. if (!$res) //1:待确认 2:订单未发送到合作方或返回代码 为失败 3 :合作方确认订单 4:合作方拒绝订单
  501. {
  502. $rs['Message'] = "未查到订单号为{$item['OrderID']}的订单信息!";
  503. $order['Orders'] = array();
  504. $rs['ResultCode'] = 9999;
  505. } else {
  506. switch ($res['CHANNEL_ORDER_STATUS']) { //OrderStatus新订只能传1待确认、3确认、4拒绝
  507. case 550: //待处理
  508. $OrderStatus = 1;
  509. break;
  510. case 551: //已接单
  511. $OrderStatus = 3;
  512. break;
  513. case 552: //已拒绝
  514. $OrderStatus = 4;
  515. break;
  516. }
  517. $dt = [
  518. 'OrderStatus' => $OrderStatus,
  519. 'HotelConfirmNo' => $res['ORDER_ID'],
  520. 'ReturnCode' => 0,
  521. ];
  522. $data['OrderEntity'] = $dt;
  523. $order['Orders'][] = $data;
  524. }
  525. }
  526. return $order;
  527. }
  528. /**
  529. * User:Steven
  530. *
  531. * Desc:SetRoomPrice(设置房型价格)
  532. * 1.接口调用方:合作方
  533. * 2.接口返回方:携程
  534. * 3.调用频率:不限制,建议不大于50万次/分钟(QPS<1万)
  535. * 4.使用说明:携程建议当价格变化时,立即进行推送。携程方面是异步处理价格。
  536. * param $begin_date string
  537. * param $end_date string
  538. * param $hotel_id string
  539. * param $base_room_id string
  540. * param $room_id string
  541. * @return mixed
  542. */
  543. public function actionSetRoomPrice(array $param = [])
  544. {
  545. $this->post = ($this->post == []) ? Yii::$app->request->post() : $this->post;
  546. if (!empty($param)) {
  547. $this->post = $param;
  548. }
  549. $post = $this->post;
  550. $post['StartDate'] = empty($post['StartDate']) ? date('Y-m-d') : $post['StartDate'];
  551. $post['EndDate'] = empty($post['EndDate']) ? date('Y-m-d', strtotime('+90 days')) : $post['EndDate'];
  552. //至少提供90天的数据,一次最多推送120天的房价房态数据,超过120天数据需要分批推送
  553. $PriceInfos = array();
  554. //获取酒店房价数据
  555. $runHotelDsitrib = new RunHotelDistrib();
  556. $res = $runHotelDsitrib->getRoomPrice($post);
  557. $HRInfo = OperaHotelRoom::find()->select(['a.ROOM_NAME', 'b.HOTEL_NAME'])->joinWith('operaHotel b')
  558. ->from('opera_hotel_room a')
  559. ->where(['a.HOTEL_ID' => $post['hotel_id'], 'a.BASE_ROOM_TYPE' => $post['parent_room_type'], 'a.ROOM_TYPE' => $post['room_type']]);
  560. if ($res['code'] != 0) {
  561. if ($res['code'] == 1 || $res['code'] == 3) {
  562. $arr = array(
  563. "agentid" => 1000002,
  564. "title" => $res['info'],
  565. "msg" => '酒店名称:' . $HRInfo['HOTEL_NAME'] . "\n" . '房型名称:' . $HRInfo['ROOM_NAME'] . '开始日期:' . $post['StartDate'] . "\n" . '结束日期:' . $post['EndDate'],
  566. "touser" => $this->_developerList,
  567. );
  568. zOfficeWechat::sendMsg($arr);
  569. }
  570. return false;
  571. }
  572. $dayZone = $this->dateGroup($res['data']);
  573. if (isset($dayZone['code'])) {
  574. //警报:推送RTX
  575. $arr = array(
  576. "agentid" => 1000002,
  577. "title" => '(报警)设置房型价格接口:',
  578. "msg" => '酒店名称:' . $HRInfo['HOTEL_NAME'] . "\n" . '房型名称:' . $HRInfo['ROOM_NAME'] . '开始日期:' . $post['StartDate'] . "\n" . '结束日期:' . $post['EndDate'],
  579. "touser" => $this->_developerList,
  580. );
  581. zOfficeWechat::sendMsg($arr);
  582. return false;
  583. }
  584. $rs = '';
  585. //将分段后的时间分别推送房价格
  586. $ctrip_room_id = RoomRelation::getChannelId($res['data'][0]['ROOM_ID'], Yii::$app->params['ctrip']['relation_supplier_id']); //携程的房型ID
  587. $ctrip_hotel_id = HotelRelation::getChannelId($post['hotel_id'], Yii::$app->params['ctrip']['relation_supplier_id']); //携程的房型ID
  588. foreach ($dayZone as $value) {
  589. foreach ($res['data'] as $key => $item) {
  590. if ($item['RUN_DATE'] >= $value['StartDate'] && $item['RUN_DATE'] <= $value['EndDate']) {
  591. $Prices['Price'] = array(
  592. 'AmountBeforeTaxFee' => $item['PROD_PRICE'], //税前
  593. 'AmountAfterTaxFee' => $item['PROD_PRICE'], //税后
  594. 'CostAmountBeforeTaxFee' => $item['PROD_PRICE'],//税前成本(底价)
  595. 'CostAmountAfterTaxFee' => $item['PROD_PRICE'], //税后成本
  596. 'Day' => '1' //连住天数,暂不用,默认为1
  597. );
  598. //PriceInfo节点代表一天的价格,每天的价格可以不同
  599. $PriceInfo['PriceInfo'] = array(
  600. 'Prices' => $Prices,
  601. 'Stays' => 1, //连住,暂不用,默认为1
  602. 'BlanceType' => Yii::$app->params['ctrip']['balance_type'], //支付类型
  603. 'PriceType' => Yii::$app->params['ctrip']['price_type'], //价格类型
  604. 'Breakfast' => $item['BREAKFAST_INCLUDE'], //早餐
  605. 'Applicability' => '111111' //适用人群
  606. );
  607. $PriceInfos['PriceInfos'][] = $PriceInfo;
  608. unset($res['data'][$key]);
  609. }
  610. }
  611. //根据日期范围生成多天的 SetRoomPriceItem(目前我们系统的业务逻辑是:每次只能录入单个房型多天的价格)
  612. $SetRoomPriceItem['SetRoomPriceItem'] = array(
  613. 'PriceInfos' => $PriceInfos['PriceInfos'],
  614. 'RoomID' => $ctrip_room_id,
  615. 'StartDate' => $value['StartDate'] . 'T00:00:00',
  616. 'EndDate' => $value['EndDate'] . 'T00:00:00',
  617. 'Currency' => Yii::$app->params['ctrip']['currency_type'],
  618. );
  619. $RoomTypeList = array(
  620. 'SetRoomPriceItems' => $SetRoomPriceItem,
  621. 'HotelID' => $ctrip_hotel_id, //Ctrip的酒店编号
  622. 'Submitor' => YII::$app->params['ctrip']['submitor'], //提交人,集团名拼音
  623. 'Title' => '房价推送成功',
  624. 'Priority' => 'N' //是否优先处理,暂不用,默认为N
  625. );
  626. $soap = new SoapService($RoomTypeList, 'SetRoomPrice', 'SetAdaperRoomPriceRequest', '1.2');
  627. $rs = $soap->exec(3, $post['user_id']);
  628. unset($PriceInfos['PriceInfos']);
  629. if (!$rs['flag'] || $rs['data']['RequestResult']['RequestResult'] != 0) {
  630. //警报:RTX通知
  631. $arr = array(
  632. "agentid" => 1000002,
  633. "title" => '(报警)房价推送失败:',
  634. "msg" => json_encode($post),
  635. "touser" => $this->_developerList,
  636. );
  637. zOfficeWechat::sendMsg($arr);
  638. }
  639. }
  640. return Json::encode($rs);
  641. }
  642. /**
  643. * User:Steven
  644. * Desc:将日期按照连续不连续进行分组
  645. * @param $data
  646. * @return array
  647. */
  648. public function dateGroup($data)
  649. {
  650. //将房态按时间分段
  651. $dayZone = [];
  652. $firstDay = '';
  653. $current = 0;
  654. foreach ($data as $key => $value) {
  655. if ($key == 0) {
  656. $dayZone[$current]['StartDate'] = $value['RUN_DATE'];
  657. $dayZone[$current]['EndDate'] = $value['RUN_DATE'];
  658. $firstDay = $value['RUN_DATE'];
  659. } else {
  660. $firstDay = strtotime($firstDay);
  661. $secondDay = strtotime($value['RUN_DATE']);
  662. $days = ($secondDay - $firstDay) / 86400;
  663. //用于判断当前日期与该组数据的StartDate差值是否是120,一次最多推送120天数据,大于120天分组推送
  664. $diff = ($firstDay - strtotime($dayZone[$current]['StartDate'])) / 86400 / 90;
  665. if ($days == 1 && !($diff > 0 && is_int($diff))) {
  666. $dayZone[$current]['EndDate'] = $value['RUN_DATE'];
  667. } elseif ($diff > 0 && is_int($diff)) {
  668. $current++;
  669. $dayZone[$current]['StartDate'] = $value['RUN_DATE'];
  670. $dayZone[$current]['EndDate'] = $value['RUN_DATE'];
  671. } elseif ($days < 1) {
  672. return ['code' => 0, 'msg' => '子房型数据重复'];
  673. } else {
  674. $current++;
  675. $dayZone[$current]['StartDate'] = $value['RUN_DATE'];
  676. $dayZone[$current]['EndDate'] = $value['RUN_DATE'];
  677. }
  678. $firstDay = $value['RUN_DATE'];
  679. }
  680. }
  681. return $dayZone;
  682. }
  683. /**
  684. * User:Steven
  685. *
  686. * Desc:UpdateRoomQuantity(更新保留房数量)
  687. * 1-1.接口调用方:合作方
  688. * 1-2.接口返回方:携程
  689. * 1-3.调用频率:限制, 建议10次/分钟,并会视情况调整
  690. * 1-4.使用说明:携程建议当房量变化时,立即进行推送。携程方面是异步处理房量更新操作。
  691. * 一个请求最多只允许更新 10 个酒店下的房型,一个请求只允许 120 天内的房量, 一个请求 只允许发送少于 100 个房型。
  692. *
  693. * param StartDate
  694. * param EndDate
  695. * param hotel_id
  696. * param parent_room_type
  697. * param room_type
  698. *
  699. * @return mixed
  700. *
  701. */
  702. public function actionUpdateRoomQuantity(array $param = [])
  703. {
  704. $this->post = ($this->post == []) ? Yii::$app->request->post() : $this->post;
  705. if (!empty($param))
  706. $this->post = $param;
  707. $post = $this->post;
  708. $runHotelDsitrib = new RunHotelDistrib();
  709. $roomQuantity = $runHotelDsitrib->getRoomQuantity($post);
  710. if ($roomQuantity['code'] != 0) {
  711. //警报:RTX通知
  712. if ($roomQuantity['code'] == 1 || $roomQuantity['code'] == 3) {
  713. $arr = array(
  714. "agentid" => 1000002,
  715. "title" => $roomQuantity['info'],
  716. "msg" => json_encode($post),
  717. "touser" => $this->_developerList,
  718. );
  719. zOfficeWechat::sendMsg($arr);
  720. }
  721. return false;
  722. }
  723. $RoomQuantityEntityList = array();
  724. $dateZone = $this->divisionDate($roomQuantity['data']);
  725. if (empty($roomQuantity['data']) || empty($dateZone)) {
  726. return false;
  727. }
  728. $push_rs = array();
  729. $ctrip_room_id = RoomRelation::getChannelId($roomQuantity['data'][0]['ROOM_ID'], Yii::$app->params['ctrip']['relation_supplier_id']); //携程的房型ID
  730. $ctrip_hotel_id = HotelRelation::getChannelId($post['hotel_id'], Yii::$app->params['ctrip']['relation_supplier_id']); //携程的房型ID
  731. foreach ($dateZone as $key => $val) {
  732. foreach ($roomQuantity['data'] as $k => $value) {
  733. if ($val['StartDate'] <= $value['RUN_DATE'] && $val['EndDate'] >= $value['RUN_DATE']) {
  734. if ($value['RUN_STATUS'] == 329 || $value['AUTHORITY_STATUS'] == 0 || $value['IS_ONSALE'] == 0 || $value['BASE_ROOM_IS_ONSALE'] == 0 || $value['BASE_ROOM_RUN_STATUS'] != 1) { //关房操作(如果没有临时保留房须推送0;关房的时候,需要同时推送保留房数量 为0)
  735. $RoomQuantityEntity['RoomQuantityEntity'] = array(
  736. 'RoomTypeID' => $ctrip_room_id, //Ctrip 房型编号
  737. 'RoomQuantityCount' => '0', //临时保留房数
  738. 'RoomQuantityUpdateType' => 'AvailableCount', //临时保留房数更 新方式
  739. 'StartDate' => $value['RUN_DATE'] . 'T00:00:00', //开始时间
  740. 'EndDate' => $value['RUN_DATE'] . 'T00:00:00',
  741. 'FreeSale' => 'F', //Free Sale 目前只支持以下 两种: T F
  742. 'ReserveTime' => Utils::timeHour($value['ReserveTime']), //保留房最晚预订 时间
  743. 'RoomStatus' => 'N', //保留房不可超 N,满房 NoRoom;G,良好 Good;L,不可超 Limited G表示开房,N表示关房,L表示保留房限量售卖
  744. 'Restorable' => 'F', //保留房可恢复 目前只支持以下 两种:T,F
  745. );
  746. } else {
  747. if ($value['OVERSELL_FLAG'] != 1) { // 1:允许超卖 0:不允许超卖
  748. if ($value['REMAINING_COUNT'] <= 0) { //限量售卖(不超卖)的情况下 且库存为0 直接推成关房
  749. $RoomStatus = 'N'; //G表示开房,N表示关房,L表示保留房限量售卖
  750. } else {
  751. $RoomStatus = 'L'; //G表示开房,N表示关房,L表示保留房限量售卖
  752. }
  753. } else {
  754. $RoomStatus = 'G';
  755. }
  756. $RoomQuantityEntity['RoomQuantityEntity'] = array(
  757. 'RoomTypeID' => $ctrip_room_id, //Ctrip 房型编号
  758. 'RoomQuantityCount' => $value['REMAINING_COUNT'] < 0 ? 0 : $value['REMAINING_COUNT'], //临时保留房数
  759. 'RoomQuantityUpdateType' => 'AvailableCount', //临时保留房数更 新方式
  760. 'StartDate' => $value['RUN_DATE'] . 'T00:00:00', //开始时间
  761. 'EndDate' => $value['RUN_DATE'] . 'T00:00:00',
  762. 'FreeSale' => 'F', //Free Sale 目前只支持以下 两种: T F
  763. 'ReserveTime' => Utils::timeHour($value['ReserveTime']), //保留房最晚预订 时间
  764. 'RoomStatus' => $RoomStatus, //保留房不可超 N,满房 NoRoom;G,良好 Good;L,不可超 Limited G表示开房,N表示关房,L表示保留房限量售卖
  765. 'Restorable' => 'F', //保留房可恢复 目前只支持以下 两种:T,F
  766. );
  767. }
  768. $RoomQuantityEntityList['room_info'][] = $RoomQuantityEntity;
  769. unset($roomQuantity['data'][$k]);
  770. }
  771. }
  772. if (empty($RoomQuantityEntityList['room_info'])) {
  773. continue;
  774. }
  775. //一个酒店
  776. $hotel_id['HotelID'] = $ctrip_hotel_id;
  777. $SequenceID = \Yii::$app->cache->get('Ctrip_SequenceID');
  778. if (!$SequenceID) {
  779. $rs = \Yii::$app->cache->set('Ctrip_SequenceID', time());
  780. if (!$rs) {
  781. $arr = array(
  782. "agentid" => 1000002,
  783. "title" => '保留房消息序号SequenceID写入缓存失败',
  784. "msg" => json_encode($post),
  785. "touser" => $this->_developerList,
  786. );
  787. zOfficeWechat::sendMsg($arr);
  788. return false;
  789. }
  790. $SequenceID = \Yii::$app->cache->get('Ctrip_SequenceID');
  791. }
  792. \Yii::$app->cache->set('Ctrip_SequenceID', $SequenceID + 1);
  793. $UpdateRoomQuantityRequest = array(
  794. 'SequenceID' => $SequenceID,
  795. 'HotelIDList' => array(
  796. 'HotelIDEntity' => $hotel_id,
  797. ),
  798. 'RoomQuantityEntityList' => $RoomQuantityEntityList['room_info'],
  799. 'Editer' => YII::$app->params['ctrip']['submitor'],
  800. );
  801. $soap = new SoapService($UpdateRoomQuantityRequest, 'UpdateRoomQuantity', 'UpdateRoomQuantityRequest', '1.2');
  802. $res = $soap->exec(2, $post['user_id']);
  803. if (!$res['flag'] || $res['data']['Response']['CtripSoapResponse']['ResultCode'] != 0) {
  804. $result['code'] = 1;
  805. $result['msg'] = urlencode('保留房数量推送失败!');
  806. $result['data'] = $res['data']['Response']; //将$begin_date, $end_date, $hotel_id, $base_room_id, $room_id信息拼接起来触发报警机制
  807. $arr = array(
  808. "agentid" => 1000002,
  809. "title" => '(报警)更新保留房数量接口:',
  810. "msg" => '保留房数量推送失败!' . "\n" . '错误信息:' . $res['data']['Response']['CtripSoapResponse']['Message'], //json_encode($post),
  811. "touser" => $this->_developerList,
  812. );
  813. zOfficeWechat::sendMsg($arr);
  814. }
  815. unset($RoomQuantityEntityList['room_info']);
  816. $push_rs[] = $res;
  817. }
  818. return json_encode($push_rs);
  819. }
  820. /**
  821. * User: wangxj
  822. *
  823. * 将时间分段进行推送,因为携程不允许中间日期不连续
  824. * param int $hotel_id
  825. * param int $parent_room_type
  826. * param int $room_type
  827. * param string $StartDate
  828. * param string $EndDate
  829. * @param
  830. *
  831. * @return string
  832. *
  833. */
  834. public function actionSetRoomInfo(array $param = [])
  835. {
  836. $this->post = ($this->post == []) ? Yii::$app->request->post() : $this->post;
  837. if (!empty($param))
  838. $this->post = $param;
  839. $post = $this->post;
  840. $room = OperaHotelRoom::findOne(['HOTEL_ID' => $post['hotel_id'], 'PARENT_ROOM_TYPE' => $post['parent_room_type'], 'ROOM_TYPE' => $post['room_type'], 'CANCEL_FLAG' => 0]);
  841. if ($room == null) {
  842. return json_encode(['code' => 1, 'msg' => '子房型获取失败酒店id: ' . $post['hotel_id'] . ', 子房型id:' . $post['room_type']]);
  843. }
  844. $stocks = RunHotelDistrib::find()
  845. ->select(['DISTINCT(RUN_DATE)', 'CREATE_USER_ID', 'CREATE_TIME', 'UPDATE_USER_ID', 'UPDATE_TIME', 'DISTRIB_ID', 'HOTEL_ID', 'BASE_ROOM_TYPE', 'ROOM_TYPE',
  846. 'REMAINING_COUNT', 'SALED_COUNT', 'PROD_PRICE', 'CUS_PRICE', 'RUN_STATUS', 'OVERSELL_FLAG', 'CONSUME_STOCK_TYPE'])
  847. ->where(['HOTEL_ID' => $post['hotel_id'], 'BASE_ROOM_TYPE' => $post['parent_room_type'], 'ROOM_TYPE' => $post['room_type'],
  848. 'DISTRIB_ID' => Yii::$app->params['ctrip']['supplier_id']])
  849. ->andFilterWhere(['between', 'RUN_DATE', $post['StartDate'], $post['EndDate']])
  850. ->orderBy('RUN_DATE')
  851. // -> createCommand() -> getRawSql();
  852. ->all();
  853. //将房态按时间分段
  854. $dayZone = [];
  855. $firstDay = '';
  856. $current = 0;
  857. foreach ($stocks as $key => $stock) {
  858. if ($key == 0) {
  859. $dayZone[$current]['StartDate'] = $stock['RUN_DATE'];
  860. $dayZone[$current]['EndDate'] = $stock['RUN_DATE'];
  861. $firstDay = $stock['RUN_DATE'];
  862. } else {
  863. $firstDay = strtotime($firstDay);
  864. $secondDay = strtotime($stock['RUN_DATE']);
  865. $days = ($secondDay - $firstDay) / 86400;
  866. $diff = ($firstDay - strtotime($dayZone[$current]['StartDate'])) / 86400 / 90;
  867. if ($days == 1 && !($diff > 0 && is_int($diff))) {
  868. $dayZone[$current]['EndDate'] = $stock['RUN_DATE'];
  869. } elseif ($diff > 0 && is_int($diff)) {
  870. $current++;
  871. $dayZone[$current]['StartDate'] = $stock['RUN_DATE'];
  872. $dayZone[$current]['EndDate'] = $stock['RUN_DATE'];
  873. } elseif ($days < 1) {
  874. return json_encode(['code' => 1, 'msg' => '子房型数据重复,酒店:' . $post['hotel_id'] . "\n基础房型id:" . $post['parent_room_type'] . "\n子房型id:" . $post['room_type'] . "\n房型日期:" . $stock['RUN_DATE']]);
  875. } else {
  876. $current++;
  877. $dayZone[$current]['StartDate'] = $stock['RUN_DATE'];
  878. $dayZone[$current]['EndDate'] = $stock['RUN_DATE'];
  879. }
  880. $firstDay = $stock['RUN_DATE'];
  881. }
  882. }
  883. $result = ['code' => 0];
  884. //将分段后的时间分别推送房态
  885. foreach ($dayZone as $item) {
  886. $res = $this->pushRoomInfo($room, $item['StartDate'], $item['EndDate']);
  887. if ($res['code'] != 0) {
  888. $result = $res;
  889. }
  890. }
  891. return Json::encode($result);
  892. }
  893. /**
  894. * User: wangxj
  895. *
  896. * 推送房态
  897. * @param OperaHotelRoom $room
  898. * @param string $StartDate
  899. * @param string $EndDate
  900. * @param
  901. *
  902. * @return array
  903. *
  904. */
  905. protected function pushRoomInfo($room, $StartDate, $EndDate)
  906. {
  907. $actionName = 'SetRoomInfo';
  908. $post = $this->post;
  909. $post['Spider_room'] = $room->ID;
  910. $post['StartDate'] = $StartDate;
  911. $post['EndDate'] = $EndDate;
  912. $model = new CtripRoomInfo();
  913. if ($model->load($post, '') && $model->validate()) {
  914. //将 CtripRoomInfo对象中的数据作为房态粒度进行推送
  915. $data_xml['StartDate'] = $model->StartDate . 'T00:00:00';
  916. $data_xml['EndDate'] = $model->EndDate . 'T00:00:00';
  917. $data_xml['RoomID'] = $model->RoomID;
  918. $data_xml['RoomInfoItems'] = $model->RoomInfoItems;
  919. $soap = new SoapService($data_xml, $actionName, $actionName . 'Request');
  920. $res = $soap->exec(3, $post['user_id']);
  921. if ($res['data']['RequestResult']['ResultCode'] == 0) {
  922. $result['code'] = 0;
  923. } else {
  924. $result['code'] = $res['data']['RequestResult']['ResultCode'];
  925. $result['msg'] = $res['data']['RequestResult']['Message'];
  926. }
  927. } else {
  928. $result['code'] = 1;
  929. $result['msg'] = Utils::getModelError($model);
  930. }
  931. return $result;
  932. }
  933. /**
  934. * User: wangxj
  935. *
  936. * 保存日志方便查询
  937. * @param string $Invoketype
  938. * @param string $string
  939. *
  940. */
  941. protected function writeLog($Invoketype, $string)
  942. {
  943. $userIp = Yii::$app->request->userIP;
  944. $string = date('Y-m-d H:i:s') . " $Invoketype " . "【" . $userIp . "】" . PHP_EOL . $string . PHP_EOL;
  945. if (!file_exists(__DIR__ . '/../../../runtime/logs/soap/receive')) {
  946. mkdir(__DIR__ . '/../../../runtime/logs/soap/receive', 0777, true);
  947. }
  948. file_put_contents(__DIR__ . '/../../../runtime/logs/soap/receive/' . date('Y-m-d') . '.log', $string, FILE_APPEND);
  949. }
  950. /**
  951. * @param \yii\base\Action $action
  952. * @param mixed $result
  953. * @return mixed
  954. */
  955. public function afterAction($action, $result)
  956. {
  957. //发送rtx
  958. $tmp_result = json_decode($result, true);
  959. if (isset($tmp_result['code']) && $tmp_result['code'] != '0' && !in_array($action->id, ['set-room-price', 'update-room-quantity'])) {
  960. //获取mapping失败,不发送rtx,又没有标识,以文字区别
  961. if (isset($tmp_result['msg']) && $tmp_result['msg'] != '获取mapping失败') {
  962. $arr = array(
  963. "agentid" => 1000002,
  964. "title" => $action->id . ' code :' . $tmp_result['code'] . ' msg: ' . (isset($tmp_result['msg']) ? $tmp_result['msg'] : '无msg字段'),
  965. "msg" => json_encode($this->data) . '\n' . json_encode($this->post),
  966. "touser" => $this->_developerList,
  967. );
  968. zOfficeWechat::sendMsg($arr);
  969. }
  970. }
  971. $endTime = microtime(TRUE);
  972. $scTime = $endTime - $this->startTime;
  973. $incrementTime = round(floatval($scTime), 3);//时间差
  974. $string = date('Y-m-d H:i:s', time()) . ' ';
  975. $string .= $_SERVER['REQUEST_URI'] . PHP_EOL;
  976. $body = file_get_contents("php://input");
  977. if (empty($body) == false) {
  978. if (is_array($body)) {
  979. $string .= 'body : ' . json_encode($body) . PHP_EOL;
  980. } else {
  981. $string .= 'body : ' . $body . PHP_EOL;
  982. }
  983. }
  984. $string .= 'PUT : ' . $result . PHP_EOL;
  985. $string .= 'time:' . $incrementTime . 's' . PHP_EOL . PHP_EOL;
  986. // file_put_contents(__DIR__ . '/../../../runtime/logs/getSoap/' . date('Y-m-d') . '.log', $string, FILE_APPEND);
  987. return parent::afterAction($action, $result);
  988. }
  989. public function divisionDate($data)
  990. {
  991. //将房态按时间分段
  992. $dayZone = [];
  993. $firstDay = '';
  994. $current = 0;
  995. foreach ($data as $key => $value) {
  996. if ($key == 0) {
  997. $dayZone[$current]['StartDate'] = $value['RUN_DATE'];
  998. $dayZone[$current]['EndDate'] = $value['RUN_DATE'];
  999. $firstDay = $value['RUN_DATE'];
  1000. } else {
  1001. $firstDay = strtotime($firstDay);
  1002. //用于判断当前日期与该组数据的StartDate差值是否是120,一次最多推送120天数据,大于120天分组推送
  1003. $diff = ($firstDay - strtotime($dayZone[$current]['StartDate'])) / 86400 / 99;
  1004. if ($diff < 1) {
  1005. $dayZone[$current]['EndDate'] = $value['RUN_DATE'];
  1006. } else {
  1007. $current++;
  1008. $dayZone[$current]['StartDate'] = $value['RUN_DATE'];
  1009. $dayZone[$current]['EndDate'] = $value['RUN_DATE'];
  1010. }
  1011. $firstDay = $value['RUN_DATE'];
  1012. }
  1013. }
  1014. return $dayZone;
  1015. }
  1016. }
  1017. ?>