RentBikeController.php 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Mead
  5. * Date: 2019/11/6
  6. * Time: 8:53 PM.
  7. */
  8. namespace App\Http\Controllers\V1;
  9. use Alipay\EasySDK\Kernel\Util\ResponseChecker;
  10. use App\Handlers\BaseBikeControl;
  11. use App\Handlers\BikeHandler;
  12. use App\Handlers\BikeStatusInfoSyncHandler;
  13. use App\Handlers\ConvertHandler;
  14. use App\Http\Requests\RetryBikeRequest;
  15. use App\Jobs\CloseRentOrderJob;
  16. use App\Maps\CacheMap;
  17. use App\Models\Area;
  18. use App\Models\AreaSetting;
  19. use App\Models\Auth;
  20. use App\Models\Bike;
  21. use App\Models\RentOrder;
  22. use App\Models\RentOrderBikeOperate;
  23. use App\Models\User;
  24. use App\Models\WalletLog;
  25. use App\Repositories\AreaRepository;
  26. use App\Repositories\AreaSettingRepository;
  27. use App\Repositories\BikeRepository;
  28. use App\Repositories\LocationLogRepository;
  29. use App\Repositories\OrderRepository;
  30. use App\Repositories\PunishmentOrderRepository;
  31. use App\Repositories\RentOrderBikeOperateRepository;
  32. use App\Repositories\RentOrderRepository;
  33. use App\Repositories\UserRepository;
  34. use App\Transformers\RentOrderTransformer;
  35. use App\Transformers\RentUseOrderTransformer;
  36. use Carbon\Carbon;
  37. use Dingo\Api\Http\Request;
  38. use EasyWeChat\Factory;
  39. use Illuminate\Support\Facades\Log;
  40. use function EasyWeChat\Kernel\Support\generate_sign;
  41. use Illuminate\Support\Facades\Cache;
  42. use Illuminate\Support\Facades\DB;
  43. use Illuminate\Support\Facades\Redis;
  44. use Symfony\Component\HttpKernel\Exception\HttpException;
  45. /**
  46. * 日租车模块
  47. * Class RentBikeController
  48. * @package App\Http\Controllers\V1
  49. */
  50. class RentBikeController extends BaseController
  51. {
  52. /**
  53. * 租车下单
  54. * User: Mead.
  55. */
  56. public function storeOrder(Request $request, BikeRepository $bikeRepository, RentOrderRepository $rentOrderRepository, OrderRepository $orderRepository, AreaSettingRepository $areaSettingRepository, PunishmentOrderRepository $punishmentOrderRepository, UserRepository $userRepository)
  57. {
  58. try {
  59. $type = $request->get('type');
  60. $bike_no = $request->get('bike_no');
  61. $area_id = $request->get('area_id');
  62. $lat = $request->get('lat');
  63. $lng = $request->get('lng');
  64. $cache_key = "OPEN_RENT_BIKE_ORDER_{$bike_no}";
  65. if (Cache::has($cache_key)) {
  66. return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
  67. }
  68. Cache::put($cache_key, 1, Carbon::now()->addSeconds(5));
  69. $bike = $bikeRepository->byNoIsCanRentBikeGetModel($bike_no);
  70. if (!$bike) {
  71. return $this->errorNoValidation('该车暂不能用');
  72. }
  73. //以车的区域为主
  74. if ($bike->put_area_id !== $area_id) {
  75. $area_id = $bike->put_area_id;
  76. }
  77. // 判断用户押金,授权,认证,手机号状态是否正常
  78. $user = $this->user;
  79. if (User::BIND_MOBILE_NO === (int)$user->is_bind_mobile) {
  80. return $this->errorNoValidation('请先绑定您的手机号');
  81. }
  82. $setting = $areaSettingRepository->byAreaId($area_id);
  83. if ((int)$setting['is_card']) {
  84. if ((int)$user->is_card_certified === User::CARD_NO) {
  85. return $this->errorNoValidation('请您先完善实名认证');
  86. }
  87. if (User::RIDE_BIKE_AGE_NO === (int)$user->is_match_ride_age) {
  88. return $this->errorNoValidation('未成年人禁止骑车');
  89. }
  90. }
  91. if (!$setting->is_open_day_rent) {
  92. return $this->errorNoValidation('该区域租车暂不开放,敬请期待!');
  93. }
  94. if ((int)$setting['is_deposit']) {
  95. if ((int)$user->is_deposit === User::DEPOSIT_NO) {
  96. return $this->errorNoValidation('请您先交纳押金');
  97. }
  98. }
  99. $punish = $punishmentOrderRepository->checkNoPayModel($user->id);
  100. if (!$punish) return $this->errorNoValidation('您有罚单未支付,请先处理');
  101. // 判断用户是否有为支付的订单
  102. if ($orderRepository->byUserIdCheckIsExistRideOrder($user->id)) {
  103. return $this->errorNoValidation('您有未完成的订单,请先处理');
  104. }
  105. if ($rentOrderRepository->byUserIdCheckIsExistRideOrder($user->id)) {
  106. return $this->errorNoValidation('您有未完成的租车订单,请先处理');
  107. }
  108. // 判断用户是否在车的距离范围内
  109. $options = ['SORT' => 'ASC'];
  110. $redis = Redis::connection();
  111. $nearby_bikes = $redis->georadius(Bike::REDIS_BIKE_LOCATION_TAG, $lng, $lat, 1, 'km', $options);
  112. //
  113. // if (!in_array($bike->bike_no, $nearby_bikes)) {
  114. // return $this->errorNoValidation('小主,咱俩有点远!');
  115. // }
  116. $user_id = $this->user->id;
  117. $cache_key = "RIDE_RENT_ORDER_{$user_id}";
  118. if (Cache::has($cache_key)) {
  119. return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
  120. }
  121. Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
  122. //不同类型处理价格(暂不用)
  123. // 下单
  124. $rent_money = $setting->day_rent_money;
  125. $users = User::find($user['id']);
  126. $settingConfig = [
  127. 'rent_money' => $setting->day_rent_money,
  128. 'rent_time' => $setting->day_rent_hours,
  129. 'over_rent_time_money' => $setting->per_hours_day_rent_timeout_money,
  130. 'over_rent_time_max_money' => $setting->day_rent_capping_money,
  131. ];
  132. $data = [
  133. 'user_id' => $user['id'],
  134. 'no' => RentOrder::makeNo(self::$ORDER_TAG),
  135. 'type' => RentOrder::TYPE_DAY_RENT,
  136. 'bike_no' => $bike_no,
  137. 'bike_id' => $bike->id,
  138. 'area_id' => $area_id,
  139. 'phone_detail' => $users->userPhoneDetail->detail ?? '',
  140. 'start_use_bike_location' => [
  141. 'latitude' => $lat,
  142. 'longitude' => $lng,
  143. ],
  144. 'rent_money' => $rent_money,
  145. 'rent_preferential_money' => 0.00,
  146. 'rent_total_money' => $rent_money,
  147. 'status' => RentOrder::STATUS_WAIT_PAY_RENT_MONEY,
  148. 'setting' => $settingConfig,
  149. 'merchant_id' => self::$MERCHANT_ID
  150. ];
  151. $order = RentOrder::create($data);
  152. $this->dispatch(new CloseRentOrderJob($order, Carbon::now()->addMinutes(10)));
  153. // 更新用户的区域id
  154. if (!$user->register_area_id) {
  155. $user->register_area_id = $area_id;
  156. $user->save();
  157. }
  158. $order->status = RentOrder::STATUS_RENT_BIKE;
  159. $order->start_use_bike_time = now();
  160. $order->return_end_bike_time = Carbon::now()->addHours($settingConfig['rent_time'])->toDateTimeString();
  161. $order->save();
  162. $bike->is_rent = Bike::RENT_YES;
  163. $bike->is_riding = Bike::RIDING_YES;
  164. $bike->save();
  165. //同步redis
  166. (new BikeStatusInfoSyncHandler())->toBikeRideStatus(BikeStatusInfoSyncHandler::ROLE_USER, $bike->bike_no, [
  167. 'id' => $order->id,
  168. 'bike_id' => $order->bike_id,
  169. 'area_id' => $order->area_id,
  170. 'is_rent' => 1,
  171. ], $bike->merchant_id);
  172. $params['no'] = $order->no;
  173. return $this->response->array($params);
  174. } catch (\Exception $exception) {
  175. return $this->exception($exception);
  176. }
  177. }
  178. public function useOrder(Request $request, RentOrderRepository $rentOrderRepository)
  179. {
  180. try {
  181. $no = $request->get('no');
  182. $order = $rentOrderRepository->byNo($no);
  183. return $this->response->item($order, RentUseOrderTransformer::class);
  184. } catch (\Exception $exception) {
  185. return $this->exception($exception);
  186. }
  187. }
  188. /**
  189. * @param Request $request
  190. * @param RentOrderRepository $rentOrderRepository
  191. *
  192. * @return \Dingo\Api\Http\Response
  193. * User: Mead
  194. */
  195. public function show(Request $request, RentOrderRepository $rentOrderRepository)
  196. {
  197. try {
  198. $no = $request->get('no');
  199. $order = $rentOrderRepository->byNo($no);
  200. return $this->response->item($order, new RentOrderTransformer());
  201. } catch (\Exception $exception) {
  202. return $this->exception($exception);
  203. }
  204. }
  205. /**
  206. * 结束租车
  207. * User: Mead.
  208. */
  209. public function closeOrder(Request $request, RentOrderRepository $rentOrderRepository, BikeRepository $bikeRepository, LocationLogRepository $locationLogRepository, AreaSettingRepository $areaSettingRepository)
  210. {
  211. try {
  212. $bike_no = $request->get('bike_no');
  213. $order_no = $request->get('order_no');
  214. $lat = $request->get('lat');
  215. $lng = $request->get('lng');
  216. $order = $rentOrderRepository->byNoGetRideOrder($order_no);
  217. if (!$order) {
  218. return $this->errorNoValidation('订单不存在或订单已结算');
  219. }
  220. if (Bike::RIDING_YES === (int)$order->bike_is_riding) {
  221. return $this->errorNoValidation('请先关锁再还车');
  222. }
  223. if ($rentOrderRepository->checkUserMoreCloseOrder($this->user->id)) {
  224. return $this->errorNoValidation('您今天太频繁操作车辆');
  225. }
  226. $user_id = $this->user->id;
  227. $cache_key = "RIDE_CLOSE_RENT_ORDER_{$user_id}";
  228. if (Cache::has($cache_key)) {
  229. return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
  230. }
  231. Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
  232. //获取车的最后位置
  233. $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no, CacheMap::IS_OPEN_MONGODB_DUG);
  234. if ($location['lat'] <= 0) {
  235. $location['lat'] = $order->end_use_bike_location['latitude'];
  236. $location['lng'] = $order->end_use_bike_location['longitude'];
  237. if ($location['lat'] <= 0) {
  238. $location['lat'] = $lat;
  239. $location['lng'] = $lng;
  240. }
  241. }
  242. // 更新车的信息
  243. $bikeModel = $bikeRepository->byIdGetModel($order->bike_id);
  244. $bikeModel->is_riding = Bike::RIDING_NO;
  245. $bikeModel->is_rent = Bike::RENT_NO;
  246. $bikeModel->save();
  247. //更新redis
  248. (new BikeStatusInfoSyncHandler())->toBikeWaitRideStatus($order->bike_no, $location['lng'], $location['lat'], $bikeModel->merchant_id);
  249. // 判断是否经常这样操作(未做)
  250. $second = Carbon::now()->diffInSeconds(Carbon::parse($order->start_use_bike_time));
  251. if ($second <= AreaSetting::CLOSE_BIKE_TIME) {
  252. // 关闭订单
  253. $order->status = RentOrder::STATUS_CLOSE_ORDER;
  254. $order->end_use_bike_location = [
  255. 'latitude' => $lat,
  256. 'longitude' => $lng,
  257. ];
  258. $order->end_use_bike_time = now();
  259. $order->rent_money = 0;
  260. $order->save();
  261. //退钱
  262. // 记录临时关锁
  263. return $this->response->item($order, RentOrderTransformer::class);
  264. }
  265. //检查是否在禁停区
  266. $BikeHandler = new BikeHandler();
  267. $is_ban_stop_bike = $BikeHandler->byLocationCheckIsInBanStopParking($location['lat'], $location['lng'], $order->area_id, $lat, $lng);
  268. if ($is_ban_stop_bike) {
  269. return $this->errorNoValidation('禁停区域内禁止停车!');
  270. }
  271. // 结束订单
  272. $setting = $order->setting;
  273. $money = 0.00;
  274. $over_hours = 0;
  275. //是否需要收取超出费用
  276. $is_over_time = (strtotime($order->return_end_bike_time) < time());
  277. if ($is_over_time) {
  278. //超出时间
  279. $over_hours = ceil(Carbon::now()->diffInMinutes(Carbon::parse($order->return_end_bike_time)) / 60);
  280. $hours = ceil(Carbon::now()->diffInMinutes(Carbon::parse($order->start_use_bike_time)) / 60);
  281. if ($hours > 24) {
  282. //超过1天
  283. $day = ceil($hours / 24);
  284. $end_hours = $hours % 24;
  285. //日封顶租金*天
  286. $money = bcmul($setting['over_rent_time_max_money'], ($day - 1), 2);
  287. // $money = bcadd($money, $setting['rent_money'], 2);
  288. if ($end_hours > $setting['rent_time']) {
  289. // 超过一天 又超过8小时
  290. // (超时费 + 日封顶租金*天)
  291. $money = bcadd(bcmul(($end_hours - $setting['rent_time']), $setting['over_rent_time_money'], 2), $money, 2);
  292. }
  293. } else {
  294. // 不超过1天 但是超过8小时
  295. $money = bcmul($over_hours, $setting['over_rent_time_money'], 2);
  296. // (超时费 + 基础租金) 是否大于日封顶租金
  297. $total_money = bcadd($money, $setting['rent_money'], 2);
  298. if ($total_money > $setting['over_rent_time_max_money']) {
  299. $money = bcsub($setting['over_rent_time_max_money'], $setting['rent_money'], 2);
  300. }
  301. }
  302. }
  303. //计算骑行距离
  304. $order->use_bike_distance_length = bcdiv($location['mileage'], 1000, 2);
  305. // 日租结算
  306. $order->time_money = $money;
  307. $order->distance_money = 0.00;
  308. $order->preferential_money = 0.00;
  309. $order->over_hours = $over_hours;
  310. // 租金 + 超时费
  311. $order->total_money = bcadd($money, $order->rent_money, 2);
  312. $order->pay_money = $order->total_money;
  313. //判断是否收取调度费
  314. if ($order->dispatch_money > 0) {
  315. $order->total_money = bcadd($order->total_money, $order->dispatch_money, 2);
  316. }
  317. if ($order->total_money > 0) {
  318. $order->status = RentOrder::STATUS_CLOSE_RENT_BIKE;
  319. } else {
  320. $order->status = RentOrder::STATUS_COMPLETE_ORDER;
  321. }
  322. //计算用车时间 (分)
  323. $order->use_bike_time_length = ceil($second / 60);
  324. // 车辆最后位置 (防止定位失败的情况)
  325. if (empty($order->end_use_bike_location)) {
  326. $order->end_use_bike_location = [
  327. 'latitude' => $lat,
  328. 'longitude' => $lng,
  329. ];
  330. }
  331. $order->end_use_bike_time = Carbon::now();
  332. $order->order_total_money = $order->total_money;
  333. $order->save();
  334. // 删除redis订单
  335. if (RentOrder::STATUS_COMPLETE_ORDER === (int)$order->status) {
  336. (new BikeStatusInfoSyncHandler())->toBikeWaitRideStatus($order->bike_no, $location['lng'], $location['lat'], $bikeModel->merchant_id);
  337. }
  338. return $this->response->item($order, RentOrderTransformer::class);
  339. } catch (HttpException $exception) {
  340. return $this->errorNoValidation($exception->getMessage(), $exception->getStatusCode());
  341. }
  342. }
  343. public function payShow(Request $request, RentOrderRepository $rentOrderRepository, RentOrderBikeOperateRepository $rentOrderBikeOperateRepository)
  344. {
  345. try {
  346. $order_no = $request->get('order_no');
  347. $order = $rentOrderRepository->byNoAndUserId($order_no, $this->user->id);
  348. if (!$order) {
  349. return $this->errorNoValidation('订单不存在!');
  350. }
  351. // 检查用户余额是否够
  352. $is_user_wallet = true;
  353. if ($order->pay_money > $this->user->wallet_money) {
  354. // 余额不够
  355. $is_user_wallet = false;
  356. }
  357. if (bccomp($order->total_money, 0) === 0) {
  358. $order->pay_type = RentOrder::PAY_STATUS_OK;
  359. $order->status = RentOrder::STATUS_CLOSE_ORDER;
  360. }
  361. $order->save();
  362. // 检查是否系统自动锁车
  363. $is_system_off_lock = $rentOrderBikeOperateRepository->checkLowPowerOffLock($order->id);
  364. $is_coupon = false;
  365. $userCoupons = [];
  366. $ridingCard = [];
  367. return $this->response->array([
  368. 'order' => $order->append(['use_bike_time_length_text', 'use_bike_distance_length_text', 'end_use_bike_time_timestamp'])->toArray(),
  369. 'orders' => [
  370. 'id' => $order->id,
  371. 'no' => $order->no,
  372. 'bike_no' => $order->bike_no,
  373. 'use_bike_time_length_text' => $order->use_bike_time_length_text,
  374. 'use_bike_distance_length_text' => $order->use_bike_distance_length_text,
  375. 'end_use_bike_time_timestamp' => $order->end_use_bike_time_timestamp,
  376. 'pay_status' => $order->pay_status,
  377. 'pay_money' => $order->pay_money,
  378. 'time_money' => $order->time_money, // 时长费
  379. 'rent_money' => $order->rent_money, // 租费
  380. 'dispatch_money' => $order->dispatch_money, // 调度费
  381. 'distance_money' => $order->distance_money, // 里程费用
  382. 'total_money' => $order->total_money,// 加调度费的总金额
  383. 'order_total_money' => bcadd($order->rent_money, $order->time_money, 2), // 不加调度费的总金额
  384. 'order_wait_pay_money' => empty($userCoupons) ? $order->total_money : $userCoupons['order_wait_pay_money'], // 总待支付
  385. 'total_preferential_money' => empty($userCoupons) ? $order->preferential_money : $userCoupons['total_preferential_money'], // 总优惠
  386. ],
  387. 'wallet_pay_status' => $is_user_wallet,
  388. 'wallet_money' => $this->user->wallet_money,
  389. 'user_coupon' => [
  390. 'is_coupon' => $is_coupon,
  391. 'coupon_preferential_money' => empty($userCoupons) ? '0.00' : $userCoupons['coupon_preferential_money'], // 优惠券优惠的金额
  392. 'coupon_user_bags_id' => empty($userCoupons) ? 0 : $userCoupons['id'],
  393. ],
  394. 'user_card' => [
  395. 'is_card' => empty($ridingCard) ? false : true,
  396. 'card' => $ridingCard,
  397. 'card_preferential_money' => $order->preferential_money, // 没支付之前优惠金额就是 骑行卡优惠的金额
  398. ],
  399. 'system_off_lock' => [
  400. 'is_system_off_lock' => empty($is_system_off_lock) ? false : true,
  401. 'system_off_lock_text' => '电量过低,系统自动还车,敬请谅解,如有疑问请致电客服'
  402. ],
  403. ]);
  404. } catch (\Exception $exception) {
  405. return $this->exception($exception);
  406. }
  407. }
  408. public function pay(Request $request, RentOrderRepository $rentOrderRepository)
  409. {
  410. try {
  411. $pay_type = $request->get('payment_type', self::PATMENT_TYPE_MINIAPP);
  412. $order_no = $request->get('order_no');
  413. $order = $rentOrderRepository->byNo($order_no);
  414. if (!$order) {
  415. return $this->errorBadRequest('订单不存在');
  416. }
  417. if (RentOrder::STATUS_COMPLETE_ORDER === (int)$order->status) {
  418. return $this->errorNoValidation('订单已完成');
  419. }
  420. if (RentOrder::STATUS_CLOSE_ORDER === (int)$order->status) {
  421. return $this->errorNoValidation('订单已关闭');
  422. }
  423. if (RentOrder::PAY_STATUS_OK === (int)$order->pay_status) {
  424. return $this->errorNoValidation('订单已支付');
  425. }
  426. if (RentOrder::STATUS_RENT_BIKE === (int)$order->status) {
  427. return $this->errorNoValidation('请先结束租车订单,再支付');
  428. }
  429. $user = $this->user;
  430. if ($order->user_id !== $user->id) {
  431. return $this->errorNoValidation('非法操作');
  432. }
  433. $response = '';
  434. $user_id = $user['id'];
  435. $cache_key = "PAY_RENT_ORDER_{$user_id}";
  436. if (Cache::has($cache_key)) {
  437. return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
  438. }
  439. Cache::put($cache_key, 1, Carbon::now()->addSeconds(5));
  440. if ($pay_type == self::PATMENT_TYPE_ACCOUNT) {
  441. //余额支付
  442. if (bccomp($order->total_money, $this->user->wallet_money) === 1) {
  443. // 余额不够
  444. return $this->errorNoValidation('用户余额不够');
  445. }
  446. DB::transaction(function () use ($order, $user) {
  447. //添加钱包记录
  448. WalletLog::log(WalletLog::OPERATE_TYPE_SUB, $order->total_money, $user->id, WalletLog::TYPE_SUB_WALLET_RENT_ORDER_MONEY, $order->area_id, $order->id, RentOrder::class);
  449. //修改订单记录
  450. $order->pay_status = RentOrder::PAY_STATUS_OK;
  451. $order->pay_money = $order->total_money;
  452. $order->pay_time = now();
  453. $order->pay_type = RentOrder::PAY_TYPE_ACCOUNT;
  454. $order->status = RentOrder::STATUS_COMPLETE_ORDER;
  455. $order->order_total_money = $order->total_money;
  456. $order->save();
  457. });
  458. $response = [
  459. 'pay_order_status' => true,
  460. ];
  461. } else {
  462. $userauth = userAuthinfo(self::$MERCHANT, $user_id);
  463. if ($userauth['code'] != 1) {
  464. return $this->errorNoValidation($userauth['msg']);
  465. }
  466. switch (self::$SOURCE_TYPE) {
  467. case self::SOURCE_TYPE_WECHAT:
  468. //微信支付
  469. $payment = Factory::payment(wechat_pay_config(self::$MERCHANT)); // 微信支付
  470. $order->over_no = RentOrder::makeOverNo();
  471. $order->save();
  472. $result = $payment->order->unify([
  473. 'body' => "用户支付日租车租车费用-" . self::$MERCHANT['wxapp_name'],
  474. 'out_trade_no' => $order->no,
  475. 'trade_type' => 'JSAPI', // 必须为JSAPI
  476. 'openid' => $userauth['data']['credential'], // 这里的openid为付款人的openid
  477. 'total_fee' => wechat_fee($order->total_money), // 总价
  478. 'attach' => makeNoTag(RentOrder::NO_TAG),
  479. 'notify_url' => config('app.url') . '/api/payments/wechat-rent-notify',
  480. ]);
  481. if ($result['return_code'] === 'FAIL') return $this->errorNoValidation('下单失败');
  482. // 如果成功生成统一下单的订单,那么进行二次签名
  483. if ($result['result_code'] === 'FAIL') {
  484. //判断是否重复下单
  485. if ($result['err_code'] === 'INVALID_REQUEST') {
  486. $order->no = RentOrder::makeNo(self::$ORDER_TAG);
  487. $order->save();
  488. $result = $payment->order->unify([
  489. 'body' => "用户支付日租车租车费用-" . self::$MERCHANT['wxapp_name'],
  490. 'out_trade_no' => $order->no,
  491. 'trade_type' => 'JSAPI', // 必须为JSAPI
  492. 'openid' => $userauth['data']['credential'], // 这里的openid为付款人的openid
  493. 'total_fee' => wechat_fee($order->total_money), // 总价
  494. 'attach' => makeNoTag(RentOrder::NO_TAG),
  495. 'notify_url' => config('app.url') . '/api/payments/wechat-rent-notify',
  496. ]);
  497. } elseif ($result['err_code'] === 'ORDERPAID') {
  498. $order->pay_status = RentOrder::PAY_STATUS_OK;
  499. $order->pay_time = now();
  500. $order->pay_type = RentOrder::PAY_TYPE_WECHAT;
  501. $order->pay_money = $order->total_money;
  502. $order->order_total_money = $order->pay_money;
  503. $order->status = RentOrder::STATUS_COMPLETE_ORDER;
  504. $order->save();
  505. $order->pay_rent_over_order_callback();
  506. return $this->errorNoValidation('订单已支付,请勿重复支付!');
  507. } else {
  508. return $this->errorNoValidation('下单失败');
  509. }
  510. }
  511. if ('SUCCESS' === $result['return_code'] && 'SUCCESS' === $result['result_code']) {
  512. // 二次签名的参数必须与下面相同
  513. $params = [
  514. 'appId' => $userauth['data']['identifier'],
  515. 'timeStamp' => time(),
  516. 'nonceStr' => $result['nonce_str'],
  517. 'package' => 'prepay_id=' . $result['prepay_id'],
  518. 'signType' => 'MD5',
  519. ];
  520. // self::$MERCHANT['pay_key']为商户的key
  521. $params['paySign'] = generate_sign($params, self::$MERCHANT['pay_key']);
  522. $response = $params;
  523. } else {
  524. return $this->errorNoValidation('下单失败');
  525. }
  526. break;
  527. case self::SOURCE_TYPE_ALIPAY:
  528. //支付宝支付
  529. $order->over_no = RentOrder::makeOverNo();
  530. $order->save();
  531. $money = $order->total_money;
  532. $ordernono = $order->no;
  533. $notifyUrl = config('app.url') . '/api/payments/alipay_rent_notify/' . self::$MERCHANT['id'];
  534. $result = alipay_mini_config(self::$MERCHANT, $notifyUrl)->payment()->common()
  535. ->create("用户支付日租车租车费用-" . self::$MERCHANT['wxapp_name'], $ordernono, $money, $userauth['data']['credential']);
  536. $responseChecker = new ResponseChecker();
  537. if (!($responseChecker->success($result))) {
  538. //客服修改支付价格后重新生成订单
  539. if ($result->subCode == 'ACQ.CONTEXT_INCONSISTENT') { //信息被篡改判断
  540. $order->no = RentOrder::makeNo(self::$ORDER_TAG);
  541. $order->save();
  542. $money = $order->total_money;
  543. $ordernono = $order->no;
  544. $result = alipay_mini_config(self::$MERCHANT, $notifyUrl)->payment()->common()
  545. ->create("用户支付日租车租车费用-" . self::$MERCHANT['wxapp_name'], $ordernono, $money, $userauth['data']['credential']);
  546. if (!($responseChecker->success($result))) {
  547. return $this->errorNoValidation("调用失败,原因:" . $result->msg . "," . $result->subMsg);
  548. }
  549. } else {
  550. return $this->errorNoValidation("调用失败,原因:" . $result->msg . "," . $result->subMsg);
  551. }
  552. }
  553. $response = [];
  554. $response['tradeNo'] = $result->tradeNo; //获取支付宝订单号
  555. return $this->response->array($response);
  556. break;
  557. default:
  558. return $this->errorBadRequest('支付类型不对');
  559. break;
  560. }
  561. }
  562. $response['order_no'] = $order->no;
  563. return $this->response->array($response);
  564. } catch (\Exception $exception) {
  565. return $this->exception($exception);
  566. }
  567. }
  568. /**
  569. * 开锁
  570. * User: Mead.
  571. */
  572. public function openBike(Request $request, RentOrderRepository $rentOrderRepository, BikeRepository $bikeRepository)
  573. {
  574. try {
  575. $order_no = $request->get('order_no');
  576. $lat = $request->get('lat');
  577. $lng = $request->get('lng');
  578. $order = $rentOrderRepository->byNoGetRideOrder($order_no);
  579. if (!$order) {
  580. return $this->errorNoValidation('订单不存在');
  581. }
  582. if ($order->user_id !== $this->user->id) {
  583. return $this->errorNoValidation('非法操作');
  584. }
  585. $user_id = $this->user['id'];
  586. $cache_key = "RENT_ORDER_OPEN_BIKE_{$user_id}";
  587. if (Cache::has($cache_key)) {
  588. return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
  589. }
  590. Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
  591. $box_no = $bikeRepository->byIdGetBoxNo($order->bike_id);
  592. (new BaseBikeControl($box_no))::openLock();
  593. (new BikeStatusInfoSyncHandler())->toBikeRentRideStatus($order->bike_no);
  594. // 记录日志信息
  595. RentOrderBikeOperate::log($order->id, RentOrderBikeOperate::TYPE_OPEN_BIKE, $order->bike_id, $this->user->id, $lat, $lng);
  596. $order->bike_is_riding = Bike::RIDING_YES;
  597. $order->save();
  598. //增加次数
  599. Cache::remember('increment_use_bike', 1, function () use ($order) {
  600. return RentOrder::where('id', $order->id)->increment('use_bike_count');
  601. });
  602. return $this->success();
  603. } catch (\Exception $exception) {
  604. return $this->exception($exception);
  605. }
  606. }
  607. /**
  608. * 关锁
  609. * User: Mead.
  610. */
  611. public function closeBike(Request $request, RentOrderRepository $rentOrderRepository, BikeRepository $bikeRepository, LocationLogRepository $locationLogRepository)
  612. {
  613. try {
  614. $order_no = $request->get('order_no');
  615. $lat = $request->get('lat');
  616. $lng = $request->get('lng');
  617. $order = $rentOrderRepository->byNoGetRideOrder($order_no);
  618. if (!$order) {
  619. return $this->errorNoValidation('订单不存在');
  620. }
  621. if ($order->user_id !== $this->user->id) {
  622. return $this->errorNoValidation('非法操作');
  623. }
  624. $user_id = $this->user['id'];
  625. $cache_key = "RENT_ORDER_CLOSE_BIKE_{$user_id}";
  626. if (Cache::has($cache_key)) {
  627. return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
  628. }
  629. Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
  630. $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no, CacheMap::IS_OPEN_MONGODB_DUG);
  631. if ($location['lat'] <= 0) {
  632. $location['lat'] = $lat;
  633. $location['lng'] = $lng;
  634. }
  635. $order->end_use_bike_location = [
  636. 'latitude' => $location['lat'],
  637. 'longitude' => $location['lng'],
  638. ];
  639. $order->bike_is_riding = Bike::RIDING_NO;
  640. $order->save();
  641. //最后骑行时间
  642. $bikeModel = $bikeRepository->byIdGetModel($order->bike_id);
  643. $bikeModel->last_use_bike_end_time = date('Y-m-d H:i:s');
  644. $bikeModel->save();
  645. $box_no = $bikeRepository->byIdGetBoxNo($order->bike_id);
  646. (new BaseBikeControl($box_no))::closeLock();
  647. // 记录日志信息
  648. RentOrderBikeOperate::log($order->id, RentOrderBikeOperate::TYPE_CLONE_BIKE, $order->bike_id, $this->user->id, $lat, $lng);
  649. (new BikeStatusInfoSyncHandler())->toBikeRentWaitRideStatus($order->bike_no);
  650. return $this->success();
  651. } catch (\Exception $exception) {
  652. return $this->exception($exception);
  653. }
  654. }
  655. /**
  656. * 日租订单列表页.
  657. *
  658. * @param Request $request
  659. * @param RentOrder $rentOrder
  660. * User: Mead
  661. */
  662. public function orders(Request $request, RentOrder $rentOrder)
  663. {
  664. try {
  665. $query = $rentOrder->query();
  666. $query->where('pay_status', RentOrder::PAY_STATUS_OK);
  667. if ($year = $request->get('year', date('Y'))) {
  668. $query->whereYear('created_at', $year);
  669. }
  670. if ($month = $request->get('month', date('m'))) {
  671. $query->whereMonth('created_at', $month);
  672. }
  673. $orders = $query->where('user_id', $this->user->id)->orderBy('id', 'desc')->paginate();
  674. $orders->appends($request->only(['year', 'month']))->withPath(config('app.url') . '/api/rent/orders');
  675. return $this->response->paginator($orders, RentOrderTransformer::class);
  676. } catch (\Exception $exception) {
  677. return $this->exception($exception);
  678. }
  679. }
  680. /**
  681. * 检查是否在还车点
  682. * User: Mead.
  683. */
  684. public function checkBikeIsInStopParking(Request $request, BikeRepository $bikeRepository, RentOrderRepository $rentOrderRepository, AreaSettingRepository $areaSettingRepository, LocationLogRepository $locationLogRepository, AreaRepository $areaRepository)
  685. {
  686. $bike_no = $request->get('bike_no');
  687. $order_no = $request->get('order_no');
  688. $user_lat = $request->get('lat');
  689. $user_lng = $request->get('lng');
  690. try {
  691. $order = $rentOrderRepository->byNo($order_no);
  692. if (!$order) {
  693. return $this->errorBadRequest('非法请求');
  694. }
  695. $user_id = $this->user['id'];
  696. $cache_key = "RENT_ORDER_CHECK_BIKE_IS_PARK_{$user_id}";
  697. if (Cache::has($cache_key)) {
  698. return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
  699. }
  700. Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
  701. $box_no = $bikeRepository->byNoGetBoxNO($order->bike_no);
  702. (new BaseBikeControl($box_no))::nowBikeLocation();
  703. $setting = $areaSettingRepository->byAreaId($order->area_id);
  704. $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no, CacheMap::IS_OPEN_MONGODB_DUG);
  705. if ($location['lat'] <= 0) {
  706. $location['lat'] = $order->end_use_bike_location['latitude'];
  707. $location['lng'] = $order->end_use_bike_location['longitude'];
  708. if ($location['lat'] <= 0) {
  709. $location['lat'] = $user_lat;
  710. $location['lng'] = $user_lng;
  711. }
  712. }
  713. //检查是否在骑行区域
  714. $area = $areaRepository->byIdGetModelRedis($order->area_id);
  715. if (!$area) {
  716. $area = Area::where('id', $order->area_id)->first();
  717. }
  718. $is_out_area = $this->isOutArea($location['lat'], $location['lng'], $area);
  719. if (!$is_out_area) {
  720. return $this->errorNoValidation('超出骑行区域,暂不能还车');
  721. }
  722. //检查是否在禁停区
  723. $BikeHandler = new BikeHandler();
  724. $is_ban_stop_bike = $BikeHandler->byLocationCheckIsInBanStopParking($location['lat'], $location['lng'], $order->area_id, $user_lat, $user_lng);
  725. if ($is_ban_stop_bike) {
  726. return $this->errorNoValidation('禁停区域内禁止停车!');
  727. }
  728. // //运动中不能锁车
  729. // if ($location['speed']) {
  730. // (new BaseBikeControl($box_no))::nowBikeLocation();
  731. //
  732. // return $this->errorNoValidation('运动中不能关锁', 450);
  733. // }
  734. //判断是否全区域内可停
  735. if ($areaSettingRepository->byAreaIdGetIsWholeAreaHuanche($order->area_id) === AreaSetting::WHOLE_AREA_HUANCHE_OK) {
  736. return [
  737. 'is_dispatch' => true,
  738. 'is_stop_bike' => true,
  739. 'dispatch_money' => 0,
  740. ];
  741. }
  742. // 判断是否在停车点
  743. $BikeHandler = new BikeHandler();
  744. $is_huanche = $BikeHandler->byLocationCheckIsInStopParking($location['lat'], $location['lng'], $order->area_id, $user_lat, $user_lng);
  745. if (!$is_huanche['status']) {
  746. // 不在还车点
  747. $dispatch_money = $BikeHandler->byDistanceGetDistanceMoney($is_huanche['distance'], $setting);
  748. RentOrder::where('id', $order->id)->update([
  749. 'dispatch_money' => $dispatch_money,
  750. ]);
  751. return [
  752. 'is_dispatch' => false,
  753. 'is_stop_bike' => false,
  754. 'dispatch_money' => $dispatch_money,
  755. ];
  756. }
  757. return [
  758. 'is_dispatch' => true,
  759. 'is_stop_bike' => true,
  760. 'dispatch_money' => 0,
  761. ];
  762. } catch (HttpException $exception) {
  763. return $this->errorNoValidation($exception->getMessage(), $exception->getStatusCode());
  764. }
  765. }
  766. /**
  767. * 判断是否在骑行区.
  768. *
  769. * @param $lat
  770. * @param $lng
  771. * @param $box_no
  772. * User: Mead
  773. */
  774. private function isOutArea($lat, $lng, $area)
  775. {
  776. try {
  777. $location = [
  778. 'latitude' => $lat,
  779. 'longitude' => $lng,
  780. ];
  781. $fences = $area['area_fence'];
  782. $centre = $area['area_centre'];
  783. $radius = $area['area_radius'];
  784. // 判断是否在骑行区域
  785. $ConvertHandler = (new ConvertHandler());
  786. $is_out_area = $ConvertHandler->is_point_in_polygon($location, $fences);
  787. return $is_out_area;
  788. } catch (\Exception $exception) {
  789. return $this->exception($exception);
  790. }
  791. }
  792. /**
  793. * 寻铃
  794. * @param Request $request
  795. * @param OrderRepository $orderRepository
  796. * @param BikeRepository $bikeRepository
  797. * User: Fx
  798. */
  799. public function retryBell(RetryBikeRequest $request, RentOrderRepository $rentOrderRepository, BikeRepository $bikeRepository)
  800. {
  801. try {
  802. $order_no = $request->get('order_no');
  803. $bike_no = $request->get('bike_no');
  804. $order = $rentOrderRepository->checkUserIsRetryOpenLock($order_no, $bike_no, $this->user->id);
  805. if (!$order) return $this->errorNoValidation('没有此订单');
  806. $box_no = $bikeRepository->byNoGetBoxNO($bike_no);
  807. $re = (new BaseBikeControl($box_no))::bellBike();
  808. return $this->response->array([
  809. 'is_ok' => $re
  810. ]);
  811. } catch (\Exception $exception) {
  812. return $this->exception($exception);
  813. }
  814. }
  815. /**
  816. * 检查是否可以结束订单
  817. * @param Request $request
  818. * @param BikeRepository $bikeRepository
  819. * @param RentOrderRepository $rentOrderRepository
  820. * @param LocationLogRepository $locationLogRepository
  821. * @param AreaRepository $areaRepository
  822. * @return array|void
  823. * Author: Mead
  824. */
  825. public function checkBikeIsRidingArea(Request $request, BikeRepository $bikeRepository, RentOrderRepository $rentOrderRepository, LocationLogRepository $locationLogRepository, AreaRepository $areaRepository)
  826. {
  827. $bike_no = $request->get('bike_no');
  828. $order_no = $request->get('order_no');
  829. $user_lat = $request->get('lat');
  830. $user_lng = $request->get('lng');
  831. try {
  832. $order = $rentOrderRepository->byNo($order_no);
  833. if (!$order) {
  834. return $this->errorBadRequest('非法请求');
  835. }
  836. $second = Carbon::now()->diffInSeconds(Carbon::parse($order->start_use_bike_time));
  837. if ($second < AreaSetting::CLOSE_BIKE_TIME) {
  838. //小于60秒直接锁车
  839. return [
  840. 'is_close_order' => true,
  841. ];
  842. }
  843. $user_id = $this->user['id'];
  844. $cache_key = "RENT_ORDER_CHECK_BIKE_IS_RIDING_PARK_{$user_id}";
  845. if (Cache::has($cache_key)) {
  846. return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
  847. }
  848. Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
  849. $box_no = $bikeRepository->byNoGetBoxNO($order->bike_no);
  850. (new BaseBikeControl($box_no))::nowBikeLocation();
  851. $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no, CacheMap::IS_OPEN_MONGODB_DUG);
  852. if ($location['lat'] <= 0) {
  853. $location['lat'] = $order->end_use_bike_location['latitude'];
  854. $location['lng'] = $order->end_use_bike_location['longitude'];
  855. if ($location['lat'] <= 0) {
  856. $location['lat'] = $user_lat;
  857. $location['lng'] = $user_lng;
  858. }
  859. }
  860. //检查是否在骑行区域
  861. $area = $areaRepository->byIdGetModelRedis($order->area_id);
  862. if (!$area) {
  863. $area = Area::where('id', $order->area_id)->first();
  864. }
  865. $is_out_area = $this->isOutArea($location['lat'], $location['lng'], $area);
  866. if (!$is_out_area) {
  867. return $this->errorNoValidation('超出骑行区域,暂不能还车');
  868. }
  869. //检查是否在禁停区
  870. $BikeHandler = new BikeHandler();
  871. $is_ban_stop_bike = $BikeHandler->byLocationCheckIsInBanStopParking($location['lat'], $location['lng'], $order->area_id, $user_lat, $user_lng);
  872. if ($is_ban_stop_bike) {
  873. return $this->errorNoValidation('禁停区域内禁止停车!');
  874. }
  875. return [
  876. 'is_close_order' => false,
  877. ];
  878. } catch (HttpException $exception) {
  879. return $this->exception($exception);
  880. }
  881. }
  882. /**
  883. * Author: Mead
  884. */
  885. public function expectRentOrderMoney(Request $request, BikeRepository $bikeRepository, RentOrderRepository $rentOrderRepository, AreaSettingRepository $areaSettingRepository, LocationLogRepository $locationLogRepository, AreaRepository $areaRepository)
  886. {
  887. $bike_no = $request->get('bike_no');
  888. $order_no = $request->get('order_no');
  889. $user_lat = $request->get('lat');
  890. $user_lng = $request->get('lng');
  891. try {
  892. $order = $rentOrderRepository->byNo($order_no);
  893. if (!$order) {
  894. return $this->errorBadRequest('非法请求');
  895. }
  896. $second = Carbon::now()->diffInSeconds(Carbon::parse($order->start_use_bike_time));
  897. if ($second < AreaSetting::CLOSE_BIKE_TIME) {
  898. //小于60秒直接锁车
  899. return [
  900. 'dispatch_money' => 0,
  901. 'time_money' => 0,
  902. 'rent_total_money' => 0,
  903. 'total_money' => 0,
  904. ];
  905. }
  906. $user_id = $this->user['id'];
  907. $cache_key = "RENT_ORDER_EXPECT_MONEY_{$user_id}";
  908. if (Cache::has($cache_key)) {
  909. return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
  910. }
  911. Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
  912. $box_no = $bikeRepository->byNoGetBoxNO($order->bike_no);
  913. (new BaseBikeControl($box_no))::nowBikeLocation();
  914. $setting = $areaSettingRepository->byAreaId($order->area_id);
  915. $money = 0.00;
  916. $over_hours = 0;
  917. //是否需要收取超出费用
  918. $is_over_time = (strtotime($order->return_end_bike_time) < time());
  919. if ($is_over_time) {
  920. //超出时间
  921. $over_hours = ceil(Carbon::now()->diffInMinutes(Carbon::parse($order->return_end_bike_time)) / 60);
  922. $hours = ceil(Carbon::now()->diffInMinutes(Carbon::parse($order->start_use_bike_time)) / 60);
  923. if ($hours > 24) {
  924. //超过1天
  925. $day = ceil($hours / 24);
  926. $end_hours = $hours % 24;
  927. //日封顶租金*天
  928. $money = bcmul($setting['over_rent_time_max_money'], ($day - 1), 2);
  929. // $money = bcadd($money, $setting['rent_money'], 2);
  930. if ($end_hours > $setting['rent_time']) {
  931. // 超过一天 又超过8小时
  932. // (超时费 + 日封顶租金*天)
  933. $money = bcadd(bcmul(($end_hours - $setting['rent_time']), $setting['over_rent_time_money'], 2), $money, 2);
  934. }
  935. } else {
  936. // 不超过1天 但是超过8小时
  937. $money = bcmul($over_hours, $setting['over_rent_time_money'], 2);
  938. // (超时费 + 基础租金) 是否大于日封顶租金
  939. $total_money = bcadd($money, $setting['rent_money'], 2);
  940. if ($total_money > $setting['over_rent_time_max_money']) {
  941. $money = bcsub($setting['over_rent_time_max_money'], $setting['rent_money'], 2);
  942. }
  943. }
  944. }
  945. $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no, CacheMap::IS_OPEN_MONGODB_DUG);
  946. //计算骑行距离
  947. // $order->use_bike_distance_length = bcdiv($location['mileage'], 1000, 2);
  948. if ($location['lat'] <= 0) {
  949. $location['lat'] = $order->end_use_bike_location['latitude'];
  950. $location['lng'] = $order->end_use_bike_location['longitude'];
  951. if ($location['lat'] <= 0) {
  952. $location['lat'] = $user_lat;
  953. $location['lng'] = $user_lng;
  954. }
  955. }
  956. $money = floatval($money);
  957. $total_money = floatval(bcadd($money, $order->rent_total_money, 2));
  958. $rent_total_money = floatval($order->rent_total_money);
  959. //判断是否全区域内可停
  960. if ($areaSettingRepository->byAreaIdGetIsWholeAreaHuanche($order->area_id) === AreaSetting::WHOLE_AREA_HUANCHE_OK) {
  961. return [
  962. 'dispatch_money' => 0,
  963. 'time_money' => $money,
  964. 'rent_total_money' => $rent_total_money,
  965. 'total_money' => $total_money,
  966. ];
  967. }
  968. // 判断是否在停车点
  969. $BikeHandler = new BikeHandler();
  970. $is_huanche = $BikeHandler->byLocationCheckIsInStopParking($location['lat'], $location['lng'], $order->area_id, $user_lat, $user_lng);
  971. if (!$is_huanche['status']) {
  972. // 不在还车点
  973. $dispatch_money = $BikeHandler->byDistanceGetDistanceMoney($is_huanche['distance'], $setting);
  974. RentOrder::where('id', $order->id)->update([
  975. 'dispatch_money' => $dispatch_money,
  976. ]);
  977. return [
  978. 'dispatch_money' => $dispatch_money,
  979. 'time_money' => $money,
  980. 'rent_total_money' => $rent_total_money,
  981. 'total_money' => floatval(bcadd($total_money, $dispatch_money, 2)),
  982. ];
  983. }
  984. return [
  985. 'dispatch_money' => 0,
  986. 'time_money' => $money,
  987. 'rent_total_money' => $rent_total_money,
  988. 'total_money' => $total_money,
  989. ];
  990. } catch (HttpException $exception) {
  991. return $this->exception($exception);
  992. }
  993. }
  994. }