Taxi.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. <?php
  2. namespace app\api\controller\v1;
  3. use app\api\controller\ApiController;
  4. use app\api\model\taxi\MotorRecord;
  5. use app\api\service\SmsCode;
  6. use app\common\model\TaxiUsersLevel;
  7. use app\common\validate\IDMustBePositiveInt;
  8. use app\http\IResponse;
  9. use EasyWeChat\Factory;
  10. use think\Db;
  11. use think\facade\Cache;
  12. class Taxi extends ApiController
  13. {
  14. /**
  15. * 获取车辆
  16. *
  17. * @url GET /taxi/nearby?page=1
  18. * @author 许祖兴 < zuxing.xu@lettered.cn>
  19. * @date 2020/7/3 16:29
  20. *
  21. * @return \think\response\Json
  22. * @throws \think\db\exception\DataNotFoundException
  23. * @throws \think\db\exception\ModelNotFoundException
  24. * @throws \think\exception\DbException
  25. */
  26. public function getNearby()
  27. {
  28. $param = $this->request->param();
  29. $param['category_id'] = $this->request->param('category_id', 0);
  30. $limit = 10;
  31. $map['status'] = 1;
  32. if ($param['category_id']) {
  33. $map['category_id'] = $param['category_id'];
  34. }
  35. //
  36. $taxi = model('common/Taxi')->with(['user'])
  37. ->where($map)
  38. ->select();
  39. return $this->ApiJson(0,'获取成功', $taxi);
  40. }
  41. /**
  42. * 用车信息
  43. *
  44. * @url GET /taxi/:id
  45. * @author 许祖兴 < zuxing.xu@lettered.cn>
  46. * @date 2020/7/1 10:37
  47. *
  48. * @param int $id 用车ID
  49. * @return \think\response\Json
  50. * @throws \Lettered\Support\Exceptions\EvidentException
  51. * @throws \think\db\exception\DataNotFoundException
  52. * @throws \think\db\exception\ModelNotFoundException
  53. * @throws \think\exception\DbException
  54. */
  55. public function getTaxiByID($id)
  56. {
  57. (new IDMustBePositiveInt())->valid();
  58. $taxi = model('common/Taxi')->with(['user'])->hidden(['user.id_card'])
  59. ->find($id);
  60. if (!$taxi){
  61. return $this->ApiJson(-1, '不存在用车编号');
  62. }
  63. return $this->ApiJson(0, '获取用车信息成功', $taxi);
  64. }
  65. /**
  66. * 用车
  67. */
  68. public function callTaxi()
  69. {
  70. $params = $this->request->param();
  71. // 参数校验
  72. $valid = $this->validate($params, [
  73. 'taxi_id|关联车辆' => 'require',
  74. 'mobile|联系方式' => 'require',
  75. 'count|乘车人数' => 'require',
  76. 'depart|起始位置' => 'require',
  77. 'arrive|送达位置' => 'require',
  78. 'km|公里数' => 'require',
  79. 'price|价格' => 'require',
  80. ]);
  81. // 错误返回
  82. if(true !== $valid){
  83. return $this->ApiJson(-1, $valid);
  84. };
  85. $user = $this->auth->user();
  86. // 统计订单
  87. $count = model('common/TaxiOrder')->where('status','>=','2')->where(['is_free' => '1','user_id' => $user['id']])->count('id');
  88. // 创建订单
  89. $params['order_no'] = get_order_no();
  90. $params['user_id'] = $user['id'];
  91. $order = model('common/TaxiOrder')::create($params,true);
  92. //
  93. if ($order){
  94. // 创建对应支付记录
  95. $trade_no = get_order_no();
  96. $logID = model('common/OrderPaylog')->storeBy([
  97. 'out_trade_no' => $trade_no,
  98. 'total_price' => $params['price'],
  99. 'order_idx' => $order['id'],
  100. 'ascription' => 'motor' // 归属订单
  101. ]);
  102. // 免单优惠 20201201 添加条件 仅限xx 公里以下 不包含 xx 公里
  103. if ($count < sys_config('taxi_order_free_num','store') && $params['km'] < sys_config('taxi_order_free_km','store')){
  104. model('common/OrderPaylog')->updateBy($logID,[
  105. 'pay_price' => $params['price'],
  106. 'is_pay' => 1
  107. ]);
  108. model('common/TaxiOrder')->updateBy($order['id'], [
  109. 'is_free' => 1, // 免单
  110. 'status' => 2
  111. ]);
  112. // 后台推送
  113. // push_socket_data('motor',[
  114. // 'id' => $order['id'],
  115. // 'msg' => '有新的(免费)摩的订单等待处理哟,点击前往!'
  116. // ]);
  117. return $this->ApiJson(0,"本单免费,等待师傅接驾", [
  118. 'type' => 'free',
  119. 'success' => "ok!"
  120. ]);
  121. }
  122. // 返回支付单号
  123. return $this->ApiJson(0,'订单提交成功', [
  124. 'type' => 'wx',
  125. 'success' => "ok!",
  126. 'trade_no' => $trade_no
  127. ]);
  128. }
  129. return $this->ApiJson(-1,'发生异常,请骚后重试...');
  130. }
  131. /**
  132. * 用车,新的地图下单方式
  133. */
  134. public function newCallTaxi()
  135. {
  136. $datas = $this->request->param();
  137. // 参数校验
  138. $valid = $this->validate($datas, [
  139. 'mobile|联系方式' => 'require',
  140. 'count|乘车人数' => 'require',
  141. 'depart|起始位置' => 'require',
  142. 'arrive|送达位置' => 'require',
  143. 'km|公里数' => 'require',
  144. 'price|价格' => 'require',
  145. ]);
  146. // 错误返回
  147. if(true !== $valid){
  148. return $this->ApiJson(-1, $valid);
  149. };
  150. $user = $this->auth->user();
  151. // 统计订单
  152. $count = model('common/TaxiOrder')->where('status','>=','2')->where(['is_free' => '1','user_id' => $user['id']])->count('id');
  153. // 创建订单
  154. $driver = sys_config('', 'driver');
  155. $divide = isset($driver['platform_divide'])? $driver['platform_divide'] : 0;
  156. $depart = isset($datas['depart'])? $datas['depart'] : '';
  157. $arrive = isset($datas['arrive'])? $datas['arrive'] : '';
  158. $params = [
  159. 'user_id'=> $user['id'],
  160. 'category_id'=> isset($datas['category_id'])? $datas['category_id'] : 0,
  161. 'order_no'=> get_order_no(),
  162. 'price'=> isset($datas['price'])? $datas['price'] : 0.00,
  163. 'settle_price' => $divide>0 && $divide<=100? round($datas['price']*(100-$divide)/100, 2) : $datas['price'],
  164. 'count'=> isset($datas['count'])? $datas['count'] : 0,
  165. 'mobile'=> isset($datas['mobile'])? $datas['mobile'] : '',
  166. 'depart'=> $depart,
  167. 'depart_address'=> isset($datas['depart_address'])? $datas['depart_address'] : $depart,
  168. 'arrive'=> $arrive,
  169. 'arrive_address'=> isset($datas['arrive_address'])? $datas['arrive_address'] : $arrive,
  170. 'depart_lat'=> isset($datas['depart_lat'])? $datas['depart_lat'] : 0,
  171. 'depart_lng'=> isset($datas['depart_lng'])? $datas['depart_lng'] : 0,
  172. 'lat'=> isset($datas['lat'])? $datas['lat'] : 0,
  173. 'lng'=> isset($datas['lng'])? $datas['lng'] : 0,
  174. 'km'=> isset($datas['km'])? $datas['km'] : '',
  175. ];
  176. // 验证是否有未支付订单,有则直接更新订单为新订单
  177. $hasOrderId = model('common/TaxiOrder')->where(['user_id'=> $user['id'],'status'=> 1])->order('created_at','desc')->value('id');
  178. if($hasOrderId){
  179. model('common/TaxiOrder')->where(['id'=> $hasOrderId])->update($params);
  180. $order = model('common/TaxiOrder')->where(['id'=> $hasOrderId])->findOrFail();
  181. }else{
  182. $order = model('common/TaxiOrder')::create($params,true);
  183. }
  184. // 订单信息验证处理
  185. if ($order && $order['id']){
  186. // 创建对应支付记录
  187. $trade_no = get_order_no();
  188. $logID = model('common/OrderPaylog')->storeBy([
  189. 'out_trade_no' => $trade_no,
  190. 'total_price' => $params['price'],
  191. 'order_idx' => $order['id'],
  192. 'ascription' => 'motor' // 归属订单
  193. ]);
  194. // 免单优惠 20201201 添加条件 仅限xx 公里以下 不包含 xx 公里
  195. if ($count < sys_config('taxi_order_free_num','store') && $params['km'] < sys_config('taxi_order_free_km','store')){
  196. model('common/OrderPaylog')->updateBy($logID,[
  197. 'pay_price' => $params['price'],
  198. 'is_pay' => 1
  199. ]);
  200. model('common/TaxiOrder')->updateBy($order['id'], [
  201. 'is_free' => 1, // 免单
  202. 'status' => 2
  203. ]);
  204. // 后台推送
  205. // push_socket_data('motor',[
  206. // 'id' => $order['id'],
  207. // 'msg' => '有新的(免费)摩的订单等待处理哟,点击前往!'
  208. // ]);
  209. return $this->ApiJson(0,"本单免费,等待师傅接驾", [
  210. 'type' => 'free',
  211. 'success' => "ok!"
  212. ]);
  213. }
  214. // 返回支付单号
  215. return $this->ApiJson(0,'订单提交成功', [
  216. 'type' => 'wx',
  217. 'success' => "ok!",
  218. 'order_id' => $order['id'],
  219. 'trade_no' => $trade_no
  220. ]);
  221. }
  222. return $this->ApiJson(-1,'发生异常,请骚后重试...');
  223. }
  224. /**
  225. * 订单详情
  226. *
  227. * @author 许祖兴 < zuxing.xu@lettered.cn>
  228. * @date 2020/7/6 11:09
  229. *
  230. * @return \think\response\Json
  231. * @throws \Lettered\Support\Exceptions\FailedException
  232. * @throws \think\db\exception\DataNotFoundException
  233. * @throws \think\db\exception\ModelNotFoundException
  234. * @throws \think\exception\DbException
  235. */
  236. public function taxiOrder()
  237. {
  238. $param = $this->request->param();
  239. // 数据校验
  240. $valid = $this->validate($param, [
  241. 'order_id' => 'require',
  242. ]);
  243. // 错误
  244. if (true !== $valid) {
  245. return $this->ApiJson(-1, $valid);
  246. }
  247. $info = model('common/TaxiOrder')->with(['paylog','user','taxi','taxiUser'])
  248. ->where(['user_id' => $this->auth->user()['id'], 'id'=> $param['order_id']])
  249. ->find();
  250. return $this->ApiJson(0,'获取成功', $info);
  251. }
  252. /**
  253. * 当前进行中订单详情
  254. *
  255. * @author 许祖兴 < zuxing.xu@lettered.cn>
  256. * @date 2020/7/6 11:09
  257. *
  258. * @return \think\response\Json
  259. * @throws \Lettered\Support\Exceptions\FailedException
  260. * @throws \think\db\exception\DataNotFoundException
  261. * @throws \think\db\exception\ModelNotFoundException
  262. * @throws \think\exception\DbException
  263. */
  264. public function waitOrder()
  265. {
  266. $info = model('common/TaxiOrder')->with(['paylog','user','taxi','taxiUser'])
  267. ->where(['user_id' => $this->auth->user()['id']])
  268. ->whereIn('status',[2,3])
  269. ->order('created_at','desc')
  270. ->find();
  271. if($info){
  272. if($info['taxi_user']){
  273. $info['taxi_user']['level_name'] = TaxiUsersLevel::where(['level'=>$info['taxi_user']['level']])->value('title');
  274. }
  275. }
  276. return $this->ApiJson(0,'获取成功', !is_null($info)? $info : []);
  277. }
  278. /**
  279. * 订单
  280. *
  281. * @author 许祖兴 < zuxing.xu@lettered.cn>
  282. * @date 2020/7/6 11:09
  283. *
  284. * @return \think\response\Json
  285. * @throws \Lettered\Support\Exceptions\FailedException
  286. * @throws \think\db\exception\DataNotFoundException
  287. * @throws \think\db\exception\ModelNotFoundException
  288. * @throws \think\exception\DbException
  289. */
  290. public function order()
  291. {
  292. $param = $this->request->param();
  293. $limit = 10;
  294. // 数据校验
  295. $valid = $this->validate($param, [
  296. 'page' => 'require',
  297. ]);
  298. // 错误
  299. if (true !== $valid) {
  300. return $this->ApiJson(-1, $valid);
  301. }
  302. $orders = model('common/TaxiOrder')
  303. ->with(['paylog'])
  304. ->where(['user_id' => $this->auth->user()['id']])
  305. ->limit((($param['page'] - 1) * $limit) . "," . $limit)
  306. ->order(['id' => 'desc'])
  307. ->select();
  308. return $this->ApiJson(0,'获取成功', $orders);
  309. }
  310. /**
  311. * @desc 取消订单
  312. * @return \think\response\Json
  313. * @throws \think\db\exception\DataNotFoundException
  314. * @throws \think\db\exception\ModelNotFoundException
  315. * @throws \think\exception\DbException
  316. * @author weichuanbao<654745815@qq.com>
  317. * @date 2021/12/2 0002
  318. */
  319. public function cancelOrder()
  320. {
  321. $param = $this->request->param();
  322. // 数据校验
  323. $valid = $this->validate($param, [
  324. 'id' => 'require|number',
  325. ]);
  326. // 错误
  327. if (true !== $valid) {
  328. return $this->ApiJson(-1, $valid);
  329. }
  330. $row = model('common/TaxiOrder')->with(['paylog'])
  331. ->field('id,taxi_uid,taxi_id,status,created_at')
  332. ->whereNotIn('status', [0,5])
  333. ->find($param['id']);
  334. $user = $this->auth->user();
  335. if ($row) {
  336. if (time() - $row['created_at']['val'] < (60 * 10)) {
  337. // return $this->ApiJson(-1, '10分钟内无法取消订单');
  338. }
  339. $taxiUid = isset($row['taxi_uid'])? intval($row['taxi_uid']) : 0;
  340. if ($row['status'] == 2 || $row['status'] == 3) {
  341. $config = Cache::get('system_config');
  342. $total_price = $row->paylog['total_price'];
  343. // 如果平台已指派司机,则扣除部分金额
  344. $cost_price = 0;
  345. $total = $total_price;
  346. $createTime = isset($row['created_at'])? $row['created_at'] : 0;
  347. $cancelTime = isset($config['store']['store_cancel_time'])? $config['store']['store_cancel_time'] : 0;
  348. $taxiUser = model('common/TaxiUser')->where(['id'=> $taxiUid])->find();
  349. $taxiUserId = isset($taxiUser['user_id'])? $taxiUser['user_id'] : 0;
  350. if ($row['status'] == 3 ) {
  351. // 免费取消时间内不扣除
  352. if($cancelTime<=0 || $createTime < (time() - $cancelTime*60)){
  353. $total_price = round($total_price * (1 - $config['store']['store_cancel_order']/100), 2);
  354. $cost_price = $total-$total_price;
  355. }
  356. }
  357. if ($row->paylog['pay_type'] == 'balance') {
  358. model('common/Users')->changeBalance(
  359. $user['id'],
  360. $total_price,
  361. "取消成功,取消金额【" . $total_price . "】",
  362. true
  363. );
  364. // 退款扣除金额直接给司机
  365. if($taxiUserId && $cost_price>0){
  366. model('common/Users')->changePartnership(
  367. $taxiUserId,
  368. $cost_price,
  369. "取消订单,扣除金额到账【" . $cost_price . "】",
  370. 30,
  371. true
  372. );
  373. }
  374. } else if ($row->paylog['pay_type'] == 'property') {
  375. model('common/Users')->changeProperty(
  376. $user['id'],
  377. $total_price,
  378. "取消成功,取消资产【{$total_price}】",
  379. true
  380. );
  381. // 退款扣除金额直接给司机
  382. if($taxiUserId && $cost_price>0){
  383. model('common/Users')->changePartnership(
  384. $taxiUserId,
  385. $cost_price,
  386. "取消订单,扣除金额到账【" . $cost_price . "】",
  387. 30,
  388. true
  389. );
  390. }
  391. } else if ($row->paylog['pay_type'] == 'wechat') {
  392. // 加载配置
  393. $wechat = sys_config('', 'wechat');
  394. $config = [
  395. // 前面的appid什么的也得保留哦
  396. 'app_id' => $wechat['mini_appid'],
  397. 'mch_id' => $wechat['pay_mch_id'],
  398. 'key' => $wechat['pay_secret_key'],
  399. // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
  400. 'cert_path' => $wechat['cert_path'], // XXX: 绝对路径!!!!
  401. 'key_path' => $wechat['key_path'], // XXX: 绝对路径!!!!
  402. // 'notify_url' => 'https://api.gxrrj.cn/api/v1/wechat/notify',
  403. // 'notify_url' => 'http://rrj.gxnwsoft.com/api/v1/wechat/refundNotify',
  404. // 'sandbox' => true
  405. ];
  406. // 创建应用实例
  407. $app = Factory::payment($config);
  408. // Example:
  409. $result = $app->refund->byOutTradeNumber($row->paylog['out_trade_no'], get_order_no(), $row->paylog['total_price'] * 100, $total_price * 100, [
  410. // 可在此处传入其他参数,详细参数见微信支付文档
  411. 'refund_desc' => '用户申请退款',
  412. ]);
  413. app()->log(json_encode($result));
  414. if ($result['return_code'] == 'SUCCESS') {
  415. if ($result['result_code'] != 'SUCCESS') {
  416. $this->ApiJson(-1, '失败');
  417. }
  418. }
  419. // 退款扣除金额直接给司机
  420. if($taxiUserId && $cost_price>0){
  421. model('common/Users')->changePartnership(
  422. $taxiUserId,
  423. $cost_price,
  424. "取消订单,扣除金额到账【" . $cost_price . "】",
  425. 30,
  426. true
  427. );
  428. }
  429. }
  430. }
  431. // 后台推送
  432. push_socket_data('motor',[
  433. 'id' => $row['id'],
  434. 'msg' => '有用户取消订单,点击前往!'
  435. ]);
  436. Db::startTrans();
  437. $row->status = 5;
  438. $row->settle_price = $cost_price;
  439. $row->remark = $param['result'];
  440. if(!$row->save()){
  441. Db::rollback();
  442. return IResponse::failure('取消失败');
  443. }
  444. if ($row['taxi_id'] && !\app\common\model\Taxi::where(['taxi_user_id' => $taxiUid, 'id' => $row['taxi_id']])->update(['status' => 1])) {
  445. Db::rollback();
  446. return IResponse::failure('取消失败');
  447. }
  448. Db::commit();
  449. return $this->ApiJson(0, '取消成功', $row);
  450. }
  451. return $this->ApiJson(-1, '取消失败');
  452. }
  453. }