Order.php 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\model\BillApply;
  4. use app\common\model\OrderComment;
  5. use app\common\model\OrderLogisticsUrge;
  6. use app\common\model\ShoppingTrolley;
  7. use app\common\model\DeliveryAddress;
  8. use app\common\model\StoreGoods;
  9. use app\common\model\StoreGoodsItem;
  10. use app\common\model\GoodsOrder;
  11. use app\common\model\GoodsOrderItem;
  12. use app\common\model\User;
  13. use app\common\model\UserMessage;
  14. use app\common\service\ExpressService;
  15. use app\common\service\UserSynth;
  16. use think\Db;
  17. use think\Exception;
  18. /**
  19. * @title 订单
  20. * @controller Order
  21. * @group base
  22. */
  23. class Order extends Base
  24. {
  25. public $int_rate = 100;
  26. public function initialize()
  27. {
  28. parent::initialize();
  29. parent::checkLogin();
  30. }
  31. /**
  32. * @title 订单确认页面(立即购买)
  33. * @desc 订单确认页面
  34. * @author qc
  35. * @url /api/Order/confirmOrderImmediately
  36. * @method GET
  37. * @header name:Authorization require:1 desc:Token
  38. * @param name:goods_id type:int require:1 default:0 desc:商品id
  39. * @param name:spec_id type:int require:1 default:0 desc:商品多规格的规格id
  40. * @param name:num type:int default:1 desc:数量
  41. * @return name:name type:string default:-- desc:商品名称
  42. * @return name:cover type:string default:-- desc:商品封面图
  43. * @return name:desc type:string default:-- desc:商品简述(副标题)
  44. * @return name:freight_type type:int default:-- desc:运费类型0固定金额,1运费模板
  45. * @return name:freight_id type:int default:-- desc:模板id(freight_type=1)
  46. * @return name:postage type:float default:-- desc:运费(freight_type=0)
  47. * @return name:total_price type:float default:-- desc:商品金额[不含运费]
  48. * @return name:freight type:float default:-- desc:运费
  49. * @return name:freight_code type:int default:1 desc:运费提示编号【1所选地址支持发货,0所选地址不支持发货】
  50. * @return name:freight_msg type:string default:-- desc:运费提示信息【freight_code=1忽略】
  51. * @return name:goods_no type:string default:-- desc:规格货号
  52. * @return name:goods_spec type:string default:-- desc:规格
  53. * @return name:sell_price type:float default:-- desc:售价
  54. * @return name:add_info type:array default:-- desc:默认收货地址(设置才有)
  55. * @return name:add_info.pro_id type:int default:-- desc:省id
  56. * @return name:add_info.city_id type:int default:-- desc:市id
  57. * @return name:add_info.county_id type:int default:-- desc:县区id
  58. * @return name:add_info.pro_name type:string default:-- desc:省名
  59. * @return name:add_info.city_name type:string default:-- desc:市名
  60. * @return name:add_info.county_name type:string default:-- desc:县区名
  61. * @return name:add_info.detail type:string default:-- desc:详细地址
  62. * @return name:add_info.phone type:string default:-- desc:联系电话
  63. * @return name:add_info.name type:string default:-- desc:联系人
  64. * @return name:freight type:float default:-- desc:运费
  65. * @return name:freight_code type:int default:1 desc:运费提示编号【1所选地址支持发货,0所选地址不支持发货】
  66. * @return name:freight_msg type:string default:-- desc:运费提示信息【freight_code=1忽略】
  67. */
  68. public function confirmOrderImmediately(){
  69. $goods_id = input('get.goods_id');
  70. $spec_id = input('get.spec_id');
  71. $num = input('get.num',1);
  72. $field = 'id,name,cover,desc,low_price,status,is_deleted,freight_type,postage,freight_id';
  73. $goods_info = StoreGoods::field($field)->where('id',$goods_id)->find()->toArray();
  74. $spec_info = StoreGoodsItem::where('id',$spec_id)->find()->toArray();
  75. $goods_info['total_price']= bcmul($spec_info['sell_price'],$num,2);
  76. $goods_info['goods_spec']= $spec_info['goods_spec'];
  77. $goods_info['goods_no']= $spec_info['goods_no'];
  78. $goods_info['sell_price']= $spec_info['sell_price'];
  79. $add_info = DeliveryAddress::where(['user_id'=>$this->user_id,'is_mr'=>1])->find();
  80. $freight = 0;
  81. if($add_info){
  82. $goods_freight = ExpressService::getGoodsExpressPrice($goods_info,$add_info->id,$num);
  83. if($goods_freight['code'] !=200){
  84. $this->is_commit = false;
  85. $this->ret_msg = $goods_freight['msg'];
  86. }
  87. if($goods_freight['code'] == 200) $freight = $goods_freight['freight'];
  88. }
  89. $this->success('ok',['goods_info'=>$goods_info,
  90. 'add_info' =>$add_info ? $add_info->toArray():null,
  91. 'freight' =>$freight,
  92. 'freight_msg' => $this->ret_msg,
  93. 'freight_code' => $this->is_commit ? 1 :0
  94. ]);
  95. }
  96. /**
  97. * @title 生成订单(立即购买)
  98. * @desc 立即购买场景
  99. * @author qc
  100. * @url /api/Order/createOrderImmediately
  101. * @method POST
  102. * @header name:Authorization require:1 desc:Token
  103. * @param name:goods_id type:int require:1 default:0 desc:商品id
  104. * @param name:spec_id type:int require:1 default:0 desc:商品多规格的规格id
  105. * @param name:num type:int default:1 desc:数量
  106. * @param name:add_id type:int default:1 desc:收货地址id
  107. * @param name:remark type:string default:1 desc:订单备注
  108. *
  109. * @param name:bill_info type:string default:-- desc:发票信息--json【不开票可以不传】
  110. * @param name:bill_info.type type:int default:-- desc:类型id
  111. * @param name:bill_info.header type:string default:-- desc:抬头名称[公司名称||个人名称]
  112. * @param name:bill_info.identify_number type:string default:-- desc:纳税人识别号
  113. * @param name:bill_info.email type:string default:-- desc:邮箱
  114. * @param name:bill_info.remark type:string default:-- desc:备注
  115. *
  116. * @return name:order_id type:int default:1 desc:订单id
  117. */
  118. public function createOrderImmediately()
  119. {
  120. $goods_id = input('post.goods_id');
  121. $spec_id = input('post.spec_id');
  122. $num = input('post.num');
  123. $add_id = input('post.add_id');
  124. $remark = input('post.remark');
  125. $post_bill = input('post.bill_info');
  126. $bill_info = json_decode(stripslashes($post_bill),true);
  127. if(!$goods_id || !$spec_id) $this->error('请选择商品');
  128. if($num <=0 ) $this->error('数量有误');
  129. if(!$add_id ) $this->error('请选择收货地址');
  130. Db::startTrans();
  131. try {
  132. $add_info = DeliveryAddress::find($add_id)->toArray();
  133. $order_insert = [
  134. 'user_id' => $this->user_id,
  135. 'order_no' => get_order_sn(),
  136. 'goods_num' => $num,
  137. 'pro_name' => $add_info['pro_name'],
  138. 'city_name' => $add_info['city_name'],
  139. 'county_name' => $add_info['county_name'],
  140. 'user_name' => $add_info['name'],
  141. 'add_detail' => $add_info['detail'],
  142. 'phone' => $add_info['phone'],
  143. 'remark' => $remark,
  144. ];
  145. $goods_info = StoreGoods::with(['itemList'=>function($query)use($spec_id){
  146. return $query->where('id',$spec_id)->where('is_deleted',0);
  147. }])->where('id',$goods_id)->where('is_deleted',0)->where('status',1)->find();
  148. if(!$goods_info) throw new Exception('商品已下架');
  149. $goods_info = $goods_info->toArray();
  150. if(empty($goods_info['item_list'])) throw new Exception('该规格已下架');
  151. if($goods_info['item_list'][0]['stock'] < $num) throw new Exception('库存不足');
  152. $order_insert['original_price'] = bcmul($num,$goods_info['item_list'][0]['original_price'],2);// 原价
  153. $true_cost = $goods_info['item_list'][0]['sell_price'];//实际售价
  154. $spec_info = $goods_info['item_list'][0];
  155. $price_goods = bcmul($num,$true_cost,2); // 需要支付商品价格
  156. // 获取运费信息
  157. $exp_data = ExpressService::getGoodsExpressPrice($goods_info,$add_info,$num);
  158. if($exp_data['code'] != 200 ) throw new Exception($exp_data['msg']);
  159. $price_express = $exp_data['freight']; // 商品运费
  160. //订单金额 = 商品金额 + 运费
  161. $order_money = bcadd($price_goods,$price_express ,2);
  162. if($order_money < 0) $this->exception('订单金额有误');
  163. $order_insert['price_total'] = $order_money;
  164. $order_insert['price_goods'] = $price_goods;
  165. $order_insert['price_express'] = $price_express;
  166. $order_info = GoodsOrder::create($order_insert);
  167. $order_item = [
  168. 'user_id' => $this->user_id,
  169. 'order_id' => $order_info->id,
  170. 'goods_id' => $goods_id,
  171. 'goods_no' => $spec_info['goods_no'],
  172. 'goods_spec' => $spec_info['goods_spec'],
  173. 'goods_name' => $goods_info['name'],
  174. 'spec_title' => $spec_info['spec_title'],
  175. 'spec_id' => $spec_info['id'],
  176. 'cover' => $goods_info['cover'],
  177. 'original_price' => $spec_info['original_price'],
  178. 'sell_price' => $true_cost,
  179. 'pay_price' => $order_money,
  180. 'num' => $num,
  181. ];
  182. GoodsOrderItem::create($order_item);
  183. StoreGoods::where('id',$goods_id)->setDec('stock',$num);
  184. StoreGoodsItem::where('id',$spec_id)->setDec('stock',$num);
  185. // 申请开票
  186. if($order_money > 0 && !empty($bill_info)){
  187. $ret_val = UserSynth::buildBillApply($this->user_id, $order_info->id,2,$bill_info,0,1,$bill_info['remark'],0);
  188. if($ret_val['code'] != 200) $this->exception($ret_val['msg']);
  189. }
  190. Db::commit();
  191. }catch (\Exception $e){
  192. $this->is_commit = false;
  193. $this->ret_msg = $e->getMessage();
  194. Db::rollback();
  195. }
  196. $this->is_commit ? $this->success('添加成功',['order_id'=>$order_info->id]):$this->error($this->ret_msg);
  197. }
  198. /**
  199. * @title 生成订单(购物车)
  200. * @desc 购物车场景
  201. * @author qc
  202. * @url /api/Order/createOrderByTrolley
  203. * @method POST
  204. * @header name:Authorization require:1 desc:Token
  205. * @param name:ids type:int require:1 default:0 desc:购物车记录id
  206. * @param name:add_id type:int default:1 desc:收货地址id
  207. * @param name:remark type:string default:1 desc:订单备注
  208. *
  209. * @param name:bill_info type:string default:-- desc:发票信息--json【不开票可以不传】
  210. * @param name:bill_info.type type:int default:-- desc:类型id
  211. * @param name:bill_info.header type:string default:-- desc:抬头名称[公司名称||个人名称]
  212. * @param name:bill_info.identify_number type:string default:-- desc:纳税人识别号
  213. * @param name:bill_info.email type:string default:-- desc:邮箱
  214. * @param name:bill_info.remark type:string default:-- desc:备注
  215. *
  216. * @return name:order_id type:int default:1 desc:订单id
  217. */
  218. public function createOrderByTrolley()
  219. {
  220. $ids = input('post.ids');
  221. $add_id = input('post.add_id');
  222. $remark = input('post.remark');
  223. $post_bill = input('post.bill_info');
  224. $bill_info = json_decode(stripslashes($post_bill),true);
  225. if(!$ids) $this->error('请选择商品');
  226. if(!$add_id ) $this->error('请选择收货地址');
  227. $ret_data = ['order_id'=>0];
  228. Db::startTrans();
  229. try{
  230. $add_info = DeliveryAddress::where('id',$add_id)->find()->toArray();
  231. $trolley_list = ShoppingTrolley::with(['goodsSpec','goodsInfo'])->where('id','in',$ids)->select()->toArray();
  232. if(empty($trolley_list)) $this->exception('购物车记录有误');
  233. // 计算运费
  234. $price_express = 0;// 总运费
  235. $goods_list = ShoppingTrolley::where('id','in',$ids)->field('goods_id,sum(num) as total_num')->group('goods_id')->select()->toArray();
  236. foreach ($goods_list as $v){
  237. $goods_info = StoreGoods::field('name,freight_type,freight_id,postage')->where('id',$v['goods_id'])->find()->toArray();
  238. $freight_data = ExpressService::getGoodsExpressPrice($goods_info,$add_info,$v['total_num']);
  239. if($freight_data['code'] != 200){
  240. $this->exception($goods_info['name'].$freight_data['msg']);
  241. break;
  242. }
  243. $price_express += $freight_data['freight'];
  244. }
  245. // 计算运费 end
  246. $price_goods = 0; // 商品总金额
  247. $original_total = 0; // 商品总原价
  248. $total_num = 0;// 商品总数量
  249. $order_item = [];// 订单列表
  250. foreach ($trolley_list as $trolley)
  251. {
  252. //验证库存
  253. if( $trolley['goods_spec']['stock'] < $trolley['num']) $this->exception('商品库存不足');
  254. // 扣除库存
  255. StoreGoodsItem::stockChange($trolley['spec_id'],$trolley['goods_id'],$trolley['num'],-1);
  256. $price_goods += $trolley['num'] * $trolley['goods_spec']['sell_price'];
  257. $original_total += $trolley['num'] * $trolley['goods_spec']['original_price'];
  258. $total_num +=$trolley['num'];
  259. $order_item[] = [
  260. 'user_id' => $this->user_id,
  261. 'goods_id' => $trolley['goods_id'],
  262. 'goods_no' => $trolley['goods_spec']['goods_no'],
  263. 'goods_name' => $trolley['goods_info']['name'],
  264. 'goods_spec' => $trolley['goods_spec']['goods_spec'],
  265. 'spec_title' => $trolley['goods_spec']['spec_title'],
  266. 'spec_id' => $trolley['spec_id'],
  267. 'cover' => $trolley['goods_info']['cover'],
  268. 'original_price' => $trolley['goods_spec']['original_price'],
  269. 'sell_price' => $trolley['goods_spec']['sell_price'],
  270. 'num' => $trolley['num'],
  271. 'trolley_id' => $trolley['id'],
  272. ];
  273. }
  274. $order_insert = [
  275. 'user_id' => $this->user_id,
  276. 'order_no' => get_order_sn(),
  277. 'goods_num' => $total_num,
  278. 'pro_name' => $add_info['pro_name'],
  279. 'city_name' => $add_info['city_name'],
  280. 'county_name' => $add_info['county_name'],
  281. 'user_name' => $add_info['name'],
  282. 'add_detail' => $add_info['detail'],
  283. 'phone' => $add_info['phone'],
  284. 'remark' => $remark,
  285. ];
  286. $price_total = bcadd($price_goods ,$price_express,2);
  287. $order_insert['price_total'] = $price_total;
  288. $order_insert['price_goods'] = $price_goods ;
  289. $order_insert['original_total'] = $original_total ;
  290. $order_insert['price_express'] = $price_express ;
  291. $order_info = GoodsOrder::create($order_insert);// 生成订单
  292. array_walk($order_item,function (&$v,$k)use ($order_info){
  293. $v['order_id'] = $order_info->id;
  294. });
  295. (new GoodsOrderItem())->insertAll($order_item);// 生成订单商品详情
  296. ShoppingTrolley::where('id','in',$ids)->delete();// 删除购物车
  297. $ret_data['order_id'] = $order_info->id;
  298. // 申请开票
  299. if($price_total > 0 && !empty($bill_info)){
  300. $ret_val = UserSynth::buildBillApply($this->user_id, $order_info->id,2,$bill_info,0,1,$bill_info['remark'],0);
  301. if($ret_val['code'] != 200) $this->exception($ret_val['msg']);
  302. }
  303. Db::commit();
  304. }catch (\Exception $e){
  305. $this->ret_msg = $e->getMessage();
  306. $this->is_commit = false;
  307. Db::rollback();
  308. }
  309. $this->transReturn($ret_data);
  310. }
  311. /**
  312. * @title 订单支付
  313. * @desc 订单支付
  314. * @author qc
  315. * @url /api/Order/payOrder
  316. * @method POST
  317. * @header name:Authorization require:1 desc:Token
  318. * @param name:order_id type:int require:1 default:0 desc:订单id
  319. * @param name:pay_type type:int require:1 default:0 desc:支付方式(1.h5微信,2.h5支付宝,3移动支付(微信),4移动支付(支付宝),5.h5微信内支付)
  320. * @return name:config type:array default:0 desc:小程序支付配置
  321. * @return name:config.appId type:string default:-- desc:公众账号ID(小程序支付)
  322. * @return name:config.signType type:string default:-- desc:签名类型(小程序支付)
  323. * @return name:config.paySign type:string default:-- desc:签名(小程序支付)
  324. * @return name:config.nonceStr type:string default:-- desc:随机字符串(小程序支付&&APP支付)
  325. * @return name:config.timestamp type:string default:-- desc:时间戳小程序支付&&APP支付)
  326. * @return name:config.partnerid type:string default:-- desc:商户号(App支付)
  327. * @return name:config.prepayid type:string default:-- desc:唯一支付号(App支付)
  328. * @return name:config.package type:string default:-- desc:package(App支付)
  329. * @return name:config.sign type:string default:-- desc:签名(App支付)
  330. * @return name:code_url type:string default:-- desc:付款码url
  331. */
  332. public function payOrder()
  333. {
  334. $order_id = input('post.order_id');
  335. $pay_type = input('post.pay_type');
  336. $order_info = GoodsOrder::with('orderItem')->where('id',$order_id)->find()->toArray();
  337. if($order_info['status'] != 0) $this->error('订单状态错误');
  338. if($order_info['cancel_state'] != 0 || $order_info['is_deleted'] != 0) $this->error('订单异常');
  339. if($order_info['price_total'] <= 0) $this->error('订单金额错误');
  340. $pay_no = $order_info['pay_no'] ? $order_info['pay_no'] : get_order_sn();// 支付单号
  341. if(!$order_info['pay_no']) GoodsOrder::where('id',$order_id)->update(['pay_no'=>$pay_no]);
  342. $user_info = User::with('wallet')->where('id',$this->user_id)->find()->toArray();
  343. if(in_array($order_info['pay_type'],[1,3,5]) && in_array($pay_type,[1,3,5]) && $pay_type != $order_info['pay_type'] )$this->error('微信支付冲突,请选择支付宝支付');
  344. $ret_data = ['pay_status'=>0,'config'=>[],'code_url'=>''];
  345. Db::startTrans();
  346. GoodsOrder::where('id',$order_id)->update(['pay_type'=>$pay_type]);
  347. try {
  348. switch ($pay_type){
  349. case 1://微信
  350. $notify_url = $this->request->root(true) . '/api/we_chat_pay/goodsOrderNotify';
  351. $pay_config = WeChatPay::wxPay('订单支付',$pay_no,$order_info['price_total'],$notify_url,'MWEB');
  352. if($pay_config['code'] != 200) $this->exception($pay_config['msg']);
  353. $pay_config['config']['mch_id'] = config('app.wx_pay')['mch_id'];
  354. $pay_config['config']['pay_no'] = $pay_no;
  355. $pay_config['config']['notify_url'] = $notify_url;
  356. $pay_config['config']['mweb_url'] = $pay_config['mweb_url'];
  357. $pay_config['config']['total_fee'] = $order_info['price_total'] * 100;
  358. $ret_data['config'] = $pay_config['config'];
  359. break;
  360. case 2:
  361. $notify_url = $this->request->root(true) . '/api/Alipay/goodsOrderNotify';
  362. $return_url ='https://'.$_SERVER['HTTP_HOST']."/dist/#/my";
  363. $config = Alipay::ali_pay_h5('订单支付',$pay_no,$order_info['price_total'],$notify_url,$return_url);
  364. $ret_data['config']['ali_url'] = $config;
  365. $ret_data['ali_url'] = $config;
  366. break;
  367. case 3: //移动支付(微信)
  368. $notify_url = $this->request->root(true) . '/api/we_chat_pay/goodsOrderNotify';
  369. $pay_config = WeChatPay::wxPay('订单支付',$pay_no,$order_info['price_total'],$notify_url,'APP');
  370. if($pay_config['code'] != 200) $this->exception($pay_config['msg']);
  371. $ret_data['config'] = $pay_config['config'];
  372. break;
  373. case 4://移动支付(支付宝)
  374. $notify_url = $this->request->root(true) . '/api/Alipay/goodsOrderNotify';
  375. $config = Alipay::ali_pay('订单支付',$pay_no,$order_info['price_total'],$notify_url);
  376. $ret_data['config']['ali_url'] = $config;
  377. $ret_data['ali_url'] = $config;
  378. break;
  379. case 5 :
  380. if(!$user_info['openid']) $this->exception('请绑定openid');
  381. $notify_url = $this->request->root(true) . '/api/we_chat_pay/goodsOrderNotify';
  382. $pay_config = WeChatPay::wxPay('订单支付',$pay_no,$order_info['price_total'],$notify_url,'JSAPI',$user_info['openid']);
  383. if($pay_config['code'] != 200) $this->exception($pay_config['msg']);
  384. $ret_data['config'] = $pay_config['config'];
  385. break;
  386. }
  387. Db::commit();
  388. }catch (\Exception $e){
  389. $this->is_commit = false;
  390. $this->ret_msg = $e->getMessage();
  391. Db::rollback();
  392. }
  393. $this->transReturn($ret_data);
  394. }
  395. /**
  396. * @title 获取订单列表
  397. * @desc 获取订单列表
  398. * @author qc
  399. * @method GET
  400. * @url /api/Order/getOrderList
  401. * @header name:Authorization require:1 desc:Token
  402. * @param name:page type:int default:1 desc:页数
  403. * @param name:page_num type:int default:20 desc:每页数
  404. * @param name:status type:int default:-1 desc:订单状态(0待支付,1已支付(待发货),2已发货(待收货),3已收货(已完成),8已退款,9取消)
  405. * @param name:pay_state type:int default:-1 desc:支付状态(-1全部,0未支付,1已支付)
  406. * @param name:cancel_state type:int default:-1 desc:取消状态(-1全部,0未取消,1已取消)
  407. * @param name:apply_refund type:int default:-1 desc:申请退款状态(-1全部,0未申请||已取消,1已申请)
  408. * @return name:id type:int default:-- desc:订单id
  409. * @return name:id type:int default:-- desc:订单id
  410. * @return name:order_no type:string default:-- desc:订单号
  411. * @return name:price_total type:float default:-- desc:待支付金额(商品价格+运费)
  412. * @return name:price_goods type:float default:-- desc:商品金额
  413. * @return name:price_express type:float default:-- desc:运费金额
  414. * @return name:pay_state type:int default:-- desc:支付状态(0未支付1已支付)
  415. * @return name:pay_type type:int default:-- desc:支付方式(1.h5微信,2.h5支付宝,3移动支付(微信),4移动支付(支付宝),5.h5微信内支付)
  416. * @return name:pay_no type:string default:-- desc:支付号
  417. * @return name:pay_at type:string default:-- desc:支付时间
  418. * @return name:cancel_state type:int default:-- desc:取消状态(0未取消1已取消)
  419. * @return name:cancel_at type:string default:-- desc:取消时间
  420. * @return name:refund_state type:int default:-- desc:退款状态(0未申请1待审核,2审核拒绝,3审核通过)
  421. * @return name:express_state type:int default:-- desc:发货状态(0未发货,1已发货,2已签收)
  422. * @return name:express_company_title type:string default:-- desc:发货快递公司名称
  423. * @return name:express_send_no type:string default:-- desc:物流单号
  424. * @return name:express_send_at type:string default:-- desc:发货时间
  425. * @return name:status type:int default:-- desc:订单状态(0待支付,1已支付(待发货),2已发货(待收货),3已收货(已完成),8已退款,9取消)
  426. * @return name:create_at type:string default:-- desc:下单时间
  427. * @return name:remark type:string default:-- desc:订单备注
  428. * @return name:goods_num type:int default:-- desc:订单商品总数量
  429. * @return name:pro_name type:string default:-- desc:省名称(收货地址)
  430. * @return name:city_name type:string default:-- desc:市名称(收货地址)
  431. * @return name:county_name type:string default:-- desc:县区名称(收货地址)
  432. * @return name:add_detail type:string default:-- desc:详细地址(收货地址)
  433. * @return name:user_name type:string default:-- desc:收货人
  434. * @return name:phone type:string default:-- desc:收货人联系电话
  435. * @return name:order_item type:array default:-- desc:订单商品列表
  436. * @return name:order_item.name type:float default:-- desc:商品名
  437. * @return name:order_item.cover type:float default:-- desc:商品图
  438. * @return name:order_item.sell_price type:float default:-- desc:购买价格
  439. * @return name:order_item.goods_spec type:float default:-- desc:规格
  440. * @return name:order_item.num type:int default:-- desc:数量
  441. *
  442. * @return name:bill_info type:array default:-- desc:发票申请信息
  443. * @return name:bill_info.header type:string default:0 desc:抬头
  444. * @return name:bill_info.type type:int default:0 desc:发票类型
  445. * @return name:bill_info.email type:string default:0 desc:邮箱
  446. * @return name:bill_info.phone type:string default:0 desc:电话
  447. * @return name:bill_info.bank type:string default:0 desc:开户行
  448. * @return name:bill_info.card_no type:string default:0 desc:银行账号
  449. * @return name:bill_info.identify_number type:string default:0 desc:纳税人识别号
  450. * @return name:bill_info.bill_img type:string default:0 desc:点子发票url
  451. * @return name:bill_info.remark type:string default:0 desc:备注
  452. */
  453. public function getOrderList()
  454. {
  455. $status = input('get.status',-1);
  456. $pay_state = input('get.pay_state',-1);
  457. $cancel_state = input('get.cancel_state',-1);
  458. $refund_state = input('get.apply_refund',-1);
  459. $where = [];
  460. $where[] = ['user_id','=',$this->user_id];
  461. $where[] = ['is_deleted','=',0];
  462. if($status > -1) $where[] = ['status','=',$status];
  463. if($pay_state > -1) $where[] = ['pay_state','=',$pay_state];
  464. if($cancel_state > -1) $where[] = ['cancel_state','=',$cancel_state];
  465. if($refund_state == 0) $where[] = ['refund_state','=',$refund_state];
  466. if($refund_state == 1) $where[] = ['refund_state','in','1,2,3,4'];
  467. $field = 'id,order_no,price_total,price_goods,price_express,create_at,pay_at,pay_type,goods_num,remark,pro_name,city_name,county_name,add_detail,pay_state,user_name,phone,remark,cancel_state,cancel_at,refund_state,express_state,express_company_title,express_send_no,express_send_at';
  468. $list = GoodsOrder::with(['orderItem'])->field($field)->where($where)->order('id desc ')
  469. ->limit($this->off_set,$this->page_num)
  470. ->select()->toArray();
  471. foreach ($list as &$info) {
  472. $bill_info = BillApply::field('id,header,type,phone,email,bank,card_no,identify_number,bill_img,remark')->where(['order_type'=>2,'order_id'=>$info['id']])->find();
  473. $info['bill_info'] = !empty($bill_info) ? $bill_info->toArray() : null;
  474. foreach ($info['order_item'] as &$v) {
  475. $v['goods_spec'] = str_replace(['::',';;'],[':',';'],$v['goods_spec']);
  476. }
  477. }
  478. $total_num = GoodsOrder::where($where)->count();
  479. $this->success('ok',['list'=>$list,'total_count'=>$total_num,'page_num'=>$this->page_num]);
  480. }
  481. /**
  482. * @title 获取订单详情
  483. * @desc 获取订单详情
  484. * @author qc
  485. * @method GET
  486. * @url /api/Order/getOrderDetail
  487. * @header name:Authorization require:1 desc:Token
  488. * @param name:order_id type:int default:-- desc:订单id
  489. * @return name:id type:int default:-- desc:订单id
  490. * @return name:order_no type:string default:-- desc:订单号
  491. * @return name:price_total type:float default:-- desc:待支付金额(商品价格+运费)
  492. * @return name:price_goods type:float default:-- desc:商品金额
  493. * @return name:price_express type:float default:-- desc:运费金额
  494. * @return name:pay_state type:int default:-- desc:支付状态(0未支付1已支付)
  495. * @return name:pay_type type:int default:-- desc:支付方式(1.h5微信,2.h5支付宝,3移动支付(微信),4移动支付(支付宝),5.h5微信内支付)
  496. * @return name:pay_no type:string default:-- desc:支付号
  497. * @return name:pay_at type:string default:-- desc:支付时间
  498. * @return name:cancel_state type:int default:-- desc:取消状态(0未取消1已取消)
  499. * @return name:cancel_at type:string default:-- desc:取消时间
  500. * @return name:refund_state type:int default:-- desc:退款状态(0未申请1待审核,2审核拒绝,3审核通过)
  501. * @return name:express_state type:int default:-- desc:发货状态(0未发货,1已发货,2已签收)
  502. * @return name:express_company_title type:string default:-- desc:发货快递公司名称
  503. * @return name:express_send_no type:string default:-- desc:物流单号
  504. * @return name:express_send_at type:string default:-- desc:发货时间
  505. * @return name:status type:int default:-- desc:订单状态(0待支付,1已支付(待发货),2已发货(待收货),3已收货(已完成),8已退款,9取消)
  506. * @return name:create_at type:string default:-- desc:下单时间
  507. * @return name:remark type:string default:-- desc:订单备注
  508. * @return name:goods_num type:int default:-- desc:订单商品总数量
  509. * @return name:pro_name type:string default:-- desc:省名称(收货地址)
  510. * @return name:city_name type:string default:-- desc:市名称(收货地址)
  511. * @return name:county_name type:string default:-- desc:县区名称(收货地址)
  512. * @return name:add_detail type:string default:-- desc:详细地址(收货地址)
  513. * @return name:user_name type:string default:-- desc:收货人
  514. * @return name:phone type:string default:-- desc:收货人联系电话
  515. * @return name:order_item type:array default:-- desc:订单商品列表(按商品id分组)
  516. * @return name:order_item.name type:float default:-- desc:商品名
  517. * @return name:order_item.cover type:float default:-- desc:商品图
  518. * @return name:order_item.sell_price type:float default:-- desc:购买价格
  519. * @return name:order_item.goods_spec type:float default:-- desc:规格
  520. * @return name:order_item.num type:int default:-- desc:数量
  521. *
  522. * @return name:bill_info type:array default:-- desc:发票申请信息
  523. * @return name:bill_info.header type:string default:0 desc:抬头
  524. * @return name:bill_info.type type:int default:0 desc:发票类型
  525. * @return name:bill_info.email type:string default:0 desc:邮箱
  526. * @return name:bill_info.phone type:string default:0 desc:电话
  527. * @return name:bill_info.bank type:string default:0 desc:开户行
  528. * @return name:bill_info.card_no type:string default:0 desc:银行账号
  529. * @return name:bill_info.identify_number type:string default:0 desc:纳税人识别号
  530. * @return name:bill_info.bill_img type:string default:0 desc:点子发票url
  531. * @return name:bill_info.remark type:string default:0 desc:备注
  532. */
  533. public function getOrderDetail()
  534. {
  535. $order_id = input('get.order_id');
  536. $field = 'id,order_no,price_total,price_goods,price_express,create_at,pay_at,pay_type,goods_num,remark,pro_name,city_name,county_name,add_detail,pay_state,user_name,phone,remark,cancel_state,cancel_at,refund_state,express_state,express_company_title,express_send_no,express_send_at';
  537. $detail = GoodsOrder::where('id',$order_id)->field($field)->find()->toArray();
  538. $detail['order_item'] = (new GoodsOrderItem())->getOrderItem($order_id);
  539. foreach ($detail['order_item'] as &$v) {
  540. $v['goods_spec'] = str_replace(['::',';;'],[':',';'],$v['goods_spec']);
  541. }
  542. $bill_info = BillApply::field('id,header,type,phone,email,bank,card_no,identify_number,bill_img,remark')->where(['order_type'=>2,'order_id'=>$detail['id']])->find();
  543. $detail['bill_info'] = !empty($bill_info) ? $bill_info->toArray() : null;
  544. $this->success('ok',['detail'=>$detail]);
  545. }
  546. /**
  547. * @title 计算商品运费(一个商品)
  548. * @desc 计算商品运费(一个商品)
  549. * @author qc
  550. * @url /api/Order/getGoodsFreight
  551. * @method GET
  552. * @header name:Authorization require:1 desc:Token
  553. * @param name:goods_id type:int require:1 default:0 desc:商品id
  554. * @param name:num type:int require:1 default:0 desc:商品数量
  555. * @param name:add_id type:int require:1 default:0 desc:收货地址id
  556. * @return name:freight type:float require:0 default:0 desc运费金额
  557. */
  558. public function getGoodsFreight()
  559. {
  560. $goods_id = input('get.goods_id');
  561. $num = input('get.num');
  562. $add_id = input('get.add_id');
  563. $goods_info = StoreGoods::where('id',$goods_id)->find()->toArray();
  564. $add_info = DeliveryAddress::where('id',$add_id)->find()->toArray();
  565. $freight_data = ExpressService::getGoodsExpressPrice($goods_info,$add_info,$num);
  566. if($freight_data['code'] != 200 ) $this->error($freight_data['msg']);
  567. $this->success('ok',['freight'=>$freight_data['freight']]);
  568. }
  569. /**
  570. * @title 计算购物车商品运费
  571. * @desc 计算购物车商品运费
  572. * @author qc
  573. * @url /api/Order/getTrolleyFreight
  574. * @method GET
  575. * @header name:Authorization require:1 desc:Token
  576. * @param name:ids type:int require:1 default:0 desc:购物车商品id串
  577. * @param name:add_id type:int require:1 default:0 desc:收货地址id
  578. * @return name:freight type:float require:0 default:0 desc运费金额
  579. */
  580. public function getTrolleyFreight()
  581. {
  582. $trolley_ids = input('get.ids');
  583. $add_id = input('get.add_id');
  584. $goods_list = ShoppingTrolley::where('id','in',$trolley_ids)
  585. ->field('goods_id,sum(num) as total_num')
  586. ->group('goods_id')
  587. ->select()->toArray();
  588. $total_price = 0;
  589. $add_info = DeliveryAddress::where('id',$add_id)->find()->toArray();
  590. foreach ($goods_list as $v){
  591. $goods_info = StoreGoods::field('name,freight_type,freight_id,postage')->where('id',$v['goods_id'])->find()->toArray();
  592. $freight_data = ExpressService::getGoodsExpressPrice($goods_info,$add_info,$v['total_num']);
  593. if($freight_data['code'] != 200){
  594. $this->error($goods_info['name'].$freight_data['msg']);
  595. break;
  596. }
  597. $total_price += $freight_data['freight'];
  598. }
  599. $this->success('ok',['freight'=>$total_price]);
  600. }
  601. /**
  602. * @title 取消订单
  603. * @desc 取消订单
  604. * @author qc
  605. * @url /api/Order/cancelOrder
  606. * @method POST
  607. * @header name:Authorization require:1 desc:Token
  608. * @param name:order_id type:int require:1 default:0 desc:订单id
  609. */
  610. public function cancelOrder()
  611. {
  612. $order_id = input('post.order_id');
  613. Db::startTrans();
  614. try {
  615. $detail = GoodsOrder::with('orderItem')->where('id',$order_id)->find()->toArray();
  616. if($detail['status'] != 0) $this->exception('订单状态有误');
  617. // 取消订单状态
  618. GoodsOrder::update(['status'=>9],['id'=>$order_id]);
  619. // 订单处理
  620. foreach ($detail['order_item'] as $item_info) {
  621. // 更改订单详情状态
  622. GoodsOrderItem::update(['status'=>9],['id'=>$item_info['id']]);
  623. StoreGoodsItem::stockChange($item_info['spec_id'],$item_info['goods_id'],$item_info['num']);
  624. }
  625. Db::commit();
  626. }catch (\Exception $e){
  627. $this->ret_msg = $e->getMessage();
  628. $this->is_commit = false;
  629. Db::rollback();
  630. }
  631. $this->is_commit ? $this->success('取消成功') : $this->error($this->ret_msg);
  632. }
  633. /**
  634. * @title 删除订单
  635. * @desc 删除订单
  636. * @author qc
  637. * @url /api/Order/deleteOrder
  638. * @method POST
  639. * @header name:Authorization require:1 desc:Token
  640. * @param name:order_id type:int require:1 default:0 desc:订单id
  641. */
  642. public function deleteOrder()
  643. {
  644. $order_id = input('post.order_id');
  645. $detail = GoodsOrder::with('orderItem')->where('id',$order_id)->find()->toArray();
  646. if($detail['status'] == 0) $this->error('请先取消订单');
  647. GoodsOrder::update(['is_deleted'=>1],['id'=>$order_id]);
  648. $this->success('删除成功');
  649. }
  650. /**
  651. * @title 更换订单收货地址
  652. * @desc 更换订单收货地址(仅待支付订单可以修改地址)
  653. * @author qc
  654. * @url /api/Order/changeOrderDelivery
  655. * @method POST
  656. * @header name:Authorization require:1 desc:Token
  657. * @param name:order_id type:int require:1 default:0 desc:订单id
  658. * @param name:add_id type:int require:1 default:0 desc:收货地址id
  659. */
  660. public function changeOrderDelivery()
  661. {
  662. $order_id = input('post.order_id');
  663. $add_id = input('post.add_id');
  664. $detail = GoodsOrder::where('id',$order_id)->find()->toArray();
  665. if($detail['status'] != 0) $this->error('操作错误');
  666. $add_info = DeliveryAddress::where('id',$add_id)->find()->toArray();
  667. $order_update =[
  668. 'pro_name' => $add_info['pro_name'],
  669. 'city_name' => $add_info['city_name'],
  670. 'county_name' => $add_info['county_name'],
  671. 'add_detail' => $add_info['detail'],
  672. 'user_name' => $add_info['name'],
  673. 'phone' => $add_info['phone'],
  674. ];
  675. GoodsOrder::update($order_update,['id'=>$order_id]);
  676. $this->success('修改成功');
  677. }
  678. /**
  679. * @title 确认收货
  680. * @desc 确认收货
  681. * @author qc
  682. * @url /api/Order/confirmReceipt
  683. * @method POST
  684. * @header name:Authorization require:1 desc:Token
  685. * @param name:order_id type:int require:1 default:0 desc:订单id
  686. */
  687. public function confirmReceipt()
  688. {
  689. $order_id = input('post.order_id');
  690. $detail = GoodsOrder::with('orderItem')->where('id',$order_id)->find()->toArray();
  691. if($detail['status'] == 0) $this->error('订单未支付');
  692. if($detail['status'] == 1) $this->error('订单未发货');
  693. if($detail['status'] == 3) $this->error('订单已收货');
  694. GoodsOrder::update(['status'=>3,'express_state'=>2],['id'=>$order_id]);
  695. GoodsOrderItem::update(['status'=>3,'express_state'=>2],['order_id'=>$order_id]);
  696. UserMessage::create(['user_id'=>$this->user_id,'type_id'=>3,'relation_id'=>$order_id,'content'=>'订单收货成功']);
  697. $this->success('已确认收货');
  698. }
  699. /**
  700. * @title 获取物流详情
  701. * @desc 获取物流详情
  702. * @author qc
  703. * @url /api/Order/deliveryDetails
  704. * @method GET
  705. * @header name:Authorization require:1 desc:Token
  706. * @param name:order_id type:string require:1 default:-- desc:订单id
  707. * @return name:number type:string default:-- desc:单号
  708. * @return name:type type:string default:-- desc:快递类型
  709. * @return name:list type:array default:-- desc:数据列表
  710. * @return name:list.time type:string default:-- desc:时间
  711. * @return name:list.status type:string default:-- desc:内容
  712. * @return name:deliverystatus type:int default:-- desc:0:快递收件(揽件)1.在途中2.正在派件3.已签收4.派送失败5.疑难件6.退件签收
  713. * @return name:issign type:int default:-- desc:是否签收(1.是否签收)
  714. * @return name:expName type:string default:-- desc:快递公司名称
  715. * @return name:expSite type:string default:-- desc:快递公司官网
  716. * @return name:expPhone type:string default:-- desc:快递公司电话
  717. * @return name:courier type:string default:-- desc:快递员 或 快递站(没有则为空)
  718. * @return name:courierPhone type:string default:-- desc:快递员电话 (没有则为空)
  719. * @return name:updateTime type:string default:-- desc:快递轨迹信息最新时间
  720. * @return name:takeTime type:string default:-- desc:发货到收货消耗时长 (截止最新轨迹)
  721. * @return name:logo type:string default:-- desc:快递公司LOGO
  722. */
  723. public function deliveryDetails(){
  724. $send_no = GoodsOrder::where('id',input('get.order_id'))->value('express_send_no');
  725. if(!$send_no) $this->error('订单没有发货');
  726. $data = get_delivery($send_no);
  727. $this->success('ok',$data);
  728. }
  729. /**
  730. * @title 发货提醒
  731. * @desc 发货提醒
  732. * @author qc
  733. * @url /api/Order/orderUrge
  734. * @method POST
  735. * @header name:Authorization require:1 desc:Token
  736. * @param name:order_id type:string require:1 default:-- desc:订单id
  737. */
  738. public function orderUrge()
  739. {
  740. $order_id = input('post.order_id');
  741. $order_info = GoodsOrder::where('id',$order_id)->find();
  742. if(!$order_info ) $this->error('订单错误');
  743. if(!$order_info->pay_state != 1 ) $this->error('订单未支付');
  744. if(!$order_info->express_send_no != '' ) $this->error('订单已发货');
  745. $urge_ret = ExpressService::orderUrge($order_id,$this->user_id);
  746. $urge_ret['code'] == 200 ? $this->success($urge_ret['msg']) : $this->error($urge_ret['msg']);
  747. }
  748. /**
  749. * @title 获取订单催发记录
  750. * @desc 获取订单催发记录
  751. * @author qc
  752. * @url /api/Order/getUrgeList
  753. * @method GET
  754. * @header name:Authorization require:1 desc:Token
  755. * @param name:order_id type:string require:1 default:-- desc:订单id
  756. */
  757. public function getUrgeList()
  758. {
  759. $order_id = input('get.order_id');
  760. $list = OrderLogisticsUrge::where(['order_id'=>$order_id,'table_name'=>'dd_store_order'])->order('id desc')->select()->toArray();
  761. $this->success('ok',['list'=>$list]);
  762. }
  763. /**
  764. *
  765. * @title 申请开票
  766. * @desc 申请开票
  767. * @author qc
  768. * @method POST
  769. * @url /api/Order/applyBill
  770. * @header name:Authorization require:1 desc:Token
  771. * @param name:order_id type:string default:1 desc:订单id
  772. * @param name:type type:int default:-- desc:类型id
  773. * @param name:header type:string default:-- desc:抬头名称[公司名称||个人名称]
  774. * @param name:identify_number type:string default:-- desc:纳税人识别号
  775. * @param name:email type:string default:-- desc:邮箱
  776. * @param name:remark type:string default:-- desc:备注
  777. */
  778. public function applyBill()
  779. {
  780. $order_id = input('post.order_id');
  781. $post = input('post.');
  782. $order_info = GoodsOrder::where('id',$order_id)->find()->toArray();
  783. if(!$order_info['pay_state'])$this->error('订单未支付');
  784. if(BillApply::checkBillApply($order_id,2)) $this->error('已申请开票');
  785. $ret_val = UserSynth::buildBillApply($this->user_id, $order_id, 2,$post,0,1,$post['remark']);
  786. if($ret_val['code'] != 200) $this->error($ret_val['msg']);
  787. $this->success('申请成功');
  788. }
  789. /**
  790. *
  791. * @title 订单商品添加购物车
  792. * @desc 订单商品添加购物车
  793. * @author qc
  794. * @method POST
  795. * @url /api/Order/addTrolleyFromOrder
  796. * @header name:Authorization require:1 desc:Token
  797. * @param name:order_id type:string default:1 desc:订单id
  798. */
  799. public function addTrolleyFromOrder(){
  800. $order_id = input('post.order_id');
  801. Db::startTrans();
  802. try {
  803. $detail = GoodsOrder::with('orderItem')->where('id',$order_id)->find()->toArray();
  804. foreach ($detail['order_item'] as $item_info) {
  805. $goods_info = StoreGoods::getGoodsSpec($item_info['goods_id'],$item_info['spec_id']);
  806. if(!$goods_info) $this->exception('商品已下架');
  807. if(empty($goods_info['item_list'])) $this->exception('商品规格已下架');
  808. if($goods_info['item_list'][0]['stock'] < $item_info['num'])$this->exception('库存不足');
  809. //某商品某规格是否已经添加购物车
  810. $trolley_id = ShoppingTrolley::checkTrolley($this->user_id,$item_info['goods_id'],$item_info['spec_id']);
  811. // 添加到购物车
  812. if($trolley_id) {
  813. ShoppingTrolley::where('id',$trolley_id)->setInc('num',$item_info['num']);
  814. }else{
  815. $trolley_info = [
  816. 'user_id' => $this->user_id,
  817. 'goods_id' => $item_info['goods_id'],
  818. 'spec_id' => $item_info['spec_id'],
  819. 'goods_no' => $goods_info['item_list'][0]['goods_no'],
  820. 'num' => $item_info['num'],
  821. ];
  822. ShoppingTrolley::create($trolley_info);
  823. }
  824. }
  825. Db::commit();
  826. }catch (\Exception $e){
  827. $this->ret_msg = $e->getMessage();
  828. $this->is_commit = false;
  829. Db::rollback();
  830. }
  831. $this->is_commit ? $this->success('添加成功') : $this->error($this->ret_msg);
  832. }
  833. }