1216 lines
42 KiB
PHP
Executable File
1216 lines
42 KiB
PHP
Executable File
<?php
|
||
// +----------------------------------------------------------------------
|
||
// | ShopXO 国内领先企业级B2C免费开源电商系统
|
||
// +----------------------------------------------------------------------
|
||
// | Copyright (c) 2011~2019 http://shopxo.net All rights reserved.
|
||
// +----------------------------------------------------------------------
|
||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||
// +----------------------------------------------------------------------
|
||
// | Author: Devil
|
||
// +----------------------------------------------------------------------
|
||
namespace app\service;
|
||
|
||
use think\Db;
|
||
use think\facade\Hook;
|
||
use app\service\GoodsService;
|
||
use app\service\UserService;
|
||
use app\service\ResourcesService;
|
||
|
||
/**
|
||
* 购买服务层
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 0.0.1
|
||
* @datetime 2016-12-01T21:51:08+0800
|
||
*/
|
||
class BuyService
|
||
{
|
||
/**
|
||
* 购物车添加
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2018-08-29
|
||
* @desc description
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function CartAdd($params = [])
|
||
{
|
||
// 请求参数
|
||
$p = [
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'goods_id',
|
||
'error_msg' => '商品id有误',
|
||
],
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'stock',
|
||
'error_msg' => '购买数量有误',
|
||
],
|
||
[
|
||
'checked_type' => 'min',
|
||
'key_name' => 'stock',
|
||
'checked_data' => 1,
|
||
'error_msg' => '购买数量有误',
|
||
],
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'user',
|
||
'error_msg' => '用户信息有误',
|
||
],
|
||
];
|
||
$ret = ParamsChecked($params, $p);
|
||
if($ret !== true)
|
||
{
|
||
return DataReturn($ret, -1);
|
||
}
|
||
|
||
// 查询用户状态是否正常
|
||
$ret = UserService::UserStatusCheck('id', $params['user']['id']);
|
||
if($ret['code'] != 0)
|
||
{
|
||
return $ret;
|
||
}
|
||
|
||
// 获取商品
|
||
$goods_id = intval($params['goods_id']);
|
||
$goods = Db::name('Goods')->where(['id'=>$goods_id, 'is_shelves'=>1, 'is_delete_time'=>0])->find();
|
||
if(empty($goods))
|
||
{
|
||
return DataReturn('商品不存在或已删除', -2);
|
||
}
|
||
|
||
// 规格处理
|
||
$spec = self::GoodsSpecificationsHandle($params);
|
||
|
||
// 获取商品基础信息
|
||
$goods_base = GoodsService::GoodsSpecDetail(['id'=>$goods_id, 'spec'=>$spec]);
|
||
if($goods_base['code'] != 0)
|
||
{
|
||
return $goods_base;
|
||
}
|
||
|
||
// 获取商品规格图片
|
||
if(!empty($spec))
|
||
{
|
||
$images = self::BuyGoodsSpecImages($goods_id, $spec);
|
||
if(!empty($images))
|
||
{
|
||
$goods['images'] = $images;
|
||
$goods['images_old'] = ResourcesService::AttachmentPathViewHandle($images);
|
||
}
|
||
}
|
||
|
||
// 添加购物车
|
||
$data = [
|
||
'user_id' => $params['user']['id'],
|
||
'goods_id' => $goods_id,
|
||
'title' => $goods['title'],
|
||
'images' => $goods['images'],
|
||
'original_price'=> $goods_base['data']['spec_base']['original_price'],
|
||
'price' => $goods_base['data']['spec_base']['price'],
|
||
'stock' => intval($params['stock']),
|
||
'spec' => empty($spec) ? '' : json_encode($spec),
|
||
];
|
||
|
||
// 存在则更新
|
||
$where = ['user_id'=>$data['user_id'], 'goods_id'=>$data['goods_id'], 'spec'=>$data['spec']];
|
||
$temp = Db::name('Cart')->where($where)->find();
|
||
if(empty($temp))
|
||
{
|
||
$data['add_time'] = time();
|
||
if(Db::name('Cart')->insertGetId($data) > 0)
|
||
{
|
||
return DataReturn('加入成功', 0, self::UserCartTotal($params));
|
||
}
|
||
} else {
|
||
$data['upd_time'] = time();
|
||
$data['stock'] += $temp['stock'];
|
||
if($data['stock'] > $goods['inventory'])
|
||
{
|
||
$data['stock'] = $goods['inventory'];
|
||
}
|
||
if(Db::name('Cart')->where($where)->update($data))
|
||
{
|
||
return DataReturn('加入成功', 0, self::UserCartTotal($params));
|
||
}
|
||
}
|
||
|
||
return DataReturn('加入失败', -100);
|
||
}
|
||
|
||
/**
|
||
* 商品规格解析
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2018-09-21
|
||
* @desc description
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
private static function GoodsSpecificationsHandle($params = [])
|
||
{
|
||
$spec = '';
|
||
if(!empty($params['spec']))
|
||
{
|
||
if(!is_array($params['spec']))
|
||
{
|
||
$spec = json_decode(htmlspecialchars_decode($params['spec']), true);
|
||
} else {
|
||
$spec = $params['spec'];
|
||
}
|
||
}
|
||
return empty($spec) ? '' : $spec;
|
||
}
|
||
|
||
/**
|
||
* 获取购物车列表
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2018-08-29
|
||
* @desc description
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function CartList($params = [])
|
||
{
|
||
// 请求参数
|
||
$p = [
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'user',
|
||
'error_msg' => '用户信息有误',
|
||
],
|
||
];
|
||
$ret = ParamsChecked($params, $p);
|
||
if($ret !== true)
|
||
{
|
||
return DataReturn($ret, -1);
|
||
}
|
||
|
||
$where = (!empty($params['where']) && is_array($params['where'])) ? $params['where'] : [];
|
||
$where['c.user_id'] = $params['user']['id'];
|
||
|
||
$field = 'c.*, g.inventory_unit, g.is_shelves, g.is_delete_time, g.buy_min_number, g.buy_max_number, g.model';
|
||
$data = Db::name('Cart')->alias('c')->join(['__GOODS__'=>'g'], 'g.id=c.goods_id')->where($where)->field($field)->select();
|
||
|
||
|
||
// 数据处理
|
||
if(!empty($data))
|
||
{
|
||
foreach($data as &$v)
|
||
{
|
||
// 规格
|
||
$v['spec'] = empty($v['spec']) ? null : json_decode($v['spec'], true);
|
||
|
||
// 获取商品基础信息
|
||
$goods_base = GoodsService::GoodsSpecDetail(['id'=>$v['goods_id'], 'spec'=>$v['spec']]);
|
||
if($goods_base['code'] == 0)
|
||
{
|
||
$v['inventory'] = $goods_base['data']['spec_base']['inventory'];
|
||
$v['price'] = (float) $goods_base['data']['spec_base']['price'];
|
||
$v['original_price'] = (float) $goods_base['data']['spec_base']['original_price'];
|
||
$v['spec_weight'] = $goods_base['data']['spec_base']['weight'];
|
||
$v['spec_coding'] = $goods_base['data']['spec_base']['coding'];
|
||
$v['spec_barcode'] = $goods_base['data']['spec_base']['barcode'];
|
||
} else {
|
||
return $goods_base;
|
||
}
|
||
|
||
// 基础信息
|
||
$v['goods_url'] = MyUrl('index/goods/index', ['id'=>$v['goods_id']]);
|
||
$v['images_old'] = $v['images'];
|
||
$v['images'] = ResourcesService::AttachmentPathViewHandle($v['images']);
|
||
$v['total_price'] = $v['stock']* ((float) $v['price']);
|
||
$v['buy_max_number'] = ($v['buy_max_number'] <= 0) ? $v['inventory']: $v['buy_max_number'];
|
||
}
|
||
}
|
||
|
||
return DataReturn('操作成功', 0, $data);
|
||
}
|
||
|
||
/**
|
||
* 购物车删除
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2018-09-14
|
||
* @desc description
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function CartDelete($params = [])
|
||
{
|
||
// 请求参数
|
||
$p = [
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'id',
|
||
'error_msg' => '删除数据id有误',
|
||
],
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'user',
|
||
'error_msg' => '用户信息有误',
|
||
],
|
||
];
|
||
$ret = ParamsChecked($params, $p);
|
||
if($ret !== true)
|
||
{
|
||
return DataReturn($ret, -1);
|
||
}
|
||
|
||
// 查询用户状态是否正常
|
||
$ret = UserService::UserStatusCheck('id', $params['user']['id']);
|
||
if($ret['code'] != 0)
|
||
{
|
||
return $ret;
|
||
}
|
||
|
||
// 删除
|
||
$where = [
|
||
'id' => explode(',', $params['id']),
|
||
'user_id' => $params['user']['id']
|
||
];
|
||
if(Db::name('Cart')->where($where)->delete())
|
||
{
|
||
return DataReturn('删除成功', 0, self::UserCartTotal($params));
|
||
}
|
||
return DataReturn('删除失败或资源不存在', -100);
|
||
}
|
||
|
||
/**
|
||
* 购物车数量保存
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2018-09-14
|
||
* @desc description
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function CartStock($params = [])
|
||
{
|
||
// 请求参数
|
||
$p = [
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'id',
|
||
'error_msg' => '数据id有误',
|
||
],
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'goods_id',
|
||
'error_msg' => '商品id有误',
|
||
],
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'stock',
|
||
'error_msg' => '购买数量有误',
|
||
],
|
||
[
|
||
'checked_type' => 'min',
|
||
'key_name' => 'stock',
|
||
'checked_data' => 1,
|
||
'error_msg' => '购买数量有误',
|
||
],
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'user',
|
||
'error_msg' => '用户信息有误',
|
||
],
|
||
];
|
||
$ret = ParamsChecked($params, $p);
|
||
if($ret !== true)
|
||
{
|
||
return DataReturn($ret, -1);
|
||
}
|
||
|
||
// 查询用户状态是否正常
|
||
$ret = UserService::UserStatusCheck('id', $params['user']['id']);
|
||
if($ret['code'] != 0)
|
||
{
|
||
return $ret;
|
||
}
|
||
|
||
// 更新
|
||
$where = [
|
||
'id' => intval($params['id']),
|
||
'goods_id' => intval($params['goods_id']),
|
||
'user_id' => intval($params['user']['id']),
|
||
];
|
||
$data = [
|
||
'stock' => intval($params['stock']),
|
||
'upd_time' => time(),
|
||
];
|
||
if(Db::name('Cart')->where($where)->update($data))
|
||
{
|
||
return DataReturn('更新成功', 0);
|
||
}
|
||
return DataReturn('更新失败', -100);
|
||
}
|
||
|
||
/**
|
||
* 下订单 - 正常购买
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2018-09-21
|
||
* @desc description
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function BuyGoods($params = [])
|
||
{
|
||
// 请求参数
|
||
$p = [
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'stock',
|
||
'error_msg' => '购买数量有误',
|
||
],
|
||
[
|
||
'checked_type' => 'min',
|
||
'key_name' => 'stock',
|
||
'checked_data' => 1,
|
||
'error_msg' => '购买数量有误',
|
||
],
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'goods_id',
|
||
'error_msg' => '商品id有误',
|
||
],
|
||
[
|
||
'checked_type' => 'isset',
|
||
'key_name' => 'spec',
|
||
'error_msg' => '规格参数有误',
|
||
],
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'user',
|
||
'error_msg' => '用户信息有误',
|
||
],
|
||
];
|
||
$ret = ParamsChecked($params, $p);
|
||
if($ret !== true)
|
||
{
|
||
return DataReturn($ret, -1);
|
||
}
|
||
|
||
// 获取商品
|
||
$p = [
|
||
'where' => [
|
||
'id' => intval($params['goods_id']),
|
||
'is_delete_time' => 0,
|
||
'is_shelves' => 1,
|
||
],
|
||
'field' => 'id, id AS goods_id, title, images, inventory_unit, buy_min_number, buy_max_number, model',
|
||
];
|
||
$ret = GoodsService::GoodsList($p);
|
||
if(empty($ret['data'][0]))
|
||
{
|
||
return DataReturn('资源不存在或已被删除', -10);
|
||
}
|
||
|
||
// 规格
|
||
$ret['data'][0]['spec'] = self::GoodsSpecificationsHandle($params);
|
||
|
||
// 获取商品基础信息
|
||
$goods_base = GoodsService::GoodsSpecDetail(['id'=>$ret['data'][0]['goods_id'], 'spec'=>$ret['data'][0]['spec']]);
|
||
if($goods_base['code'] == 0)
|
||
{
|
||
$ret['data'][0]['inventory'] = $goods_base['data']['spec_base']['inventory'];
|
||
$ret['data'][0]['price'] = (float) $goods_base['data']['spec_base']['price'];
|
||
$ret['data'][0]['original_price'] = (float) $goods_base['data']['spec_base']['original_price'];
|
||
$ret['data'][0]['spec_weight'] = $goods_base['data']['spec_base']['weight'];
|
||
$ret['data'][0]['spec_coding'] = $goods_base['data']['spec_base']['coding'];
|
||
$ret['data'][0]['spec_barcode'] = $goods_base['data']['spec_base']['barcode'];
|
||
$ret['data'][0]['extends'] = $goods_base['data']['spec_base']['extends'];
|
||
} else {
|
||
return $goods_base;
|
||
}
|
||
|
||
// 获取商品规格图片
|
||
if(!empty($ret['data'][0]['spec']))
|
||
{
|
||
$images = self::BuyGoodsSpecImages($ret['data'][0]['goods_id'], $ret['data'][0]['spec']);
|
||
if(!empty($images))
|
||
{
|
||
$ret['data'][0]['images'] = ResourcesService::AttachmentPathViewHandle($images);
|
||
$ret['data'][0]['images_old'] = $images;
|
||
}
|
||
}
|
||
|
||
// 数量/小计
|
||
$ret['data'][0]['stock'] = $params['stock'];
|
||
$ret['data'][0]['total_price'] = $params['stock']* ((float) $ret['data'][0]['price']);
|
||
|
||
return DataReturn('操作成功', 0, $ret['data']);
|
||
}
|
||
|
||
/**
|
||
* 下订单 - 购物车
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2018-09-21
|
||
* @desc description
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function BuyCart($params = [])
|
||
{
|
||
// 请求参数
|
||
$p = [
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'ids',
|
||
'error_msg' => '购物车id有误',
|
||
],
|
||
[
|
||
'checked_type' => 'empty',
|
||
'key_name' => 'user',
|
||
'error_msg' => '用户信息有误',
|
||
],
|
||
];
|
||
$ret = ParamsChecked($params, $p);
|
||
if($ret !== true)
|
||
{
|
||
return DataReturn($ret, -1);
|
||
}
|
||
|
||
// 获取购物车数据
|
||
$params['where'] = [
|
||
'g.is_delete_time' => 0,
|
||
'g.is_shelves' => 1,
|
||
'c.id' => explode(',', $params['ids']),
|
||
];
|
||
return self::CartList($params);
|
||
}
|
||
|
||
/**
|
||
* 获取规格图片
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2019-08-02
|
||
* @desc description
|
||
* @param [int] $goods_id [商品id]
|
||
* @param [string] $spec [图片地址或空字符串]
|
||
*/
|
||
public static function BuyGoodsSpecImages($goods_id, $spec)
|
||
{
|
||
if(!empty($spec))
|
||
{
|
||
$data = Db::name('GoodsSpecType')->where(['goods_id'=>$goods_id])->field('name,value')->select();
|
||
if(!empty($data))
|
||
{
|
||
$spec_images = [];
|
||
foreach($data as $v)
|
||
{
|
||
if(!empty($v['value']))
|
||
{
|
||
foreach(json_decode($v['value'], true) as $vs)
|
||
{
|
||
if(!empty($vs['images']))
|
||
{
|
||
$spec_images[$v['name']][$vs['name']] = $vs['images'];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if(!empty($spec_images))
|
||
{
|
||
foreach($spec as $v)
|
||
{
|
||
if(array_key_exists($v['type'], $spec_images) && array_key_exists($v['value'], $spec_images[$v['type']]))
|
||
{
|
||
return $spec_images[$v['type']][$v['value']];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* 下订单购物车删除
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @datetime 2018-10-12T00:42:49+0800
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function BuyCartDelete($params = [])
|
||
{
|
||
if(isset($params['buy_type']) && $params['buy_type'] == 'cart' && !empty($params['ids']))
|
||
{
|
||
Db::name('Cart')->where(['id'=>explode(',', $params['ids'])])->delete();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 根据购买类型获取商品列表
|
||
* @author Devil
|
||
* @blog http://gong.gg/
|
||
* @version 1.0.0
|
||
* @date 2018-09-26
|
||
* @desc description
|
||
* @param [array] $params [输入参数]
|
||
*/
|
||
public static function BuyTypeGoodsList($params = [])
|
||
{
|
||
if(isset($params['buy_type']))
|
||
{
|
||
switch($params['buy_type'])
|
||
{
|
||
// 正常购买
|
||
case 'goods' :
|
||
$ret = BuyService::BuyGoods($params);
|
||
break;
|
||
|
||
// 购物车
|
||
case 'cart' :
|
||
$ret = BuyService::BuyCart($params);
|
||
break;
|
||
|
||
// 默认
|
||
default :
|
||
$ret = DataReturn('参数有误', -1);
|
||
}
|
||
} else {
|
||
$ret = DataReturn('参数有误', -1);
|
||
}
|
||
|
||
// 数据组装
|
||
if($ret['code'] == 0)
|
||
{
|
||
// 商品数据
|
||
$goods = $ret['data'];
|
||
|
||
// 用户默认地址
|
||
$address_params = [
|
||
'user' => $params['user'],
|
||
];
|
||
if(!empty($params['address_id']))
|
||
{
|
||
$address_params['where'] = ['id' => $params['address_id']];
|
||
}
|
||
$address = UserService::UserDefaultAddress($address_params);
|
||
| < |