Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

600 řádky
31 KiB

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Steven
  5. * Date: 2017/10/30
  6. * Time: 16:22
  7. */
  8. namespace backend\modules\hotel\controllers;
  9. use backend\common\Utils;
  10. use backend\modules\hotel\models\Ali\AliExecute;
  11. use backend\modules\hotel\models\Ali\AliOrder;
  12. use backend\modules\hotel\models\Ali\TopLogger;
  13. use backend\modules\hotel\models\OperaHotelRoom;
  14. use backend\modules\hotel\models\OrderInvoiceInfo;
  15. use backend\modules\hotel\models\OrderMain;
  16. use backend\modules\hotel\models\RunHotelDistrib;
  17. use common\models\BaseSupplier;
  18. use common\models\BaseSupplierSale;
  19. use Yii;
  20. use yii\filters\AccessControl;
  21. use yii\filters\ContentNegotiator;
  22. use yii\web\Response;
  23. use backend\modules\hotel\models\OperaHotelLog;
  24. use backend\modules\hotel\models\OrderHtStatusLog;
  25. use backend\modules\hotel\models\CtripOrder;
  26. use backend\modules\hotel\models\CommonOrder;
  27. class AliOrderController extends BaseController
  28. {
  29. public $enableCsrfValidation = false;
  30. private $apiParas = ''; // 接口参数
  31. private $scTime = 0; //请求响应时间差
  32. public $agent_id = self::AGENT_ALI_HOTEL_ID;
  33. public function behaviors()
  34. {
  35. //配置ContentNegotiator支持JSON和XML响应格式
  36. $behaviors['contentNegotiator'] = [
  37. 'class' => ContentNegotiator::className(),
  38. 'formats' => [
  39. 'application/xml' => Response::FORMAT_XML
  40. ],
  41. // 'only' => ['index'],//指定只是针对于index有效
  42. // 'except'=>[''] //只想剔除某个action
  43. ];
  44. $behaviors['access'] = [
  45. 'class' => AccessControl::className(),
  46. 'rules' => [
  47. [
  48. 'ips' => [
  49. /*'106.11.229.*', '106.11.230.*', '106.11.231.*', '106.11.228.*', '106.11.224.*', '106.11.225.*', '106.11.226.*', '140.205.51.*', '140.205.56.*',
  50. '106.11.227.*', '106.11.242.*', '106.11.243.*', '140.205.51.*', '140.205.144.*', '140.205.145.*', '140.205.40.*', '140.205.39.*',//阿里IP访问白名单
  51. '127.0.0.1', '106.14.56.77', '180.168.4.58', //蜘蛛及本地IP访问白名单
  52. '116.236.255.166'*/ //小黑鱼,测试功能用
  53. ],
  54. 'allow' => true,
  55. ],
  56. ],
  57. ];
  58. return $behaviors;
  59. }
  60. /**
  61. * Notes:对外接口入口
  62. * User: Steven
  63. * Date: 2018/1/17
  64. * Time: 15:16
  65. * @return object
  66. * @throws \yii\base\InvalidConfigException
  67. */
  68. public function actionIndex()
  69. {
  70. $startTime = microtime(TRUE);
  71. $request = Yii::$app->request->getRawBody();
  72. $exec = new AliExecute();
  73. $valid_res = $exec->validAuth($request);
  74. if (!$valid_res) {
  75. $result = ['Message' => '账号权限验证失败', 'ResultCode' => '-4'];
  76. } else {
  77. $this->apiParas = $exec->action_param;
  78. $action = $exec->action_id;
  79. $result = $this->$action();
  80. }
  81. $rs = \Yii::createObject([
  82. 'class' => 'yii\web\Response',
  83. 'format' => \yii\web\Response::FORMAT_XML,
  84. 'formatters' => [
  85. \yii\web\Response::FORMAT_XML => [
  86. 'class' => 'yii\web\XmlResponseFormatter',
  87. 'rootTag' => 'Result', //根节点
  88. ],
  89. ],
  90. 'data' => $result
  91. ]);
  92. $endTime = microtime(TRUE);
  93. $this->scTime = round(floatval($endTime - $startTime), 3);//时间差
  94. $logger = new TopLogger;
  95. $logger->log([date("Y-m-d H:i:s"), json_encode($result) . "\n" . 'time:' . $this->scTime . 's' . PHP_EOL], 'ali/order');
  96. return $rs;
  97. }
  98. /**
  99. * Author:Steven
  100. * Desc:酒店试单请求 用户进入预定页面之前,会通过此接口到直连商家确认产品是否可售
  101. * 1、响应时间2秒以内(超时认为试单通过) 2、有明确的成功或失败结果 3、价格、担保、退改规则有变化有正确的反馈
  102. * @return array
  103. */
  104. public function ValidateRQ()
  105. {
  106. $ali_order = new AliOrder(['scenario' => 'ValidateRQ']);
  107. $order = json_decode(json_encode($this->apiParas), true);
  108. if (!$ali_order->load($order, '') || !$ali_order->validate()) {
  109. $getError = $ali_order->getFirstErrors();
  110. $msg = '';
  111. foreach ($getError as $item) {
  112. $msg .= $item . ';';
  113. }
  114. return ['Message' => $msg, 'ResultCode' => '-116'];
  115. }
  116. $end_date = date('Y-m-d', strtotime("-1 day", strtotime($this->apiParas->CheckOut)));
  117. $data = RunHotelDistrib::getAvailProduct($this->apiParas->RatePlanCode, $this->apiParas->CheckIn, $end_date);
  118. $flag = empty($data) ? false : true;
  119. $non_book_cn = 0;
  120. foreach ($data as $item) {
  121. if ($item['RUN_STATUS'] == 329 || $item['AUTHORITY_STATUS'] == 0 || $item['ROOM_RUN_STATUS'] == 0 || $item['ROOM_IS_ONSALE'] == 0 || $item['IS_ONSALE'] == 0) {
  122. $flag = false;
  123. $non_book_cn++;
  124. }
  125. if ($this->apiParas->RoomNum > $item['REMAINING_COUNT']) {
  126. $flag = false;
  127. }
  128. $price_list[] = [
  129. 'date' => $item['RUN_DATE'],
  130. 'price' => $item['PROD_PRICE'] * 100,
  131. 'quota' => $item['REMAINING_COUNT']
  132. ];
  133. }
  134. if ($flag) {
  135. $result = [
  136. 'Message' => '',
  137. 'CreateOrderValidateKey' => time(),
  138. 'ResultCode' => '0',
  139. 'InventoryPrice' => json_encode($price_list)
  140. ];
  141. } else {
  142. $days = Utils::diffBetweenTwoDays($this->apiParas->CheckIn, $this->apiParas->CheckOut);
  143. $result = [
  144. 'Message' => '',
  145. 'CreateOrderValidateKey' => time(),
  146. 'ResultCode' => $days <= $non_book_cn ? '-1' : '-3',
  147. 'InventoryPrice' => json_encode($price_list)
  148. ];
  149. $msg = $days <= $non_book_cn ? '满房' : '房量不足(请求日期库存不全部为0,部分可售)';
  150. // 查询酒店信息
  151. $hotelInfo = OperaHotelRoom::find()
  152. ->select(["a.ROOM_NAME", "a.INNER_IDENTIFY", "b.HOTEL_NAME", "a.RP_ID"])
  153. ->leftJoin("opera_hotel as b", "a.HOTEL_ID = b.HOTEL_ID")
  154. ->from("opera_hotel_room as a")
  155. ->where(["a.ID" => $this->apiParas->RatePlanCode, "a.CANCEL_FLAG" => 0, "b.CANCEL_FLAG" => 0])
  156. ->asArray() ->one();
  157. $this->sendAliMsgToRtx('【阿里直连】酒店可定检查失败:', '原因:' . $msg . "\n酒店:" . $hotelInfo['HOTEL_NAME'] .
  158. "\n房型:" . $hotelInfo['ROOM_NAME'] . "\n内部标识:" . $hotelInfo['INNER_IDENTIFY'] . "\nRP_ID:". $hotelInfo["RP_ID"] ."\n日期:" . $this->apiParas->CheckIn . '~' . $this->apiParas->CheckOut, 2);
  159. }
  160. return $result;
  161. }
  162. /**
  163. * Notes: 预定订单 已经支付接口
  164. * 1、预订接口(BookRQ)要求多次调用返回相同的结果,且相同阿里订单号不重复创建预订
  165. * 2、支持同步和异步两种方式预订,如果需要异步处理,BookRQ返回接收成功,但不返回外部订单号即可
  166. * 3、处理能力要有合理评估并告知,去啊会根据性能要求投放流量
  167. * 4、 下单重试的时限为3分钟重试3次,查询重试的时限为30分钟重试30次,超过时限没有结果会当作失败处理,并给发出告警,需要人工处理避免占房
  168. * User: Steven
  169. * Date: 2018/1/16
  170. * Time: 11:44
  171. * @return array
  172. * @throws \yii\db\Exception
  173. */
  174. public function BookRQ()
  175. {
  176. $ali_order = new AliOrder(['scenario' => 'BookRQ']);
  177. $order = json_decode(json_encode($this->apiParas), true);
  178. //这里会在load判断是否已经存在该订单
  179. if ($ali_order->load($order, '') && $ali_order->validate()) {
  180. $res = $ali_order->validateBook(); //检查产品是否可定
  181. if ($res['ResultCode'] != 0) {
  182. $this->sendAliMsgToRtx('【阿里直连】酒店下单:', "下单失败" . "\n" . '淘宝单号' . $ali_order->TaoBaoOrderId . "\n" . '原因:' . json_decode($res["Message"], true)["reason"], 2);
  183. return $res; //这里会直接返回不可定的原因(价格或者库存校验失败)和code
  184. }
  185. $res_code = $ali_order->bookOrder();
  186. if ($res_code == AliOrder::RESPONSE_SUCCESS) { //下单成功
  187. $response = [
  188. 'Message' => AliOrder::RESPONSE_MSG[$res_code],
  189. 'ResultCode' => 0,
  190. 'OrderId' => $ali_order->zz_order_id,
  191. ];
  192. OrderMain::updateAll(['DOCKING_TYPE' => CtripOrder::ORDER_DOCKING_TYPE, 'CHANNEL_ORDER_STATUS' => OrderMain::ORDER_CHANNEL_STATUS_WAITING, 'UPDATE_TIME' => date('Y-m-d H:i:s', time())],
  193. ['and', ['CANCEL_FLAG' => 0], ['or', ['ORDER_ID' => $ali_order->zz_order_id], ['PARENT_ORDER_ID' => $ali_order->zz_order_id]]]);
  194. } else { //系统异常不能创建订单,请返回此错误码。第三方系统返回此错误码,去啊系统将自动将卖家从搜索中屏蔽。
  195. //这里我们还是返回预订成功, 然后进行异步下单(当Message和OrderId为空时表示异步下单)
  196. if ($res_code == AliOrder::RESPONSE_SYSERROR) {
  197. $ali_order->save();
  198. $response = [
  199. 'Message' => '',
  200. 'ResultCode' => 0,
  201. 'OrderId' => '',
  202. ];
  203. $this->sendAliMsgToRtx('【阿里直连】酒店下单:', "接收数据成功,系统下单失败" . "\n" . '淘宝单号:' .
  204. $ali_order->TaoBaoOrderId . "\n处理办法:" . '正常搬单,再变更订单类型为直连,后续操作同其他直连订单一致', 4);
  205. } else {
  206. $response = [
  207. 'Message' => AliOrder::RESPONSE_MSG[$res_code],
  208. 'ResultCode' => $res_code,
  209. 'OrderId' => '',
  210. ];
  211. }
  212. }
  213. return $response;
  214. } else {
  215. $error = $ali_order->getErrors();
  216. foreach ($error as $k => $v) {
  217. if ((array_key_exists($v[0], AliOrder::RESPONSE_MSG))) {
  218. $response = ['Message' => AliOrder::RESPONSE_MSG[$v[0]], 'ResultCode' => -$v[0]];
  219. } else {
  220. $response = ['Message' => AliOrder::RESPONSE_MSG[AliOrder::RESPONSE_PARAM_ERROR], 'ResultCode' => AliOrder::RESPONSE_PARAM_ERROR];
  221. }
  222. return $response;
  223. }
  224. }
  225. }
  226. /**
  227. * Author:Steven
  228. * Desc:下单接口
  229. * @param $order
  230. * @return array|bool
  231. */
  232. private function zzBook($order)
  233. {
  234. $params = [
  235. 'CreateUserID' => Yii::$app->params['ctrip']['base_user_id'],
  236. 'OrderID' => $this->OrderID, //渠道订单号
  237. 'HotelID' => $this->Spider_hotel, //酒店ID
  238. 'RoomID' => $this->Spider_room, //房型ID
  239. 'DistribID' => Yii::$app->params['ctrip']['supplier_id'],//渠道ID
  240. 'RoomNum' => $this->Quantity, //房间数量
  241. 'CheckIn' => $this->Arrival, //入住日期
  242. 'CheckOut' => $this->Departure, //离店日期,
  243. 'TotalPrice' => $this->CostAmount,//订单总价
  244. 'Currency' => $this->Currency, //币种
  245. 'ContactName' => '',//联系人姓名
  246. 'ContactTel' => '', //联系人电话
  247. 'PayType' => CommonOrder::PAY_TYPE_CREDIT, // 638:支付宝支付; 221:现金支付 ;275:授信支付;278:微信支付
  248. 'PayTradeNo' => '', //支付流水号
  249. 'OrderGuests' => CtripOrder::getGuestsName($this->Guests), //入住人信息
  250. 'Comment' => $this->Notice, //客人备注
  251. 'NeedInvoice' => 0,
  252. 'InvoiceInfos' => [ //发票信息
  253. ],
  254. 'RoomPrices' => CtripOrder::getRoomPrices($this->RoomPrices)
  255. ];
  256. $new_order = new CommonOrder(['scenario' => 'BookHotelOrder']);
  257. $room_type = OperaHotelRoom::findOne($order['RatePlanCode']);
  258. //构造下单需要的参数
  259. $user_id = Yii::$app->params['ali']['base_user_id'];
  260. $hotel_id = $order['HotelId'];
  261. $room_type = $room_type->ROOM_TYPE;
  262. $org_id = Yii::$app->params['ali']['supplier_id']; //携程渠道ID
  263. $org_num = $order['TaoBaoOrderId']; //渠道订单号
  264. $Guest_list = '';
  265. $OrderGuests = !isset($order['OrderGuests']['OrderGuest']['Name']) ? $order['OrderGuests']['OrderGuest'] : $order['OrderGuests'];
  266. foreach ($OrderGuests as $OrderGuest) {
  267. $Guest_list .= $OrderGuest['Name'] . ' ';
  268. }
  269. if (empty($Guest_list)) {
  270. $Guest_list = $order['ContactName'];
  271. }
  272. $new_room_list = '';
  273. $notes = empty($order['Comment']) ? '' : Yii::$app->params['ali']['base_user_id'] . "|" . time() . "|0|{$order['Comment']}}";
  274. $cus_list = "{{$Guest_list}{$order['ContactEmail']}," . ($order['ContactTel']) . "," . $notes . '}';
  275. $supplier = BaseSupplier::findOne(['ID' => Yii::$app->params['ali']['supplier_id']]);
  276. if ($supplier == null) {
  277. return false;
  278. }
  279. $commissionRule = $supplier->getCommissionRule(BaseSupplierSale::SALE_HOTEL);
  280. if ($commissionRule != null && $commissionRule->COMMISION_TYPE == BaseSupplierSale::TYPE_CHANNEL) {
  281. $base_com = $commissionRule->BACK_PERCENT;
  282. } else if ($commissionRule == null) {
  283. return false;
  284. } else {
  285. $base_com = 0;
  286. }
  287. $dailyInfo = !isset($order['DailyInfos']['DailyInfo']['Day']) ? $order['DailyInfos']['DailyInfo'] : $order['DailyInfos'];
  288. foreach ($dailyInfo as $DailyInfo) {
  289. $commission = round(($base_com / 100) * ($DailyInfo['Price'] / 100), 2);
  290. $new_room_list .= "{''" . $DailyInfo['Day'] . "''," . $order['RoomNum'] . "," . ($DailyInfo['Price'] / 100) . "," . $commission . "}";
  291. }
  292. //ht_make_order(259,197,9,675,'444444444','{''2017-11-09'',1,100,3.5}','{石福鹏测试,17602134075,}','23:00',0,313)
  293. // ht_make_order CALL ht_make_order(640,125,4,669,'4960112824 ','{''2017-11-24'',1,780,0}','{徐文成,,640|1511416569|1|尽量安排双床房。}','23:00',0,313)
  294. $checkin_time = date('H:i', strtotime($order['LatestArriveTime']));
  295. $sql = "CALL ht_make_order({$user_id},{$hotel_id},{$room_type},{$org_id},'{$org_num}','{$new_room_list}','{$cus_list}','{$checkin_time}',0,145)";
  296. $result = Yii::$app->db->createCommand($sql)->queryOne();
  297. $logger = new TopLogger;
  298. $logger->log([date("Y-m-d H:i:s"), "【阿里下单】" . "\n" . $sql . "\n" . json_encode($result)], 'ali/order');
  299. if ($result['errcode'] == 0) {
  300. //添加发票信息
  301. if (isset($order['InvoiceInfo']['NeedInvoice']) && $order['InvoiceInfo']['NeedInvoice'] == 1) {
  302. $order_invoice_info = new OrderInvoiceInfo();
  303. if (!$order_invoice_info->load($order['InvoiceInfo'], '')) {
  304. //加载数据失败
  305. $this->sendAliMsgToRtx('【阿里直连】酒店下单:', "保存发票信息到数据库失败,请联系技术进行处理" . "\n" . '订单号' . $result['order_id'], 1);
  306. }
  307. $order_invoice_info->InvoiceMoney = $order['TotalPrice'] / 100;
  308. $order_invoice_info->CreateUseId = Yii::$app->params['ali']['base_user_id'];
  309. $order_invoice_info->Status = 1;
  310. $order_invoice_info->ChannelId = Yii::$app->params['ali']['supplier_id'];
  311. $order_invoice_info->OrderID = $result['order_id'];
  312. $order_invoice_info->save();
  313. }
  314. //写订单日志、状态日志
  315. $orderLog = new OperaHotelLog();
  316. $orderLog->CREATE_USER_ID = Yii::$app->params['ali']['base_user_id'];
  317. $orderLog->HOTEL_ID = $order['HotelId'];
  318. $orderLog->LOG_TYPE = OperaHotelLog::LOG_TYPE_ORDER;
  319. $orderLog->ROOM_TYPE = $room_type;
  320. $orderLog->PARENT_ROOM_TYPE = $order['RoomTypeId'];
  321. $orderLog->LOG_DESC = "创建订单号为" . $result['order_id'] . "的订单";
  322. $orderLog->ORDER_ID = $result['order_id'];
  323. $orderLog->save();
  324. $statusLog = new OrderHtStatusLog();
  325. $statusLog->CREATE_USER_ID = Yii::$app->params['ali']['base_user_id'];
  326. $statusLog->UPDATE_USER_ID = Yii::$app->params['ali']['base_user_id'];
  327. $statusLog->ORDER_STATUS = OrderMain::ORDER_STATUS_WAITING_SEND;
  328. $statusLog->ORDER_ID = $result['order_id'];
  329. $statusLog->save();
  330. $count = OrderMain::updateAll(['DOCKING_TYPE' => OrderMain::ORDER_TYPE_CHANNEL, 'ORDER_PAY_STATUS' => '0', 'CHANNEL_ORDER_STATUS' => OrderMain::ORDER_CHANNEL_STATUS_WAITING,
  331. 'ORDER_STATUS' => OrderMain::ORDER_STATUS_WAITING_SEND],
  332. ['and', ['CANCEL_FLAG' => 0], ['or', ['ORDER_ID' => $result['order_id']], ['PARENT_ORDER_ID' => $result['order_id']]]]);
  333. return ['OrderId' => $result['order_id']];
  334. } else { //下单失败
  335. return false;
  336. }
  337. }
  338. /**
  339. * Author:Steven
  340. * Desc:
  341. * 使用场景:
  342. * 1、预订之后,查询预订结果 9
  343. * 2、补偿入住/NoShow状态
  344. * 3、补偿离店状态
  345. * 4、补偿账单
  346. * 5、取消订单后,查询取消结果
  347. * 要求:
  348. * 1、同步接口
  349. * 2、使用去啊订单号查询
  350. * 3、数据必须准确,必须和订单实时数据一致
  351. * 4、数据要全,预订状态、预订号、预订信息、结帐单(结帐状态后)等都需要
  352. * @return array
  353. */
  354. public function QueryStatusRQ()
  355. {
  356. $status = ''; //系统订单状态
  357. $flag = true;
  358. //QueryType 查询类型。 1-普通查询;2-下单过程中的查询(一般是进行对订单状态的确认);3-取消订单过程中的查询; 4:系统状态补偿查询
  359. $req_param = json_decode(json_encode($this->apiParas), true);
  360. if (empty($req_param['OrderId'])) { //说明是异步下单
  361. $res_order_id = OrderMain::find()->select(['ORDER_ID'])->where([
  362. 'OUTSIDE_ORDER_NO' => "{$req_param['TaoBaoOrderId']}",
  363. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_MAIN,
  364. 'PARENT_ORDER_ID' => 0,
  365. 'CANCEL_FLAG' => 0,
  366. ])->limit(1)->asArray()->one();
  367. } else {
  368. $res_order_id = OrderMain::find()->where([
  369. 'ORDER_ID' => $req_param['OrderId'],
  370. 'OUTSIDE_ORDER_NO' => "{$req_param['TaoBaoOrderId']}",
  371. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_MAIN,
  372. 'PARENT_ORDER_ID' => 0,
  373. 'CANCEL_FLAG' => 0,
  374. ])->limit(1)->asArray()->one();
  375. }
  376. $PmsResID = "";
  377. if (!empty($res_order_id)) { //在ORDER_MAIN 中下单成功
  378. $res = OrderMain::find()->select(['ORDER_ID', 'OUTSIDE_ORDER_NO', 'ORDER_VALID_STATUS', 'PROD_START_STATION_DATE', 'PROD_END_STATION_DATE',
  379. 'CHANNEL_ORDER_STATUS', 'ORDER_STATUS', 'ORDER_CONFIRM_CODE', 'ORDER_PRICE', 'ORDER_DESCRIPTION', 'PARENT_PROD_NAME'])->where([
  380. 'OUTSIDE_ORDER_NO' => $req_param['TaoBaoOrderId'],
  381. 'ORDER_ID' => $res_order_id['ORDER_ID'],
  382. 'CANCEL_FLAG' => 0,
  383. ])->asArray()->one();
  384. if ($res['CHANNEL_ORDER_STATUS'] == OrderMain::ORDER_CHANNEL_STATUS_PAYING || $res['CHANNEL_ORDER_STATUS'] == OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL
  385. || $res['CHANNEL_ORDER_STATUS'] == OrderMain::ORDER_CHANNEL_STATUS_WAITING) { //渠道待支付 待接单
  386. $status = 3;//订单等待处理中 待支付
  387. } elseif ($res['CHANNEL_ORDER_STATUS'] == OrderMain::ORDER_CHANNEL_STATUS_ACCEPT) { //渠道已接单
  388. $status = 1; //订单已经确认
  389. $PmsResID = $res['ORDER_CONFIRM_CODE']; //酒店的确认号
  390. } elseif ($res['CHANNEL_ORDER_STATUS'] == OrderMain::ORDER_CHANNEL_STATUS_REJECT
  391. || $res['CHANNEL_ORDER_STATUS'] == OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL_CONFIRMED) { //已拒绝 拒单
  392. $status = 4; //订单已取消
  393. } elseif ($res['CHANNEL_ORDER_STATUS'] == OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL_REJECT) { //渠道申请取消被拒
  394. if ($res['ORDER_STATUS'] == OrderMain::ORDER_STATUS_NO_PAID || $res['ORDER_STATUS'] == OrderMain::ORDER_STATUS_WAITING_SEND
  395. || $res['ORDER_STATUS'] = OrderMain::ORDER_STATUS_WAITING_CONFIRM) {//待支付 待发单
  396. $status = 3;//订单等待处理中
  397. } elseif ($res['ORDER_STATUS'] == OrderMain::ORDER_STATUS_CONFIRMED || $res['ORDER_STATUS'] == OrderMain::ORDER_STATUS_CHANGING
  398. || $res['ORDER_STATUS'] == OrderMain::ORDER_STATUS_FINISH) {
  399. $status = 1; //订单已经确认
  400. } elseif ($res['ORDER_STATUS'] == OrderMain::ORDER_STATUS_CANCEL_BEFORE_CONFIRM || $res['ORDER_STATUS'] == OrderMain::ORDER_STATUS_CANCEL) { //
  401. $status = 4; //订单已取消
  402. } else {
  403. $flag = false;
  404. }
  405. } elseif ($res['CHANNEL_ORDER_STATUS'] == 0) { //说明直连失败的订单,搬完单但是还没有变更成之直连的状态,这个时候也需要返回待确认
  406. $status = 3;
  407. } else {
  408. $flag = false;
  409. }
  410. } else { //order_main 中没有该订单
  411. $order = AliOrder::find()->select(['TotalPrice'])->where(['TaoBaoOrderId' => "{$req_param['TaoBaoOrderId']}"])->asArray()->one();
  412. if (empty($order)) {
  413. $result = ['ResultCode' => -302, 'Message' => '订单不存在', 'OrderId' => $req_param['OrderId']];
  414. } else {
  415. $result = [
  416. 'Message' => '',
  417. 'ResultCode' => '0',
  418. 'TaoBaoOrderId' => $req_param['TaoBaoOrderId'],
  419. 'OrderId' => '',
  420. 'Status' => 3,
  421. 'TotalRoomPrice' => $order['TotalPrice'],
  422. 'OtherFee' => 0,
  423. ];
  424. }
  425. return $result;
  426. }
  427. if (!$flag) { //查询订单状态的时候,有未判断到的其他状态,需要推送开发人员
  428. $this->sendAliMsgToRtx('【阿里直连】阿里渠道直连订单状态查询失败:', "有未判断到的其他订单状态,请关注" . "\n" . $req_param['OrderId'], '');
  429. $result = [];
  430. } else {
  431. $result = [
  432. 'Message' => '',
  433. 'ResultCode' => '0',
  434. 'TaoBaoOrderId' => $req_param['TaoBaoOrderId'],
  435. 'OrderId' => $res_order_id['ORDER_ID'],
  436. 'Status' => $status,
  437. 'PmsResID' => $PmsResID,
  438. 'TotalRoomPrice' => $res['ORDER_PRICE'] * 100,
  439. 'OtherFee' => 0,
  440. ];
  441. if ($res['PROD_START_STATION_DATE'] < date('Y-m-d', time())) {
  442. $desc = explode('|', $res['ORDER_DESCRIPTION']);
  443. $RoomQuantity = explode(',', $desc[0])[2];
  444. $result['OrderInfo'] = [
  445. 'CheckIn' => $res['PROD_START_STATION_DATE'] . ' 00:00:00',
  446. 'CheckOut' => $res['PROD_END_STATION_DATE'] . ' 00:00:00',
  447. 'RoomQuantity' => $RoomQuantity,
  448. 'Hotel' => $res['PARENT_PROD_NAME'],
  449. ];
  450. }
  451. }
  452. return $result;
  453. }
  454. /**
  455. * Author:Steven
  456. * Desc:支付成功回调 由于我们跟阿里合作的形式是先付款后下单
  457. * 根据此接口定义实现支付成功回调接口,并暴露成服务。
  458. * 此接口用于预付订单用户支付成功后通知第三方系统,仅通知一次(超时原因会重试3次)
  459. * @return array
  460. */
  461. public function PaySuccessRQ()
  462. {
  463. $flag = true;
  464. $order = json_decode(json_encode($this->apiParas), true);
  465. $res_order_id = OrderMain::find()
  466. ->leftJoin('opera_hotel_room', 'order_main.PARENT_PROD_ID=opera_hotel_room.HOTEL_ID and order_main.PROD_ID=opera_hotel_room.ROOM_TYPE and opera_hotel_room.CANCEL_FLAG=0')
  467. ->select(['ORDER_ID', 'PROD_ID', 'PARENT_PROD_ID', 'opera_hotel_room.PARENT_ROOM_TYPE'])->where([
  468. 'OUTSIDE_ORDER_NO' => "{$order['TaoBaoOrderId']}",
  469. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_MAIN,
  470. 'PARENT_ORDER_ID' => 0,
  471. 'order_main.CANCEL_FLAG' => 0,
  472. ])->limit(1)->asArray()->one();
  473. if (empty($res_order_id)) { //order_main 说明订单是异步下单
  474. $count = AliOrder::updateAll(['AlipayTradeNo' => $order['AlipayTradeNo']], ['TaoBaoOrderId' => $order['TaoBaoOrderId']]);
  475. if ($count <= 0) {
  476. $flag = false;
  477. }
  478. } else {
  479. $orderLog = new OperaHotelLog();
  480. $orderLog->CREATE_USER_ID = Yii::$app->params['ali']['base_user_id'];
  481. $orderLog->HOTEL_ID = $res_order_id['PARENT_PROD_ID'];
  482. $orderLog->LOG_TYPE = OperaHotelLog::LOG_TYPE_ORDER;
  483. $orderLog->ROOM_TYPE = $res_order_id['PROD_ID'];
  484. $orderLog->PARENT_ROOM_TYPE = $res_order_id['PARENT_ROOM_TYPE'];
  485. $orderLog->LOG_DESC = "支付订单,支付宝流水号:" . $order['AlipayTradeNo'];
  486. $orderLog->ORDER_ID = $res_order_id['ORDER_ID'];
  487. if (!$orderLog->save()) {
  488. $flag = false;
  489. }
  490. }
  491. $result = $flag ? ['Message' => '处理成功', 'ResultCode' => 0] : ['Message' => '内部错误', 'ResultCode' => -400];
  492. return $result;
  493. }
  494. /**
  495. * Author:Steven
  496. * Desc:酒店退款通知请求 此接口请求只作为退款通知申请,不会根据响应结果做退款处理。
  497. * @return array
  498. */
  499. public function OrderRefundRQ()
  500. {
  501. $req_param = json_decode(json_encode($this->apiParas), true);
  502. $res_order_id = OrderMain::find()->leftJoin('opera_hotel_room', 'order_main.PARENT_PROD_ID=opera_hotel_room.HOTEL_ID and order_main.PROD_ID=opera_hotel_room.ROOM_TYPE and opera_hotel_room.CANCEL_FLAG=0')
  503. ->select(['ORDER_ID', 'PROD_ID', 'PARENT_PROD_ID', 'opera_hotel_room.PARENT_ROOM_TYPE'])->where([
  504. 'OUTSIDE_ORDER_NO' => "{$req_param['TaoBaoOrderId']}",
  505. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_MAIN,
  506. 'PARENT_ORDER_ID' => 0,
  507. 'order_main.CANCEL_FLAG' => 0,
  508. ])->limit(1)->asArray()->one();
  509. $orderLog = new OperaHotelLog();
  510. $orderLog->CREATE_USER_ID = Yii::$app->params['ali']['base_user_id'];
  511. $orderLog->HOTEL_ID = $res_order_id['PARENT_PROD_ID'];
  512. $orderLog->LOG_TYPE = OperaHotelLog::LOG_TYPE_ORDER;
  513. $orderLog->ROOM_TYPE = $res_order_id['PROD_ID'];
  514. $orderLog->PARENT_ROOM_TYPE = $res_order_id['PARENT_ROOM_TYPE'];
  515. $orderLog->LOG_DESC = "买家申请退款,订单号:" . $res_order_id['ORDER_ID'];
  516. $orderLog->ORDER_ID = $res_order_id['ORDER_ID'];
  517. $orderLog->save();
  518. $Shipped = $req_param['Shipped'] ? '已发货' : '未发货';
  519. $this->sendAliMsgToRtx('【阿里直连】买家申请退款通知:', '订单:' . $req_param['OrderId'] . ' ' . $Shipped . "\n" . '买家申请退款,请至淘宝后台进行处理', 4);
  520. $result = ['Message' => '接受成功', 'ResultCode' => '0'];
  521. return $result;
  522. }
  523. /**
  524. * Author:Steven
  525. * Desc:用户取消订单
  526. * 1、由于我们的产品都是不可取消,所以客人申请取消,都需要我们同意或者拒绝,当同意退款的时候就会调用这个接口
  527. * 2、订单未付款 关闭时也会请求该接口
  528. * 3、我们拒单,或者我们确认无房 也会调用该接口
  529. * 4、下单失败的情况也会调用该接口
  530. * @return array
  531. */
  532. public function CancelRQ()
  533. {
  534. $req_param = json_decode(json_encode($this->apiParas), true);
  535. $res_order_id = OrderMain::find()->leftJoin('opera_hotel_room', 'order_main.PARENT_PROD_ID=opera_hotel_room.HOTEL_ID and order_main.PROD_ID=opera_hotel_room.ROOM_TYPE and opera_hotel_room.CANCEL_FLAG=0')
  536. ->select(['ORDER_ID', 'CHANNEL_ORDER_STATUS', 'PROD_ID', 'PARENT_PROD_ID', 'opera_hotel_room.PARENT_ROOM_TYPE'])->where([
  537. 'OUTSIDE_ORDER_NO' => "{$req_param['TaoBaoOrderId']}",
  538. 'ORDER_PROD_TYPE' => OrderMain::ORDER_PROD_TYPE_MAIN,
  539. 'PARENT_ORDER_ID' => 0,
  540. 'order_main.CANCEL_FLAG' => 0,
  541. ])->limit(1)->asArray()->one();
  542. if (empty($res_order_id)) {
  543. return ['Message' => '', 'ResultCode' => '-204']; //不存在该订单
  544. }
  545. $orderLog = new OperaHotelLog();
  546. $orderLog->CREATE_USER_ID = Yii::$app->params['ali']['base_user_id'];
  547. $orderLog->HOTEL_ID = $res_order_id['PARENT_PROD_ID'];
  548. $orderLog->LOG_TYPE = OperaHotelLog::LOG_TYPE_ORDER;
  549. $orderLog->ROOM_TYPE = $res_order_id['PROD_ID'];
  550. $orderLog->PARENT_ROOM_TYPE = $res_order_id['PARENT_ROOM_TYPE'];
  551. $orderLog->LOG_DESC = "买家申请取消订单,已同意取消(退款成功),订单号:" . $res_order_id['ORDER_ID'];
  552. $orderLog->ORDER_ID = $res_order_id['ORDER_ID'];
  553. $orderLog->save();
  554. if ($res_order_id['CHANNEL_ORDER_STATUS'] != OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL_CONFIRMED) {
  555. //当接收到取消通知的时候说明,订单已经同意取消或者超时自动取消,需要修改
  556. $count = OrderMain::updateAll(['CHANNEL_ORDER_STATUS' => OrderMain::ORDER_CHANNEL_STATUS_APPLY_CANCEL_CONFIRMED],
  557. ['and', ['CANCEL_FLAG' => 0], ['or', ['ORDER_ID' => $res_order_id['ORDER_ID']], ['PARENT_ORDER_ID' => $res_order_id['ORDER_ID']]]]);
  558. $orderLog = new OperaHotelLog();
  559. $orderLog->CREATE_USER_ID = Yii::$app->params['ali']['base_user_id'];
  560. $orderLog->HOTEL_ID = $res_order_id['PARENT_PROD_ID'];
  561. $orderLog->LOG_TYPE = OperaHotelLog::LOG_TYPE_ORDER;
  562. $orderLog->ROOM_TYPE = $res_order_id['PROD_ID'];
  563. $orderLog->PARENT_ROOM_TYPE = $res_order_id['PARENT_ROOM_TYPE'];
  564. $orderLog->LOG_DESC = "渠道订单状态变为已取消,订单号:" . $res_order_id['ORDER_ID'];
  565. $orderLog->ORDER_ID = $res_order_id['ORDER_ID'];
  566. $orderLog->save();
  567. } else {
  568. return ['Message' => '', 'ResultCode' => '-205']; //已取消
  569. }
  570. $this->sendAliMsgToRtx('【阿里直连】买家申请取消订单:', '订单号:' . $req_param['OrderId'] . "\n" . "阿里订单号:" . $req_param['TaoBaoOrderId'] . "\n" . '用户取消订单,请及时核实CS订单状态,如果订单在渠道上已经取消,请尽快取消CS订单', 4);
  571. $result = ['Message' => '', 'ResultCode' => '-100'];
  572. return $result;
  573. }
  574. }