Taxi.php 18 KB

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