DeliveryController.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. <?php
  2. namespace hd\controllers;
  3. use biz\ghs\classes\GhsClass;
  4. use bizGhs\custom\classes\CustomClass;
  5. use bizGhs\express\classes\DeliveryAuthTokenClass;
  6. use bizHd\order\classes\OrderClass;
  7. use bizHd\express\classes\HdDeliveryOrderClass;
  8. use hd\models\delivery\CancelOrderForm;
  9. use hd\models\delivery\CreateOrderForm;
  10. use Yii;
  11. use biz\shop\classes\ShopClass;
  12. use common\components\delivery\services\DispatchService;
  13. use common\components\util;
  14. use yii\helpers\ArrayHelper;
  15. class DeliveryController extends BaseController
  16. {
  17. public function actionList()
  18. {
  19. $platformList = [];
  20. $platformLogos = [
  21. 'dada' => ['name'=>'达达', 'logo'=>'📦'],
  22. 'shunfeng' => ['name'=>'顺丰同城', 'logo'=>'🚚'],
  23. 'meituan' => ['name'=>'美团', 'logo'=>'🍱'] ,
  24. 'fengniao' => ['name'=>'蜂鸟', 'logo'=>'🍜'],
  25. 'huolala' => ['name'=>'货拉拉跑腿', 'logo'=>'🚛'],
  26. 'shansong' => ['name'=>'闪送', 'logo'=>'⚡'],
  27. 'didi' => ['name'=>'滴滴', 'logo'=>'🚗'],
  28. 'uu' => ['name'=>'UU跑腿', 'logo'=>'🛵']
  29. ];
  30. $mainId = $this->mainId;
  31. $allDeliveries = DeliveryAuthTokenClass::getAllByCondition(['mainId'=>$mainId]);
  32. foreach($allDeliveries as $d){
  33. $item = [
  34. 'id'=>$d['platform'],
  35. 'logo'=>$platformLogos[$d['platform']]['logo'],
  36. 'name'=>$platformLogos[$d['platform']]['name'],
  37. 'is_authorized' => true,
  38. 'balance' => $d['balance']/100.0,
  39. 'access_type' => 'oauth'
  40. ];
  41. $platformList[] = $item;
  42. }
  43. util::success(['platformList'=>$platformList]);
  44. }
  45. // 花店发货 -- 获取多个平台报价
  46. public function actionHdAllDeliveryQuotes()
  47. {
  48. $post = Yii::$app->request->post();
  49. $orderTime = $post['pickupTime'];
  50. $weight = $post['weight'];
  51. $remark = $post['remark'] ?? '';
  52. $adminId = $this->adminId;
  53. util::checkRepeatCommit($adminId, 3);
  54. $orderId = intval($post['orderId']);
  55. $order = OrderClass::getById($orderId);
  56. $shop = ShopClass::getById($this->shopId);
  57. $order['weight'] = $weight;
  58. $order['remark'] = $remark;
  59. $ds = new DispatchService($this->mainId);
  60. $platformQuotes = $ds->getAllPlatformPrice($order, $shop, $orderTime);
  61. if(isset($platformQuotes['error'])){
  62. util::fail($platformQuotes['error']);
  63. }
  64. // 格式化各平台报价为前端展示格式
  65. $deliveryList = $ds->formatPlatformQuotesForDisplay($platformQuotes);
  66. // 按 price 从低到高排序
  67. ArrayHelper::multisort($deliveryList, 'price', SORT_ASC);
  68. $ret['deliveryList'] = $deliveryList;
  69. util::success($ret, "success");
  70. }
  71. // 花店向批发买花 -- 获取多个平台报价
  72. public function actionAllDeliveryQuotes()
  73. {
  74. $post = Yii::$app->request->post();
  75. $orderTime = date('Y-m-d H:i:s');
  76. // --------- $ghsShopId ----------
  77. $ghsId = $post['ghsId'] ?? 0;
  78. $ghs = GhsClass::getById($ghsId, true);
  79. if (empty($ghs)) {
  80. util::fail('获取批发商失败');
  81. }
  82. $ghsShopId = $ghs->shopId;
  83. // --------- $customId
  84. $customId = $ghs->customId ?? 0;
  85. $custom = CustomClass::getById($customId, true);
  86. if (empty($custom)) {
  87. util::fail('获取custom数据失败');
  88. }
  89. $weight = $post['weight'] ?? 1;
  90. // 生成随机订单号
  91. $prefix = 'XSD_CS-' . $ghs->mainId . '-';
  92. $orderSn = $prefix . round(microtime(true) * 1000);
  93. //构建出 Order 数据
  94. $order = [
  95. 'orderSn' => $orderSn,
  96. 'customName' => $custom['name'],
  97. 'customMobile' => $custom['mobile'],
  98. 'fullAddress' => $custom['fullAddress'],
  99. 'floor' => $custom['floor'],
  100. 'dist' => $custom['dist'],
  101. 'lat' => $custom['lat'],
  102. 'long' => $custom['long'],
  103. 'address' => $custom['address'], //'toAddress' => $order['address'],
  104. 'city' => $custom['city'],
  105. 'weight' => $weight,
  106. 'remark' => $post['remark'] ?? '',
  107. 'prePrice' => 10, // TODO 要从前端获取
  108. 'actPrice' => 10, // TODO
  109. ];
  110. $ghsShop = ShopClass::getById($ghsShopId);
  111. $ds = new DispatchService($ghs->mainId);
  112. $platformQuotes = $ds->getAllPlatformPrice($order, $ghsShop, $orderTime);
  113. if(isset($platformQuotes['error'])){
  114. util::fail($platformQuotes['error']);
  115. }
  116. $deliveryList = [];
  117. // 格式化各平台报价为前端展示格式
  118. $deliveryList = $ds->formatPlatformQuotesForDisplay($platformQuotes);
  119. // 按 price 从低到高排序
  120. ArrayHelper::multisort($deliveryList, 'price', SORT_ASC);
  121. $ret['deliveryList'] = $deliveryList;
  122. util::success($ret, "success");
  123. }
  124. // 创建订单(真实下单)
  125. public function actionCreateOrder()
  126. {
  127. $form = new CreateOrderForm();
  128. $form->loadAndValidate();
  129. $post = $form->getAttributes();
  130. $orderId = $post['orderId']; // xhOrder.id
  131. $params = $post['allParams'];
  132. $platform = $params['en_name'];// $post['platform'] 是中文
  133. $pickupTime = $post['pickupTime'];
  134. $params['mainId'] = $this->mainId;
  135. $params['ip'] = Yii::$app->request->userIP;
  136. $params['remark'] = $post['remark'];
  137. $params['total_price_fen'] = $post['price'];
  138. $params['pickupTime'] = $pickupTime['value'];
  139. $shopId = $this->shopId;
  140. $Order = OrderClass::getById($orderId, true);
  141. if(!in_array($Order['sendStatus'], [-4, -1])) {
  142. Yii::error('订单已经发过跑腿');
  143. util::fail('订单已经发过跑腿');
  144. }
  145. $ds = new DispatchService($this->mainId, $platform);
  146. $ret = $ds->createOrder($Order, $shopId, $params);
  147. if (isset($ret['code']) && $ret['code'] == 0) {
  148. $gdo = HdDeliveryOrderClass::getByCondition(['mainId'=>$this->mainId, 'orderId'=>$ret['data']['order_id']]);
  149. if (empty($gdo)) {
  150. $data = [
  151. 'mainId' => $this->mainId,
  152. 'shopId' => $this->shopId,
  153. 'deliveryId' => $ret['platform'],
  154. 'hdOrderId' => $orderId,
  155. 'orderId' => $ret['data']['order_id'],
  156. 'distance' => $ret['data']['distance'],
  157. 'fee' => $ret['data']['fee'],
  158. 'orderStatus' => 0
  159. ];
  160. HdDeliveryOrderClass::add($data);
  161. } else {
  162. Yii::info('重复创建订单');
  163. }
  164. //更新订单
  165. $Order->sendDistance = $ret['data']['distance'];
  166. $Order->sendStatus = 0;
  167. $Order->deliveryId = $ret['platform'];
  168. $Order->sendType = 2;// 2指跑腿
  169. $Order->status = 3;// 3配送中
  170. $save = $Order->save();
  171. if($save){
  172. util::success($ret, "success");
  173. }else{
  174. util::fail('创建跑腿失败(更新订单失败)');
  175. }
  176. } else {
  177. if(isset($ret['msg'])){
  178. util::fail($ret['msg']);
  179. }
  180. util::fail('创建跑腿失败');
  181. }
  182. }
  183. // 取消订单
  184. public function actionCancelOrder()
  185. {
  186. $form = new CancelOrderForm();
  187. $form->loadAndValidate();
  188. $post = $form->getAttributes();
  189. $orderId = $post['orderId'] ?? 0; // 平台的orderId,
  190. $platform = $post['platform'] ?? '';
  191. $hdOrderId = $post['hdOrderId'];
  192. // 先获取配送订单,确保 $gdo 始终可用
  193. $hdo = HdDeliveryOrderClass::getByCondition(['mainId'=>$this->mainId, 'hdOrderId'=>$hdOrderId, 'orderStatus!='=> -1], true);
  194. if(empty($hdo)) {
  195. util::fail('未找到对应订单: ' . $hdOrderId);
  196. }
  197. // 如果没有提供平台和订单ID,从配送订单中获取
  198. if($platform == '' || $orderId == 0) {
  199. $orderId = $hdo->orderId;
  200. $platform = $hdo->deliveryId;
  201. }
  202. $ds = new DispatchService($this->mainId, $platform);
  203. $cancelCostCent = 0;
  204. if($platform == 'fengniao') {
  205. //请求订单预取消接口,获取是否可取消。如果运单状态不允许取消,则直接返回
  206. $cancelParams = ['order_id'=>$orderId, 'order_cancel_code'=>$post['order_cancel_code']];
  207. $res = $ds->getAdapter()->preCancelOrder($cancelParams);
  208. if($res['code'] != 0){
  209. util::fail('运单状态不允许取消');
  210. }
  211. $cancelCostCent = $res['data']['actual_cancel_cost_cent']; //取消实际需金额(单位:分)
  212. }
  213. if($platform == 'shunfeng') {
  214. //请求订单预取消接口,获取是否可取消。如果运单状态不允许取消,则直接返回
  215. $cancelParams = ['order_id'=>$orderId, 'order_cancel_code'=>$post['order_cancel_code']];
  216. $res = $ds->getAdapter()->preCancelOrder($cancelParams);
  217. if($res['code'] != 0){
  218. util::fail('运单状态不允许取消');
  219. }
  220. $post['order_type'] = 1; //查询订单ID类型 1、顺丰订单号 2、商家订单号
  221. }
  222. $post['order_cancel_role'] = 1; //1:商户取消, 2:用户取消
  223. $ret = $ds->cancelOrder($orderId, $post);
  224. if($ret['code'] == 0) {
  225. // 更新跑腿订单与批发订单状态
  226. $hdo->orderStatus = -1;
  227. $hdo->cancelCost = $ret['platform'] !== 'fengniao' ? $ret['data']['deductionFee'] : $cancelCostCent; // 由于蜂鸟平台返回的扣费不一样造成
  228. if(!$hdo->save()) {
  229. Yii::error('保存配送订单失败: ' . json_encode($hdo->errors));
  230. util::fail('保存配送订单失败');
  231. }
  232. $Order = OrderClass::getById($hdOrderId, true, 'id, sendDistance, sendStatus, deliveryId');
  233. $Order->sendDistance = 0;
  234. $Order->sendStatus = -1;
  235. $Order->status = 5;
  236. $Order->deliveryId = '';
  237. if(!$Order->save()) {
  238. Yii::error('保存批发订单失败: ' . json_encode($Order->errors));
  239. util::fail('保存批发订单失败');
  240. }
  241. util::success($ret['data'], "success");
  242. }
  243. util::fail('取消失败');
  244. }
  245. /**
  246. * 获取订单取消原因
  247. */
  248. public function actionCancelReason()
  249. {
  250. $post = Yii::$app->request->post();
  251. $hdOrderId = $post['hdOrderId'];
  252. $platform = $post['platform'];
  253. $hdo = HdDeliveryOrderClass::getByCondition(['mainId'=>$this->mainId, 'hdOrderId'=>$hdOrderId, 'orderStatus!='=>-1], true);
  254. if(!empty($hdo)) {
  255. $orderId = $hdo->orderId;
  256. //$platform = $gdo->deliveryId;
  257. } else {
  258. util::fail('未找到对应订单: ' . $hdOrderId);
  259. }
  260. $ds = new DispatchService($this->mainId, $platform);
  261. $ret = $ds->getCancelReasonList($orderId);
  262. if($ret['code'] == 0){
  263. util::success($ret['data']);
  264. }else{
  265. Yii::error('获取订单取消原因:'.json_encode($ret));
  266. util::fail($ret['msg']);
  267. }
  268. }
  269. public function actionAddress()
  270. {
  271. $post = Yii::$app->request->post();
  272. $adminId = $this->adminId;
  273. util::checkRepeatCommit($adminId, 4);
  274. $orderId = intval($post['orderId']);
  275. $order = OrderClass::getById($orderId, false, 'fullAddress');
  276. $shop = ShopClass::getById($this->shopId, false, 'fullAddress');
  277. $ret = [
  278. "send_address" => $shop['fullAddress'],
  279. "receive_address" => $order['fullAddress']
  280. ];
  281. util::success($ret, "success");
  282. }
  283. public function actionCancelAuth()
  284. {
  285. // 有平台有对应的取消授权接口,有的没有。
  286. // 有的就对接下,然后再删除数据。没有的直接删除数据就行。
  287. $platform = Yii::$app->request->get('platform');
  288. $delivery = DeliveryAuthTokenClass::getByCondition(['mainId'=>$this->mainId, 'platform'=>$platform]);
  289. if($delivery) {
  290. if($platform == 'shansong') {
  291. $auth = new \common\components\delivery\platform\shansong\Auth();
  292. $result = $auth->cancelAuthorization($delivery['accessToken']);
  293. if($result['success']) {
  294. // 授权已取消
  295. }else{
  296. if($result['message'] == '商户未授权,请授权后再次尝试'){
  297. Yii::info($this->mainId . '--商户未授权,请授权后再次尝试');
  298. }else{
  299. util::fail('取消授权失败:'.$result['message']);
  300. }
  301. }
  302. }
  303. }else{
  304. util::fail('取消授权失败,数据未找到');
  305. }
  306. $ret = DeliveryAuthTokenClass::deleteByCondition(['mainId'=>$this->mainId, 'platform'=>$platform]);
  307. if($ret > 0){
  308. util::success(['message'=>'取消授权成功']);
  309. } else {
  310. util::fail('取消授权失败');
  311. }
  312. }
  313. public function actionGetAuthUrl()
  314. {
  315. $platform = Yii::$app->request->get('platformId');
  316. $Auth = new \common\components\delivery\services\AuthService();
  317. $mainId = $this->mainId;
  318. switch($platform){
  319. case 'shansong':
  320. $Auth->shansongAuth($mainId);
  321. break;
  322. case 'huolala':
  323. $Auth->huolalaAuth($mainId);
  324. break;
  325. case 'fengniao':
  326. $Auth->fengniaoAuth($mainId);
  327. break;
  328. case 'dada':
  329. $Auth->dadaAuth($mainId);
  330. break;
  331. case 'shunfeng':
  332. $Auth->shunfengAuth($mainId);
  333. break;
  334. case 'didi':
  335. break;
  336. default:
  337. util::error(-1, $platform . '不存在');
  338. break;
  339. }
  340. }
  341. }