审查视图

application/api/controller/Cart.php 17.6 KB
何书鹏 authored
1 2 3 4 5 6
<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\model\Goods;
何书鹏 authored
7
use app\common\model\GoodsStyle;
8
use app\common\model\GoodsSpec;
何书鹏 authored
9 10
use app\common\controller\Wechat;
use think\Db;
何书鹏 authored
11 12 13 14 15 16

/**
 * 购物车
 */
class Cart extends Api
{
1  
何书鹏 authored
17
    protected $noNeedLogin = ['getCartNum','notify'];
何书鹏 authored
18 19 20 21 22 23
    protected $noNeedRight = '*';

    public function _initialize()
    {
        parent::_initialize();
        $this->model = model('app\common\model\Cart');
何书鹏 authored
24
        $this->user = $this->auth->getUser();
何书鹏 authored
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
    }

    /**
     * 购物车-首页
     * @ApiMethod   (GET)
     * @ApiRoute    (/api/cart/index)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
     */        
    public function index(){
何书鹏 authored
41 42 43 44 45 46
        // 删除所有超过一天的立即购买数据
        $this->model
            ->where('isbuynow','1')
            ->where('createtime','<',time()-86400)
            ->delete();
        // 购物车数据
何书鹏 authored
47
        $this->success(__('成功'),$this->model->getList($this->user,['isbuynow'=>'0']));
何书鹏 authored
48 49 50
    }

    /**
51 52 53 54 55 56 57 58 59 60 61 62 63
     * 购物车-获取购物车商品总数
     * @ApiMethod   (GET)
     * @ApiRoute    (/api/cart/getCartNum)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
     */        
    public function getCartNum(){
64 65
        $total_num = $this->model->where(['user_id'=>$this->auth->id,'isbuynow'=>'0'])->sum('goods_num');
        $this->success(__('成功'),compact('total_num'));
66 67 68
    }

    /**
何书鹏 authored
69 70 71 72 73
     * 购物车-加入购物车
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="goods_id", type="integer", required=true, description="商品ID")
     * @ApiParams   (name="goods_num", type="integer", required=true, description="商品数量")
何书鹏 authored
74
     * @ApiParams   (name="goods_style", type="object", sample="{'1':'11','5':'15','7':'2','14':'25','15':'\/uploads\/20200711\/3689359dcdf1146d234930cae4958110.jpg','13':'21','12':'18'}", description="商品规格 {'风格ID':'风格值'}")
何书鹏 authored
75
     * @ApiParams   (name="user_size_id", type="integer", description="用户尺寸ID")
何书鹏 authored
76 77
     * @ApiParams   (name="spec_sku_id", type="string", description="商品sku")
     * @ApiParams   (name="isbuynow", type="string", description="是否立即购买:0=否,1=是")
何书鹏 authored
78 79 80 81 82 83 84 85 86 87
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
     */
    public function add()
    {
1  
何书鹏 authored
88
        $post = $this->request->post();
1  
何书鹏 authored
89 90
        // 对象转json字符串
        if(!empty($post['goods_style']) && is_array($post['goods_style'])){
1  
何书鹏 authored
91
            $post['goods_style'] = json_encode($post['goods_style']);
1  
何书鹏 authored
92
        }
何书鹏 authored
93
        if(!$cart_id = $this->model->add($this->user,$post)){
何书鹏 authored
94
            $this->error($this->model->getError() ?: '加入购物车失败',null,$this->model->getCode());
何书鹏 authored
95
        }
何书鹏 authored
96 97
        $this->success(__('加入购物车成功'),[
            'cart_id' => $cart_id,
何书鹏 authored
98
            'total_num' => $this->model->where('user_id',$this->user['id'])->where('isbuynow','0')->sum('goods_num')
何书鹏 authored
99
        ]);
何书鹏 authored
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    }

    /**
     * 购物车-修改尺寸
     * @ApiMethod   (GET)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="cart_id", type="integer", required=true, description="购物车ID")
     * @ApiParams   (name="user_size_id", type="integer", required=true, description="用户尺寸ID")
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
     */        
1  
何书鹏 authored
116
    public function editSize($cart_id,$user_size_id){
何书鹏 authored
117 118
        $cart = $this->model->get($cart_id);
        empty($cart) && $this->error(__('购物车信息不存在'));
何书鹏 authored
119
        $user_size = \app\common\model\UserSize::get(['user_id'=>$this->user['id'],'id'=>$user_size_id]);
何书鹏 authored
120
        empty($user_size) && $this->error(__('尺寸信息不存在'));
何书鹏 authored
121 122 123 124 125 126
        $cart->user_size_id = $user_size_id;
        $cart->save();
        $this->success(__('成功'));
    }

