123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119 |
- <?php
- /**
- * Created by PhpStorm.
- * User: Mead
- * Date: 2019/11/6
- * Time: 8:53 PM.
- */
- namespace App\Http\Controllers\V1;
- use App\Handlers\BikeControl;
- use App\Handlers\BikeHandler;
- use App\Handlers\BikeStatusInfoSyncHandler;
- use App\Handlers\ConvertHandler;
- use App\Http\Requests\RetryBikeRequest;
- use App\Jobs\CloseRentOrderJob;
- use App\Models\Area;
- use App\Models\AreaSetting;
- use App\Models\Bike;
- use App\Models\RentOrder;
- use App\Models\RentOrderBikeOperate;
- use App\Models\User;
- use App\Models\WalletLog;
- use App\Repositories\AreaRepository;
- use App\Repositories\AreaSettingRepository;
- use App\Repositories\BikeRepository;
- use App\Repositories\LocationLogRepository;
- use App\Repositories\OrderRepository;
- use App\Repositories\RentOrderBikeOperateRepository;
- use App\Repositories\RentOrderRepository;
- use App\Repositories\UserRepository;
- use App\Transformers\RentOrderTransformer;
- use App\Transformers\RentUseOrderTransformer;
- use Carbon\Carbon;
- use Dingo\Api\Http\Request;
- use Illuminate\Support\Facades\Log;
- use function EasyWeChat\Kernel\Support\generate_sign;
- use Illuminate\Support\Facades\Cache;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Redis;
- use Symfony\Component\HttpKernel\Exception\HttpException;
- /**
- * 日租车模块
- * Class RentBikeController
- * @package App\Http\Controllers\V1
- */
- class RentBikeController extends BaseController
- {
- /**
- * 租车下单
- * User: Mead.
- */
- public function storeOrder(Request $request, BikeRepository $bikeRepository, RentOrderRepository $rentOrderRepository, OrderRepository $orderRepository, AreaSettingRepository $areaSettingRepository, UserRepository $userRepository)
- {
- try {
- $type = $request->get('type');
- $bike_no = $request->get('bike_no');
- $area_id = $request->get('area_id');
- $lat = $request->get('lat');
- $lng = $request->get('lng');
- $cache_key = "OPEN_RENT_BIKE_ORDER_{$bike_no}";
- if (Cache::has($cache_key)) {
- return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
- }
- Cache::put($cache_key, 1, Carbon::now()->addSeconds(5));
- $bike = $bikeRepository->byNoIsCanRentBikeGetModel($bike_no);
- if (!$bike) {
- return $this->errorNoValidation('该车暂不能用');
- }
- //以车的区域为主
- if ($bike->put_area_id !== $area_id) {
- $area_id = $bike->put_area_id;
- }
- // 判断用户押金,授权,认证,手机号状态是否正常
- $user = $this->user;
- if (User::DEPOSIT_NO === (int)$user->is_deposit) {
- return $this->errorNoValidation('请您先交纳押金');
- }
- if ((int)$user->deposit_type === User::DEPOSIT_CARD && (int)$user->is_deposit === User::DEPOSIT_OK) {
- // 押金类型为免押金卡 判断是否过期
- if (!$userRepository->isDepositCardExpired($user->id)) {
- return $this->errorNoValidation('免押金卡已到期,请您先交纳押金');
- }
- }
- if (User::BIND_MOBILE_NO === (int)$user->is_bind_mobile) {
- return $this->errorNoValidation('请先绑定您的手机号');
- }
- if (User::CARD_NO === (int)$user->is_card_certified) {
- return $this->errorNoValidation('请您先完善实名认证');
- }
- if (User::RIDE_BIKE_AGE_NO === (int)$user->is_match_ride_age) {
- return $this->errorNoValidation('未成年人禁止骑车');
- }
- $setting = $areaSettingRepository->byAreaId($area_id);
- if (!$setting->is_open_day_rent) {
- return $this->errorNoValidation('该区域租车咱不开放,敬请期待!');
- }
- // 判断用户是否有为支付的订单
- if ($orderRepository->byUserIdCheckIsExistRideOrder($user->id)) {
- return $this->errorNoValidation('您有未完成的订单,请先处理');
- }
- if ($rentOrderRepository->byUserIdCheckIsExistRideOrder($user->id)) {
- return $this->errorNoValidation('您有未完成的租车订单,请先处理');
- }
- // 判断用户是否在车的距离范围内
- $options = ['SORT' => 'ASC'];
- $redis = Redis::connection();
- $nearby_bikes = $redis->georadius(Bike::REDIS_BIKE_LOCATION_TAG, $lng, $lat, 1, 'km', $options);
- if (!in_array($bike->bike_no, $nearby_bikes)) {
- return $this->errorNoValidation('小主,咱俩有点远!');
- }
- $user_id = $this->user->id;
- $cache_key = "RIDE_RENT_ORDER_{$user_id}";
- if (Cache::has($cache_key)) {
- return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
- }
- Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
- //不同类型处理价格(暂不用)
- // 下单
- $rent_money = $setting->day_rent_money;
- $users = User::find($user['id']);
- $settingConfig = [
- 'rent_money' => $setting->day_rent_money,
- 'rent_time' => $setting->day_rent_hours,
- 'over_rent_time_money' => $setting->per_hours_day_rent_timeout_money,
- 'over_rent_time_max_money' => $setting->day_rent_capping_money,
- ];
- $data = [
- 'user_id' => $user['id'],
- 'no' => RentOrder::makeNo(),
- 'type' => RentOrder::TYPE_DAY_RENT,
- 'bike_no' => $bike_no,
- 'bike_id' => $bike->id,
- 'area_id' => $area_id,
- 'phone_detail' => $users->userPhoneDetail->detail ?? '',
- 'start_use_bike_location' => [
- 'latitude' => $lat,
- 'longitude' => $lng,
- ],
- 'rent_money' => $rent_money,
- 'rent_preferential_money' => 0.00,
- 'rent_total_money' => $rent_money,
- 'status' => RentOrder::STATUS_WAIT_PAY_RENT_MONEY,
- 'setting' => $settingConfig,
- ];
- $order = RentOrder::create($data);
- // $this->dispatch(new CloseRentOrderJob($order, Carbon::now()->addMinutes(10)));
- // 更新用户的区域id
- if (!$user->register_area_id) {
- $user->register_area_id = $area_id;
- $user->save();
- }
- $order->status = RentOrder::STATUS_RENT_BIKE;
- $order->start_use_bike_time = now();
- $order->return_end_bike_time = Carbon::now()->addHours($settingConfig['rent_time'])->toDateTimeString();
- $order->save();
- $bike->is_rent = Bike::RENT_YES;
- $bike->is_riding = Bike::RIDING_YES;
- $bike->save();
- //同步redis
- (new BikeStatusInfoSyncHandler())->toBikeRideStatus(BikeStatusInfoSyncHandler::ROLE_USER, $bike->bike_no, [
- 'id' => $order->id,
- 'bike_id' => $order->bike_id,
- 'area_id' => $order->area_id,
- 'is_rent' => 1,
- ]);
- $params['no'] = $order->no;
- return $this->response->array($params);
- } catch (\Exception $exception) {
- return $this->errorNoValidation($exception->getMessage());
- }
- }
- public function useOrder(Request $request, RentOrderRepository $rentOrderRepository)
- {
- try {
- $no = $request->get('no');
- $order = $rentOrderRepository->byNo($no);
- return $this->response->item($order, RentUseOrderTransformer::class);
- } catch (\Exception $exception) {
- }
- }
- /**
- * @param Request $request
- * @param RentOrderRepository $rentOrderRepository
- *
- * @return \Dingo\Api\Http\Response
- * User: Mead
- */
- public function show(Request $request, RentOrderRepository $rentOrderRepository)
- {
- try {
- $no = $request->get('no');
- $order = $rentOrderRepository->byNo($no);
- return $this->response->item($order, new RentOrderTransformer());
- } catch (\Exception $exception) {
- }
- }
- /**
- * 结束租车
- * User: Mead.
- */
- public function closeOrder(Request $request, RentOrderRepository $rentOrderRepository, BikeRepository $bikeRepository, LocationLogRepository $locationLogRepository, AreaSettingRepository $areaSettingRepository)
- {
- try {
- $bike_no = $request->get('bike_no');
- $order_no = $request->get('order_no');
- $lat = $request->get('lat');
- $lng = $request->get('lng');
- $order = $rentOrderRepository->byNoGetRideOrder($order_no);
- if (!$order) {
- return $this->errorNoValidation('订单不存在或订单已结算');
- }
- if (Bike::RIDING_YES === (int)$order->bike_is_riding) {
- return $this->errorNoValidation('请先关锁再还车');
- }
- if ($rentOrderRepository->checkUserMoreCloseOrder($this->user->id)) {
- return $this->errorNoValidation('您今天太频繁操作车辆');
- }
- $user_id = $this->user->id;
- $cache_key = "RIDE_CLOSE_RENT_ORDER_{$user_id}";
- if (Cache::has($cache_key)) {
- return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
- }
- Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
- //获取车的最后位置
- $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no);
- if ($location['lat'] <= 0) {
- $location['lat'] = $order->end_use_bike_location['latitude'];
- $location['lng'] = $order->end_use_bike_location['longitude'];
- if ($location['lat'] <= 0) {
- $location['lat'] = $lat;
- $location['lng'] = $lng;
- }
- }
- // 更新车的信息
- $bikeModel = $bikeRepository->byIdGetModel($order->bike_id);
- $bikeModel->is_riding = Bike::RIDING_NO;
- $bikeModel->is_rent = Bike::RENT_NO;
- $bikeModel->save();
- //更新redis
- (new BikeStatusInfoSyncHandler())->toBikeWaitRideStatus($order->bike_no, $location['lng'], $location['lat']);
- // 判断是否经常这样操作(未做)
- $second = Carbon::now()->diffInSeconds(Carbon::parse($order->start_use_bike_time));
- if ($second <= AreaSetting::CLOSE_BIKE_TIME) {
- // 关闭订单
- $order->status = RentOrder::STATUS_CLOSE_ORDER;
- $order->end_use_bike_location = [
- 'latitude' => $lat,
- 'longitude' => $lng,
- ];
- $order->end_use_bike_time = now();
- $order->rent_money = 0;
- $order->save();
- //退钱
- // 记录临时关锁
- return $this->response->item($order, RentOrderTransformer::class);
- }
- //检查是否在禁停区
- $BikeHandler = new BikeHandler();
- $is_ban_stop_bike = $BikeHandler->byLocationCheckIsInBanStopParking($location['lat'], $location['lng'], $order->area_id);
- if ($is_ban_stop_bike) {
- return $this->errorNoValidation('禁停区域内禁止停车!');
- }
- // 结束订单
- $setting = $order->setting;
- $money = 0.00;
- $over_hours = 0;
- //是否需要收取超出费用
- $is_over_time = (strtotime($order->return_end_bike_time) < time());
- if ($is_over_time) {
- //超出时间
- $over_hours = ceil(Carbon::now()->diffInMinutes(Carbon::parse($order->return_end_bike_time)) / 60);
- $hours = ceil(Carbon::now()->diffInMinutes(Carbon::parse($order->start_use_bike_time)) / 60);
- if ($hours > 24) {
- //超过1天
- $day = ceil($hours / 24);
- $end_hours = $hours % 24;
- //日封顶租金*天
- $money = bcmul($setting['over_rent_time_max_money'], ($day - 1), 2);
- // $money = bcadd($money, $setting['rent_money'], 2);
- if ($end_hours > $setting['rent_time']) {
- // 超过一天 又超过8小时
- // (超时费 + 日封顶租金*天)
- $money = bcadd(bcmul(($end_hours - $setting['rent_time']), $setting['over_rent_time_money'], 2), $money, 2);
- }
- } else {
- // 不超过1天 但是超过8小时
- $money = bcmul($over_hours, $setting['over_rent_time_money'], 2);
- // (超时费 + 基础租金) 是否大于日封顶租金
- $total_money = bcadd($money, $setting['rent_money'], 2);
- if ($total_money > $setting['over_rent_time_max_money']) {
- $money = bcsub($setting['over_rent_time_max_money'], $setting['rent_money'], 2);
- }
- }
- }
- //计算骑行距离
- $order->use_bike_distance_length = bcdiv($location['mileage'], 1000, 2);
- // 日租结算
- $order->time_money = $money;
- $order->distance_money = 0.00;
- $order->preferential_money = 0.00;
- $order->over_hours = $over_hours;
- // 租金 + 超时费
- $order->total_money = bcadd($money, $order->rent_money, 2);
- $order->pay_money = $order->total_money;
- //判断是否收取调度费
- if ($order->dispatch_money > 0) {
- $order->total_money = bcadd($order->total_money, $order->dispatch_money, 2);
- }
- if ($order->total_money > 0) {
- $order->status = RentOrder::STATUS_CLOSE_RENT_BIKE;
- } else {
- $order->status = RentOrder::STATUS_COMPLETE_ORDER;
- }
- //计算用车时间 (分)
- $order->use_bike_time_length = ceil($second / 60);
- // 车辆最后位置 (防止定位失败的情况)
- if (empty($order->end_use_bike_location)) {
- $order->end_use_bike_location = [
- 'latitude' => $lat,
- 'longitude' => $lng,
- ];
- }
- $order->end_use_bike_time = Carbon::now();
- $order->order_total_money = $order->total_money;
- $order->save();
- // 删除redis订单
- if (RentOrder::STATUS_COMPLETE_ORDER === (int)$order->status) {
- (new BikeStatusInfoSyncHandler())->toBikeWaitRideStatus($order->bike_no, $location['lng'], $location['lat']);
- }
- return $this->response->item($order, RentOrderTransformer::class);
- } catch (HttpException $exception) {
- return $this->errorNoValidation($exception->getMessage(), $exception->getStatusCode());
- }
- }
- public function payShow(Request $request, RentOrderRepository $rentOrderRepository, RentOrderBikeOperateRepository $rentOrderBikeOperateRepository)
- {
- try {
- $order_no = $request->get('order_no');
- $order = $rentOrderRepository->byNoAndUserId($order_no, $this->user->id);
- if (!$order) {
- return $this->errorNoValidation('订单不存在!');
- }
- // 检查用户余额是否够
- $is_user_wallet = true;
- if ($order->pay_money > $this->user->wallet_money) {
- // 余额不够
- $is_user_wallet = false;
- }
- if (bccomp($order->total_money, 0) === 0) {
- $order->pay_type = RentOrder::PAY_STATUS_OK;
- $order->status = RentOrder::STATUS_CLOSE_ORDER;
- }
- $order->save();
- // 检查是否系统自动锁车
- $is_system_off_lock = $rentOrderBikeOperateRepository->checkLowPowerOffLock($order->id);
- $is_coupon = false;
- $userCoupons = [];
- $ridingCard = [];
- return $this->response->array([
- 'order' => $order->append(['use_bike_time_length_text', 'use_bike_distance_length_text', 'end_use_bike_time_timestamp'])->toArray(),
- 'orders' => [
- 'id' => $order->id,
- 'no' => $order->no,
- 'bike_no' => $order->bike_no,
- 'use_bike_time_length_text' => $order->use_bike_time_length_text,
- 'use_bike_distance_length_text' => $order->use_bike_distance_length_text,
- 'end_use_bike_time_timestamp' => $order->end_use_bike_time_timestamp,
- 'pay_status' => $order->pay_status,
- 'pay_money' => $order->pay_money,
- 'time_money' => $order->time_money, // 时长费
- 'rent_money' => $order->rent_money, // 租费
- 'dispatch_money' => $order->dispatch_money, // 调度费
- 'distance_money' => $order->distance_money, // 里程费用
- 'total_money' => $order->total_money,// 加调度费的总金额
- 'order_total_money' => bcadd($order->rent_money, $order->time_money, 2), // 不加调度费的总金额
- 'order_wait_pay_money' => empty($userCoupons) ? $order->total_money : $userCoupons['order_wait_pay_money'], // 总待支付
- 'total_preferential_money' => empty($userCoupons) ? $order->preferential_money : $userCoupons['total_preferential_money'], // 总优惠
- ],
- 'wallet_pay_status' => $is_user_wallet,
- 'wallet_money' => $this->user->wallet_money,
- 'user_coupon' => [
- 'is_coupon' => $is_coupon,
- 'coupon_preferential_money' => empty($userCoupons) ? '0.00' : $userCoupons['coupon_preferential_money'], // 优惠券优惠的金额
- 'coupon_user_bags_id' => empty($userCoupons) ? 0 : $userCoupons['id'],
- ],
- 'user_card' => [
- 'is_card' => empty($ridingCard) ? false : true,
- 'card' => $ridingCard,
- 'card_preferential_money' => $order->preferential_money, // 没支付之前优惠金额就是 骑行卡优惠的金额
- ],
- 'system_off_lock' => [
- 'is_system_off_lock' => empty($is_system_off_lock) ? false : true,
- 'system_off_lock_text' => '电量过低,系统自动还车,敬请谅解,如有疑问请致电客服'
- ],
- ]);
- } catch (\Exception $exception) {
- return $this->errorException($exception->getMessage());
- }
- }
- public function pay(Request $request, RentOrderRepository $rentOrderRepository)
- {
- try {
- $pay_type = $request->get('pay_type');
- $order_no = $request->get('order_no');
- $order = $rentOrderRepository->byNo($order_no);
- if (!$order) {
- return $this->errorBadRequest('订单不存在');
- }
- if (RentOrder::STATUS_COMPLETE_ORDER === (int)$order->status) {
- return $this->errorNoValidation('订单已完成');
- }
- if (RentOrder::STATUS_CLOSE_ORDER === (int)$order->status) {
- return $this->errorNoValidation('订单已关闭');
- }
- if (RentOrder::PAY_STATUS_OK === (int)$order->pay_status) {
- return $this->errorNoValidation('订单已支付');
- }
- if (RentOrder::STATUS_RENT_BIKE === (int)$order->status) {
- return $this->errorNoValidation('请先结束租车订单,再支付');
- }
- $user = $this->user;
- if ($order->user_id !== $user->id) {
- return $this->errorNoValidation('非法操作');
- }
- $response = '';
- $user_id = $user['id'];
- $cache_key = "PAY_RENT_ORDER_{$user_id}";
- if (Cache::has($cache_key)) {
- return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
- }
- Cache::put($cache_key, 1, Carbon::now()->addSeconds(5));
- switch ($pay_type) {
- case RentOrder::PAY_TYPE_ACCOUNT:
- //余额支付
- if (bccomp($order->total_money, $this->user->wallet_money) === 1) {
- // 余额不够
- return $this->errorNoValidation('用户余额不够');
- }
- DB::transaction(function () use ($order, $user) {
- //添加钱包记录
- 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);
- //修改订单记录
- $order->pay_status = RentOrder::PAY_STATUS_OK;
- $order->pay_money = $order->total_money;
- $order->pay_time = now();
- $order->pay_type = RentOrder::PAY_TYPE_ACCOUNT;
- $order->status = RentOrder::STATUS_COMPLETE_ORDER;
- $order->order_total_money = $order->total_money;
- $order->save();
- });
- $response = [
- 'pay_order_status' => true,
- ];
- break;
- case RentOrder::PAY_TYPE_WECHAT:
- //微信支付
- $payment = app('wechat.payment'); // 微信支付
- $username = $user->truename;
- $auth = $user->auth;
- $order->over_no = RentOrder::makeOverNo();
- $order->save();
- $result = $payment->order->unify([
- 'body' => "[{$username}]支付租车费用",
- 'out_trade_no' => $order->no,
- 'trade_type' => 'JSAPI', // 必须为JSAPI
- 'openid' => $auth['credential'], // 这里的openid为付款人的openid
- 'total_fee' => wechat_fee($order->total_money), // 总价
- 'attach' => RentOrder::NO_TAG,
- 'notify_url' => config('app.url') . '/api/payments/wechat-rent-notify',
- ]);
- if ($result['return_code'] === 'FAIL') return $this->errorNoValidation('下单失败');
- // 如果成功生成统一下单的订单,那么进行二次签名
- if ($result['result_code'] === 'FAIL') {
- //判断是否重复下单
- if ($result['err_code'] === 'INVALID_REQUEST') {
- $order->no = RentOrder::makeNo();
- $order->save();
- $result = $payment->order->unify([
- 'body' => "[{$username}]支付租车费用",
- 'out_trade_no' => $order->no,
- 'trade_type' => 'JSAPI', // 必须为JSAPI
- 'openid' => $auth['credential'], // 这里的openid为付款人的openid
- 'total_fee' => wechat_fee($order->total_money), // 总价
- 'attach' => RentOrder::NO_TAG,
- 'notify_url' => config('app.url') . '/api/payments/wechat-rent-notify',
- ]);
- } elseif ($result['err_code'] === 'ORDERPAID') {
- $order->pay_status = RentOrder::PAY_STATUS_OK;
- $order->pay_time = now();
- $order->pay_type = RentOrder::PAY_TYPE_WECHAT;
- $order->pay_money = $order->total_money;
- $order->order_total_money = $order->pay_money;
- $order->status = RentOrder::STATUS_COMPLETE_ORDER;
- $order->save();
- $order->pay_rent_over_order_callback();
- return $this->errorNoValidation('订单已支付,请勿重复支付!');
- } else {
- return $this->errorNoValidation('下单失败');
- }
- }
- if ('SUCCESS' === $result['return_code'] && 'SUCCESS' === $result['result_code']) {
- // 二次签名的参数必须与下面相同
- $params = [
- 'appId' => $auth['identifier'],
- 'timeStamp' => time(),
- 'nonceStr' => $result['nonce_str'],
- 'package' => 'prepay_id=' . $result['prepay_id'],
- 'signType' => 'MD5',
- ];
- // config('wechat.payment.default.key')为商户的key
- $params['paySign'] = generate_sign($params, config('wechat.payment.default.key'));
- $response = $params;
- } else {
- return $this->errorNoValidation('下单失败');
- }
- break;
- default:
- return $this->errorBadRequest('支付类型不对');
- break;
- }
- $response['order_no'] = $order->no;
- return $this->response->array($response);
- } catch (\Exception $exception) {
- return $this->errorNoValidation($exception->getMessage());
- }
- }
- /**
- * 开锁
- * User: Mead.
- */
- public function openBike(Request $request, RentOrderRepository $rentOrderRepository, BikeRepository $bikeRepository)
- {
- try {
- $order_no = $request->get('order_no');
- $lat = $request->get('lat');
- $lng = $request->get('lng');
- $order = $rentOrderRepository->byNoGetRideOrder($order_no);
- if (!$order) {
- return $this->errorNoValidation('订单不存在');
- }
- if ($order->user_id !== $this->user->id) {
- return $this->errorNoValidation('非法操作');
- }
- $user_id = $this->user['id'];
- $cache_key = "RENT_ORDER_OPEN_BIKE_{$user_id}";
- if (Cache::has($cache_key)) {
- return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
- }
- Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
- $box_no = $bikeRepository->byIdGetBoxNo($order->bike_id);
- BikeControl::openLock($box_no);
- (new BikeStatusInfoSyncHandler())->toBikeRentRideStatus($order->bike_no);
- // 记录日志信息
- RentOrderBikeOperate::log($order->id, RentOrderBikeOperate::TYPE_OPEN_BIKE, $order->bike_id, $this->user->id, $lat, $lng);
- $order->bike_is_riding = Bike::RIDING_YES;
- $order->save();
- //增加次数
- Cache::remember('increment_use_bike', 1, function () use ($order) {
- return RentOrder::where('id', $order->id)->increment('use_bike_count');
- });
- return $this->success();
- } catch (\Exception $exception) {
- return $this->errorNoValidation($exception->getMessage());
- }
- }
- /**
- * 关锁
- * User: Mead.
- */
- public function closeBike(Request $request, RentOrderRepository $rentOrderRepository, BikeRepository $bikeRepository, LocationLogRepository $locationLogRepository)
- {
- try {
- $order_no = $request->get('order_no');
- $lat = $request->get('lat');
- $lng = $request->get('lng');
- $order = $rentOrderRepository->byNoGetRideOrder($order_no);
- if (!$order) {
- return $this->errorNoValidation('订单不存在');
- }
- if ($order->user_id !== $this->user->id) {
- return $this->errorNoValidation('非法操作');
- }
- $user_id = $this->user['id'];
- $cache_key = "RENT_ORDER_CLOSE_BIKE_{$user_id}";
- if (Cache::has($cache_key)) {
- return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
- }
- Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
- $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no);
- if ($location['lat'] <= 0) {
- $location['lat'] = $lat;
- $location['lng'] = $lng;
- }
- $order->end_use_bike_location = [
- 'latitude' => $location['lat'],
- 'longitude' => $location['lng'],
- ];
- $order->bike_is_riding = Bike::RIDING_NO;
- $order->save();
- //最后骑行时间
- $bikeModel = $bikeRepository->byIdGetModel($order->bike_id);
- $bikeModel->last_use_bike_end_time = date('Y-m-d H:i:s');
- $bikeModel->save();
- $box_no = $bikeRepository->byIdGetBoxNo($order->bike_id);
- BikeControl::closeLock($box_no);
- // 记录日志信息
- RentOrderBikeOperate::log($order->id, RentOrderBikeOperate::TYPE_CLONE_BIKE, $order->bike_id, $this->user->id, $lat, $lng);
- (new BikeStatusInfoSyncHandler())->toBikeRentWaitRideStatus($order->bike_no);
- return $this->success();
- } catch (\Exception $exception) {
- return $this->errorNoValidation($exception->getMessage());
- }
- }
- /**
- * 日租订单列表页.
- *
- * @param Request $request
- * @param RentOrder $rentOrder
- * User: Mead
- */
- public function orders(Request $request, RentOrder $rentOrder)
- {
- try {
- $query = $rentOrder->query();
- $query->where('pay_status', RentOrder::PAY_STATUS_OK);
- if ($year = $request->get('year', date('Y'))) {
- $query->whereYear('created_at', $year);
- }
- if ($month = $request->get('month', date('m'))) {
- $query->whereMonth('created_at', $month);
- }
- $orders = $query->where('user_id', $this->user->id)->orderBy('id', 'desc')->paginate();
- $orders->appends($request->only(['year', 'month']))->withPath(config('app.url') . '/api/rent/orders');
- return $this->response->paginator($orders, RentOrderTransformer::class);
- } catch (\Exception $exception) {
- return $this->errorException($exception->getMessage());
- }
- }
- /**
- * 检查是否在还车点
- * User: Mead.
- */
- public function checkBikeIsInStopParking(Request $request, BikeRepository $bikeRepository, RentOrderRepository $rentOrderRepository, AreaSettingRepository $areaSettingRepository, LocationLogRepository $locationLogRepository, AreaRepository $areaRepository)
- {
- $bike_no = $request->get('bike_no');
- $order_no = $request->get('order_no');
- $user_lat = $request->get('lat');
- $user_lng = $request->get('lng');
- try {
- $order = $rentOrderRepository->byNo($order_no);
- if (!$order) {
- return $this->errorBadRequest('非法请求');
- }
- $user_id = $this->user['id'];
- $cache_key = "RENT_ORDER_CHECK_BIKE_IS_PARK_{$user_id}";
- if (Cache::has($cache_key)) {
- return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
- }
- Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
- $box_no = $bikeRepository->byNoGetBoxNO($order->bike_no);
- BikeControl::nowBikeLocation($box_no);
- $setting = $areaSettingRepository->byAreaId($order->area_id);
- $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no);
- if ($location['lat'] <= 0) {
- $location['lat'] = $order->end_use_bike_location['latitude'];
- $location['lng'] = $order->end_use_bike_location['longitude'];
- if ($location['lat'] <= 0) {
- $location['lat'] = $user_lat;
- $location['lng'] = $user_lng;
- }
- }
- //检查是否在骑行区域
- $area = $areaRepository->byIdGetModelRedis($order->area_id);
- if (!$area) {
- $area = Area::where('id', $order->area_id)->first();
- }
- $is_out_area = $this->isOutArea($location['lat'], $location['lng'], $area);
- if (!$is_out_area) {
- return $this->errorNoValidation('超出骑行区域,暂不能还车');
- }
- //检查是否在禁停区
- $BikeHandler = new BikeHandler();
- $is_ban_stop_bike = $BikeHandler->byLocationCheckIsInBanStopParking($location['lat'], $location['lng'], $order->area_id);
- if ($is_ban_stop_bike) {
- return $this->errorNoValidation('禁停区域内禁止停车!');
- }
- // //运动中不能锁车
- // if ($location['speed']) {
- // BikeControl::nowBikeLocation($box_no);
- //
- // return $this->errorNoValidation('运动中不能关锁', 450);
- // }
- //判断是否全区域内可停
- if ($areaSettingRepository->byAreaIdGetIsWholeAreaHuanche($order->area_id) === AreaSetting::WHOLE_AREA_HUANCHE_OK) {
- return [
- 'is_dispatch' => true,
- 'is_stop_bike' => true,
- 'dispatch_money' => 0,
- ];
- }
- // 判断是否在停车点
- $BikeHandler = new BikeHandler();
- $is_huanche = $BikeHandler->byLocationCheckIsInStopParking($location['lat'], $location['lng'], $order->area_id);
- if (!$is_huanche['status']) {
- // 不在还车点
- $dispatch_money = $BikeHandler->byDistanceGetDistanceMoney($is_huanche['distance'], $setting);
- RentOrder::where('id', $order->id)->update([
- 'dispatch_money' => $dispatch_money,
- ]);
- return [
- 'is_dispatch' => false,
- 'is_stop_bike' => false,
- 'dispatch_money' => $dispatch_money,
- ];
- }
- return [
- 'is_dispatch' => true,
- 'is_stop_bike' => true,
- 'dispatch_money' => 0,
- ];
- } catch (HttpException $exception) {
- return $this->errorNoValidation($exception->getMessage(), $exception->getStatusCode());
- }
- }
- /**
- * 判断是否在骑行区.
- *
- * @param $lat
- * @param $lng
- * @param $box_no
- * User: Mead
- */
- private function isOutArea($lat, $lng, $area)
- {
- try {
- $location = [
- 'latitude' => $lat,
- 'longitude' => $lng,
- ];
- $fences = $area['area_fence'];
- $centre = $area['area_centre'];
- $radius = $area['area_radius'];
- // 判断是否在骑行区域
- $ConvertHandler = (new ConvertHandler());
- $is_out_area = $ConvertHandler->is_point_in_polygon($location, $fences);
- return $is_out_area;
- } catch (\Exception $exception) {
- return $this->errorNoValidation($exception->getMessage());
- }
- }
- /**
- * 寻铃
- * @param Request $request
- * @param OrderRepository $orderRepository
- * @param BikeRepository $bikeRepository
- * User: Fx
- */
- public function retryBell(RetryBikeRequest $request, RentOrderRepository $rentOrderRepository, BikeRepository $bikeRepository)
- {
- try {
- $order_no = $request->get('order_no');
- $bike_no = $request->get('bike_no');
- $order = $rentOrderRepository->checkUserIsRetryOpenLock($order_no, $bike_no, $this->user->id);
- if (!$order) return $this->errorNoValidation('没有此订单');
- $box_no = $bikeRepository->byNoGetBoxNO($bike_no);
- $re = BikeControl::bellBike($box_no);
- return $this->response->array([
- 'is_ok' => $re
- ]);
- } catch (\Exception $exception) {
- return $this->errorNoValidation($exception->getMessage());
- }
- }
- /**
- * 检查是否可以结束订单
- * @param Request $request
- * @param BikeRepository $bikeRepository
- * @param RentOrderRepository $rentOrderRepository
- * @param LocationLogRepository $locationLogRepository
- * @param AreaRepository $areaRepository
- * @return array|void
- * Author: Mead
- */
- public function checkBikeIsRidingArea(Request $request, BikeRepository $bikeRepository, RentOrderRepository $rentOrderRepository, LocationLogRepository $locationLogRepository, AreaRepository $areaRepository)
- {
- $bike_no = $request->get('bike_no');
- $order_no = $request->get('order_no');
- $user_lat = $request->get('lat');
- $user_lng = $request->get('lng');
- try {
- $order = $rentOrderRepository->byNo($order_no);
- if (!$order) {
- return $this->errorBadRequest('非法请求');
- }
- $second = Carbon::now()->diffInSeconds(Carbon::parse($order->start_use_bike_time));
- if ($second < AreaSetting::CLOSE_BIKE_TIME) {
- //小于60秒直接锁车
- return [
- 'is_close_order' => true,
- ];
- }
- $user_id = $this->user['id'];
- $cache_key = "RENT_ORDER_CHECK_BIKE_IS_RIDING_PARK_{$user_id}";
- if (Cache::has($cache_key)) {
- return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
- }
- Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
- $box_no = $bikeRepository->byNoGetBoxNO($order->bike_no);
- BikeControl::nowBikeLocation($box_no);
- $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no);
- if ($location['lat'] <= 0) {
- $location['lat'] = $order->end_use_bike_location['latitude'];
- $location['lng'] = $order->end_use_bike_location['longitude'];
- if ($location['lat'] <= 0) {
- $location['lat'] = $user_lat;
- $location['lng'] = $user_lng;
- }
- }
- //检查是否在骑行区域
- $area = $areaRepository->byIdGetModelRedis($order->area_id);
- if (!$area) {
- $area = Area::where('id', $order->area_id)->first();
- }
- $is_out_area = $this->isOutArea($location['lat'], $location['lng'], $area);
- if (!$is_out_area) {
- return $this->errorNoValidation('超出骑行区域,暂不能还车');
- }
- //检查是否在禁停区
- $BikeHandler = new BikeHandler();
- $is_ban_stop_bike = $BikeHandler->byLocationCheckIsInBanStopParking($location['lat'], $location['lng'], $order->area_id);
- if ($is_ban_stop_bike) {
- return $this->errorNoValidation('禁停区域内禁止停车!');
- }
- return [
- 'is_close_order' => false,
- ];
- } catch (HttpException $exception) {
- return $this->errorNoValidation($exception->getMessage(), $exception->getStatusCode());
- }
- }
- /**
- * Author: Mead
- */
- public function expectRentOrderMoney(Request $request, BikeRepository $bikeRepository, RentOrderRepository $rentOrderRepository, AreaSettingRepository $areaSettingRepository, LocationLogRepository $locationLogRepository, AreaRepository $areaRepository)
- {
- $bike_no = $request->get('bike_no');
- $order_no = $request->get('order_no');
- $user_lat = $request->get('lat');
- $user_lng = $request->get('lng');
- try {
- $order = $rentOrderRepository->byNo($order_no);
- if (!$order) {
- return $this->errorBadRequest('非法请求');
- }
- $second = Carbon::now()->diffInSeconds(Carbon::parse($order->start_use_bike_time));
- if ($second < AreaSetting::CLOSE_BIKE_TIME) {
- //小于60秒直接锁车
- return [
- 'dispatch_money' => 0,
- 'time_money' => 0,
- 'rent_total_money' => 0,
- 'total_money' => 0,
- ];
- }
- $user_id = $this->user['id'];
- $cache_key = "RENT_ORDER_EXPECT_MONEY_{$user_id}";
- if (Cache::has($cache_key)) {
- return $this->errorNoValidation('您提交的太频繁了,请一会再提交!');
- }
- Cache::put($cache_key, 1, Carbon::now()->addSeconds(3));
- $box_no = $bikeRepository->byNoGetBoxNO($order->bike_no);
- BikeControl::nowBikeLocation($box_no);
- $setting = $areaSettingRepository->byAreaId($order->area_id);
- $money = 0.00;
- $over_hours = 0;
- //是否需要收取超出费用
- $is_over_time = (strtotime($order->return_end_bike_time) < time());
- if ($is_over_time) {
- //超出时间
- $over_hours = ceil(Carbon::now()->diffInMinutes(Carbon::parse($order->return_end_bike_time)) / 60);
- $hours = ceil(Carbon::now()->diffInMinutes(Carbon::parse($order->start_use_bike_time)) / 60);
- if ($hours > 24) {
- //超过1天
- $day = ceil($hours / 24);
- $end_hours = $hours % 24;
- //日封顶租金*天
- $money = bcmul($setting['over_rent_time_max_money'], ($day - 1), 2);
- // $money = bcadd($money, $setting['rent_money'], 2);
- if ($end_hours > $setting['rent_time']) {
- // 超过一天 又超过8小时
- // (超时费 + 日封顶租金*天)
- $money = bcadd(bcmul(($end_hours - $setting['rent_time']), $setting['over_rent_time_money'], 2), $money, 2);
- }
- } else {
- // 不超过1天 但是超过8小时
- $money = bcmul($over_hours, $setting['over_rent_time_money'], 2);
- // (超时费 + 基础租金) 是否大于日封顶租金
- $total_money = bcadd($money, $setting['rent_money'], 2);
- if ($total_money > $setting['over_rent_time_max_money']) {
- $money = bcsub($setting['over_rent_time_max_money'], $setting['rent_money'], 2);
- }
- }
- }
- $location = $locationLogRepository->byBikeNoGetLastLocation($order->bike_no);
- //计算骑行距离
- // $order->use_bike_distance_length = bcdiv($location['mileage'], 1000, 2);
- if ($location['lat'] <= 0) {
- $location['lat'] = $order->end_use_bike_location['latitude'];
- $location['lng'] = $order->end_use_bike_location['longitude'];
- if ($location['lat'] <= 0) {
- $location['lat'] = $user_lat;
- $location['lng'] = $user_lng;
- }
- }
- $money = floatval($money);
- $total_money = floatval(bcadd($money, $order->rent_total_money, 2));
- $rent_total_money = floatval($order->rent_total_money);
- //判断是否全区域内可停
- if ($areaSettingRepository->byAreaIdGetIsWholeAreaHuanche($order->area_id) === AreaSetting::WHOLE_AREA_HUANCHE_OK) {
- return [
- 'dispatch_money' => 0,
- 'time_money' => $money,
- 'rent_total_money' => $rent_total_money,
- 'total_money' => $total_money,
- ];
- }
- // 判断是否在停车点
- $BikeHandler = new BikeHandler();
- $is_huanche = $BikeHandler->byLocationCheckIsInStopParking($location['lat'], $location['lng'], $order->area_id);
- if (!$is_huanche['status']) {
- // 不在还车点
- $dispatch_money = $BikeHandler->byDistanceGetDistanceMoney($is_huanche['distance'], $setting);
- RentOrder::where('id', $order->id)->update([
- 'dispatch_money' => $dispatch_money,
- ]);
- return [
- 'dispatch_money' => $dispatch_money,
- 'time_money' => $money,
- 'rent_total_money' => $rent_total_money,
- 'total_money' => floatval(bcadd($total_money, $dispatch_money, 2)),
- ];
- }
- return [
- 'dispatch_money' => 0,
- 'time_money' => $money,
- 'rent_total_money' => $rent_total_money,
- 'total_money' => $total_money,
- ];
- } catch (HttpException $exception) {
- return $this->errorNoValidation($exception->getMessage(), $exception->getStatusCode());
- }
- }
- }
|