Order.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\model\GoodsOrder;
  4. use app\common\model\GoodsOrderItem;
  5. use app\common\model\StoreGoods;
  6. use app\common\model\StoreGoodsItem;
  7. use app\common\model\User;
  8. use think\Db;
  9. use think\Exception;
  10. /**
  11. * @title 商城订单
  12. * @controller Order
  13. * @group base
  14. */
  15. class Order extends Base
  16. {
  17. public function initialize()
  18. {
  19. parent::initialize();
  20. parent::checkLogin();
  21. }
  22. /**
  23. * @title 创建订单
  24. * @desc 创建订单
  25. * @author qc
  26. * @url /api/Order/createOrder
  27. * @method POST
  28. * @header name:Authorization require:1 desc:Token
  29. * @param name:goods_json type:string require:1 default:0 desc:商品json信息[{'goods_id':'商品id',spec_id:'规格id';'num':'数量'}]
  30. * @param name:pro_name type:string default:-- desc:收货地址--省
  31. * @param name:city_name type:string default:-- desc:收货地址--市
  32. * @param name:county_name type:string default:-- desc:收货地址--区
  33. * @param name:add_detail type:string default:-- desc:收货地址--详情
  34. * @param name:user_name type:string default:-- desc:收货人
  35. * @param name:phone type:string default:-- desc:收货人联系方式
  36. * @param name:remark type:string default:1 desc:订单备注
  37. * @return name:order_id type:int default:1 desc:订单id
  38. */
  39. public function createOrder()
  40. {
  41. $goods_json = input('post.goods_json','');
  42. $pro_name = input('post.pro_name','');
  43. $city_name = input('post.city_name','');
  44. $county_name = input('post.county_name','');
  45. $add_detail = input('post.add_detail','');
  46. $user_name = input('post.user_name','');
  47. $phone = input('post.phone','');
  48. $remark = input('post.remark','');
  49. if(!$goods_json) $this->error('请选择商品');
  50. if(!$pro_name || !$city_name || !$county_name || !$add_detail) $this->error('请完善收货地址');
  51. if(!$user_name || !$phone) $this->error('请完善收货人信息');
  52. $goods_data = json_decode($goods_json,true);
  53. $goods_ids = array_column($goods_data,'goods_id');
  54. $goods_list = StoreGoods::field('specs,lists',true)->where('id','in',implode(',',$goods_ids))->where('status',1)->where('is_deleted',0)->with('itemList')->select()->toArray();
  55. if(count($goods_list) != count($goods_ids)) $this->error('所选商品已下架');
  56. $goods_column = array_column($goods_list,null,'id');
  57. $ret_data = ['pay_status'=>0,'config'=>[],'order_id'=>0];
  58. Db::startTrans();
  59. try{
  60. // 验证商品库存start
  61. $check_goods = 0;
  62. $error_goods = '';
  63. $price_goods = 0; // 商品总金额
  64. $original_total = 0; // 商品总原价
  65. $order_item = [];// 订单列表
  66. foreach ($goods_data as $gv) {
  67. $goods_spec = $goods_column[$gv['goods_id']]['item_list'];
  68. $spec_column = array_column($goods_spec,null,'id');
  69. if(!isset($spec_column[$gv['spec_id']])){
  70. $check_goods = 1;
  71. $error_goods = $goods_column[$gv['goods_id']]['name'];
  72. break;
  73. }else if($spec_column[$gv['spec_id']]['stock'] < $gv['num']){
  74. $check_goods = 2;
  75. $error_goods = $goods_column[$gv['goods_id']]['name'];
  76. break;
  77. }
  78. $price_goods += $gv['num'] * $spec_column[$gv['spec_id']]['sell_price'];
  79. $original_total += $gv['num'] * $spec_column[$gv['spec_id']]['original_price'];
  80. $order_item[] = [
  81. 'user_id' => $this->user_id,
  82. 'goods_id' => $gv['goods_id'],
  83. 'goods_no' => $spec_column[$gv['spec_id']]['goods_no'],
  84. 'goods_name' => $goods_column[$gv['goods_id']]['name'],
  85. 'goods_spec' => $spec_column[$gv['spec_id']]['goods_spec'],
  86. 'spec_title' => $spec_column[$gv['spec_id']]['spec_title'],
  87. 'spec_id' => $gv['spec_id'],
  88. 'cover' => $spec_column[$gv['spec_id']]['cover'],
  89. 'original_price' => $spec_column[$gv['spec_id']]['original_price'],
  90. 'sell_price' => $spec_column[$gv['spec_id']]['sell_price'],
  91. 'num' => $gv['num'],
  92. ];
  93. StoreGoods::where('id',$gv['goods_id'])->setDec('stock',$gv['num']);
  94. StoreGoodsItem::where('id',$gv['spec_id'])->setDec('stock',$gv['num']);
  95. }
  96. if($check_goods == 1) $this->exception('所选商品'.$error_goods.'已下架');
  97. if($check_goods == 2) $this->exception('所选商品'.$error_goods.'规格库存不足');
  98. // 验证商品库存end
  99. $order_insert = [
  100. 'user_id' => $this->user_id,
  101. 'order_no' => get_order_sn(),
  102. 'goods_num' => array_sum(array_column($goods_data,'num')),
  103. 'pro_name' => $pro_name,
  104. 'city_name' =>$city_name,
  105. 'county_name' => $county_name,
  106. 'add_detail' => $add_detail,
  107. 'user_name' => $user_name,
  108. 'phone' => $phone,
  109. 'remark' => $remark,
  110. ];
  111. $order_insert['price_total'] = $price_goods;
  112. $order_insert['price_goods'] = $price_goods ;
  113. $order_insert['original_total'] = $original_total ;
  114. $order_insert['price_express'] = 0 ;
  115. $order_info = GoodsOrder::create($order_insert);// 生成订单
  116. array_walk($order_item,function (&$v,$k)use ($order_info){
  117. $v['order_id'] = $order_info->id;
  118. });
  119. (new GoodsOrderItem())->insertAll($order_item);// 生成订单商品详情
  120. $ret_data['order_id'] = $order_info->id;
  121. Db::commit();
  122. }catch (\Exception $e){
  123. Db::rollback();
  124. $this->error($e->getMessage());
  125. }
  126. $this->success($ret_data);
  127. }
  128. /**
  129. * @title 订单支付
  130. * @desc 订单支付
  131. * @author qc
  132. * @url /api/Order/payOrder
  133. * @method POST
  134. * @header name:Authorization require:1 desc:Token
  135. * @param name:order_id type:int require:1 default:0 desc:订单id
  136. * @return name:config type:array default:0 desc:小程序支付配置
  137. * @return name:config.appId type:string default:-- desc:appid
  138. * @return name:config.nonceStr type:string default:-- desc:随机字符串
  139. * @return name:config.signType type:string default:-- desc:签名类型
  140. * @return name:config.paySign type:string default:-- desc:签名
  141. * @return name:config.timestamp type:string default:-- desc:时间戳
  142. */
  143. public function payOrder()
  144. {
  145. $order_id = input('post.order_id');
  146. $order_info = GoodsOrder::with('orderItem')->where('id',$order_id)->find()->toArray();
  147. if($order_info['status'] != 0) $this->error('订单状态错误');
  148. if($order_info['cancel_state'] != 0 || $order_info['is_deleted'] != 0) $this->error('订单异常');
  149. if($order_info['price_total'] <= 0) $this->error('订单金额错误');
  150. $user_info = User::where('id',$this->user_id)->find()->toArray();
  151. $ret_data = ['pay_status'=>0,'config'=>[]];
  152. Db::startTrans();
  153. try {
  154. $notify_url = $this->request->root(true) . '/api/we_chat_pay/goodsOrderNotify';
  155. $pay_no = $order_info['pay_no'] ? $order_info['pay_no'] : get_order_sn();
  156. Db::table('store_order')->where(['uid'=>$this->user_id,'id'=>$order_id])->update(['pay_no'=>$pay_no]);
  157. $config = WeChatPay::wxPay('订单支付',$pay_no,$order_info['price_total'],$notify_url,'JSAPI',$user_info['openid']);
  158. if(!$config) throw new Exception('支付配置错误');
  159. $ret_data['config'] = $config;
  160. Db::commit();
  161. }catch (\Exception $e) {
  162. Db::rollback();
  163. $this->error($e->getMessage());
  164. }
  165. $this->success('ok',$ret_data);
  166. }
  167. /**
  168. * @title 获取订单列表
  169. * @desc 获取订单列表
  170. * @author qc
  171. * @method GET
  172. * @url /api/Order/getOrderList
  173. * @header name:Authorization require:1 desc:Token
  174. * @param name:page type:int default:1 desc:页数
  175. * @param name:page_num type:int default:20 desc:每页数
  176. * @param name:status type:int default:-1 desc:订单状态(-1全部,0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,8已退款,9取消)
  177. * @param name:pay_state type:int default:-1 desc:支付状态(-1全部,0未支付,1已支付)
  178. * @param name:cancel_state type:int default:-1 desc:取消状态(-1全部,0未取消,1已取消)
  179. * @param name:apply_refund type:int default:-1 desc:申请退款状态(-1全部,0未申请||已取消,1已申请)
  180. * @return name:id type:int default:-- desc:订单id
  181. * @return name:order_no type:string default:-- desc:订单号
  182. * @return name:price_total type:float default:-- desc:待支付金额
  183. * @return name:price_goods type:float default:-- desc:商品金额(用售价计算)
  184. * @return name:price_express type:float default:0 desc:运费金额
  185. * @return name:original_total type:float default:-- desc:总原价(下划线)
  186. * @return name:pay_state type:int default:-- desc:支付状态(0未支付1已支付)
  187. * @return name:pay_no type:string default:-- desc:支付号
  188. * @return name:pay_at type:string default:-- desc:支付时间
  189. * @return name:express_state type:int default:-- desc:发货状态(0未发货,1已发货,2已签收)
  190. * @return name:express_company_title type:string default:-- desc:发货快递公司名称
  191. * @return name:express_send_no type:string default:-- desc:物流单号
  192. * @return name:express_send_at type:string default:-- desc:发货时间
  193. * @return name:status type:int default:-- desc:订单状态(0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,8已退款,9取消)
  194. * @return name:create_at type:string default:-- desc:下单时间
  195. * @return name:remark type:string default:-- desc:订单备注
  196. * @return name:cancel_state type:int default:-- desc:取消状态(0未取消1已取消)
  197. * @return name:goods_num type:int default:-- desc:订单商品总数量
  198. * @return name:pro_name type:string default:-- desc:省名称(收货地址)
  199. * @return name:city_name type:string default:-- desc:市名称(收货地址)
  200. * @return name:county_name type:string default:-- desc:县区名称(收货地址)
  201. * @return name:street_name type:string default:-- desc:街道名称(收货地址)
  202. * @return name:add_detail type:string default:-- desc:详细地址(收货地址)
  203. * @return name:user_name type:string default:-- desc:收货人
  204. * @return name:phone type:string default:-- desc:收货人联系电话
  205. * @return name:order_item type:array default:-- desc:订单商品列表
  206. * @return name:order_item.name type:float default:-- desc:商品名
  207. * @return name:order_item.cover type:float default:-- desc:商品图
  208. * @return name:order_item.sell_price type:float default:-- desc:购买价格
  209. * @return name:order_item.goods_spec type:float default:-- desc:规格
  210. * @return name:order_item.num type:int default:-- desc:数量
  211. */
  212. public function getOrderList()
  213. {
  214. $status = input('get.status',-1);
  215. $pay_state = input('get.pay_state',-1);
  216. $cancel_state = input('get.cancel_state',-1);
  217. $refund_state = input('get.apply_refund',-1);
  218. $where = [];
  219. $where[] = ['user_id','=',$this->user_id];
  220. if($status > -1) $where[] = ['status','=',$status];
  221. if($pay_state > -1) $where[] = ['pay_state','=',$pay_state];
  222. if($cancel_state > -1) $where[] = ['cancel_state','=',$cancel_state];
  223. if($refund_state == 0) $where[] = ['refund_state','=',$refund_state];
  224. if($refund_state == 1) $where[] = ['refund_state','in','1,2,3,4'];
  225. $list = GoodsOrder::with(['orderItem'])->where($where)->order('id desc ')
  226. ->limit($this->off_set,$this->page_num)
  227. ->select()->toArray();
  228. $this->success('ok',['list'=>$list]);
  229. }
  230. /**
  231. * @title 获取订单详情
  232. * @desc 获取订单详情
  233. * @author qc
  234. * @method GET
  235. * @url /api/Order/getOrderDetail
  236. * @header name:Authorization require:1 desc:Token
  237. * @param name:order_id type:int default:-- desc:订单id
  238. * @return name:id type:int default:-- desc:订单id
  239. * @return name:order_no type:string default:-- desc:订单号
  240. * @return name:price_total type:float default:-- desc:待支付金额(
  241. * @return name:price_goods type:float default:-- desc:商品金额
  242. * @return name:price_express type:0 default:-- desc:运费金额
  243. * @return name:original_total type:float default:-- desc:总原价(下划线)
  244. * @return name:original_total type:float default:-- desc:总原价(下划线)
  245. * @return name:pay_state type:int default:-- desc:支付状态(0未支付1已支付)
  246. * @return name:pay_type type:int default:-- desc:支付方式(1微信)
  247. * @return name:pay_no type:string default:-- desc:支付号
  248. * @return name:pay_at type:string default:-- desc:支付时间
  249. * @return name:cancel_state type:int default:-- desc:取消状态(0未取消1已取消)
  250. * @return name:cancel_at type:string default:-- desc:取消时间
  251. * @return name:cancel_desc type:string default:-- desc:取消原因
  252. * @return name:express_state type:int default:-- desc:发货状态(0未发货,1已发货,2已签收)
  253. * @return name:express_company_title type:string default:-- desc:发货快递公司名称
  254. * @return name:express_send_no type:string default:-- desc:物流单号
  255. * @return name:express_send_at type:string default:-- desc:发货时间
  256. * @return name:status type:int default:-- desc:订单状态(0待支付,1已支付(待发货),2已发货(待收货),3已收货(待评论)4已完成,8已退款,9取消)
  257. * @return name:create_at type:string default:-- desc:下单时间
  258. * @return name:pay_at type:string default:-- desc:支付时间
  259. * @return name:remark type:string default:-- desc:订单备注
  260. * @return name:goods_num type:int default:-- desc:订单商品总数量
  261. * @return name:pro_name type:string default:-- desc:省名称(收货地址)
  262. * @return name:city_name type:string default:-- desc:市名称(收货地址)
  263. * @return name:county_name type:string default:-- desc:县区名称(收货地址)
  264. * @return name:street_name type:string default:-- desc:街道名称(收货地址)
  265. * @return name:add_detail type:string default:-- desc:详细地址(收货地址)
  266. * @return name:user_name type:string default:-- desc:收货人
  267. * @return name:phone type:string default:-- desc:收货人联系电话
  268. * @return name:order_item type:array default:-- desc:订单商品列表(按商品id分组)
  269. * @return name:order_item.name type:float default:-- desc:商品名
  270. * @return name:order_item.cover type:float default:-- desc:商品图
  271. * @return name:order_item.sell_price type:float default:-- desc:购买价格
  272. * @return name:order_item.goods_spec type:float default:-- desc:规格
  273. * @return name:order_item.num type:int default:-- desc:数量
  274. */
  275. public function getOrderDetail()
  276. {
  277. $order_id = input('get.order_id');
  278. $detail = GoodsOrder::where('id',$order_id)->find()->toArray();
  279. $detail['order_item'] = (new GoodsOrderItem())->getOrderItem($order_id);
  280. $this->success('ok',['detail'=>$detail]);
  281. }
  282. /**
  283. * @title 取消订单
  284. * @desc 取消订单
  285. * @author qc
  286. * @url /api/Order/cancelOrder
  287. * @method POST
  288. * @header name:Authorization require:1 desc:Token
  289. * @param name:order_id type:int require:1 default:0 desc:订单id
  290. */
  291. public function cancelOrder()
  292. {
  293. $order_id = input('post.order_id');
  294. Db::startTrans();
  295. try {
  296. $detail = GoodsOrder::with('orderItem')->where('id',$order_id)->find()->toArray();
  297. if($detail['status'] != 0) $this->exception('订单状态有误');
  298. // 取消订单状态
  299. GoodsOrder::update(['status'=>9],['id'=>$order_id]);
  300. // 订单处理
  301. foreach ($detail['order_item'] as $item_info) {
  302. // 更改订单详情状态
  303. GoodsOrderItem::update(['status'=>9],['id'=>$item_info['id']]);
  304. // 商品规格库存返回
  305. StoreGoodsItem::where('id',$item_info['spec_id'])->setInc('stock',$item_info['num']);
  306. // 商品总库存增加
  307. StoreGoods::where('id',$item_info['goods_id'])->setInc('stock',$item_info['num']);
  308. }
  309. Db::commit();
  310. }catch (\Exception $e){
  311. $this->ret_msg = $e->getMessage();
  312. $this->is_commit = false;
  313. Db::rollback();
  314. }
  315. $this->is_commit ? $this->success('取消成功') : $this->error($this->ret_msg);
  316. }
  317. /**
  318. * @title 确认收货
  319. * @desc 确认收货
  320. * @author qc
  321. * @url /api/Order/confirmReceipt
  322. * @method POST
  323. * @header name:Authorization require:1 desc:Token
  324. * @param name:order_id type:int require:1 default:0 desc:订单id
  325. */
  326. public function confirmReceipt()
  327. {
  328. $order_id = input('post.order_id');
  329. $detail = GoodsOrder::with('orderItem')->where('id',$order_id)->find()->toArray();
  330. if($detail['status'] == 0) $this->error('订单未支付');
  331. if($detail['status'] == 1) $this->error('订单未发货');
  332. if($detail['status'] == 3) $this->error('订单已收货');
  333. GoodsOrder::update(['status'=>3,'express_state'=>2],['id'=>$order_id]);
  334. GoodsOrderItem::update(['status'=>3,'express_state'=>2],['order_id'=>$order_id]);
  335. $this->success('已确认收货');
  336. }
  337. }