DeliveryController.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. <?php
  2. namespace ghs\controllers;
  3. use biz\shop\classes\ShopClass;
  4. use bizGhs\express\classes\ShansAuthTokenClass;
  5. use bizGhs\order\classes\OrderClass;
  6. use common\components\delivery\services\adapter\HuolalaAdapter;
  7. use common\components\util;
  8. use common\components\delivery\services\DispatchService;
  9. use Yii;
  10. /**
  11. * 聚合配送(自配 + 聚合动力)
  12. * Class DeliveryController
  13. * @package ghs\controllers
  14. */
  15. class DeliveryController extends BaseController
  16. {
  17. public $guestAccess = ['callback', 'shansong-auth-callback', 'huolala-auth-callback'];
  18. // ------------------ 授权(账号绑定) ---------------------
  19. //授权
  20. public function actionMerchantAuth()
  21. {
  22. //闪送授权(商户授权:授权后能为商户下所有门店发单)
  23. $auth = new \common\components\delivery\platform\shansong\Auth();
  24. $redirectUrl = 'https://api.shop.hzghd.com/delivery/shansong-auth-callback';
  25. $authUrl = $auth->generateMerchantAuthUrl($this->mainId, $redirectUrl);
  26. // 重定向用户
  27. header('Location: ' . $authUrl);
  28. }
  29. public function actionHuolalaAuth()
  30. {
  31. $huoLalaAuth = new \common\components\delivery\platform\huolala\Auth();
  32. $mainId = $this->mainId;
  33. $redirectUrl = 'https://api.shop.hzghd.com/delivery/huolala-auth-callback' . '?mainId=' . $mainId;
  34. $authUrl = $huoLalaAuth->generateAuthUrl($redirectUrl);
  35. header('Location: ' . $authUrl);
  36. }
  37. public function actionFengniaoAuth()
  38. {
  39. $fengnaioAuth = new \common\components\delivery\platform\fengniao\Auth();
  40. $mainId = $this->mainId;
  41. $redirectUrl = 'https://api.shop.hzghd.com/delivery/fengniao-auth-callback' . '?mainId=' . $mainId;
  42. $authUrl = $fengnaioAuth->generateAuthUrl($redirectUrl);
  43. header('Location: ' . $authUrl);
  44. }
  45. public function actionDadaAuth()
  46. {
  47. $dadaAuth = new \common\components\delivery\platform\dada\Auth();
  48. $ticket = $dadaAuth->getTicket();
  49. $mainId = $this->mainId;
  50. $redirectUrl = 'https://api.shop.hzghd.com/delivery/dada-auth-callback' . '?mainId=' . $mainId;
  51. $shopNumber = '40d8391f9b05477b';
  52. $state = 'huidiao_biaoshi';
  53. $authUrl = $dadaAuth->generateAuthUrl($ticket, $state, $shopNumber);
  54. header('Location: ' . $authUrl);
  55. }
  56. public function actionHuolalaVehicle()
  57. {
  58. $mainId = $this->mainId;
  59. $authPlatforms = ShansAuthTokenClass::getByCondition(['user_id'=>$mainId, 'platform'=>'huolala']);
  60. $huolalaAdapter = new HuolalaAdapter($authPlatforms['access_token']);
  61. $cities = $huolalaAdapter->getCityVehicleList(1006);
  62. return $this->asJson($cities);
  63. }
  64. // 查询开通城市
  65. public function actionOpenCitiesLists()
  66. {
  67. $platform = Yii::$app->request->get('platform');
  68. $ds = new DispatchService($this->mainId);
  69. $cities = $ds->openCitiesLists($platform);
  70. if ($platform == 'shansong') {
  71. $newCitiesArr = [];
  72. $citiesArr = $cities['data'];
  73. foreach($citiesArr as $block) {
  74. foreach ($block['cities'] as $city) {
  75. $newCitiesArr[$city['name']] = $city;
  76. }
  77. }
  78. // 把newCitiesArr保存到 platform/huolala/cities.php 文件中
  79. $citiesFile = Yii::getAlias('@common/components/delivery/platform/shansong/cities.php');
  80. // 如果文件不存在,则创建文件
  81. if (!file_exists($citiesFile)) {
  82. file_put_contents($citiesFile, '<?php return []; ?>');
  83. }
  84. // 文件内容要包含命名空间
  85. $content = '<?php return ' . var_export($newCitiesArr, true) . '; ?>';
  86. file_put_contents($citiesFile, $content);
  87. return $newCitiesArr;
  88. } else if ($platform == 'huolala') {
  89. $citiesArr = $cities['data']['city_list'];
  90. $newCitiesArr = [
  91. 'expire' => $cities['data']['expire'],
  92. ];
  93. foreach($citiesArr as $city) {
  94. $newCitiesArr[$city['name']] = [
  95. 'city_id' => $city['city_id'],
  96. 'city_name' => $city['name'],
  97. ];
  98. }
  99. // 把newCitiesArr保存到 platform/huolala/cities.php 文件中
  100. $citiesFile = Yii::getAlias('@common/components/delivery/platform/huolala/cities.php');
  101. // 如果文件不存在,则创建文件
  102. if (!file_exists($citiesFile)) {
  103. file_put_contents($citiesFile, '<?php namespace common\components\delivery\platform\huolala; return []; ?>');
  104. }
  105. // 文件内容要包含命名空间
  106. $content = '<?php namespace common\components\delivery\platform\huolala; return ' . var_export($newCitiesArr, true) . '; ?>';
  107. file_put_contents($citiesFile, $content);
  108. return $newCitiesArr;
  109. } else {
  110. return $cities;
  111. }
  112. return $cities;
  113. }
  114. public function actionAddress()
  115. {
  116. $post = Yii::$app->request->post();
  117. $adminId = $this->adminId;
  118. util::checkRepeatCommit($adminId, 4);
  119. $orderId = intval($post['orderId']);
  120. $order = OrderClass::getById($orderId, false, 'fullAddress');
  121. $shop = ShopClass::getById($this->shopId, false, 'fullAddress');
  122. $ret = [
  123. "send_address" => $shop['fullAddress'],
  124. "receive_address" => $order['fullAddress']
  125. ];
  126. util::success($ret, "success");
  127. }
  128. // 获取多个平台报价
  129. public function actionAllDeliveryQuotes()
  130. {
  131. $post = Yii::$app->request->post();
  132. $adminId = $this->adminId;
  133. util::checkRepeatCommit($adminId, 4);
  134. $orderId = intval($post['orderId']);
  135. $order = OrderClass::getById($orderId);
  136. $shop = ShopClass::getById($this->shopId);
  137. $ds = new DispatchService($this->mainId);
  138. $platforms = $ds->getBestPlatformByPrice($order, $shop);
  139. $deliveryList = [];
  140. foreach ($platforms['quotes'] as $item) {
  141. switch ($item['platform']) {
  142. case 'shansong':
  143. $deliveryList[] = [
  144. 'name' => '闪送',
  145. 'en_name' => 'shansong',
  146. 'price' => $item['total_amount'],
  147. 'distance' => $item['total_distance'],
  148. 'type' => ''
  149. ];
  150. break;
  151. case 'fengniao':
  152. // 循环遍历 goods_infos 数组,提取有效项的信息
  153. $validGoods = [];
  154. if (!empty($item['goods_infos']) && is_array($item['goods_infos'])) {
  155. foreach ($item['goods_infos'] as $good) {
  156. if (!empty($good['is_valid']) && $good['is_valid'] == 1) {
  157. $validGoods[] = [
  158. 'actual_delivery_amount_cent' => $good['actual_delivery_amount_cent'] ?? 0,
  159. 'service_goods_id' => $good['service_goods_id'] ?? ''
  160. ];
  161. }
  162. }
  163. }
  164. $deliveryList[] = [
  165. 'name' => '蜂鸟',
  166. 'en_name' => 'fengniao',
  167. 'price' => !empty($validGoods) ? $validGoods[0]['actual_delivery_amount_cent'] : 0,
  168. 'distance' => $item['distance'],
  169. 'valid_goods' => $validGoods, // 返回所有有效的商品信息
  170. 'type' => ''
  171. ];
  172. break;
  173. case 'huolala':
  174. $deliveryList[] = [
  175. 'name' => '货拉拉',
  176. 'en_name' => 'huolala',
  177. 'price' => isset($item['price_list']) ? $item['price_list'][0]['price_conditions'][0]['total_price'] : 0,
  178. 'distance' => isset($item['price_list']) ? $item['price_list'][0]['distance_info']['distance_total'] : 0,
  179. 'type' => $item['vehicle_type'],
  180. 'city_id' => $item['city_id'],
  181. 'city_info_revision' => $item['city_info_revision'],
  182. ];
  183. break;
  184. }
  185. }
  186. $ret['deliveryList'] = $deliveryList;
  187. util::success($ret, "success");
  188. }
  189. // 创建订单(真实下单)
  190. public function actionCreateOrder()
  191. {
  192. $post = Yii::$app->request->post();
  193. $platform = $post['platform'];
  194. // huolala 需要有以下参数
  195. // 'city_id' => 下单城市ID (必需),
  196. // 'city_info_revision' => 城市版本号 (必需) -- 下单城市版本号, 示例:296,从u-city-info接口获取
  197. // 'order_vehicle_id' => 车型ID (必需),
  198. // 'vehicle_std' => ['双排座'] 车型附加要求 (可选),
  199. // 'order_time' => 用车时间戳(秒) (必需),
  200. $ds = new DispatchService($this->mainId, $platform);
  201. $order = [];
  202. $platforms = $ds->createOrder($order);
  203. }
  204. // 查询订单(查单)
  205. // 第三方回调入口
  206. /**
  207. * 回调接口
  208. */
  209. public function actionCallback()
  210. {
  211. $callbackData = Yii::$app->request->post();
  212. if (empty($callbackData)) {
  213. $postStr = file_get_contents('php://input');
  214. $callbackData = json_decode($postStr, true);
  215. if (empty($callbackData)) {
  216. util::fail('回调请求的数据为空');
  217. }
  218. }
  219. // 从配置中获取安全token
  220. // $token = Yii::$app->params['wx_intracity_token'] ?? 'your_token_here';
  221. // $result = IntraCityExpress::handleOrderCallback($callbackData, $token);
  222. // 记录回调日志
  223. Yii::info('聚合配送回调:' . json_encode($callbackData, JSON_UNESCAPED_UNICODE), 'delivery');
  224. }
  225. /**
  226. * 闪送授权回调接口
  227. */
  228. public function actionShansongAuthCallback()
  229. {
  230. $code = Yii::$app->request->get('code');
  231. $state = Yii::$app->request->get('state');
  232. $shopId = Yii::$app->request->get('shopId');
  233. $isAllStoreAuth = Yii::$app->request->get('isAllStoreAuth');
  234. $thirdStoreId = Yii::$app->request->get('thirdStoreId');
  235. $storeId = Yii::$app->request->get('storeId');
  236. // 验证state参数(防止CSRF)
  237. //if ($state != $yourUserId) {
  238. //throw new \yii\web\BadRequestHttpException('Invalid state parameter');
  239. //}
  240. // 获取AccessToken
  241. $auth = new \common\components\delivery\platform\shansong\Auth();
  242. $result = $auth->getAccessToken($code);
  243. if (!$result['success']) {
  244. throw new \yii\web\HttpException(500, '获取授权失败:' . $result['error']);
  245. }
  246. // 保存授权信息到数据库
  247. $data = [
  248. 'user_id' => $state,
  249. 'shop_id' => $shopId,
  250. 'access_token' => $result['access_token'],
  251. 'refresh_token' => $result['refresh_token'],
  252. 'expires_at' => time() + $result['expires_in'],
  253. 'auth_type' => $isAllStoreAuth ? 'all_store' : 'single_store',
  254. 'platform_type' => 'shansong'
  255. ];
  256. if (!$isAllStoreAuth) {
  257. $data['third_store_id'] = $thirdStoreId;
  258. $data['shans_store_id'] = $storeId;
  259. }
  260. ShansAuthTokenClass::add($data);
  261. if (false) {
  262. throw new \yii\web\HttpException(500, '保存授权信息失败');
  263. }
  264. return $this->asJson(['return_code' => 0, 'return_msg' => 'OK']);
  265. }
  266. /**
  267. * 货拉拉授权回调接口
  268. */
  269. public function actionHuolalaAuthCallback()
  270. {
  271. $get = Yii::$app->request->get();
  272. $getData = json_encode($get, JSON_UNESCAPED_UNICODE);
  273. Yii::info($getData);
  274. $callbackData = Yii::$app->request->post();
  275. if (empty($callbackData)) {
  276. $postStr = file_get_contents('php://input');
  277. $callbackData = json_decode($postStr, true);
  278. if (empty($callbackData)) {
  279. Yii::info('回调请求的数据为空');
  280. }
  281. }
  282. Yii::info('货拉拉授权回调:' . json_encode($callbackData, JSON_UNESCAPED_UNICODE), 'delivery');
  283. $code = $get['code'];
  284. $mainId = $get['mainId'];
  285. // 获取AccessToken
  286. $auth = new \common\components\delivery\platform\huolala\Auth();
  287. $result = $auth->getAccessToken($code);
  288. if (!$result['success']) {
  289. throw new \yii\web\HttpException(500, '获取授权失败:' . $result['error']);
  290. }
  291. // 保存授权信息到数据库
  292. $data = [
  293. 'user_id' => $mainId,
  294. 'shop_id' => $result['auth_mobile'],
  295. 'access_token' => $result['access_token'],
  296. 'refresh_token' => $result['refresh_token'],
  297. 'expires_at' => strtotime($result['auth_end_time']),
  298. 'auth_type' => 'all_store',
  299. 'platform' => 'huolala'
  300. ];
  301. ShansAuthTokenClass::add($data);
  302. return $this->asJson(['return_code' => 0, 'return_msg' => 'OK']);
  303. }
  304. /**
  305. * 蜂鸟授权回调接口
  306. */
  307. public function actionFengniaoAuthCallback()
  308. {
  309. $get = Yii::$app->request->get();
  310. $getData = json_encode($get, JSON_UNESCAPED_UNICODE);
  311. Yii::info($getData);
  312. $callbackData = Yii::$app->request->post();
  313. if (empty($callbackData)) {
  314. $postStr = file_get_contents('php://input');
  315. $callbackData = json_decode($postStr, true);
  316. if (empty($callbackData)) {
  317. Yii::info('回调请求的数据为空');
  318. }
  319. }
  320. Yii::info('蜂鸟授权回调:' . json_encode($callbackData, JSON_UNESCAPED_UNICODE), 'fengniao');
  321. $mainId = $get['mainId'];
  322. $code = $get['code'];
  323. $merchantId = $get['merchant_id'];
  324. $scope = $get['scope'];
  325. $state = $get['state'];
  326. // 获取AccessToken
  327. $auth = new \common\components\delivery\platform\fengniao\Auth();
  328. $result = $auth->getAccessToken($code, $merchantId);
  329. if (!$result['success']) {
  330. throw new \yii\web\HttpException(500, '获取授权失败:' . $result['error']);
  331. }
  332. $result = $result['data'];
  333. // 保存授权信息到数据库
  334. $data = [
  335. 'user_id' => $mainId,
  336. 'shop_id' => '',
  337. 'access_token' => $result['access_token'],
  338. 'refresh_token' => $result['refresh_token'],
  339. 'expires_at' => $result['expire_in'],
  340. 'auth_type' => 'all_store',
  341. 'platform' => 'fengniao'
  342. ];
  343. ShansAuthTokenClass::add($data);
  344. return $this->asJson(['return_code' => 0, 'return_msg' => 'OK']);
  345. }
  346. /**
  347. * 达达授权回调接口
  348. */
  349. public function actionDadaAuthCallback()
  350. {
  351. $get = Yii::$app->request->get();
  352. $getData = json_encode($get, JSON_UNESCAPED_UNICODE);
  353. Yii::info($getData);
  354. $callbackData = Yii::$app->request->post();
  355. if (empty($callbackData)) {
  356. $postStr = file_get_contents('php://input');
  357. $callbackData = json_decode($postStr, true);
  358. if (empty($callbackData)) {
  359. Yii::info('回调请求的数据为空');
  360. }
  361. }
  362. Yii::info('达达授权回调:' . json_encode($callbackData, JSON_UNESCAPED_UNICODE), 'dada');
  363. }
  364. }