    /**
何书鹏 authored
127
     * 购物车-修改定制风格
何书鹏 authored
128 129 130
     * @ApiMethod   (GET)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="cart_id", type="integer", required=true, description="购物车ID")
1  
何书鹏 authored
131
     * @ApiParams   (name="goods_style", type="object", required=true, sample="{'1':'11','5':'15','7':'2','14':'25','15':'\/uploads\/20200711\/3689359dcdf1146d234930cae4958110.jpg','13':'21','12':'18'}", description="商品风格 {'风格ID':'规格值'}")
何书鹏 authored
132 133 134 135 136 137 138 139
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
     */        
1  
何书鹏 authored
140 141
    public function editGoodsStyle($cart_id,$goods_style){
        $goods_style = htmlspecialchars_decode($goods_style);
何书鹏 authored
142 143
        $cart = $this->model->get($cart_id);
        empty($cart) && $this->error(__('购物车信息不存在'));
何书鹏 authored
144
        $cart['goods']['ismake'] == '0' && $this->error(__('该产品不属于定制商品'));
何书鹏 authored
145
        empty($goods_style) && $this->error(__('请选择您的定制信息'));
何书鹏 authored
146 147
        $model_style = GoodsStyle::get(['goods_id'=>$cart['goods_id'],'goods_style'=>$goods_style]);
        $cart->make_type = !$model_style ? '2' : '1';
何书鹏 authored
148 149
        $cart->goods_style = $goods_style;
        $goods_style_arr = json_decode($goods_style,true);
何书鹏 authored
150
        $cart->goods_price = $cart['goods']['goods_price'] + array_sum(\app\common\model\StyleValue::where('id','in',$goods_style_arr)->column('style_value_price'));
何书鹏 authored
151 152 153 154 155
        $cart->save();
        $this->success(__('成功'));
    }

    /**
1  
何书鹏 authored
156 157 158 159 160 161 162 163 164 165 166 167 168
     * 购物车-修改规格
     * @ApiMethod   (GET)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="cart_id", type="integer", required=true, description="购物车ID")
     * @ApiParams   (name="spec_sku_id", type="string", required=true, sample="1_5", description="商品规格")
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
     */        
1  
何书鹏 authored
169
    public function editGoodsSpec($cart_id,$spec_sku_id){
1  
何书鹏 authored
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
        $cart = $this->model->get($cart_id);
        empty($cart) && $this->error(__('购物车信息不存在'));
        empty($spec_sku_id) && $this->error(__('请选择规格'));
        // 检查库存
        $goods = Goods::get($cart['goods_id'],['spec_rel.spec']);
        $goods_sku = $goods->getGoodsSku($spec_sku_id);
        if($goods['ismake'] == '0' && $goods_sku['stock_num'] < $cart['goods_num']){
            $this->error(__('商品库存不足'.$cart['goods_num'].'件'));
        }
        $cart->spec_sku_id = $spec_sku_id;
        $cart->goods_price = $goods_sku['goods_price'];
        $cart->save();
        $this->success(__('成功'));
    }

    /**
何书鹏 authored
186 187 188 189 190 191 192 193 194 195 196 197 198
     * 购物车-修改商品数量
     * @ApiMethod   (GET)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="cart_id", type="integer", required=true, description="购物车ID")
     * @ApiParams   (name="goods_num", type="integer", required=true, description="商品数量")
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
     */        
1  
何书鹏 authored
199
    public function editGoodsNum($cart_id,$goods_num){
何书鹏 authored
200 201
        $cart = $this->model->get($cart_id);
        empty($cart) && $this->error(__('购物车信息不存在'));
何书鹏 authored
202
        $goods_num < 1 && $this->error(__('商品数量不能小于1'));
何书鹏 authored
203 204 205 206
        // 检查库存
        $goods = Goods::get($cart['goods_id'],['spec_rel.spec']);
        $goods_sku = $goods->getGoodsSku($cart['spec_sku_id']);
        if($goods['ismake'] == '0' && $goods_sku['stock_num'] < $goods_num){
1  
何书鹏 authored
207 208
            $this->error(__('商品库存不足'.$goods_num.'件'));
        }
何书鹏 authored
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
        $cart->goods_num = $goods_num;
        $cart->save();
        $this->success(__('成功'));
    }

