25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

477 lines
19 KiB

  1. <?php
  2. namespace backend\modules\api\logic;
  3. use backend\modules\api\models\BaseResource;
  4. use backend\modules\api\models\OperaTouristCommon;
  5. use backend\modules\api\models\OperaTouristCtrip;
  6. use backend\modules\api\models\OrderMain;
  7. use backend\modules\api\models\OrderTitle;
  8. use backend\modules\api\util\Util;
  9. use common\models\Msg;
  10. use Yii;
  11. use backend\modules\zzcs\models\OrderTitleCancelRequest;
  12. class Ctrip
  13. {
  14. /**
  15. * Function Description:携程下单验证接口
  16. * Function Name: VerifyOrder
  17. * @param $params
  18. *
  19. * @return array
  20. *
  21. * @author 娄梦宁
  22. */
  23. public function VerifyOrder($params)
  24. {
  25. $opera_tourist_ctrip = new OperaTouristCtrip();
  26. $get_tourist_stock = new GetTouristStock();
  27. # 校验产品ID
  28. if (preg_match('/^[1-9][0-9]{0,10}$/', $params['productId']) == false) {
  29. return Util::returnArrEr('产品ID错误', [], '1001');
  30. }
  31. # 1:获取携程产品对应的自由行产品
  32. $operaTouristCommon = new OperaTouristCommon();
  33. $tourist_id =$operaTouristCommon->getTouristByCode($params['productId']);
  34. if (empty($tourist_id)) {
  35. return Util::returnArrEr('产品ID不存在', [], '1001');
  36. }
  37. # 2:校验自由行产品实时库存
  38. $stock = $get_tourist_stock->getFormatTouristStock($tourist_id, $params['useDate'], 164, 2);
  39. if ($stock['code'] != 0) {
  40. return Util::returnArrEr('库存不足', ['inventory' => 0], '1003');
  41. }
  42. ##有库存,但剩余库存小于下单所需数量
  43. if ($stock['list']['max_adult_num'] < $params['count']) {
  44. return Util::returnArrEr('库存不足', ['inventory' => $stock['list']['max_adult_num']], '1003');
  45. }
  46. # 3:库存充足,返回成功
  47. return Util::returnArrSu('验证成功', ['inventory' => $stock['list']['max_adult_num']], '0000');
  48. }
  49. /**
  50. * Function Description:携程自由行下单
  51. * Function Name: CreateOrder
  52. * @param $params
  53. *
  54. * @return array
  55. *
  56. * @author 娄梦宁
  57. */
  58. public function CreateOrder($params)
  59. {
  60. # 返回信息
  61. $return = [
  62. 'otaOrderId' => $params['otaOrderId'],
  63. 'vendorOrderId' => 0,
  64. 'smsCodeType' => 1,
  65. ];
  66. if (preg_match('/^[1-9][0-9]{0,10}$/', $params['productId']) == false) {
  67. return Util::returnArrEr('产品ID错误', [], '1001');
  68. }
  69. if (empty($params['passengerInfos']['passengerInfo'])){
  70. return Util::returnArrEr('证件不能为空', $return, '1009');
  71. }
  72. # 1:传入参数的简单校验
  73. $params_check = self::createOrderCheckParams($params);
  74. if ($params_check['code'] != 0) {
  75. return Util::returnArrEr($params_check['info'], $return, '1005');
  76. }
  77. # 2:判断携程订单是否已下
  78. $order_title = new OrderTitle();
  79. $getInfo = $order_title->getCtripOrderInfoById($params['otaOrderId']);
  80. if (empty($getInfo['order_title_id']) == false) {
  81. $return['vendorOrderId'] = $getInfo['order_title_id'];
  82. return Util::returnArrSu('下单成功', $return, '0000');
  83. }
  84. # 3:找出携程产品对应的自由行产品
  85. $operaTouristCommon = new OperaTouristCommon();
  86. $tourist_id =$operaTouristCommon->getTouristByCode($params['productId']);
  87. if (empty($tourist_id)) {
  88. return Util::returnArrEr('产品ID不存在', $return, '1001');
  89. }
  90. # 4:构造自由行下单所需参数
  91. $build_params = self::createOrderBuildParams($params, $tourist_id);
  92. if (empty($build_params)) {
  93. $return['inventory'] = 0;
  94. return Util::returnArrEr('库存不足', $return, '1003');
  95. }
  96. # 校验证件
  97. $passenger_info = json_decode($build_params['passenger_info'], true);
  98. if ($passenger_info == []) {
  99. return Util::returnArrEr('证件不能为空', $return, '1009');
  100. }
  101. foreach ($passenger_info as $val) {
  102. if (empty($val['passenger_name']) || empty($val['passenger_cardid'])) {
  103. return Util::returnArrEr('证件不能为空', $return, '1009');
  104. }
  105. }
  106. $res = Msg::httpRequest(CS1_DOMAIN . '/api/submit-order', $build_params);
  107. $result = json_decode($res, true);
  108. if (isset($result['code']) && $result['code'] == 0) {
  109. #组合订单修改is_connected_order
  110. $order_title::updateAll(['is_connected_order' => 1], ['order_title_id' => $result['order_title_id']]);
  111. $return['vendorOrderId'] = $result['order_title_id'];
  112. return Util::returnArrSu('下单成功', $return, '0000');
  113. }
  114. $return['inventory'] = 0;
  115. return Util::returnArrEr('库存不足', $return, '1100');
  116. }
  117. /**
  118. * Function Description:携程自由行下单前简单的参数校验
  119. * Function Name: createOrderCheckParams
  120. * @param $params
  121. *
  122. * @return array
  123. *
  124. * @author 娄梦宁
  125. */
  126. private function createOrderCheckParams($params)
  127. {
  128. if (empty($params['otaOrderId'])) {
  129. return [
  130. 'code' => 1,
  131. 'info' => '参数为空 otaOrderId'
  132. ];
  133. }
  134. if (empty($params['productId'])) {
  135. return [
  136. 'code' => 1,
  137. 'info' => '参数为空 productId'
  138. ];
  139. }
  140. if (empty($params['count'])) {
  141. return [
  142. 'code' => 1,
  143. 'info' => '参数为空 count'
  144. ];
  145. }
  146. if (empty($params['contactName'])) {
  147. return [
  148. 'code' => 1,
  149. 'info' => '参数为空 contactName'
  150. ];
  151. }
  152. if (empty($params['contactMobile'])) {
  153. return [
  154. 'code' => 1,
  155. 'info' => '参数为空 contactMobile'
  156. ];
  157. }
  158. if (empty($params['useDate'])) {
  159. return [
  160. 'code' => 1,
  161. 'info' => '参数为空 useDate'
  162. ];
  163. }
  164. return ['code' => 0];
  165. }
  166. /**
  167. * Function Description:处理携程自由行下单参数
  168. * Function Name: createOrderBuildParams
  169. * @param $params
  170. * @param $tourist_id
  171. *
  172. * @return array
  173. *
  174. * @author 娄梦宁
  175. */
  176. private function createOrderBuildParams($params, $tourist_id)
  177. {
  178. $transObj = new TouristToResource();
  179. # 出行人信息
  180. $passenger_info = [];
  181. if (isset($params['passengerInfos']['passengerInfo']) && !empty($params['passengerInfos']['passengerInfo'])) {
  182. if (empty($params['passengerInfos']['passengerInfo']['name']) == false) {
  183. $passengerInfo[] = $params['passengerInfos']['passengerInfo'];
  184. } else {
  185. $passengerInfo = $params['passengerInfos']['passengerInfo'];
  186. }
  187. foreach ($passengerInfo as $key => $val) {
  188. $passenger_info[] = [
  189. 'passenger_name' => $val['name'],
  190. 'passenger_mobile' => $val['mobile'],
  191. 'passenger_cardid' => $val['cardNo']
  192. ];
  193. }
  194. }
  195. # 产品数组
  196. $prodArr = [
  197. 1 => [
  198. 'prod_id' => 'TR-' . $tourist_id . '-1',
  199. 'prod_name' => '成人票',
  200. 'prod_num' => $params['count']
  201. ],
  202. 2 => [
  203. 'prod_id' => 'TR-' . $tourist_id . '-2',
  204. 'prod_name' => '儿童票',
  205. 'prod_num' => 0
  206. ]
  207. ];
  208. #如果没有传入价格则获取价格
  209. if (empty($params['price'])) {
  210. $getTouristStock = new GetTouristStock();
  211. $payPrice = $getTouristStock->getTouristPayTotal($tourist_id, $params['useDate'], Yii::$app->params['ctrip_config']['supplier_id'], 2, $prodArr);
  212. if (isset($payPrice['code']) && $payPrice['code'] == 0) {
  213. $params['price'] = $payPrice['list']['total_money'];
  214. } else {
  215. return [];
  216. }
  217. }
  218. # 订单信息
  219. $order_info = [
  220. 'user_id' => 2,
  221. 'member_id' => 1,
  222. 'outside_sale_org_id' => Yii::$app->params['ctrip_config']['supplier_id'],
  223. 'outside_sale_order_no' => $params['otaOrderId'],
  224. 'total_money' => $params['price'],
  225. 'order_book_status' => 0,
  226. 'pay_type' => 275,
  227. 'order_pay_status' => 1,
  228. 'sales_man' => ''
  229. ];
  230. $trans_res = $transObj->getTouristToAll($tourist_id, $params['useDate'],
  231. $prodArr,
  232. [
  233. 'customer_name' => $params['contactName'],
  234. 'customer_mobile' => $params['contactMobile'],
  235. 'customer_id_type' => 150,
  236. 'customer_id_no' => empty($params['contactIdCardNo']) ? '' : $params['contactIdCardNo'],
  237. ],
  238. $order_info, Yii::$app->params['ctrip_config']['supplier_id']);
  239. if ($trans_res['code'] != 0) {
  240. return [];
  241. }
  242. # 自由行下单前身份加密校验
  243. $user = 'ctrip';
  244. $user_key = 'ctrip';
  245. $request_time = time();
  246. //加密规则为 request_time(linux时间戳)前三位 + user + user_key + request_time(linux时间戳)末尾三位,进行MD5加密后,换成大写字母
  247. $auth_code = strtoupper(md5(substr($request_time, 0, 3) . "|" . $user . "|" . $user_key . "|" . substr($request_time, strlen($request_time) - 3, 3)));
  248. #最终参数封装
  249. $trans_arr = $trans_res['list'];
  250. $data['product_name'] = $trans_arr['product_name'];
  251. $data['bus_product'] = empty($trans_arr['bus_product']) ? '' : json_encode($trans_arr['bus_product']);
  252. $data['hotel_product'] = empty($trans_arr['hotel_product']) ? '' : json_encode($trans_arr['hotel_product']);
  253. $data['ticket_product'] = empty($trans_arr['ticket_product']) ? '' : json_encode($trans_arr['ticket_product']);
  254. $data['customer_info'] = json_encode($trans_arr['customer_info']);
  255. $data['order_info'] = json_encode($trans_arr['order_info']);//这里内含的outside_sale_org_id为该运营主体对应的内部采购渠道id
  256. $data['group_order_price'] = $params['price'];//组合产品销售价格
  257. $data['tourist_mark'] = $tourist_id;//$tourist_mark 标志该组合下单是否是自由行产品下单:0表示否,如是则为 tourist_id
  258. $data['tourist_org_id'] = Yii::$app->params['ctrip_config']['supplier_id'];//自由行产品销售渠道id,区别于order_info里的outside_sale_org_id[运营主体所对应]内部采购渠道id
  259. $data['tourist_extra_info'] = json_encode(array('adult_num' => $params['count'], 'child_num' => 0));//自由行产品附属信息(成人和儿童数)
  260. $data['action'] = 'submit_group_order';
  261. $data['passenger_info'] = json_encode($passenger_info);
  262. $data['buy_insurance'] = 0;
  263. $data['insurance'] = '';
  264. $data['auth_code'] = $auth_code;
  265. $data['user_key'] = $user_key;
  266. $data['user'] = $user;
  267. $data['user_id'] = 2;
  268. $data['request_time'] = $request_time;
  269. $data['tourist_id'] = $tourist_id;
  270. $data['date'] = $params['useDate'];
  271. $data['product_name'] = empty($params['otaProductName']) ? $trans_arr['product_name'] : $params['otaProductName'];
  272. return $data;
  273. }
  274. /**
  275. * Des:取消接口
  276. * Name: CancelOrder
  277. * @param $params array
  278. * @return array
  279. * @author 倪宗锋
  280. */
  281. public function CancelOrder($params)
  282. {
  283. if (empty($params['cancelCount'])) {//取消产品数量
  284. return Util::returnArrEr("参数为空【cancelCount】", [], '1005');
  285. }
  286. if (empty($params['otaOrderId'])) {//携程订单ID
  287. return Util::returnArrEr("参数为空【otaOrderId】", [], '1005');
  288. }
  289. if (empty($params['sequenceId'])) {//流水号
  290. return Util::returnArrEr("参数为空【sequenceId】", [], '1005');
  291. }
  292. # 2 订单信息校验
  293. $orderTitle = new OrderTitle();
  294. $titleInfo = $orderTitle->getCtripTitleInfo($params['otaOrderId']);
  295. if (empty($titleInfo['order_title_id'])) {//订单信息是否存在
  296. return Util::returnArrEr("订单不存在", [], '2001');
  297. }
  298. if ($titleInfo['order_title_status'] == 3) {//订单状态是否支持申请取消订单
  299. return Util::returnArrEr("该订单已经使用", [], '2002');
  300. }
  301. if ($titleInfo['order_title_status'] == 4) {//订单状态是否支持申请取消订单
  302. return Util::returnArrEr("该订单已经取消,不可重复申请", [], '2003');
  303. }
  304. if ($titleInfo['adult_num'] != $params['cancelCount']) {//校验订单产品数量是否一致
  305. return Util::returnArrEr("取消数量不正确", [], '2004');
  306. }
  307. if ($titleInfo['is_connected_order'] != 1 || $titleInfo['outside_sale_org_id']!=Yii::$app->params['ctrip_config']['supplier_id']) {//校验订单是否是携程直连订单
  308. return Util::returnArrEr("非携程直连订单,不支持取消", [], '2111');
  309. }
  310. # 3 订单取消记录校验
  311. $orderTitleCancelRequest = new OrderTitleCancelRequest();
  312. $cancelLast = $orderTitleCancelRequest->getLastInfo($titleInfo['order_title_id']);
  313. if (empty($cancelLast['order_title_id']) == false) {
  314. # 5 设置 成功返回值
  315. $return = [
  316. 'cancelCount' => $params['cancelCount'],
  317. 'charge' => 0,
  318. 'orderStatus' => 2,
  319. 'auditDuration' => 2
  320. ];
  321. if (in_array($cancelLast['request_status'], [3, 4])) {//如果取消申请失败
  322. $return['orderStatus'] = 4;
  323. }
  324. if ($cancelLast['request_status'] == 2) {//如果取消申请成功
  325. $return['orderStatus'] = 3;
  326. }
  327. return Util::returnArrSu('', $return);
  328. }
  329. # 4 插入新记录
  330. $data = [
  331. 'order_title_id' => $titleInfo['order_title_id'],
  332. 'from_org_id' => \Yii::$app->params['ctrip_config']['supplier_id'],
  333. 'create_time' => date('Y-m-d H:i:s'),
  334. 'limit_time' => '120',
  335. 'last_time' => date('Y-m-d H:i:s', strtotime('+24 hours')),
  336. 'sequence_id' => $params['sequenceId']
  337. ];
  338. $flag = $orderTitleCancelRequest->addRow($data);
  339. if ($flag != 0) {
  340. # 5 设置 成功返回值
  341. $return = [
  342. 'cancelCount' => $params['cancelCount'],
  343. 'charge' => 0,
  344. 'orderStatus' => 2,
  345. 'auditDuration' => 24
  346. ];
  347. return Util::returnArrSu('', $return);
  348. }
  349. return Util::returnArrEr('申请取消失败', [], '2199');
  350. }
  351. /**
  352. * Des:查询订单信息
  353. * Name: QueryOrder
  354. * @param $params
  355. * @return array
  356. * @author 倪宗锋
  357. */
  358. public function QueryOrder($params)
  359. {
  360. # 1 参数校验
  361. if (empty($params['otaOrderId'])) {//携程订单ID
  362. return Util::returnArrEr("参数为空【otaOrderId】", [], '4100');
  363. }
  364. # 2 订单信息校验
  365. $orderTitle = new OrderTitle();
  366. $titleInfo = $orderTitle->getCtripTitleInfo($params['otaOrderId']);
  367. if (empty($titleInfo['order_title_id'])) {//订单信息是否存在
  368. return Util::returnArrEr("订单不存在", [], '4001');
  369. }
  370. if ($titleInfo['is_connected_order'] != 1) {//校验订单是否直连订单
  371. return Util::returnArrEr("非携程直连订单,不支持查询", [], '4102');
  372. }
  373. if ($titleInfo['outside_order_no'] != $params['otaOrderId']) {//校验携程订单号是否一致
  374. return Util::returnArrEr("otaOrderId不正确!", [], '4103');
  375. }
  376. # 5设置 成功返回值
  377. $return = [
  378. 'otaOrderId' => $titleInfo['outside_order_no'],
  379. 'vendorOrderId' => $titleInfo['order_title_id'],
  380. 'orderStatus' => 0,
  381. 'amount' => $titleInfo['order_title_all_price'],
  382. 'count' => $titleInfo['adult_num'],
  383. 'useCount' => 0,
  384. 'cancelCount' => 0
  385. ];
  386. if ($titleInfo['order_title_status'] == 3) {//订单状态已完成
  387. $return['orderStatus'] = 5;//订单已完成
  388. $return['useCount'] = $titleInfo['adult_num'];//使用数等于总数
  389. } elseif ($titleInfo['request_status'] == 0) {//没有取消申请 则是新订单
  390. $return['orderStatus'] = 1;//新订单
  391. } elseif ($titleInfo['request_status'] == 1) {//1 申请审核中
  392. $return['orderStatus'] = 2;//申请取消成功
  393. } elseif ($titleInfo['request_status'] == 2) {//2 申请审核通过
  394. $return['orderStatus'] = 3;//取消(审核)成功
  395. $return['cancelCount'] = $titleInfo['adult_num'];//取消数量
  396. } elseif (in_array($titleInfo['request_status'], [3, 4])) {//3 申请审核被拒 4 申请超时被拒
  397. $return['orderStatus'] = 4;//取消(审核)失败
  398. }
  399. return Util::returnArrSu('', $return);
  400. }
  401. /**
  402. * Function Description:获取出发城市列表
  403. * Function Name: GetFromCityList
  404. * @param $params
  405. * @return array
  406. * @author 田玲菲
  407. */
  408. public function GetFromCityList($params){
  409. $baseResource = new BaseResource();
  410. $res = $baseResource->getFromCities();
  411. $data = [];
  412. foreach($res as $k=>$v){
  413. $data['fromCityList'][] = $v['res_name'];
  414. }
  415. return Util::returnArrSu('', $data);
  416. }
  417. /**
  418. * Function Description:获取到达城市列表
  419. * Function Name: GetToCityList
  420. * @param $params
  421. * @return array
  422. * @author 田玲菲
  423. */
  424. public function GetToCityList($params){
  425. //1. 验证参数
  426. if (empty($params['fromCity'])) { //出发城市
  427. return Util::returnArrEr("参数为空【fromCity】", [], '2100');
  428. }
  429. //2. 根据res_name获取res_id
  430. $baseResource = new BaseResource();
  431. $res = $baseResource->getResId($params['fromCity']);
  432. if(count($res)<1){
  433. return Util::returnArrEr("查询出错", [], '2101');
  434. }
  435. $res_id = $res['res_id'];
  436. // 3.获取所有的prod_id
  437. $res1 = $baseResource->getProdIds();
  438. if(isset($res1['prod_id'])){
  439. $prod_arr = $res1['prod_id'];
  440. }else{
  441. $prod_arr = [];
  442. }
  443. //2. 根据res_id获取到达城市
  444. $result = $baseResource->getTocities($res_id,$prod_arr);
  445. foreach ($result as &$v){
  446. $v['preSaleStart'] = date("Y-m-d",strtotime($v['preSaleStart']));
  447. $v['preSaleEnd'] = date("Y-m-d");
  448. }
  449. $data['toCityList'] = $result;
  450. return Util::returnArrSu('', $data);
  451. }
  452. }