Order.php 17 KB

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