    /**
     * 购物车-删除
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="cart_id", type="integer", required=true, description="购物车ID")
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
     */
1  
何书鹏 authored
227
    public function delete($cart_id)
何书鹏 authored
228 229 230 231 232 233
    {
        $this->model->where('id',$cart_id)->delete();
        $this->success(__('成功'));
    }

    /**
何书鹏 authored
234 235 236 237 238 239 240 241 242 243 244 245 246 247
     * 购物车-选中取消
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="cart_ids", type="string", required=true, description="购物车ID集合")
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
     */
    public function select($cart_ids)
    {
何书鹏 authored
248 249 250 251 252 253 254
        $where = [
            'user_id' => $this->user['id'],
            'isbuynow' => '0'
        ];
        // 传过来的选中
        $this->model
            ->where($where)
何书鹏 authored
255
            ->where('id','in',$cart_ids)
何书鹏 authored
256 257 258 259 260 261 262
            ->update(['isselected'=>'1']);
        // 未传过来的取消选中
        $this->model
            ->where($where)
            ->where('id','notin',$cart_ids)
            ->update(['isselected'=>'0']);
        $this->success(__('成功'));
何书鹏 authored
263 264 265
    }

    /**
何书鹏 authored
266 267 268 269 270 271 272 273 274 275 276 277 278 279
     * 结算和支付(结算用GET,支付用POST)
     * @ApiMethod   (POST)
     * @ApiHeaders  (name=token, type=string, required=true, description="请求的Token")
     * @ApiParams   (name="cart_ids", type="string", required=true, description="购物车ID集合")
     * @ApiParams   (name="user_address_id", type="integer", description="用户地址ID")
     * @ApiParams   (name="user_coupon_id", type="integer", description="用户优惠券ID")
     * @ApiParams   (name="score_switch", type="integer", description="积分开关:0=关,1=开")
     * @ApiReturnParams   (name="code", type="integer", required=true, sample="0")
     * @ApiReturnParams   (name="msg", type="string", required=true, sample="返回成功")
     * @ApiReturnParams   (name="data", type="object", description="扩展数据返回")
     * @ApiReturn   ({
         'code':'1',
         'msg':'返回成功'
        })
何书鹏 authored
280
     */
何书鹏 authored
281
    public function pay()
何书鹏 authored
282
    {
1  
何书鹏 authored
283
        $data = $this->request->param();//接收get和post两种数据
何书鹏 authored
284
        empty($data['cart_ids']) && $this->error(__('参数【cart_ids】不能为空'));
何书鹏 authored
285
        $order = $this->model->getList($this->user,['id'=>['in',$data['cart_ids']]],$data);
何书鹏 authored
286
        if (!$this->request->isPost()) {
何书鹏 authored
287 288 289
            $this->success(__('成功'),$order);
        }
        // 生成订单信息错误
何书鹏 authored
290 291
        if ($this->model->getError()) {
            $this->error($this->model->getError());
何书鹏 authored
292 293
        }
        // 创建订单
何书鹏 authored
294
        $model = new \app\common\model\Order;
何书鹏 authored
295
        if ($model->add($this->user['id'], $order)) {
何书鹏 authored
296 297
            // 删除结算购物车商品
            $this->model->where(['id'=>['in',$data['cart_ids']]])->delete();
1  
何书鹏 authored
298
            if($order['order_price'] > 0){
何书鹏 authored
299 300
                // 发起微信支付
                $Wechat = new Wechat;
何书鹏 authored
301
                $order['order_price'] = 0.01;//测试金额
何书鹏 authored
302 303 304 305
                if(!$payment = $Wechat->wxPay($model['order_no'], $this->user['openid'], $order['order_price'])){
                    $this->error($Wechat->getError());
                }
                // $payment = [];
1  
何书鹏 authored
306 307 308 309 310 311 312 313
            }else{
                $this->notifyTest($model['order_no']);
                $payment = [];
            }
            $this->success(__('成功'),[
                'payment' => $payment,
                'order_id' => $model['id']
            ]);
何书鹏 authored
314 315
        }
        $error = $model->getError() ?: '订单创建失败';
何书鹏 authored
316 317 318 319 320 321 322 323 324 325 326 327 328 329
        return $this->error($error);
    }

