OrderController.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Http\Controllers\ApiController;
  4. use App\Servers\CommonServer;
  5. use App\Servers\OrderServer;
  6. use App\Servers\RedisDataServer;
  7. use App\Servers\ShoppingCartServer;
  8. use Carbon\Carbon;
  9. use Illuminate\Validation\Rules\In;
  10. /**
  11. * 外卖订单
  12. */
  13. class OrderController extends ApiController
  14. {
  15. /**
  16. * 前端获取订单状态
  17. */
  18. function getOrderStatus()
  19. {
  20. $statusArr = [
  21. 0=>'全部',
  22. 1=>'待支付',
  23. 2=>'制作中',
  24. 3=>'已完成',
  25. 4=>'已取消',
  26. 5=>'退款',
  27. ];
  28. $data = [];
  29. foreach ($statusArr as $key=>$value){
  30. $data[] = [
  31. 'key' => $key,
  32. 'name' => $value,
  33. ];
  34. }
  35. return $this->apiResponseSuccess('成功',array_values($data));
  36. }
  37. /**
  38. * 下单
  39. */
  40. function createOrder()
  41. {
  42. $m_id = $this->getMemberId();//用户id
  43. $commonServer = CommonServer::creatServer();
  44. $shop_id = $commonServer->filtrationStr('shop_id');//商家id
  45. $order_type = $commonServer->filtrationStr('$order_type',1);//订单类型 1堂食订单 2打包订单
  46. $table_number = $commonServer->filtrationStr('table_number');//桌号
  47. $diner_number = $commonServer->filtrationStr('diner_number');//就餐人数
  48. $note = $commonServer->filtrationStr('note');//备注
  49. if (empty($shop_id)) return $this->apiResponseError('商家错误');
  50. if (!in_array($order_type,[1,2])){
  51. return $this->apiResponseError('就餐方式错误');
  52. }
  53. if (empty($table_number) || $table_number < 0) return $this->apiResponseError('桌号错误');
  54. if (empty($diner_number) || $table_number < 0) return $this->apiResponseError('就餐人数错误');
  55. if (!empty($note) && mb_strlen($note) > 30 ) return $this->apiResponseError('备注最大30');
  56. //获取购买的商品信息
  57. $goods = ShoppingCartServer::creatServer()->getShoppingList($m_id,$shop_id);
  58. if (count($goods['goods_list']) <= 0) {
  59. return $this->apiResponseError('商品信息错误');
  60. }
  61. //加锁
  62. $lock_key = $shop_id.'lockOrderCreate';
  63. $lock_value = uniqid(bin2hex(random_bytes(10)), true);
  64. $lock = RedisDataServer::creatServer()->lockKey($lock_key,$lock_value,500);
  65. if (!$lock){
  66. return $this->apiResponseError('下单人数过多,请稍候');
  67. }
  68. //下单
  69. $res = OrderServer::creatServer()->createOrder($m_id,$shop_id,$order_type,$table_number,$diner_number,$note,$goods);
  70. //删除锁key-防止死锁
  71. RedisDataServer::creatServer()->unLockKey($lock_key,$lock_value);
  72. if ($res['code'] == 0) {
  73. return $this->apiResponseError($res['msg']);
  74. }
  75. return $this->apiResponseSuccess('订单创建成功', $res['data']);
  76. }
  77. /**
  78. * 获取订单支付信息
  79. * @return \Illuminate\Http\JsonResponse
  80. */
  81. function getOrderPayInfo()
  82. {
  83. $m_id = $this->getMemberId();//用户id
  84. $commonServer = CommonServer::creatServer();
  85. $order_id = $commonServer->filtrationStr('order_id');//订单id
  86. if (empty($order_id)) {
  87. return $this->apiResponseError('缺少必要参数');
  88. }
  89. $member = Member::where('id', $m_id)->select(['id', 'money'])->first();
  90. if (empty($member)) {
  91. return $this->apiResponseError('会员信息错误');
  92. }
  93. $order_info = Order::where('id', $order_id)
  94. ->where('m_id', $m_id)
  95. ->where('order_status', 1)
  96. ->select(['id', 'order_status', 'order_money','pay_money','coupon_money', 'order_sn', 'shop_id','created_at'])
  97. ->first();
  98. if (empty($order_info)) {
  99. return $this->apiResponseError('订单已失效');
  100. }
  101. $order_info->{'member_money'} = $member['money'];//用户余额
  102. //订单过期时间
  103. $end_time = config('order.order_repeal_time', 10) * 60;
  104. $order_info->{'time'} = strtotime($order_info->{'created_at'}) + $end_time;
  105. return $this->apiResponseSuccess('获取数据成功', $order_info);
  106. }
  107. /**
  108. * 支付订单
  109. */
  110. function payOrder()
  111. {
  112. $m_id = $this->getMemberId();//用户id
  113. $commonServer = CommonServer::creatServer();
  114. $order_id = $commonServer->filtrationStr('order_id');//订单id
  115. $pay_type = $commonServer->filtrationStr('pay_type',1);//支付方式 1微信 2支付宝 3余额支付
  116. $system_type = request()->input('system_type',2);//1微信h5 2微信小程序 3qq小程序
  117. if (empty($order_id)) return $this->apiResponseError('请选择订单');
  118. if (!in_array($pay_type, [1, 2, 3])) return $this->apiResponseError('支付方式错误');
  119. if (!in_array($system_type, [1, 2, 3])) return $this->apiResponseError('来源平台错误');
  120. $order_info = Order::where('id', $order_id)
  121. ->where('m_id', $m_id)
  122. ->where('order_status', 1)
  123. ->select(['id', 'order_status','order_money', 'pay_money', 'order_sn', 'm_id','shop_id'])
  124. ->first();
  125. if (empty($order_info)) {
  126. return $this->apiResponseError('订单已失效');
  127. }
  128. //获取商家状态
  129. $shop_status = Shop::where('id', $order_info['shop_id'])->value('status');
  130. if ($shop_status != 1) {
  131. return $this->apiResponseError('商家已闭店');
  132. }
  133. //定义返回参数
  134. $data = ['pay_status' => false, 'wx_pay' => [], 'zfb_pay' => []];
  135. if($pay_type == 1) {
  136. //微信支付
  137. $notify_url = route('notify.order_wx');
  138. $wx_openid = MemberOpenId::where('m_id', $m_id)->where('type', $system_type)->value('openid');
  139. if (empty($wx_openid)) {
  140. return $this->apiResponseError('用户信息错误');
  141. }
  142. $wx_pay = WeixinServer::creatServer()->wxJsPay($order_info->{'order_sn'}, $order_info->{'pay_money'}, $notify_url, '外卖订单', $wx_openid);
  143. $data['wx_pay'] = $wx_pay;
  144. }elseif ($pay_type == 2) {
  145. $data['zfb_pay'] = [];
  146. }else{//余额支付
  147. $member = Member::where('id', $m_id)->select(['id', 'money'])->first();
  148. if (empty($member)) {
  149. return $this->apiResponseError('会员信息错误');
  150. }
  151. if ($member->{'money'} < $order_info->{'pay_money'}) {
  152. return $this->apiResponseError('余额不足');
  153. }
  154. //余额扣款
  155. $ret = OrderServer::creatServer()->balancePay($order_info);
  156. if (empty($ret)) {
  157. return $this->apiResponseError('余额支付失败');
  158. }
  159. $data['pay_status'] = true;
  160. }
  161. return $this->apiResponseSuccess('成功', $data);
  162. }
  163. /**
  164. * 用户获取外卖订单列表
  165. */
  166. function getOrderList()
  167. {
  168. $m_id = $this->getMemberId();//用户id
  169. $commonServer = CommonServer::creatServer();
  170. $status = $commonServer->filtrationStr('status',-1);//状态 0全部 1待支付 2待接单 3配送中 4待评价 5退款/撤销
  171. $where = [['o.m_id',$m_id], ['o.is_del',0]];
  172. $list = Order::from('order as o')
  173. ->leftJoin('shops as s','s.id','=','o.shop_id')
  174. ->where($where)
  175. ->where(function ($q) use ($status){
  176. if ($status == 1){
  177. $q->where('o.order_status',1);
  178. }elseif ($status == 2){
  179. $q->where('o.order_status',2);
  180. }elseif ($status == 3){
  181. $q->whereIn('o.order_status',[4,5,6]);
  182. }elseif ($status == 4){
  183. $q->where('o.order_status',7);
  184. $q->where('o.is_comment',0);
  185. }elseif ($status == 5){
  186. $q->whereIn('o.order_status',[3,8,9,10]);
  187. }
  188. })
  189. ->select(['o.id','o.order_sn','o.order_status','o.pay_money','o.is_comment','o.goods_number','o.created_at','o.shop_id','s.shop_name','s.shop_logo'])
  190. ->orderBy('o.id','desc')
  191. ->paginate(10);
  192. foreach ($list as $value){
  193. $value->{'refund_status'} = OrderDetails::where('order_id',$value->{'id'})->value('refund_status');
  194. $value->{'shop_name'} = $commonServer->truncateChineseString($value->{'shop_name'},16);
  195. $value->{'item'} = OrderItem::where('order_id',$value->{'id'})->select(['goods_name','goods_img'])->orderBy('id','asc')->get();
  196. $value->initializeModel();
  197. }
  198. return $this->apiResponseSuccess('成功', [
  199. 'items' => $list->items(),
  200. 'total' => $list->total(),
  201. 'limit' => 10,
  202. ]);
  203. }
  204. /**
  205. * 取消订单
  206. */
  207. function cancelOrder()
  208. {
  209. $m_id = $this->getMemberId();//用户id
  210. $commonServer = CommonServer::creatServer();
  211. $order_id = $commonServer->filtrationStr('order_id');//订单id
  212. $refund_msg = $commonServer->filtrationStr('refund_msg','');//退款原因
  213. if (empty($order_id) || !is_numeric($order_id)) {
  214. return $this->apiResponseError('请选择订单');
  215. }
  216. if (empty($refund_msg)) return $this->apiResponseError('请选择原因');
  217. $order_info = Order::where('m_id', $m_id)
  218. ->where('id', $order_id)
  219. ->where('is_del',0)
  220. ->select(['id','order_sn','m_id','operate_id','school_id', 'time', 'order_type','order_status','pay_money','pay_type','pay_code', 'shop_id','coupon_id'])
  221. ->first();
  222. if (empty($order_info)) return $this->apiResponseError('订单信息错误');
  223. if (!in_array($order_info['order_status'], [2,4])) {
  224. return $this->apiResponseError('当前订单不能取消');
  225. }
  226. //获取需要的配送时间
  227. $date = date('Y-m-d H:i:s');
  228. $current_time = Carbon::parse($date, config('app.timezone'))->format('Y-m-d H:i:s');
  229. //获取需要的配送时间
  230. $delivery_time = ShopServer::creatServer()->getShopDeliveryTime($order_info->{'shop_id'});
  231. $time = Carbon::parse($order_info->{'time'}, config('app.timezone'))->subMinutes($delivery_time + 30)->format('Y-m-d H:i:s');
  232. if ($order_info->{'order_status'} == 2 || $current_time < $time){//订单状态为待接单或者当前时间小于预定送达时间 - ($delivery_time + 30)
  233. $ret = OrderServer::creatServer()->refundPay($order_info,'用户取消订单,原因:'.$refund_msg);
  234. if (empty($ret)) {
  235. return $this->apiResponseError('退款失败');
  236. }
  237. $refund_sn = $ret['refund_sn'];
  238. $refund_money = $ret['refund_money'];
  239. Order::where('id', $order_info->{'id'})->update(['order_status' => 8]);
  240. OrderDetails::where('order_id', $order_info->{'id'})->update(['refund_status' => 2,'refund_sn'=>$refund_sn,'refund_money'=>$refund_money,'refund_msg'=>$refund_msg]);
  241. //添加记录
  242. OrderRecordServer::creatServer()->writeRecord($order_info->{'id'},$order_info->{'shop_id'},0,0,'用户发起订单退款,退款完成,原因:'.$refund_msg);
  243. //回退优惠卷
  244. CouponServer::creatServer()->backCoupon($order_info->{'m_id'},$order_info->{'coupon_id'});
  245. //获取订单商品,商品不是无限库存需要回退库存
  246. $goods = OrderItem::from('order_item as i')
  247. ->leftJoin('goods as g','g.id','=','i.goods_id')
  248. ->where('i.order_id',$order_id)
  249. ->select(['i.goods_number','i.goods_id','i.goods_spec_id','i.seckill_money','g.is_infinite','g.stock'])
  250. ->get();
  251. foreach ($goods as $value){
  252. if ($value->{'is_infinite'} != 1){//回退库存
  253. Goods::where('id',$value['goods_id'])->increment('stock',$value['goods_number']);
  254. }
  255. if ($value->{'seckill_money'} > 0){
  256. $key_name = 'seckill_'.$value['goods_id'];
  257. RedisDataServer::creatServer()->addOneQueue($key_name, 1);
  258. }
  259. }
  260. //投递用户订单统计任务
  261. JobServer::creatServer()->sendMemberOrderTotal($order_info->{'m_id'},$order_info->{'school_id'},1,$order_info->{'created_at'},0,$order_info->{'pay_money'});
  262. //投递商户订单统计任务
  263. JobServer::creatServer()->sendShopOrderTotal($order_info->{'shop_id'},$order_info->{'school_id'},1,$order_info->{'created_at'},0,$order_info->{'pay_money'});
  264. JobServer::creatServer()->sendSchoolOrderTotal($order_info->{'school_id'},1,$order_info->{'created_at'},0,$order_info->{'pay_money'});
  265. return $this->apiResponseSuccess('退款成功');
  266. }else{//已接单需要商家同意
  267. $ret = Order::where('id', $order_info->{'id'})->update(['order_status' => 8]);
  268. OrderDetails::where('order_id', $order_info->{'id'})->update(['refund_status' => 1,'refund_msg'=>$refund_msg]);
  269. if (empty($ret)) {
  270. return $this->apiResponseError('申请退款失败');
  271. } else {
  272. //添加记录
  273. OrderRecordServer::creatServer()->writeRecord($order_info->{'id'},$order_info->{'shop_id'},0,0,'用户发起订单退款,等待商家确认,原因:'.$refund_msg);
  274. //投递打印任务
  275. JobServer::creatServer()->cancelOrderPrintJob($order_info->{'id'},$order_info->{'shop_id'},1);
  276. return $this->apiResponseSuccess('等待商家同意中');
  277. }
  278. }
  279. }
  280. /**
  281. * 订单详情
  282. */
  283. function getOrderInfo()
  284. {
  285. $m_id = $this->getMemberId();//用户id
  286. $commonServer = CommonServer::creatServer();
  287. $order_id = $commonServer->filtrationStr('order_id');//订单id
  288. if (empty($order_id)) return $this->apiResponseError('请选择订单');
  289. $where = [['o.m_id',$m_id], ['o.is_del',0], ['o.id',$order_id]];
  290. $order = Order::from('order as o')
  291. ->leftJoin('order_address as a','a.order_id','=','o.id')
  292. ->leftJoin('order_details as d','d.order_id','=','o.id')
  293. ->where($where)
  294. ->select(['o.id','o.order_sn','o.time','o.pay_type','o.m_id','o.note','o.order_status','o.pay_money','o.is_comment','o.goods_number','o.coupon_money','o.shop_id','o.created_at','d.refund_status','d.pack_price','d.delivery_money','d.finish_time','d.finish_image','a.school_id','a.dorm_id','a.consignee','a.phone as consignee_tel','a.address'])
  295. ->first();
  296. if (empty($order)) return $this->apiResponseError('订单不存在');
  297. $order->{'school_name'} = School::where('id',$order->{'school_id'})->value('school_name');
  298. $order->{'dorm_name'} = SchoolDorm::where('id',$order->{'dorm_id'})->value('name');
  299. $order->{'shop'} = Shop::where('id',$order->{'shop_id'})->select(['shop_name','shop_logo','shop_phone'])->first();
  300. $order->{'item'} = OrderItem::where('order_id',$order_id)
  301. ->select(['goods_name','goods_img','goods_attr','goods_number','goods_price'])
  302. ->orderBy('id','asc')
  303. ->get();
  304. //获取最新的骑手id
  305. $rider_id = OrderRecord::where('order_id',$order_id)->where('rider_id','>',0)->orderBy('id','desc')->value('rider_id');
  306. if (!empty($rider_id)){
  307. $rider = Rider::where('id',$rider_id)->select(['rider_name','phone'])->first();
  308. }else{
  309. $rider['rider_name'] = '';
  310. $rider['phone'] = '';
  311. }
  312. $order->{'rider'} = $rider;
  313. $order->initializeModel();
  314. return $this->apiResponseSuccess('成功', $order);
  315. }
  316. /**
  317. * 修改收货地址
  318. */
  319. function updateAddress()
  320. {
  321. $m_id = $this->getMemberId();//用户id
  322. $commonServer = CommonServer::creatServer();
  323. $order_id = $commonServer->filtrationStr('order_id');//订单id
  324. $address_id = $commonServer->filtrationStr('address_id', '');//地址id
  325. if (empty($order_id) || !is_numeric($order_id)) {
  326. return $this->apiResponseError('缺少必要参数');
  327. }
  328. if (empty($address_id)) {
  329. return $this->apiResponseError('请输入新地址信息');
  330. }
  331. $where = [['m_id', $m_id], ['id',$order_id], ['is_del', 0]];
  332. $order = Order::where($where)
  333. ->select(['id', 'order_sn', 'order_status', 'm_id'])
  334. ->orderBy('id', 'desc')
  335. ->first();
  336. if (empty($order)) {
  337. return $this->apiResponseError('订单信息错误');
  338. }
  339. if ($order->{'order_status'} > 2) {
  340. return $this->apiResponseError('订单状态错误');
  341. }
  342. //获取地址信息
  343. $address_info = MemberAddress::where('m_id',$m_id)
  344. ->where('id',$address_id)
  345. ->where('is_del',0)
  346. ->select(['id','phone','school_id','dorm_id','consignee','address'])
  347. ->first();
  348. if (empty($address_info)) {
  349. return $this->apiResponseError('地址信息错误');
  350. }
  351. $info = OrderAddress::where('m_id',$m_id)->where('order_id',$order_id)->select(['id','school_id'])->first();
  352. //判断收货地址是否在一个学校
  353. if ($info->{'school_id'} != $address_info->{'school_id'}) {
  354. return $this->apiResponseError('收货地址与该订单不在同一学校');
  355. }
  356. $res = OrderServer::creatServer()->saveAddress($m_id,$order_id, $address_info);
  357. if (!$res) {
  358. return $this->apiResponseError('修改失败');
  359. }
  360. //添加记录
  361. OrderRecordServer::creatServer()->writeRecord($order_id,0,0,0,'用户修改收货地址');
  362. return $this->apiResponseSuccess('修改成功');
  363. }
  364. }