123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 |
- <?php
- namespace app\api\controller\mall;
- use app\common\controller\Api;
- use app\common\model\OrderInfo;
- use app\common\model\OrderVoucher;
- use app\common\model\Refund;
- use app\common\service\OrderService;
- use app\common\service\RefundService;
- use app\common\validate\TaxValidate;
- use Carbon\Carbon;
- use think\Cache;
- use think\Db;
- use app\common\model\Orders as Order;
- use Yansongda\Supports\Arr;
- /**
- * 商城订单接口
- * @inheritdoc
- */
- class Orders extends Api
- {
- use TaxValidate;
- protected $noNeedRight="*";
- public $taxApi=false;
- /**
- * 预下单
- * @ApiMethod (POST)
- * @ApiParams (name=frm,description="来源1直接下单2购物车")
- * @ApiParams (name=form,description="key为规格id,对象:num购买数量,num_install安装数量")
- * @ApiParams (name=coupon_use,description=是否使用优惠券)
- * @ApiParams (name=coupon_id,description=优惠券id)
- * @ApiReturnParams (name=amount_total,description=总价,包含没有优惠的所有的价格)
- * @ApiReturnParams (name=amount_pay,description=实际需要支付的价格)
- * @ApiReturnParams (name=amount_coupon,description=优惠券优惠的金额)
- * @ApiReturnParams (name=amount_coupon_kill,description=秒杀活动优惠的金额)
- * @ApiReturnParams (name=amount_install,description=安装费的金额)
- * @ApiReturnParams (name=amount_discount,description=总优惠金额)
- * @ApiReturnParams (name=num,description=总数量)
- * @ApiReturnParams (name=num_install,description=总安装数量)
- * @ApiReturnParams (name=goods,0.description=商品列表数组)
- * @ApiReturnParams (name=goods.0.num,description=购买数量)
- * @ApiReturnParams (name=goods.0.num_install,description=安装数量)
- * @ApiReturnParams (name=goods.0.sku,description=sku对象)
- * @ApiReturnParams (name=goods.0.goods,description=商品对象)
- * @ApiReturnParams (name=goods.0.amount_total,description=总价,包含没有优惠的所有的价格)
- * @ApiReturnParams (name=goods.0.amount_pay,description=实际需要支付的价格)
- * @ApiReturnParams (name=goods.0.amount_goods,description=商品总价)
- * @ApiReturnParams (name=goods.0.amount_goods_real,description=商品扣除优惠的实际总价)
- * @ApiReturnParams (name=goods.0.amount_coupon,description=优惠券优惠的金额)
- * @ApiReturnParams (name=goods.0.amount_coupon_kill,description=秒杀活动优惠的金额)
- * @ApiReturnParams (name=goods.0.amount_install,description=安装费的金额)
- */
- public function preview(){
- $data=$this->_validate([
- 'coupon_id|优惠券'=>['integer','requireIf:coupon_use,1'],
- 'form|商品'=>['require','array','min:1'],
- 'frm|来源'=>['require','in:1,2'],
- ]);
- $user=$this->auth->getUser();
- $goods=$data['form'];
- $service=new OrderService();
- $service->setUser($user);
- $service->setGoods($goods);
- $service->setFrm($data['frm']);
- $service->setCouponUse($data['coupon_use']??false);
- $service->setCouponId($data['coupon_id']??0);
- $info=$service->calculate();
- $this->success('',$info);
- }
- /**
- * 提交订单
- * @ApiMethod (POST)
- * @ApiParams (name=frm,description="来源1直接下单2购物车")
- * @ApiParams (name=form,description="key为规格id,对象:num购买数量,num_install安装数量,{1:{num:1,num_install:2}}")
- * @ApiParams (name=coupon_use,description=是否使用优惠券)
- * @ApiParams (name=coupon_id,description=优惠券id)
- * @ApiParams (name=remark,description=留言)
- * @ApiParams (name=address_id,description=收货地址id)
- * @ApiParams (name=is_tax,description=是1否0需要开票)
- * @ApiParams (name=customer_send_time,description="预定发货时间,datetime")
- * @ApiParams (name=tax,description=发票信息)
- * @ApiParams (name=tax.paper_type,description=1电子2纸质)
- * @ApiParams (name=tax.self_type,description=1专票2普票)
- * @ApiParams (name=tax.u_type,description=1个人2企业)
- * @ApiParams (name=tax.name,description="姓名u_type=1时候必须")
- * @ApiParams (name=tax.com_name,description="单位名称,self_type=1或2,u_type=2时候必须")
- * @ApiParams (name=tax.bank_name,description="开户行,self_type=1,u_type=2时候必须")
- * @ApiParams (name=tax.bank_no,description="开户行账号,self_type=1,u_type=2时候必须")
- * @ApiParams (name=tax.tax_no,description="税号,self_type=1或2,u_type=2时候必须")
- * @ApiParams (name=tax.reg_addr,description="注册地址,self_type=1,u_type=2时候必须")
- * @ApiParams (name=tax.reg_phone,description="注册电话,self_type=1,u_type=2时候必须")
- */
- public function create(){
- $data=$this->_validate([
- 'coupon_id|优惠券'=>['integer','requireIf:coupon_use,1'],
- 'form|商品'=>['require','array','min:1'],
- 'frm|来源'=>['require','in:1,2'],
- 'remark|备注'=>['max:50'],
- 'address_id|收货地址'=>['require','integer','gt:0'],
- 'customer_send_time|发货时间'=>['date'],
- ]);
- $this->validateTax();
- if(!empty($data['customer_send_time']) && strtotime($data['customer_send_time'])<Carbon::now()->startOfDay()->addDays(config('site.send_delay_day'))->timestamp){
- $this->error('发货时间过早');
- }
- $user=$this->auth->getUser();
- $address=$user->address()->find($data['address_id']);
- abortIf(!$address,'地址不存在');
- $goods=$data['form'];
- $service=new OrderService();
- $service->setUser($user);
- $service->setGoods($goods);
- $service->setFrm(1);
- $service->setSubmit(true);
- $service->setClearCart(true);
- $service->setCouponUse($data['coupon_use']??false);
- $service->setCouponId($data['coupon_id']??0);
- Db::startTrans();
- $info=$service->calculate();
- if($info['amount_pay']==0){
- $this->error('支付金额有误');
- }
- $order=new Order();
- $order['user_id']=$user['id'];
- $order['order_no']=order_no();
- $order['amount_total']=$info['amount_total'];
- $order['amount_pay']=$info['amount_pay'];
- $order['amount_install']=$info['amount_install'];
- $order['amount_coupon']=$info['amount_coupon'];
- $order['amount_coupon_kill']=$info['amount_coupon_kill'];
- $order['amount_coupon_level']=$info['amount_coupon_level'];
- $order['amount_discount']=$info['amount_discount'];
- $order['amount_cmn']=$info['amount_cmn'];
- $order['num']=$info['num'];
- $order['num_install']=$info['num_install'];
- $order['tax']=$data['tax']??null;
- $order->save();
- $amount_profit=0;
- foreach ($info['goods'] as $everyGoods){
- $orderInfo=OrderInfo::saveInfo($order,$everyGoods);
- $amount_profit=bcadd($amount_profit,$orderInfo['amount_profit']);
- }
- $order['amount_profit']=$amount_profit;
- $order['amount_profit_per']=bcmul(100,bcdiv($order['amount_profit'],$order['amount_pay']));
- $order->save();
- $order->address()->save($address->orderAddress());
- Db::commit();
- $this->success('',$this->orderDetail($order['id']));
- }
- /**
- * 订单详情
- * @ApiParams (name=id,description="订单ID")
- */
- public function show(){
- $data=$this->_validate([
- 'id'=>['require'],
- ]);
- $user=$this->auth->getUser();
- $order=$this->orderDetail($data['id']);
- $goodsBak=$order->info[0]->goodsBak;
- if(!($goodsBak['goods']['is_fix']??0)) {
- Cache::remember("user_order_show_{$user['id']}", time(), 86400);
- }
- $this->success('',$order);
- }
- protected function orderDetail($orderId){
- $order= Order::with(['info','info.refund','address','logistics','logistics.com','voucher'])->findOrFail($orderId);
- foreach ($order['info'] as $info){
- $info->append(['goods','sku']);
- Refund::makeRefundConfig($info);
- }
- return $order;
- }
- /**
- * 取消订单
- * @ApiParams (name=id,description="订单ID")
- */
- public function cancel(){
- $data=$this->_validate([
- 'id'=>['require'],
- ]);
- $user=$this->auth->getUser();
- $order=$user->orders()->findOrFail($data['id']);
- $order->allowCancel() && $order->makeCancel();
- $this->success();
- }
- /**
- * 用户订单列表
- * @ApiParams (name=page,description=分页)
- * @ApiParams (name=limit,description=分页)
- * @ApiParams (name=status,description=状态)
- * @ApiReturnParams (name=is_evaled,description=是否已评价)
- */
- public function users(){
- $user=$this->auth->getUser();
- $map=[];
- $status=input('status');
- if(is_numeric($status)){
- $map['status']=$status;
- }
- if($this->taxApi){
- $map['tax']=['neq','[]'];
- }
- $orders=$user->orders()
- ->where($map)
- ->with(['info','voucher','logistics','logistics.com'])
- ->order('id','desc')
- ->paginate(input('limit',15));
- foreach ($orders as $order){
- //$order['info']=$order->info()->with(['goodsBak'])->find();
- $order->append(['is_evaled']);
- }
- $this->success('',$orders);
- }
- /**
- * 支付订单
- * @ApiParams (name=id,description=订单ID)
- * @ApiParams (name=pay_type,description=支付方式1企业网银2微信3支付宝4银联5代付6线下支付)
- * @ApiReturnParams (name=qr,description=微信支付宝返回的二维码)
- * @ApiReturnParams (name=account_name,description=线下支付会返【账户名称】)
- * @ApiReturnParams (name=bank_no,description=线下支付会返【银行卡号】)
- * @ApiReturnParams (name=bank_name,description=线下支付会返【银行名称】)
- */
- public function pay(){
- $data=$this->_validate([
- 'id'=>['require'],
- 'pay_type|支付方式'=>['require','in:'.implode(',',array_keys(Order::getPayTypes()))]
- ]);
- $user=$this->auth->getUser();
- $order=Order::findOrFail($data['id']);
- if(!$order->is_wait_pay){
- $this->error('非待支付状态无法支付');
- }
- $data=$order->makePayInfo($data['pay_type']);
- $this->success('',$data);
- }
- /**
- * 申请售后或修改售后信息
- * @ApiParams (name=refund_type,description=1退款2退款退货3仅退货4取消订单5换货保修)
- * @ApiParams (name=num,description=退货数量)
- * @ApiParams (name=num_install,description=退安装数量)
- * @ApiParams (name=order_info_id,description=订单ID)
- * @ApiParams (name=refund_by,description=配置里的type里的key)
- * @ApiParams (name=reason1,description=配置里的reason里的key)
- * @ApiParams (name=reason2,description=原因2)
- * @ApiParams (name=amount,description=金额)
- * @ApiParams (name=fix_order_no,description=维修订单号,在拍维修费时需要)
- */
- public function refund(){
- $data=$this->_validate([
- 'order_info_id|订单'=>['require','integer','gt:0'],
- ]);
- $user=$this->auth->getUser();
- Db::startTrans();
- $orderInfo=$user->orderInfo()->lock(true)->findOrFail($data['order_info_id']);
- $order= Order::lock(true)->where('id',$orderInfo['order_id'])->find();
- if(!$order){
- Db::rollback();
- $this->error('订单不存在');
- }
- $order->allowRefund();
- $refund=$orderInfo->refund;
- if($refund && $refund['refund_status']==$refund::REFUND_ING){
- Db::rollback();
- $this->error('您已提交,不能再次提交');
- }
- $config=Refund::makeRefundConfig($orderInfo,false,false);
- if(empty($config)){
- Db::rollback();
- $this->error('该订单无法满足售后条件');
- }
- $this->_validate([
- 'refund_type|售后方式'=>['require','in:'.implode(',',array_filter(array_keys($config['refund_type'])))],
- //'num|数量'=>['require','integer','gt:0',"elt:{$orderInfo['num']}"],
- 'refund_by|退货方式'=>['require','integer','egt:0','in:'.implode(',',array_keys($config['type']))],
- 'reason1|退款退货原因'=>['require','integer','egt:0','in:'.implode(',',array_keys($config['reason']))],
- 'reason2|原因'=>['require','max:100'],
- ]);
- if($config['req_amount']){
- /*$this->_validate([
- 'amount|金额'=>['require','float','gt:0',"elt:{$orderInfo['amount_pay']}"],
- ]);*/
- $data['amount']=RefundService::setOrderInfo($orderInfo,$orderInfo['num'],$orderInfo['num_install'])->amount(true);
- $data['num']=$config['num'];
- $data['num_install']=$config['num_install'];
- }else{
- $data['amount']=0;
- $this->_validate([
- 'num_install|安装数量'=>['require','integer','gt:0',"elt:{$orderInfo['num_install']}"],
- ]);
- }
- $fix_order_id=0;
- if($config['req_order']){
- $this->_validate([
- 'fix_order_no|维修订单号'=>['require',],
- ]);
- $showTime=Cache::get("user_order_show_{$user['id']}",null);
- if(!$showTime){
- $this->error('请先支付维修单',$showTime);
- }
- $fixOrder=$user->orders()->statusPay()
- ->where('order_no',$data['fix_order_no'])
- ->where('pay_time','>',$showTime)
- ->find();
- if(!$fixOrder){
- $this->error('未找到维修订单',$showTime);
- }
- $goodsBak=$fixOrder->info[0]->goodsBak;
- if(!$fixOrder||($goodsBak['goods']['is_fix']??0)!=1){
- $this->error('请完成维修订单支付');
- }
- $fix_order_id=$fixOrder['id'];
- }
- if($data['refund_type']==Refund::REFUND_TYPE_ALL){
- $refundCount=$orderInfo->refunds()->where('refund_type',Refund::REFUND_TYPE_ALL)->count();
- if($refundCount>=3){
- Db::rollback();
- $this->error('申请超过3次无法再次申请');
- }
- }
- $newRefund=Refund::create([
- 'user_id'=>$user->id,
- 'order_id'=>$orderInfo['order_id'],
- 'order_info_id'=>$orderInfo['id'],
- 'goods_id'=>$orderInfo['goods_id'],
- 'refund_type'=>$data['refund_type'],
- 'refund_by'=>$data['refund_by'],
- 'num'=>$data['num'],
- 'num_install'=>$data['num_install'],
- 'amount'=>$data['amount'],
- 'reason1'=>$data['reason1'],
- 'reason2'=>$data['reason2'],
- 'fix_order_id'=>$fix_order_id,
- ]);
- $orderInfo['refund_id']=$newRefund['id'];
- $orderInfo->save();
- #未发货直接退款取消
- /* if($order->is_wait_send){
- $newRefund['refund_type']=Refund::REFUND_TYPE_MONEY;
- $newRefund['amount']=$orderInfo['amount_pay'];
- $newRefund['num']=$orderInfo['num'];
- $newRefund->save();
- $newRefund->makeAudit(1);
- }*/
- Db::commit();
- $this->success();
- }
- /**
- * 取消售后
- * @ApiParams (name=order_info_id,description=子订单ID)
- */
- public function refund_cancel(){
- $data=$this->_validate([
- 'order_info_id'=>['require'],
- ]);
- $user=$this->auth->getUser();
- $orderInfo=$user->orderInfo()->findOrFail($data['order_info_id']);
- $refund=$orderInfo->refund;
- if(!$refund){
- $this->error('售后不存在');
- }
- if(!$refund->allowCancel()){
- $this->error('该售后不允许取消');
- }
- $refund->makeCancel();
- $this->success();
- }
- /**
- * 确认收货
- * @ApiParams (name=id,description=订单ID)
- */
- public function commit(){
- $data=$this->_validate([
- 'id'=>['require','integer'],
- ]);
- $user=$this->auth->getUser();
- $order=$user->orders()->findOrFail($data['id']);
- if(!$order->allowOver()){
- $this->error('该订单不允许确认');
- }
- $order->makeOver();
- $this->success();
- }
- /**
- * 上传(重新上传)打款凭证
- * @ApiParams (name=id,description=订单ID)
- * @ApiParams (name=bank_no,description=银行卡号)
- * @ApiParams (name=bank_name,description=银行开户行)
- * @ApiParams (name=bank_username,description=银行持卡人姓名)
- * @ApiParams (name=image,description=凭证图片)
- */
- public function po_complete(){
- $user=$this->auth->getUser();
- $data=$this->_validate([
- 'id|订单'=>['require'],
- //'bank_no|银行卡号'=>['require'],
- //'bank_name|银行开户行'=>['require'],
- //'bank_username|银行持卡人姓名'=>['require'],
- //'image|凭证图片'=>['require'],
- ]);
- Db::startTrans();
- $voucher=OrderVoucher::where('order_id',$data['id'])->order('id','desc')->lock(true)->find();
- if($voucher && $voucher['status']==1){
- Db::rollback();
- $this->error('该凭证已通过无法再次提交');
- }
- $order=$user->orders()->lock(true)->findOrFail($data['id']);
- if($order->is_closed){
- Db::rollback();
- $this->error('订单已关闭');
- }
- if($order->is_payed && $order->pay_type!=$order::PT_OFF){
- $this->error('支付方式不支持提交');
- }
- $newData= Arr::only($data,['bank_no','bank_name','bank_username','image']);
- $newData['status']=0;
- if($voucher && $voucher['status']==0){
- $voucher->save($newData);
- }else{
- $newData['order_id']=$data['id'];
- $newData['user_id']=$user['id'];
- $voucher=OrderVoucher::create($newData);
- }
- if($order->is_payed){
- $voucher['status']=1;
- $voucher['is_auto']=1;
- $voucher->save();
- }
- $order['order_voucher_id']=$voucher['id'];
- $order['pay_type']= Order::PT_OFF;
- $order->save();
- Db::commit();
- $this->success('',$voucher);
- }
- /**
- * 售后列表
- * @ApiParams (name=page,description=分页)
- * @ApiParams (name=limit,description=分页)
- * @ApiReturnParams (name=id,description=退款记录ID)
- * @ApiReturnParams (name=refund_status,description="退款状态10申请处理中20申请通过30申请驳回40已取消")
- * @ApiReturnParams (name=refund_type,description="退款退货类型1仅退款2退款退货3仅退货")
- * @ApiReturnParams (name=refund_by,description="退货方式")
- * @ApiReturnParams (name=reason1,description="退款退货原因")
- * @ApiReturnParams (name=reason2,description="退款退货原因")
- * @ApiReturnParams (name=num,description="退款退货数量")
- * @ApiReturnParams (name=amount,description="退款退货金额")
- * @ApiReturnParams (name=create_time,description="创建时间")
- * @ApiReturnParams (name=audit_remark,description="审核备注")
- * @ApiReturnParams (name=order_no,description="退款单号")
- * @ApiReturnParams (name=pay_status,description="退款状态1成功2失败")
- * @ApiReturnParams (name=pay_remark,description="支付备注")
- */
- public function service_list(){
- $user=$this->auth->getUser();
- $list=$user->refund()
- ->order('id','desc')
- ->with(['order_info','orders'])
- ->paginate(input('limit',15));
- $this->success('',$list);
- }
- /**
- * 订单物流查询
- * @ApiParams (name=id,description=订单ID)
- * @ApiReturnParams (name=time,description="时间")
- * @ApiReturnParams (name=content,description="内容")
- */
- public function logistics_order(){
- $user=$this->auth->getUser();
- $data=$this->_validate([
- 'id'=>['require'],
- ]);
- $order=$user->orders()->findOrFail($data['id']);
- $logistics=$order->logistics;
- if(!$logistics){
- $this->error('未上传物流信息');
- }
- $info['logistics']=logistics()
- ->setNo($logistics['trans_no'])
- ->setLogistics($logistics->com)
- ->setPhone($order->address->mobile)
- ->query();
- $this->success('',$info);
- }
- /**
- * 订单物流地图轨迹
- * @ApiParams (name=id,description=订单ID)
- * @ApiReturnParams (name=trailUrl,description="轨迹地图链接")
- */
- public function logistics_map(){
- $user=$this->auth->getUser();
- $data=$this->_validate([
- 'id'=>['require'],
- ]);
- $order=$user->orders()->findOrFail($data['id']);
- $logistics=$order->logistics;
- if(!$logistics){
- $this->error('未上传物流信息');
- }
- $info['logistics']=logistics()
- ->setNo($logistics['trans_no'])
- ->setLogistics($logistics->com)
- ->setPhone($order->address->mobile)
- ->setExtend([
- 'from' =>$logistics->from(),
- 'to'=>$order->address->to(),
- ])
- ->maptrack();
- $this->success('',$info);
- }
- }
|