    /**
     * 异步回调
     */
    public function notify()
    {
        $payment = Wechat::payment();
        $response = $payment->handlePaidNotify(function($message, $fail){
            if ($message['return_code'] !== 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
                return $fail('通信失败,请稍后再通知我');
            }
            // 用户支付失败 - 支付失败也需要返回true,表示服务器已处理,不然微信会反复通知,没有意义
何书鹏 authored
330
            if ($message['result_code'] === 'FAIL') {
何书鹏 authored
331 332 333
                return true;
            }
            // 支付成功后的业务逻辑
何书鹏 authored
334
            if ($message['result_code'] === 'SUCCESS') {
何书鹏 authored
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
                Db::startTrans();
                try {
                    // 处理订单
                    $this->handleOrder($message['out_trade_no']);
                    Db::commit();
                } catch (\think\exception\PDOException $e) {
                    Db::rollback();
                    return $fail('服务器处理失败,请稍后再通知我');
                } catch (\think\Exception $e) {
                    Db::rollback();
                    return $fail('服务器处理失败,请稍后再通知我');
                }
            }
            return true;
        });
        $response->send(); // return $response;
    }

    /**
     * 异步回调
     */
    public function notifyTest($order_no)
    {
        Db::startTrans();
        try {
            $this->handleOrder($order_no);
            Db::commit();
        } catch (\think\exception\PDOException $e) {
            Db::rollback();
何书鹏 authored
364
            $this->error($e->getMessage());
何书鹏 authored
365 366 367
            return false;
        } catch (\think\Exception $e) {
            Db::rollback();
何书鹏 authored
368
            $this->error($e->getMessage());
何书鹏 authored
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
            return false;
        }
        return true;
    }

    /**
     * 异步回调-处理订单
     */
    private function handleOrder($order_no)
    {
        $order = \app\common\model\Order::get(['order_no'=>$order_no]);
        if (!$order || $order['pay_status'] == '1') { // 如果订单不存在 或者 订单已经支付过了
            return true; // 告诉微信,我已经处理完了,订单没找到,别再通知我了
        }
        $order->pay_time = time(); // 更新支付时间为当前时间
        $order->pay_status = '1';
        $order->save();
386 387 388 389
        // 整理批量更新商品销量
        $goodsSave = [];
        // 批量更新商品规格:sku销量、库存
        $goodsSpecSave = [];
390
        foreach($order['goods'] as $v){
391 392 393 394 395
            $goodsSave[] = [
                'id' => $v['goods_id'],
                'sale_num' => ['inc', $v['goods_num']]
            ];
            $specData = [
何书鹏 authored
396
                'id' => Goods::get($v['goods_id'],['spec_rel.spec'])->getGoodsSku($v['spec_sku_id'])['id'],
397 398 399
                'sale_num' => ['inc', $v['goods_num']]
            ];
            // 非定制商品减库存
何书鹏 authored
400
            if($v['goods']['ismake'] == '0'){
401
                $specData['stock_num'] = ['dec', $v['goods_num']];
402
            }
403
            $goodsSpecSave[] = $specData;
404
        }
405 406 407 408
        // 更新商品总销量
        (new Goods)->allowField(true)->isUpdate()->saveAll($goodsSave);
        // 更新商品规格库存
        (new GoodsSpec)->allowField(true)->isUpdate()->saveAll($goodsSpecSave);
何书鹏 authored
409 410 411 412 413 414 415 416
        // 订单支付-赠送积分
        if($order['order_price'] > 0){
            $sendscore = config('site.sendscore'); // 消费多少元赠送1积分
            $score = bcdiv($order['order_price'],$sendscore); // 赠送积分
            if($score >= 1){
                \app\common\model\User::score($score,$order['user_id'],'订单支付-赠送积分');
            }
        }
何书鹏 authored
417
        return true;
何书鹏 authored
418 419
    }
}