Browse Source

删除不需要文件

master
wanghongjun 3 years ago
parent
commit
e5c24d1127
  1. 78
      source/application/api/model/Article.php
  2. 347
      source/application/api/model/Cart.php
  3. 28
      source/application/api/model/Category.php
  4. 229
      source/application/api/model/Comment.php
  5. 23
      source/application/api/model/CommentImage.php
  6. 86
      source/application/api/model/Coupon.php
  7. 24
      source/application/api/model/Delivery.php
  8. 41
      source/application/api/model/DeliveryRule.php
  9. 26
      source/application/api/model/Express.php
  10. 37
      source/application/api/model/Goods.php
  11. 23
      source/application/api/model/GoodsImage.php
  12. 24
      source/application/api/model/GoodsSku.php
  13. 14
      source/application/api/model/GoodsSpecRel.php
  14. 637
      source/application/api/model/Order.php
  15. 23
      source/application/api/model/OrderAddress.php
  16. 35
      source/application/api/model/OrderGoods.php
  17. 171
      source/application/api/model/OrderRefund.php
  18. 23
      source/application/api/model/OrderRefundAddress.php
  19. 15
      source/application/api/model/OrderRefundImage.php
  20. 37
      source/application/api/model/Setting.php
  21. 14
      source/application/api/model/Spec.php
  22. 14
      source/application/api/model/SpecValue.php
  23. 23
      source/application/api/model/UploadFile.php
  24. 192
      source/application/api/model/User.php
  25. 132
      source/application/api/model/UserAddress.php
  26. 197
      source/application/api/model/UserCoupon.php
  27. 29
      source/application/api/model/Wxapp.php
  28. 24
      source/application/api/model/WxappCategory.php
  29. 22
      source/application/api/model/WxappHelp.php
  30. 24
      source/application/api/model/WxappNavbar.php
  31. 221
      source/application/api/model/WxappPage.php
  32. 37
      source/application/api/model/WxappPrepayId.php
  33. 76
      source/application/api/model/article/Category.php
  34. 185
      source/application/api/model/bargain/Active.php
  35. 102
      source/application/api/model/dealer/Apply.php
  36. 23
      source/application/api/model/dealer/Capital.php
  37. 116
      source/application/api/model/dealer/Order.php
  38. 100
      source/application/api/model/dealer/Referee.php
  39. 22
      source/application/api/model/dealer/Setting.php
  40. 51
      source/application/api/model/dealer/User.php
  41. 99
      source/application/api/model/dealer/Withdraw.php
  42. 193
      source/application/api/model/recharge/Order.php
  43. 32
      source/application/api/model/recharge/OrderPlan.php
  44. 73
      source/application/api/model/recharge/Plan.php
  45. 50
      source/application/api/model/sharing/Active.php
  46. 23
      source/application/api/model/sharing/ActiveUsers.php
  47. 23
      source/application/api/model/sharing/Category.php
  48. 235
      source/application/api/model/sharing/Comment.php
  49. 23
      source/application/api/model/sharing/CommentImage.php
  50. 60
      source/application/api/model/sharing/Goods.php
  51. 23
      source/application/api/model/sharing/GoodsImage.php
  52. 24
      source/application/api/model/sharing/GoodsSku.php
  53. 14
      source/application/api/model/sharing/GoodsSpecRel.php
  54. 709
      source/application/api/model/sharing/Order.php
  55. 23
      source/application/api/model/sharing/OrderAddress.php
  56. 35
      source/application/api/model/sharing/OrderGoods.php
  57. 171
      source/application/api/model/sharing/OrderRefund.php
  58. 23
      source/application/api/model/sharing/OrderRefundAddress.php
  59. 15
      source/application/api/model/sharing/OrderRefundImage.php
  60. 38
      source/application/api/model/sharing/Setting.php
  61. 131
      source/application/api/model/store/Shop.php
  62. 65
      source/application/api/model/store/shop/Clerk.php
  63. 15
      source/application/api/model/store/shop/ClerkRel.php
  64. 15
      source/application/api/model/store/shop/Order.php
  65. 38
      source/application/api/model/user/BalanceLog.php
  66. 30
      source/application/api/model/wxapp/Formid.php
  67. 77
      source/application/api/model/wxapp/LiveRoom.php
  68. 66
      source/application/api/service/Payment.php
  69. 874
      source/application/api/service/order/Checkout.php
  70. 150
      source/application/api/service/order/PaySuccess.php
  71. 79
      source/application/api/service/recharge/PaySuccess.php
  72. 907
      source/application/api/service/sharing/order/Checkout.php
  73. 152
      source/application/api/service/sharing/order/PaySuccess.php

78
source/application/api/model/Article.php

@ -1,78 +0,0 @@
<?php
namespace app\api\model;
use app\common\exception\BaseException;
use app\common\model\Article as ArticleModel;
/**
* 商品评价模型
* Class Article
* @package app\api\model
*/
class Article extends ArticleModel
{
/**
* 追加字段
* @var array
*/
protected $append = [
'show_views',
'view_time'
];
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'is_delete',
'wxapp_id',
'create_time',
'update_time'
];
public function getViewTimeAttr($value, $data)
{
return date('Y-m-d', $data['create_time']);
}
/**
* 文章详情
* @param $article_id
* @return ArticleModel|null
* @throws BaseException
* @throws \think\Exception
* @throws \think\exception\DbException
*/
public static function detail($article_id)
{
if (!$model = parent::detail($article_id)) {
throw new BaseException(['msg' => '文章不存在']);
}
// 累积阅读数
$model->setInc('actual_views', 1);
return $model;
}
/**
* 获取文章列表
* @param int $category_id
* @param int $limit
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList($category_id = 0, $limit = 15)
{
$category_id > 0 && $this->where('category_id', '=', $category_id);
return $this->field(['article_content'], true)
->with(['image', 'category'])
->where('article_status', '=', 1)
->where('is_delete', '=', 0)
->order(['article_sort' => 'asc', 'create_time' => 'desc'])
->paginate($limit, false, [
'query' => \request()->request()
]);
}
}

347
source/application/api/model/Cart.php

@ -1,347 +0,0 @@
<?php
namespace app\api\model;
use think\Cache;
use app\api\model\store\Shop as ShopModel;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\enum\DeliveryType as DeliveryTypeEnum;
use app\common\service\delivery\Express as ExpressService;
/**
* 购物车管理
* Class Cart
* @package app\api\model
*/
class Cart
{
/* @var string $error 错误信息 */
public $error = '';
/* @var \think\Model|\think\Collection $user 用户信息 */
private $user;
/* @var int $user_id 用户id */
private $user_id;
/* @var int $wxapp_id 小程序商城id */
private $wxapp_id;
/* @var array $cart 购物车列表 */
private $cart = [];
/* @var bool $clear 是否清空购物车 */
private $clear = false;
/**
* 构造方法
* Cart constructor.
* @param \think\Model|\think\Collection $user
*/
public function __construct($user)
{
$this->user = $user;
$this->user_id = $this->user['user_id'];
$this->wxapp_id = $this->user['wxapp_id'];
$this->cart = Cache::get('cart_' . $this->user_id) ?: [];
}
/**
* 购物车列表 (含商品信息)
* @param string $cartIds 购物车id集
* @param int $delivery 配送方式
* @param int $pay_type 支付方式
* @param int $shop_id 自提门店id
* @return array
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getList(
$cartIds = null,
$delivery = DeliveryTypeEnum::EXPRESS,
$pay_type = PayTypeEnum::WECHAT,
$shop_id = 0
)
{
// 返回的数据
$returnData = [];
// 获取购物车商品列表
$goodsList = $this->getGoodsList($cartIds);
// 订单商品总数量
$orderTotalNum = array_sum(array_column($goodsList, 'total_num'));
// 订单商品总金额
$orderTotalPrice = array_sum(array_column($goodsList, 'total_price'));
// 处理配送方式
if ($delivery == DeliveryTypeEnum::EXPRESS) {
$this->orderExpress($returnData, $goodsList, $orderTotalPrice);
} elseif ($delivery == DeliveryTypeEnum::EXTRACT) {
$shop_id > 0 && $returnData['extract_shop'] = ShopModel::detail($shop_id);
}
// 可用优惠券列表
$couponList = UserCoupon::getUserCouponList($this->user['user_id'], $orderTotalPrice);
return array_merge([
'goods_list' => array_values($goodsList), // 商品列表
'order_total_num' => $orderTotalNum, // 商品总数量
'order_total_price' => sprintf('%.2f', $orderTotalPrice), // 商品总金额 (不含运费)
'order_pay_price' => sprintf('%.2f', $orderTotalPrice), // 实际支付金额
'delivery' => $delivery, // 配送类型
'coupon_list' => array_values($couponList), // 优惠券列表
'address' => $this->user['address_default'], // 默认地址
'exist_address' => !$this->user['address']->isEmpty(), // 是否存在收货地址
'express_price' => '0.00', // 配送费用
'intra_region' => true, // 当前用户收货城市是否存在配送规则中
'extract_shop' => [], // 自提门店信息
'pay_type' => $pay_type, // 支付方式
'has_error' => $this->hasError(),
'error_msg' => $this->getError(),
], $returnData);
}
/**
* 订单配送-快递配送
* @param $returnData
* @param $goodsList
* @param $orderTotalPrice
*/
private function orderExpress(&$returnData, $goodsList, $orderTotalPrice)
{
// 当前用户收货城市id
$cityId = $this->user['address_default'] ? $this->user['address_default']['city_id'] : null;
// 初始化配送服务类
$ExpressService = new ExpressService(
$this->wxapp_id,
$cityId,
$goodsList,
OrderTypeEnum::MASTER
);
// 获取不支持当前城市配送的商品
$notInRuleGoods = $ExpressService->getNotInRuleGoods();
// 验证商品是否在配送范围
$intraRegion = $returnData['intra_region'] = $notInRuleGoods === false;
if ($intraRegion == false) {
$notInRuleGoodsName = $notInRuleGoods['goods_name'];
$this->setError("很抱歉,您的收货地址不在商品 [{$notInRuleGoodsName}] 的配送范围内");
} else {
// 计算配送金额
$ExpressService->setExpressPrice();
}
// 订单总运费金额
$expressPrice = $returnData['express_price'] = $ExpressService->getTotalFreight();
// 订单总金额 (含运费)
$returnData['order_pay_price'] = bcadd($orderTotalPrice, $expressPrice, 2);
}
/**
* 获取购物车列表
* @param string|null $cartIds 购物车索引集 (为null时则获取全部)
* @return array
*/
private function getCartList($cartIds = null)
{
if (empty($cartIds)) return $this->cart;
$cartList = [];
$indexArr = (strpos($cartIds, ',') !== false) ? explode(',', $cartIds) : [$cartIds];
foreach ($indexArr as $index) {
isset($this->cart[$index]) && $cartList[$index] = $this->cart[$index];
}
return $cartList;
}
/**
* 获取购物车中的商品列表
* @param $cartIds
* @return array|bool
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function getGoodsList($cartIds)
{
// 购物车商品列表
$goodsList = [];
// 获取购物车列表
$cartList = $this->getCartList($cartIds);
if (empty($cartList)) {
$this->setError('当前购物车没有商品');
return $goodsList;
}
// 购物车中所有商品id集
$goodsIds = array_unique(array_column($cartList, 'goods_id'));
// 获取并格式化商品数据
$goodsData = [];
foreach ((new Goods)->getListByIds($goodsIds) as $item) {
$goodsData[$item['goods_id']] = $item;
}
// 格式化购物车数据列表
foreach ($cartList as $cart) {
// 判断商品不存在则自动删除
if (!isset($goodsData[$cart['goods_id']])) {
$this->delete($cart['goods_id'] . '_' . $cart['goods_sku_id']);
continue;
}
/* @var Goods $goods */
$goods = $goodsData[$cart['goods_id']];
// 判断商品是否已删除
if ($goods['is_delete']) {
$this->delete($cart['goods_id'] . '_' . $cart['goods_sku_id']);
continue;
}
// 商品sku信息
$goods['goods_sku_id'] = $cart['goods_sku_id'];
// 商品sku不存在则自动删除
if (!$goods['goods_sku'] = $goods->getGoodsSku($cart['goods_sku_id'])) {
$this->delete($cart['goods_id'] . '_' . $cart['goods_sku_id']);
continue;
}
// 判断商品是否下架
if ($goods['goods_status']['value'] != 10) {
$this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 已下架');
}
// 判断商品库存
if ($cart['goods_num'] > $goods['goods_sku']['stock_num']) {
$this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 库存不足');
}
// 商品单价
$goods['goods_price'] = $goods['goods_sku']['goods_price'];
// 购买数量
$goods['total_num'] = $cart['goods_num'];
// 商品总价
$goods['total_price'] = $total_price = bcmul($goods['goods_price'], $cart['goods_num'], 2);
$goodsList[] = $goods->toArray();
}
return $goodsList;
}
/**
* 添加购物车
* @param $goods_id
* @param $goods_num
* @param $goods_sku_id
* @return bool
*/
public function add($goods_id, $goods_num, $goods_sku_id)
{
// 购物车商品索引
$index = $goods_id . '_' . $goods_sku_id;
// 商品信息
$goods = Goods::detail($goods_id);
// 判断商品是否下架
if (!$goods || $goods['is_delete'] || $goods['goods_status']['value'] != 10) {
$this->setError('很抱歉,商品信息不存在或已下架');
return false;
}
// 商品sku信息
$goods['goods_sku'] = $goods->getGoodsSku($goods_sku_id);
// 判断商品库存
$cartGoodsNum = $goods_num + (isset($this->cart[$index]) ? $this->cart[$index]['goods_num'] : 0);
if ($cartGoodsNum > $goods['goods_sku']['stock_num']) {
$this->setError('很抱歉,商品库存不足');
return false;
}
$create_time = time();
$data = compact('goods_id', 'goods_num', 'goods_sku_id', 'create_time');
if (empty($this->cart)) {
$this->cart[$index] = $data;
return true;
}
isset($this->cart[$index]) ? $this->cart[$index]['goods_num'] = $cartGoodsNum : $this->cart[$index] = $data;
return true;
}
/**
* 减少购物车中某商品数量
* @param $goods_id
* @param $goods_sku_id
*/
public function sub($goods_id, $goods_sku_id)
{
$index = $goods_id . '_' . $goods_sku_id;
$this->cart[$index]['goods_num'] > 1 && $this->cart[$index]['goods_num']--;
}
/**
* 删除购物车中指定商品
* @param $cart_ids (支持字符串ID集)
*/
public function delete($cart_ids)
{
$indexArr = strpos($cart_ids, ',') !== false
? explode(',', $cart_ids) : [$cart_ids];
foreach ($indexArr as $index) {
if (isset($this->cart[$index])) unset($this->cart[$index]);
}
}
/**
* 获取当前用户购物车商品总数量(含件数)
* @return int
*/
public function getTotalNum()
{
return array_sum(array_column($this->cart, 'goods_num'));
}
/**
* 获取当前用户购物车商品总数量(不含件数)
* @return int
*/
public function getGoodsNum()
{
return count($this->cart);
}
/**
* 析构方法
* 将cart数据保存到缓存文件
*/
public function __destruct()
{
$this->clear !== true && Cache::set('cart_' . $this->user_id, $this->cart, 86400 * 15);
}
/**
* 清空当前用户购物车
* @param null $cart_ids
*/
public function clearAll($cart_ids = null)
{
if (empty($cart_ids)) {
$this->clear = true;
Cache::rm('cart_' . $this->user_id);
} else {
$this->delete($cart_ids);
}
}
/**
* 设置错误信息
* @param $error
*/
private function setError($error)
{
empty($this->error) && $this->error = $error;
}
/**
* 是否存在错误
* @return bool
*/
private function hasError()
{
return !empty($this->error);
}
/**
* 获取错误信息
* @return string
*/
public function getError()
{
return $this->error;
}
}

28
source/application/api/model/Category.php

@ -1,28 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Category as CategoryModel;
/**
* 商品分类模型
* Class Category
* @package app\common\model
*/
class Category extends CategoryModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
// 'create_time',
'update_time'
];
public static function getList() {
}
}

229
source/application/api/model/Comment.php

@ -1,229 +0,0 @@
<?php
namespace app\api\model;
use app\common\exception\BaseException;
use app\common\model\Comment as CommentModel;
use app\common\library\helper;
/**
* 商品评价模型
* Class Comment
* @package app\api\model
*/
class Comment extends CommentModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'status',
'sort',
'order_id',
'goods_id',
'order_goods_id',
'is_delete',
'update_time'
];
/**
* 关联用户表
* @return \think\model\relation\BelongsTo
*/
public function user()
{
return $this->belongsTo('User')->field(['user_id', 'nickName', 'avatarUrl']);
}
/**
* 获取指定商品评价列表
* @param $goods_id
* @param int $scoreType
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getGoodsCommentList($goods_id, $scoreType = -1)
{
// 筛选条件
$filter = [
'goods_id' => $goods_id,
'is_delete' => 0,
'status' => 1,
];
// 评分
$scoreType > 0 && $filter['score'] = $scoreType;
return $this->with(['user', 'OrderGoods', 'image.file'])
->where($filter)
->order(['sort' => 'asc', 'create_time' => 'desc'])
->paginate(15, false, [
'query' => request()->request()
]);
}
/**
* 获取指定评分总数
* @param $goods_id
* @return array|false|\PDOStatement|string|\think\Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getTotal($goods_id)
{
return $this->field([
'count(comment_id) AS `all`',
'count(score = 10 OR NULL) AS `praise`',
'count(score = 20 OR NULL) AS `review`',
'count(score = 30 OR NULL) AS `negative`',
])->where([
'goods_id' => $goods_id,
'is_delete' => 0,
'status' => 1
])->find();
}
/**
* 验证订单是否允许评价
* @param Order $order
* @return boolean
*/
public function checkOrderAllowComment($order)
{
// 验证订单是否已完成
if ($order['order_status']['value'] != 30) {
$this->error = '该订单未完成,无法评价';
return false;
}
// 验证订单是否已评价
if ($order['is_comment'] == 1) {
$this->error = '该订单已完成评价';
return false;
}
return true;
}
/**
* 根据已完成订单商品 添加评价
* @param Order $order
* @param \think\Collection|OrderGoods $goodsList
* @param $post
* @return boolean
* @throws \Exception
*/
public function addForOrder($order, $goodsList, $post)
{
// 生成 formData
$formData = $this->formatFormData($post);
// 生成评价数据
$data = $this->createCommentData($order['user_id'], $order['order_id'], $goodsList, $formData);
if (empty($data)) {
$this->error = '没有输入评价内容';
return false;
}
return $this->transaction(function () use ($order, $goodsList, $formData, $data) {
// 记录评价内容
$result = $this->isUpdate(false)->saveAll($data);
// 记录评价图片
$this->saveAllImages($result, $formData);
// 更新订单评价状态
$isComment = count($goodsList) === count($data);
$this->updateOrderIsComment($order, $isComment, $result);
return true;
});
}
/**
* 更新订单评价状态
* @param Order $order
* @param $isComment
* @param $commentList
* @return array|false
* @throws \Exception
*/
private function updateOrderIsComment($order, $isComment, $commentList)
{
// 更新订单商品
$orderGoodsData = [];
foreach ($commentList as $comment) {
$orderGoodsData[] = [
'order_goods_id' => $comment['order_goods_id'],
'is_comment' => 1
];
}
// 更新订单
$isComment && $order->save(['is_comment' => 1]);
return (new OrderGoods)->saveAll($orderGoodsData);
}
/**
* 生成评价数据
* @param $user_id
* @param $order_id
* @param $goodsList
* @param $formData
* @return array
* @throws BaseException
*/
private function createCommentData($user_id, $order_id, $goodsList, $formData)
{
$data = [];
foreach ($goodsList as $goods) {
if (!isset($formData[$goods['order_goods_id']])) {
throw new BaseException(['msg' => '提交的数据不合法']);
}
$item = $formData[$goods['order_goods_id']];
$item['content'] = trim($item['content']);
!empty($item['content']) && $data[$goods['order_goods_id']] = [
'score' => $item['score'],
'content' => $item['content'],
'is_picture' => !empty($item['uploaded']),
'sort' => 100,
'status' => 1,
'user_id' => $user_id,
'order_id' => $order_id,
'goods_id' => $item['goods_id'],
'order_goods_id' => $item['order_goods_id'],
'wxapp_id' => self::$wxapp_id
];
}
return $data;
}
/**
* 格式化 formData
* @param string $post
* @return array
*/
private function formatFormData($post)
{
$formJsonData = htmlspecialchars_decode($post);
return helper::arrayColumn2Key(helper::jsonDecode($formJsonData), 'order_goods_id');
}
/**
* 记录评价图片
* @param $commentList
* @param $formData
* @return bool
* @throws \Exception
*/
private function saveAllImages($commentList, $formData)
{
// 生成评价图片数据
$imageData = [];
foreach ($commentList as $comment) {
$item = $formData[$comment['order_goods_id']];
foreach ($item['uploaded'] as $imageId) {
$imageData[] = [
'comment_id' => $comment['comment_id'],
'image_id' => $imageId,
'wxapp_id' => self::$wxapp_id
];
}
}
$model = new CommentImage;
return !empty($imageData) && $model->saveAll($imageData);
}
}

23
source/application/api/model/CommentImage.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\CommentImage as CommentImageModel;
/**
* 商品图片模型
* Class GoodsImage
* @package app\api\model
*/
class CommentImage extends CommentImageModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
];
}

86
source/application/api/model/Coupon.php

@ -1,86 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Coupon as CouponModel;
/**
* 优惠券模型
* Class Coupon
* @package app\api\model
*/
class Coupon extends CouponModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'receive_num',
'is_delete',
'create_time',
'update_time',
];
/**
* 获取优惠券列表
* @param bool $user
* @param null $limit
* @param bool $only_receive
* @return false|\PDOStatement|string|\think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getList($user = false, $limit = null, $only_receive = false)
{
// 构造查询条件
$this->where('is_delete', '=', 0);
// 只显示可领取(未过期,未发完)的优惠券
if ($only_receive) {
$this->where(' IF ( `total_num` > - 1, `receive_num` < `total_num`, 1 = 1 )')
->where('IF ( `expire_type` = 20, (`end_time` + 86400) >= ' . time() . ', 1 = 1 )');
}
// 优惠券列表
$couponList = $this->order(['sort' => 'asc', 'create_time' => 'desc'])->limit($limit)->select();
// 获取用户已领取的优惠券
if ($user !== false) {
$UserCouponModel = new UserCoupon;
$userCouponIds = $UserCouponModel->getUserCouponIds($user['user_id']);
foreach ($couponList as $key => $item) {
$couponList[$key]['is_receive'] = in_array($item['coupon_id'], $userCouponIds);
}
}
return $couponList;
}
/**
* 验证优惠券是否可领取
* @return bool
*/
public function checkReceive()
{
if ($this['total_num'] > -1 && $this['receive_num'] >= $this['total_num']) {
$this->error = '优惠券已发完';
return false;
}
if ($this['expire_type'] == 20 && ($this->getData('end_time') + 86400) < time()) {
$this->error = '优惠券已过期';
return false;
}
return true;
}
/**
* 累计已领取数量
* @return int|true
* @throws \think\Exception
*/
public function setIncReceiveNum()
{
return $this->setInc('receive_num');
}
}

24
source/application/api/model/Delivery.php

@ -1,24 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Delivery as DeliveryModel;
/**
* 配送模板模型
* Class Delivery
* @package app\api\model
*/
class Delivery extends DeliveryModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
'update_time'
];
}

41
source/application/api/model/DeliveryRule.php

@ -1,41 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\DeliveryRule as DeliveryRuleModel;
/**
* 配送模板区域及运费模型
* Class DeliveryRule
* @package app\api\model
*/
class DeliveryRule extends DeliveryRuleModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
'update_time'
];
/**
* 追加字段
* @var array
*/
protected $append = ['region_data'];
/**
* 地区集转为数组格式
* @param $value
* @param $data
* @return array
*/
public function getRegionDataAttr($value, $data)
{
return explode(',', $data['region']);
}
}

26
source/application/api/model/Express.php

@ -1,26 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Express as ExpressModel;
/**
* 物流公司模型
* Class Express
* @package app\api\model
*/
class Express extends ExpressModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'express_code',
'sort',
'wxapp_id',
'create_time',
'update_time'
];
}

37
source/application/api/model/Goods.php

@ -1,37 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Goods as GoodsModel;
/**
* 商品模型
* Class Goods
* @package app\api\model
*/
class Goods extends GoodsModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'sales_initial',
'sales_actual',
'is_delete',
'wxapp_id',
'create_time',
'update_time'
];
/**
* 商品详情:HTML实体转换回普通字符
* @param $value
* @return string
*/
public function getContentAttr($value)
{
return htmlspecialchars_decode($value);
}
}

23
source/application/api/model/GoodsImage.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\GoodsImage as GoodsImageModel;
/**
* 商品图片模型
* Class GoodsImage
* @package app\api\model
*/
class GoodsImage extends GoodsImageModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
];
}

24
source/application/api/model/GoodsSku.php

@ -1,24 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\GoodsSku as GoodsSkuModel;
/**
* 商品规格模型
* Class GoodsSku
* @package app\api\model
*/
class GoodsSku extends GoodsSkuModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
'update_time'
];
}

14
source/application/api/model/GoodsSpecRel.php

@ -1,14 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\GoodsSpecRel as GoodsSpecRelModel;
/**
* 商品规格关系模型
* Class GoodsSpecRel
* @package app\api\model
*/
class GoodsSpecRel extends GoodsSpecRelModel
{
}

637
source/application/api/model/Order.php

@ -1,637 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Order as OrderModel;
use app\api\model\GoodsSku as GoodsSkuModel;
use app\api\model\store\Shop as ShopModel;
use app\api\model\dealer\Order as DealerOrderModel;
use app\api\model\OrderGoods as OrderGoodsModel;
use app\common\service\delivery\Express as ExpressService;
use app\api\service\Payment as PaymentService;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\order\PayStatus as PayStatusEnum;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\enum\DeliveryType as DeliveryTypeEnum;
use app\common\exception\BaseException;
/**
* 订单模型
* Class Order
* @package app\api\model
*/
class Order extends OrderModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'update_time'
];
/**
* 订单确认-立即购买
* @param User $user
* @param int $goods_id 商品id
* @param int $goods_num
* @param int $goods_sku_id
* @param int $delivery 配送方式
* @param int $pay_type 支付方式
* @param int $shop_id 自提门店id
* @return array
* @throws BaseException
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getBuyNow(
$user,
$goods_id,
$goods_num,
$goods_sku_id,
$delivery,
$pay_type,
$shop_id = 0
)
{
// 商品信息
/* @var Goods $goods */
$goods = Goods::detail($goods_id);
// 判断商品是否下架
if (!$goods || $goods['is_delete'] || $goods['goods_status']['value'] != 10) {
throw new BaseException(['msg' => '很抱歉,商品信息不存在或已下架']);
}
// 商品sku信息
$goods['goods_sku'] = $goods->getGoodsSku($goods_sku_id);
// 判断商品库存
if ($goods_num > $goods['goods_sku']['stock_num']) {
$this->setError('很抱歉,商品库存不足');
}
// 返回的数据
$returnData = [];
// 商品单价
$goods['goods_price'] = $goods['goods_sku']['goods_price'];
// 商品总价
$goods['total_num'] = $goods_num;
$goods['total_price'] = $goodsTotalPrice = bcmul($goods['goods_price'], $goods_num, 2);
// 商品详情
$goodsList = [$goods->toArray()];
// 处理配送方式
if ($delivery == DeliveryTypeEnum::EXPRESS) {
$this->orderExpress($returnData, $user, $goodsList, $goodsTotalPrice);
} elseif ($delivery == DeliveryTypeEnum::EXTRACT) {
$shop_id > 0 && $returnData['extract_shop'] = ShopModel::detail($shop_id);
}
// 可用优惠券列表
$couponList = UserCoupon::getUserCouponList($user['user_id'], $goodsTotalPrice);
return array_merge([
'goods_list' => array_values($goodsList), // 商品详情
'order_total_num' => $goods_num, // 商品总数量
'order_total_price' => $goodsTotalPrice, // 商品总金额 (不含运费)
'order_pay_price' => $goodsTotalPrice, // 订单总金额 (含运费)
'delivery' => $delivery, // 配送类型
'coupon_list' => array_values($couponList), // 优惠券列表
'address' => $user['address_default'], // 默认地址
'exist_address' => !$user['address']->isEmpty(), // 是否存在收货地址
'express_price' => '0.00', // 配送费用
'intra_region' => true, // 当前用户收货城市是否存在配送规则中
'extract_shop' => [], // 自提门店信息
'pay_type' => $pay_type, // 支付方式
'has_error' => $this->hasError(),
'error_msg' => $this->getError(),
], $returnData);
}
/**
* 订单配送-快递配送
* @param $returnData
* @param $user
* @param $goodsList
* @param $goodsTotalPrice
*/
private function orderExpress(&$returnData, $user, $goodsList, $goodsTotalPrice)
{
// 当前用户收货城市id
$cityId = $user['address_default'] ? $user['address_default']['city_id'] : null;
// 初始化配送服务类
$ExpressService = new ExpressService(
static::$wxapp_id,
$cityId,
$goodsList,
OrderTypeEnum::MASTER
);
// 获取不支持当前城市配送的商品
$notInRuleGoods = $ExpressService->getNotInRuleGoods();
// 验证商品是否在配送范围
$intraRegion = $returnData['intra_region'] = $notInRuleGoods === false;
if ($intraRegion == false) {
$notInRuleGoodsName = $notInRuleGoods['goods_name'];
$this->setError("很抱歉,您的收货地址不在商品 [{$notInRuleGoodsName}] 的配送范围内");
} else {
// 计算配送金额
$ExpressService->setExpressPrice();
}
// 订单总运费金额
$expressPrice = $returnData['express_price'] = $ExpressService->getTotalFreight();
// 订单总金额 (含运费)
$returnData['order_pay_price'] = bcadd($goodsTotalPrice, $expressPrice, 2);
}
/**
* 创建新订单
* @param \app\api\model\User $user
* @param array $order 订单信息
* @param int $coupon_id 优惠券id
* @param string $remark
* @return bool
* @throws \Exception
*/
public function createOrder(
$user,
$order,
$coupon_id = null,
$remark = '')
{
// 表单验证
if (!$this->validateOrderForm($user, $order)) {
return false;
}
// 创建新的订单信息
$this->transaction(function () use ($order, $user, $coupon_id, $remark) {
// 设置订单优惠券信息
$this->setCouponPrice($order, $coupon_id);
// 记录订单信息
$this->add($user['user_id'], $order, $remark);
// 记录收货地址
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
$this->saveOrderAddress($user['user_id'], $order['address']);
}
// 保存订单商品信息
$this->saveOrderGoods($user['user_id'], $order);
// 更新商品库存 (针对下单减库存的商品)
$this->updateGoodsStockNum($order['goods_list']);
// 获取订单详情
$detail = self::getUserOrderDetail($this['order_id'], $user['user_id']);
// 记录分销商订单
DealerOrderModel::createOrder($detail);
});
// 余额支付标记订单已支付
if ($order['pay_type'] == PayTypeEnum::BALANCE) {
$this->paymentByBalance($this['order_no']);
}
return true;
}
/**
* 构建微信支付请求
* @param \app\api\model\User $user
* @return array
* @throws BaseException
* @throws \think\exception\DbException
*/
public function paymentByWechat($user)
{
return PaymentService::wechat(
$user,
$this['order_id'],
$this['order_no'],
$this['pay_price'],
OrderTypeEnum::MASTER
);
}
/**
* 余额支付标记订单已支付
* @param string $orderNo 订单号
* @return bool
* @throws BaseException
* @throws \think\Exception
* @throws \think\exception\DbException
*/
public function paymentByBalance($orderNo)
{
// 获取订单详情
$model = new \app\task\model\Order;
$order = $model->payDetail($orderNo);
// 发起余额支付
$status = $order->paySuccess(PayTypeEnum::BALANCE);
if (!$status) {
$this->error = $order->error;
}
return $status;
}
/**
* 表单验证 (订单提交)
* @param \app\api\model\User $user 用户信息
* @param array $order 订单信息
* @return bool
*/
private function validateOrderForm($user, &$order)
{
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
if (empty($order['address'])) {
$this->error = '请先选择收货地址';
return false;
}
}
if ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
if (empty($order['extract_shop'])) {
$this->error = '请先选择自提门店';
return false;
}
}
// 余额支付时判断用户余额是否足够
if ($order['pay_type'] == PayTypeEnum::BALANCE) {
if ($user['balance'] < $order['order_pay_price']) {
$this->error = '用户余额不足,无法使用余额支付';
return false;
}
}
return true;
}
/**
* 设置订单优惠券信息
* @param $order
* @param $coupon_id
* @return bool
* @throws BaseException
* @throws \think\exception\DbException
*/
private function setCouponPrice(&$order, $coupon_id)
{
if ($coupon_id > 0 && !empty($order['coupon_list'])) {
// 获取优惠券信息
$couponInfo = [];
foreach ($order['coupon_list'] as $coupon)
$coupon['user_coupon_id'] == $coupon_id && $couponInfo = $coupon;
if (empty($couponInfo)) throw new BaseException(['msg' => '未找到优惠券信息']);
// 计算订单金额 (抵扣后)
$orderTotalPrice = bcsub($order['order_total_price'], $couponInfo['reduced_price'], 2);
$orderTotalPrice <= 0 && $orderTotalPrice = '0.01';
// 记录订单信息
$order['coupon_id'] = $coupon_id;
$order['coupon_price'] = $couponInfo['reduced_price'];
$order['order_pay_price'] = bcadd($orderTotalPrice, $order['express_price'], 2);
// 设置优惠券使用状态
$model = UserCoupon::detail($coupon_id);
$model->setIsUse();
return true;
}
$order['coupon_id'] = 0;
$order['coupon_price'] = 0.00;
return true;
}
/**
* 新增订单记录
* @param $user_id
* @param $order
* @param string $remark
* @return false|int
*/
private function add($user_id, &$order, $remark = '')
{
$data = [
'user_id' => $user_id,
'order_no' => $this->orderNo(),
'total_price' => $order['order_total_price'],
'coupon_id' => $order['coupon_id'],
'coupon_price' => $order['coupon_price'],
'pay_price' => $order['order_pay_price'],
'delivery_type' => $order['delivery'],
'pay_type' => $order['pay_type'],
'buyer_remark' => trim($remark),
'wxapp_id' => self::$wxapp_id,
];
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
$data['express_price'] = $order['express_price'];
} elseif ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
$data['extract_shop_id'] = $order['extract_shop']['shop_id'];
}
return $this->save($data);
}
/**
* 保存订单商品信息
* @param $user_id
* @param $order
* @return int
*/
private function saveOrderGoods($user_id, &$order)
{
// 订单商品列表
$goodsList = [];
// 订单商品实付款金额 (不包含运费)
$realTotalPrice = bcsub($order['order_pay_price'], $order['express_price'], 2);
foreach ($order['goods_list'] as $goods) {
/* @var Goods $goods */
// 计算商品实际付款价
$total_pay_price = $realTotalPrice * $goods['total_price'] / $order['order_total_price'];
$goodsList[] = [
'user_id' => $user_id,
'wxapp_id' => self::$wxapp_id,
'goods_id' => $goods['goods_id'],
'goods_name' => $goods['goods_name'],
'image_id' => $goods['image'][0]['image_id'],
'deduct_stock_type' => $goods['deduct_stock_type'],
'spec_type' => $goods['spec_type'],
'spec_sku_id' => $goods['goods_sku']['spec_sku_id'],
'goods_sku_id' => $goods['goods_sku']['goods_sku_id'],
'goods_attr' => $goods['goods_sku']['goods_attr'],
'content' => $goods['content'],
'goods_no' => $goods['goods_sku']['goods_no'],
'goods_price' => $goods['goods_sku']['goods_price'],
'line_price' => $goods['goods_sku']['line_price'],
'goods_weight' => $goods['goods_sku']['goods_weight'],
'total_num' => $goods['total_num'],
'total_price' => $goods['total_price'],
'total_pay_price' => sprintf('%.2f', $total_pay_price),
'is_ind_dealer' => $goods['is_ind_dealer'],
'dealer_money_type' => $goods['dealer_money_type'],
'first_money' => $goods['first_money'],
'second_money' => $goods['second_money'],
'third_money' => $goods['third_money'],
];
}
return $this->goods()->saveAll($goodsList);
}
/**
* 更新商品库存 (针对下单减库存的商品)
* @param $goods_list
* @throws \Exception
*/
private function updateGoodsStockNum($goods_list)
{
$deductStockData = [];
foreach ($goods_list as $goods) {
// 下单减库存
$goods['deduct_stock_type'] == 10 && $deductStockData[] = [
'goods_sku_id' => $goods['goods_sku']['goods_sku_id'],
'stock_num' => ['dec', $goods['total_num']]
];
}
!empty($deductStockData) && (new GoodsSkuModel)->isUpdate()->saveAll($deductStockData);
}
/**
* 记录收货地址
* @param $user_id
* @param $address
* @return false|\think\Model
*/
private function saveOrderAddress($user_id, $address)
{
if ($address['region_id'] == 0 && !empty($address['district'])) {
$address['detail'] = $address['district'] . ' ' . $address['detail'];
}
return $this->address()->save([
'user_id' => $user_id,
'wxapp_id' => self::$wxapp_id,
'name' => $address['name'],
'phone' => $address['phone'],
'province_id' => $address['province_id'],
'city_id' => $address['city_id'],
'region_id' => $address['region_id'],
'detail' => $address['detail'],
]);
}
/**
* 用户中心订单列表
* @param $user_id
* @param string $type
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList($user_id, $type = 'all')
{
// 筛选条件
$filter = [];
// 订单数据类型
switch ($type) {
case 'all':
break;
case 'payment';
$filter['pay_status'] = PayStatusEnum::PENDING;
$filter['order_status'] = 10;
break;
case 'delivery';
$filter['pay_status'] = PayStatusEnum::SUCCESS;
$filter['delivery_status'] = 10;
$filter['order_status'] = 10;
break;
case 'received';
$filter['pay_status'] = PayStatusEnum::SUCCESS;
$filter['delivery_status'] = 20;
$filter['receipt_status'] = 10;
$filter['order_status'] = 10;
break;
case 'comment';
$filter['is_comment'] = 0;
$filter['order_status'] = 30;
break;
}
return $this->with(['goods.image'])
->where('user_id', '=', $user_id)
->where($filter)
->order(['create_time' => 'desc'])
->paginate(15, false, [
'query' => \request()->request()
]);
}
/**
* 取消订单
* @return bool|false|int
* @throws \Exception
*/
public function cancel()
{
if ($this['delivery_status']['value'] == 20) {
$this->error = '已发货订单不可取消';
return false;
}
$this->transaction(function () {
// 回退商品库存
(new OrderGoodsModel)->backGoodsStock($this['goods']);
// 更新订单状态
$this->save(['order_status' => $this['pay_status']['value'] == PayStatusEnum::SUCCESS ? 21 : 20]);
});
return true;
}
/**
* 确认收货
* @return bool
* @throws \think\exception\PDOException
*/
public function receipt()
{
// 验证订单是否合法
if ($this['delivery_status']['value'] == 10 || $this['receipt_status']['value'] == 20) {
$this->error = '该订单不合法';
return false;
}
$this->startTrans();
try {
// 更新订单状态
$this->save([
'receipt_status' => 20,
'receipt_time' => time(),
'order_status' => 30
]);
// 发放分销商佣金
DealerOrderModel::grantMoney($this, OrderTypeEnum::MASTER);
$this->commit();
return true;
} catch (\Exception $e) {
$this->error = $e->getMessage();
$this->rollback();
return false;
}
}
/**
* 获取订单总数
* @param $user_id
* @param string $type
* @return int|string
* @throws \think\Exception
*/
public function getCount($user_id, $type = 'all')
{
// 筛选条件
$filter = [];
// 订单数据类型
switch ($type) {
case 'all':
break;
case 'payment';
$filter['pay_status'] = PayStatusEnum::PENDING;
break;
case 'received';
$filter['pay_status'] = PayStatusEnum::SUCCESS;
$filter['delivery_status'] = 20;
$filter['receipt_status'] = 10;
break;
case 'comment';
$filter['order_status'] = 30;
$filter['is_comment'] = 0;
break;
}
return $this->where('user_id', '=', $user_id)
->where('order_status', '<>', 20)
->where($filter)
->count();
}
/**
* 订单详情
* @param $order_id
* @param null $user_id
* @return null|static
* @throws BaseException
* @throws \think\exception\DbException
*/
public static function getUserOrderDetail($order_id, $user_id)
{
if (!$order = self::get([
'order_id' => $order_id,
'user_id' => $user_id,
], [
'goods' => ['image', 'sku', 'goods', 'refund'],
'address', 'express', 'extract_shop'
])
) {
throw new BaseException(['msg' => '订单不存在']);
}
return $order;
}
/**
* 判断商品库存不足 (未付款订单)
* @param $goodsList
* @return bool
*/
public function checkGoodsStatusFromOrder(&$goodsList)
{
foreach ($goodsList as $goods) {
// 判断商品是否下架
if (!$goods['goods'] || $goods['goods']['goods_status']['value'] != 10) {
$this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 已下架');
return false;
}
// 付款减库存
if ($goods['deduct_stock_type'] == 20 && $goods['sku']['stock_num'] < 1) {
$this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 库存不足');
return false;
}
}
return true;
}
/**
* 判断当前订单是否允许核销
* @param static $order
* @return bool
*/
public function checkExtractOrder(&$order)
{
if (
$order['pay_status']['value'] == PayStatusEnum::SUCCESS
&& $order['delivery_type']['value'] == DeliveryTypeEnum::EXTRACT
&& $order['delivery_status']['value'] == 10
) {
return true;
}
$this->setError('该订单不能被核销');
return false;
}
/**
* 当前订单是否允许申请售后
* @return bool
*/
public function isAllowRefund()
{
// 允许申请售后期限
$refund_days = Setting::getItem('trade')['order']['refund_days'];
if ($refund_days == 0) {
return false;
}
if (time() > $this['receipt_time'] + ((int)$refund_days * 86400)) {
return false;
}
if ($this['receipt_status']['value'] != 20) {
return false;
}
return true;
}
/**
* 设置错误信息
* @param $error
*/
private function setError($error)
{
empty($this->error) && $this->error = $error;
}
/**
* 是否存在错误
* @return bool
*/
public function hasError()
{
return !empty($this->error);
}
}

23
source/application/api/model/OrderAddress.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\OrderAddress as OrderAddressModel;
/**
* 订单收货地址模型
* Class OrderAddress
* @package app\api\model
*/
class OrderAddress extends OrderAddressModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
];
}

35
source/application/api/model/OrderGoods.php

@ -1,35 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\OrderGoods as OrderGoodsModel;
/**
* 订单商品模型
* Class OrderGoods
* @package app\api\model
*/
class OrderGoods extends OrderGoodsModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'content',
'wxapp_id',
'create_time',
];
/**
* 获取未评价的商品
* @param $order_id
* @return OrderGoods[]|false
* @throws \think\exception\DbException
*/
public static function getNotCommentGoodsList($order_id)
{
return self::all(['order_id' => $order_id, 'is_comment' => 0], ['orderM', 'image']);
}
}

171
source/application/api/model/OrderRefund.php

@ -1,171 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\OrderRefund as OrderRefundModel;
/**
* 售后单模型
* Class OrderRefund
* @package app\api\model
*/
class OrderRefund extends OrderRefundModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'update_time'
];
/**
* 追加字段
* @var array
*/
protected $append = [
'state_text', // 售后单状态文字描述
];
/**
* 售后单状态文字描述
* @param $value
* @param $data
* @return string
*/
public function getStateTextAttr($value, $data)
{
// 已完成
if ($data['status'] == 20) {
$text = [10 => '已同意退货并已退款', 20 => '已同意换货'];
return $text[$data['type']];
}
// 已取消
if ($data['status'] == 30) {
return '已取消';
}
// 已拒绝
if ($data['status'] == 10) {
// return '已拒绝';
return $data['type'] == 10 ? '已拒绝退货退款' : '已拒绝换货';
}
// 进行中
if ($data['status'] == 0) {
if ($data['is_agree'] == 0) {
return '等待审核中';
}
if ($data['type'] == 10) {
return $data['is_user_send'] ? '已发货,待平台确认' : '已同意退货,请及时发货';
}
}
return $value;
}
/**
* 获取用户售后单列表
* @param $user_id
* @param int $state
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList($user_id, $state = -1)
{
$state > -1 && $this->where('status', '=', $state);
return $this->with(['order_master', 'order_goods.image'])
->where('user_id', '=', $user_id)
->order(['create_time' => 'desc'])
->paginate(15, false, [
'query' => \request()->request()
]);
}
/**
* 用户发货
* @param $data
* @return false|int
*/
public function delivery($data)
{
if (
$this['type']['value'] != 10
|| $this['is_agree']['value'] != 10
|| $this['is_user_send'] != 0
) {
$this->error = '当前售后单不合法,不允许该操作';
return false;
}
if ($data['express_id'] <= 0) {
$this->error = '请选择物流公司';
return false;
}
if (empty($data['express_no'])) {
$this->error = '请填写物流单号';
return false;
}
return $this->save([
'is_user_send' => 1,
'send_time' => time(),
'express_id' => (int)$data['express_id'],
'express_no' => $data['express_no'],
]);
}
/**
* 新增售后单记录
* @param $user
* @param $goods
* @param $data
* @return bool
* @throws \Exception
*/
public function apply($user, $goods, $data)
{
$this->startTrans();
try {
// 新增售后单记录
$this->save([
'order_goods_id' => $data['order_goods_id'],
'order_id' => $goods['order_id'],
'user_id' => $user['user_id'],
'type' => $data['type'],
'apply_desc' => $data['content'],
'is_agree' => 0,
'status' => 0,
'wxapp_id' => self::$wxapp_id,
]);
// 记录凭证图片关系
if (isset($data['images']) && !empty($data['images'])) {
$this->saveImages($this['order_refund_id'], $data['images']);
}
$this->commit();
return true;
} catch (\Exception $e) {
$this->error = $e->getMessage();
$this->rollback();
return false;
}
}
/**
* 记录售后单图片
* @param $order_refund_id
* @param $images
* @return bool
* @throws \Exception
*/
private function saveImages($order_refund_id, $images)
{
// 生成评价图片数据
$data = [];
foreach (explode(',', $images) as $image_id) {
$data[] = [
'order_refund_id' => $order_refund_id,
'image_id' => $image_id,
'wxapp_id' => self::$wxapp_id
];
}
return !empty($data) && (new OrderRefundImage)->saveAll($data);
}
}

23
source/application/api/model/OrderRefundAddress.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\OrderRefundAddress as OrderRefundAddressModel;
/**
* 售后单退货地址模型
* Class OrderRefundAddress
* @package app\api\model
*/
class OrderRefundAddress extends OrderRefundAddressModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time'
];
}

15
source/application/api/model/OrderRefundImage.php

@ -1,15 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\OrderRefundImage as OrderRefundImageModel;
/**
* 售后单图片模型
* Class OrderRefundImage
* @package app\api\model
*/
class OrderRefundImage extends OrderRefundImageModel
{
}

37
source/application/api/model/Setting.php

@ -1,37 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Setting as SettingModel;
/**
* 系统设置模型
* Class Setting
* @package app\api\model
*/
class Setting extends SettingModel
{
/**
* 获取积分名称
* @return string
*/
public static function getPointsName()
{
return static::getItem('points')['points_name'];
}
/**
* 获取微信订阅消息设置
*/
public static function getSubmsg()
{
$data = [];
foreach (static::getItem('submsg') as $groupName => $group) {
foreach ($group as $itemName => $item) {
$data[$groupName][$itemName]['template_id'] = $item['template_id'];
}
}
return $data;
}
}

14
source/application/api/model/Spec.php

@ -1,14 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Spec as SpecModel;
/**
* 规格/属性(组)模型
* Class Spec
* @package app\api\model
*/
class Spec extends SpecModel
{
}

14
source/application/api/model/SpecValue.php

@ -1,14 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\SpecValue as SpecValueModel;
/**
* 规格/属性(值)模型
* Class SpecValue
* @package app\api\model
*/
class SpecValue extends SpecValueModel
{
}

23
source/application/api/model/UploadFile.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\UploadFile as UploadFileModel;
/**
* 文件库模型
* Class UploadFile
* @package app\api\model
*/
class UploadFile extends UploadFileModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
];
}

192
source/application/api/model/User.php

@ -1,192 +0,0 @@
<?php
namespace app\api\model;
use think\Cache;
use app\common\library\wechat\WxUser;
use app\common\exception\BaseException;
use app\common\model\User as UserModel;
use app\api\model\dealer\Referee as RefereeModel;
use app\api\model\dealer\Setting as DealerSettingModel;
/**
* 用户模型类
* Class User
* @package app\api\model
*/
class User extends UserModel
{
private $token;
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'open_id',
'is_delete',
'wxapp_id',
'create_time',
'update_time'
];
/**
* 获取用户信息
* @param $token
* @return null|static
* @throws \think\exception\DbException
*/
public static function getUser($token)
{
return self::detail(['open_id' => Cache::get($token)['openid']]);
}
/**
* 用户登录
* @param array $post
* @return string
* @throws BaseException
* @throws \think\Exception
* @throws \think\exception\DbException
*/
public function login($post)
{
// 微信登录 获取session_key
$session = $this->wxlogin($post['code']);
// 自动注册用户
$referee_id = isset($post['referee_id']) ? $post['referee_id'] : null;
$userInfo = json_decode(htmlspecialchars_decode($post['user_info']), true);
$user_id = $this->register($session['openid'], $userInfo, $referee_id);
// 生成token (session3rd)
$this->token = $this->token($session['openid']);
// 记录缓存, 7天
Cache::set($this->token, $session, 86400 * 7);
return $user_id;
}
/**
* 获取token
* @return mixed
*/
public function getToken()
{
return $this->token;
}
/**
* 微信登录
* @param $code
* @return array|mixed
* @throws BaseException
* @throws \think\exception\DbException
*/
private function wxlogin($code)
{
// 获取当前小程序信息
$wxConfig = Wxapp::getWxappCache();
// 微信登录 (获取session_key)
$WxUser = new WxUser($wxConfig['app_id'], $wxConfig['app_secret']);
if (!$session = $WxUser->sessionKey($code))
throw new BaseException(['msg' => 'session_key 获取失败']);
return $session;
}
/**
* 生成用户认证的token
* @param $openid
* @return string
*/
private function token($openid)
{
$wxapp_id = self::$wxapp_id;
// 生成一个不会重复的随机字符串
$guid = \getGuidV4();
// 当前时间戳 (精确到毫秒)
$timeStamp = microtime(true);
// 自定义一个盐
$salt = 'token_salt';
return md5("{$wxapp_id}_{$timeStamp}_{$openid}_{$guid}_{$salt}");
}
/**
* 自动注册用户
* @param $open_id
* @param $data
* @param int $referee_id
* @return mixed
* @throws \Exception
* @throws \think\exception\DbException
*/
private function register($open_id, $data, $referee_id = null)
{
// 查询用户是否已存在
$user = self::detail(['open_id' => $open_id]);
$model = $user ?: $this;
$data['open_id'] = $open_id;
$data['wxapp_id'] = self::$wxapp_id;
// 用户昵称
$data['nickName'] = preg_replace('/[\xf0-\xf7].{3}/', '', $data['nickName']);
try {
$this->startTrans();
// 保存/更新用户记录
if (!$model->allowField(true)->save($data))
throw new BaseException(['msg' => '用户注册失败']);
// 记录推荐人关系
if (!$user && $referee_id > 0)
RefereeModel::createRelation($model['user_id'], $referee_id);
$this->commit();
} catch (\Exception $e) {
$this->rollback();
throw new BaseException(['msg' => $e->getMessage()]);
}
return $model['user_id'];
}
/**
* 个人中心菜单列表
* @return array
*/
public function getMenus()
{
$menus = [
'address' => [
'name' => '收货地址',
'url' => 'pages/address/index',
'icon' => 'map'
],
'coupon' => [
'name' => '领券中心',
'url' => 'pages/coupon/coupon',
'icon' => 'lingquan'
],
'sharing_order' => [
'name' => '拼团订单',
'url' => 'pages/sharing/order/index',
'icon' => 'pintuan'
],
'my_coupon' => [
'name' => '我的优惠券',
'url' => 'pages/user/coupon/coupon',
'icon' => 'youhuiquan'
],
'dealer' => [
'name' => '分销中心',
'url' => 'pages/dealer/index/index',
'icon' => 'fenxiaozhongxin'
],
'help' => [
'name' => '我的帮助',
'url' => 'pages/user/help/index',
'icon' => 'help'
],
];
// 判断分销功能是否开启
if (DealerSettingModel::isOpen()) {
$menus['dealer']['name'] = DealerSettingModel::getDealerTitle();
} else {
unset($menus['dealer']);
}
return $menus;
}
}

132
source/application/api/model/UserAddress.php

@ -1,132 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Region;
use app\common\model\UserAddress as UserAddressModel;
/**
* 用户收货地址模型
* Class UserAddress
* @package app\common\model
*/
class UserAddress extends UserAddressModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
'update_time'
];
/**
* @param $user_id
* @return false|static[]
* @throws \think\exception\DbException
*/
public function getList($user_id)
{
return self::all(compact('user_id'));
}
/**
* 新增收货地址
* @param User $user
* @param $data
* @return bool
* @throws \think\exception\PDOException
*/
public function add($user, $data)
{
// 整理地区信息
$region = explode(',', $data['region']);
$province_id = Region::getIdByName($region[0], 1);
$city_id = Region::getIdByName($region[1], 2, $province_id);
$region_id = Region::getIdByName($region[2], 3, $city_id);
// 添加收货地址
$this->startTrans();
try {
$this->allowField(true)->save([
'name' => $data['name'],
'phone' => $data['phone'],
'province_id' => $province_id,
'city_id' => $city_id,
'region_id' => $region_id,
'detail' => $data['detail'],
'district' => ($region_id === 0 && !empty($region[2])) ? $region[2] : '',
'user_id' => $user['user_id'],
'wxapp_id' => self::$wxapp_id
]);
// 设为默认收货地址
!$user['address_id'] && $user->save(['address_id' => $this['address_id']]);
$this->commit();
return true;
} catch (\Exception $e) {
$this->error = $e->getMessage();
$this->rollback();
return false;
}
}
/**
* 编辑收货地址
* @param $data
* @return false|int
*/
public function edit($data)
{
// 添加收货地址
$region = explode(',', $data['region']);
$province_id = Region::getIdByName($region[0], 1);
$city_id = Region::getIdByName($region[1], 2, $province_id);
$region_id = Region::getIdByName($region[2], 3, $city_id);
return $this->allowField(true)->save([
'name' => $data['name'],
'phone' => $data['phone'],
'province_id' => $province_id,
'city_id' => $city_id,
'region_id' => $region_id,
'detail' => $data['detail'],
'district' => ($region_id === 0 && !empty($region[2])) ? $region[2] : '',
]);
}
/**
* 设为默认收货地址
* @param null|static $user
* @return int
*/
public function setDefault($user)
{
// 设为默认地址
return $user->save(['address_id' => $this['address_id']]);
}
/**
* 删除收货地址
* @param null|static $user
* @return int
*/
public function remove($user)
{
// 查询当前是否为默认地址
$user['address_id'] == $this['address_id'] && $user->save(['address_id' => 0]);
return $this->delete();
}
/**
* 收货地址详情
* @param $user_id
* @param $address_id
* @return null|static
* @throws \think\exception\DbException
*/
public static function detail($user_id, $address_id)
{
return self::get(compact('user_id', 'address_id'));
}
}

197
source/application/api/model/UserCoupon.php

@ -1,197 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\UserCoupon as UserCouponModel;
use think\Db;
/**
* 用户优惠券模型
* Class UserCoupon
* @package app\api\model
*/
class UserCoupon extends UserCouponModel
{
/**
* 获取用户优惠券列表
* @param $user_id
* @param bool $is_use 是否已使用
* @param bool $is_expire 是否已过期
* @return false|\PDOStatement|string|\think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getList($user_id, $is_use = false, $is_expire = false)
{
return $this->where('user_id', '=', $user_id)
->where('is_use', '=', $is_use ? 1 : 0)
->where('is_expire', '=', $is_expire ? 1 : 0)
->select();
}
/**
* 获取用户优惠券总数量(可用)
* @param $user_id
* @return int|string
* @throws \think\Exception
*/
public function getCount($user_id)
{
return $this->where('user_id', '=', $user_id)
->where('is_use', '=', 0)
->where('is_expire', '=', 0)
->count();
}
/**
* 获取用户优惠券ID集
* @param $user_id
* @return array
*/
public function getUserCouponIds($user_id)
{
return $this->where('user_id', '=', $user_id)->column('coupon_id');
}
/**
* 领取优惠券
* @param $user
* @param $coupon_id
* @return bool|false|int
* @throws \think\exception\DbException
*/
public function receive($user, $coupon_id)
{
// 获取优惠券信息
$coupon = Coupon::detail($coupon_id);
// 验证优惠券是否可领取
if (!$this->checkReceive($user, $coupon)) {
return false;
}
// 添加领取记录
return $this->add($user, $coupon);
}
/**
* 添加领取记录
* @param $user
* @param Coupon $coupon
* @return bool
*/
private function add($user, $coupon)
{
// 计算有效期
if ($coupon['expire_type'] == 10) {
$start_time = time();
$end_time = $start_time + ($coupon['expire_day'] * 86400);
} else {
$start_time = $coupon['start_time']['value'];
$end_time = $coupon['end_time']['value'];
}
Db::startTrans();
try {
// 添加领取记录
$this->save([
'coupon_id' => $coupon['coupon_id'],
'name' => $coupon['name'],
'color' => $coupon['color']['value'],
'coupon_type' => $coupon['coupon_type']['value'],
'reduce_price' => $coupon['reduce_price'],
'discount' => $coupon->getData('discount'),
'min_price' => $coupon['min_price'],
'expire_type' => $coupon['expire_type'],
'expire_day' => $coupon['expire_day'],
'start_time' => $start_time,
'end_time' => $end_time,
'apply_range' => $coupon['apply_range'],
'user_id' => $user['user_id'],
'wxapp_id' => self::$wxapp_id
]);
// 更新优惠券领取数量
$coupon->setIncReceiveNum();
Db::commit();
return true;
} catch (\Exception $e) {
$this->error = $e->getMessage();
Db::rollback();
return false;
}
}
/**
* 验证优惠券是否可领取
* @param $user
* @param Coupon $coupon
* @return bool
*/
private function checkReceive($user, $coupon)
{
if (!$coupon) {
$this->error = '优惠券不存在';
return false;
}
if (!$coupon->checkReceive()) {
$this->error = $coupon->getError();
return false;
}
// 验证是否已领取
$userCouponIds = $this->getUserCouponIds($user['user_id']);
if (in_array($coupon['coupon_id'], $userCouponIds)) {
$this->error = '该优惠券已领取';
return false;
}
return true;
}
/**
* 订单结算优惠券列表
* @param $user_id
* @param $orderPayPrice
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function getUserCouponList($user_id, $orderPayPrice)
{
$list = (new self)->getList($user_id);
$data = [];
foreach ($list as $coupon) {
// 最低消费金额
if ($orderPayPrice < $coupon['min_price']) continue;
// 有效期范围内
if ($coupon['start_time']['value'] > time()) continue;
$key = $coupon['user_coupon_id'];
$data[$key] = [
'user_coupon_id' => $coupon['user_coupon_id'],
'name' => $coupon['name'],
'color' => $coupon['color'],
'coupon_type' => $coupon['coupon_type'],
'reduce_price' => $coupon['reduce_price'],
'discount' => $coupon['discount'],
'min_price' => $coupon['min_price'],
'expire_type' => $coupon['expire_type'],
'start_time' => $coupon['start_time'],
'end_time' => $coupon['end_time'],
];
// 计算打折金额
if ($coupon['coupon_type']['value'] == 20) {
$reduce_price = $orderPayPrice * ($coupon['discount'] / 10);
$data[$key]['reduced_price'] = bcsub($orderPayPrice, $reduce_price, 2);
} else
$data[$key]['reduced_price'] = $coupon['reduce_price'];
}
return array_sort($data, 'reduced_price', true);
}
/**
* 设置优惠券为已使用
* @return false|int
*/
public function setIsUse()
{
return $this->save(['is_use' => 1]);
}
}

29
source/application/api/model/Wxapp.php

@ -1,29 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\Wxapp as WxappModel;
/**
* 微信小程序模型
* Class Wxapp
* @package app\api\model
*/
class Wxapp extends WxappModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'app_name',
'app_id',
'app_secret',
'mchid',
'apikey',
'create_time',
'update_time'
];
}

24
source/application/api/model/WxappCategory.php

@ -1,24 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\WxappCategory as WxappCategoryModel;
/**
* 微信小程序分类页模板
* Class WxappCategory
* @package app\api\model
*/
class WxappCategory extends WxappCategoryModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
'update_time'
];
}

22
source/application/api/model/WxappHelp.php

@ -1,22 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\WxappHelp as WxappHelpModel;
/**
* 小程序帮助中心
* Class WxappHelp
* @package app\api\model
*/
class WxappHelp extends WxappHelpModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'create_time',
'update_time',
];
}

24
source/application/api/model/WxappNavbar.php

@ -1,24 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\WxappNavbar as WxappNavbarModel;
/**
* 微信小程序导航栏模型
* Class WxappNavbar
* @package app\api\model
*/
class WxappNavbar extends WxappNavbarModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
'update_time'
];
}

221
source/application/api/model/WxappPage.php

@ -1,221 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\WxappPage as WxappPageModel;
use app\api\model\sharing\Goods as SharingGoodsModel;
use app\api\model\store\Shop as ShopModel;
/**
* 微信小程序diy页面模型
* Class WxappPage
* @package app\api\model
*/
class WxappPage extends WxappPageModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
'update_time'
];
/**
* DIY页面详情
* @param User $user
* @param int $page_id
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public static function getPageData($user, $page_id = null)
{
// 页面详情
$detail = $page_id > 0 ? parent::detail($page_id) : parent::getHomePage();
// 页面diy元素
$items = $detail['page_data']['items'];
// 页面顶部导航
isset($detail['page_data']['page']) && $items['page'] = $detail['page_data']['page'];
// 获取动态数据
$model = new self;
foreach ($items as $key => $item) {
if ($item['type'] === 'window') {
$items[$key]['data'] = array_values($item['data']);
} else if ($item['type'] === 'goods') {
$items[$key]['data'] = $model->getGoodsList($item);
} else if ($item['type'] === 'sharingGoods') {
$items[$key]['data'] = $model->getSharingGoodsList($item);
} else if ($item['type'] === 'coupon') {
$items[$key]['data'] = $model->getCouponList($user, $item);
} else if ($item['type'] === 'article') {
$items[$key]['data'] = $model->getArticleList($item);
} else if ($item['type'] === 'special') {
$items[$key]['data'] = $model->getSpecialList($item);
} else if ($item['type'] === 'shop') {
$items[$key]['data'] = $model->getShopList($item);
}
}
return ['page' => $items['page'], 'items' => $items];
}
/**
* 商品组件:获取商品列表
* @param $item
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function getGoodsList($item)
{
// 获取商品数据
$model = new Goods;
if ($item['params']['source'] === 'choice') {
// 数据来源:手动
$goodsIds = array_column($item['data'], 'goods_id');
$goodsList = $model->getListByIds($goodsIds, 10);
} else {
// 数据来源:自动
$goodsList = $model->getList(10, $item['params']['auto']['category'], '',
$item['params']['auto']['goodsSort'], false, $item['params']['auto']['showNum']);
}
if ($goodsList->isEmpty()) return [];
// 格式化商品列表
$data = [];
foreach ($goodsList as $goods) {
$data[] = [
'goods_id' => $goods['goods_id'],
'goods_name' => $goods['goods_name'],
'selling_point' => $goods['selling_point'],
'image' => $goods['image'][0]['file_path'],
'goods_price' => $goods['sku'][0]['goods_price'],
'line_price' => $goods['sku'][0]['line_price'],
];
}
return $data;
}
/**
* 商品组件:获取拼团商品列表
* @param $item
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function getSharingGoodsList($item)
{
// 获取商品数据
$model = new SharingGoodsModel;
if ($item['params']['source'] === 'choice') {
// 数据来源:手动
$goodsIds = array_column($item['data'], 'goods_id');
$goodsList = $model->getListByIds($goodsIds, 10);
} else {
// 数据来源:自动
$goodsList = $model->getList(10, $item['params']['auto']['category'], '',
$item['params']['auto']['goodsSort'], false, $item['params']['auto']['showNum']);
}
if ($goodsList->isEmpty()) return [];
// 格式化商品列表
$data = [];
foreach ($goodsList as $goods) {
$data[] = [
'goods_id' => $goods['goods_id'],
'goods_name' => $goods['goods_name'],
'selling_point' => $goods['selling_point'],
'people' => $goods['people'],
'goods_sales' => $goods['goods_sales'],
'image' => $goods['image'][0]['file_path'],
'sharing_price' => $goods['sku'][0]['sharing_price'],
'goods_price' => $goods['sku'][0]['goods_price'],
'line_price' => $goods['sku'][0]['line_price'],
];
}
return $data;
}
/**
* 优惠券组件:获取优惠券列表
* @param $user
* @param $item
* @return false|\PDOStatement|string|\think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function getCouponList($user, $item)
{
// 获取优惠券数据
return (new Coupon)->getList($user, $item['params']['limit'], true);
}
/**
* 文章组件:获取文章列表
* @param $item
* @return array
* @throws \think\exception\DbException
*/
private function getArticleList($item)
{
// 获取文章数据
$model = new Article;
$articleList = $model->getList($item['params']['auto']['category'], $item['params']['auto']['showNum']);
return $articleList->isEmpty() ? [] : $articleList->toArray()['data'];
}
/**
* 头条快报:获取头条列表
* @param $item
* @return array
* @throws \think\exception\DbException
*/
private function getSpecialList($item)
{
// 获取头条数据
$model = new Article;
$articleList = $model->getList($item['params']['auto']['category'], $item['params']['auto']['showNum']);
return $articleList->isEmpty() ? [] : $articleList->toArray()['data'];
}
/**
* 线下门店组件:获取门店列表
* @param $item
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function getShopList($item)
{
// 获取商品数据
$model = new ShopModel;
if ($item['params']['source'] === 'choice') {
// 数据来源:手动
$shopIds = array_column($item['data'], 'shop_id');
$shopList = $model->getListByIds($shopIds);
} else {
// 数据来源:自动
$shopList = $model->getList(null, false, false, $item['params']['auto']['showNum']);
}
if ($shopList->isEmpty()) return [];
// 格式化商品列表
$data = [];
foreach ($shopList as $shop) {
$data[] = [
'shop_id' => $shop['shop_id'],
'shop_name' => $shop['shop_name'],
'logo_image' => $shop['logo']['file_path'],
'phone' => $shop['phone'],
'region' => $shop['region'],
'address' => $shop['address'],
];
}
return $data;
}
}

37
source/application/api/model/WxappPrepayId.php

@ -1,37 +0,0 @@
<?php
namespace app\api\model;
use app\common\model\WxappPrepayId as WxappPrepayIdModel;
use app\common\enum\OrderType as OrderTypeEnum;
/**
* 小程序prepay_id模型
* Class WxappPrepayId
* @package app\api\model
*/
class WxappPrepayId extends WxappPrepayIdModel
{
/**
* 新增记录
* @param $prepayId
* @param $orderId
* @param $userId
* @param int $orderType
* @return false|int
*/
public function add($prepayId, $orderId, $userId, $orderType = OrderTypeEnum::MASTER)
{
return $this->save([
'prepay_id' => $prepayId,
'order_id' => $orderId,
'order_type' => $orderType,
'user_id' => $userId,
'can_use_times' => 0,
'used_times' => 0,
'expiry_time' => time() + (7 * 86400),
'wxapp_id' => self::$wxapp_id,
]);
}
}

76
source/application/api/model/article/Category.php

@ -1,76 +0,0 @@
<?php
namespace app\api\model\article;
use think\Cache;
use app\store\model\Article as ArticleModel;
use app\common\model\article\Category as CategoryModel;
/**
* 文章分类模型
* Class Category
* @package app\api\model\article
*/
class Category extends CategoryModel
{
/**
* 分类详情
* @param $category_id
* @return Category|null
* @throws \think\exception\DbException
*/
public static function detail($category_id)
{
return static::get($category_id);
}
/**
* 添加新记录
* @param $data
* @return false|int
*/
public function add($data)
{
$data['wxapp_id'] = self::$wxapp_id;
$this->deleteCache();
return $this->allowField(true)->save($data);
}
/**
* 编辑记录
* @param $data
* @return bool|int
*/
public function edit($data)
{
$this->deleteCache();
return $this->allowField(true)->save($data);
}
/**
* 删除商品分类
* @param $category_id
* @return bool|int
*/
public function remove($category_id)
{
// 判断是否存在文章
$articleCount = ArticleModel::getArticleTotal(['category_id' => $category_id]);
if ($articleCount > 0) {
$this->error = '该分类下存在' . $articleCount . '个文章,不允许删除';
return false;
}
$this->deleteCache();
return $this->delete();
}
/**
* 删除缓存
* @return bool
*/
private function deleteCache()
{
return Cache::rm('article_category_' . self::$wxapp_id);
}
}

185
source/application/api/model/bargain/Active.php

@ -1,185 +0,0 @@
<?php
namespace app\api\model\bargain;
use app\common\model\bargain\Active as ActiveModel;
use app\api\model\bargain\Task as TaskModel;
use app\api\model\bargain\TaskHelp as TaskHelpModel;
use app\common\service\Goods as GoodsService;
/**
* 砍价活动模型
* Class Active
* @package app\api\model\bargain
*/
class Active extends ActiveModel
{
/**
* 隐藏的字段
* @var array
*/
protected $hidden = [
'peoples',
'is_self_cut',
'initial_sales',
'actual_sales',
'sort',
'create_time',
'update_time',
'wxapp_id',
'is_delete',
];
/**
* 获取器:分享标题
* @param $value
* @return mixed
*/
public function getShareTitleAttr($value)
{
return htmlspecialchars_decode($value);
}
/**
* 获取器:砍价助力语
* @param $value
* @return mixed
*/
public function getPromptWordsAttr($value)
{
return htmlspecialchars_decode($value);
}
/**
* 活动会场列表
* @param array $param
* @return mixed|\think\Paginator
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getHallList($param = [])
{
return $this->getList($param);
}
/**
* 获取砍价活动列表(根据活动id集)
* @param $activeIds
* @param array $param
* @return mixed|\think\Paginator
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getListByIds($activeIds, $param = [])
{
$this->where('active_id', 'in', $activeIds);
return $this->getList($param);
}
/**
* 获取砍价活动列表
* @param $param
* @return mixed|\think\Paginator
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function getList($param)
{
// 商品列表获取条件
$params = array_merge([
'status' => 1, // 商品状态
'sortType' => 'all', // 排序类型
'sortPrice' => false, // 价格排序 高低
'listRows' => 15, // 每页数量
], $param);
// 排序规则
if ($params['sortType'] === 'all') {
$this->order(['sort' => 'asc', $this->getPk() => 'desc']);
} elseif ($params['sortType'] === 'sales') {
$this->order(['active_sales' => 'desc']);
} elseif ($params['sortType'] === 'price') {
$this->order(['floor_price' => $params['sortPrice'] ? 'desc' : 'asc']);
}
// 砍价活动列表
$list = $this->field(['*', '(actual_sales + initial_sales) as active_sales'])
->where('start_time', '<=', time())
->where('end_time', '>=', time())
->where('status', '=', 1)
->where('is_delete', '=', 0)
->order(['sort' => 'asc', $this->getPk() => 'desc'])
->paginate($params['listRows'], false, [
'query' => \request()->request()
]);
// 设置商品数据
$list = GoodsService::setGoodsData($list);
// 整理正在砍价的助力信息
$list = $this->setHelpsData($list);
return $list;
}
/**
* 整理正在砍价的助力信息
* @param $list
* @return mixed
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function setHelpsData($list)
{
$model = new TaskHelpModel;
foreach ($list as &$item) {
$item['helps'] = $model->getHelpListByActiveId($item['active_id']);
$item['helps_count'] = $model->getHelpCountByActiveId($item['active_id']);
}
return $list;
}
/**
* 获取砍价活动详情
* @param $activeId
* @return Active|bool|null
* @throws \think\exception\DbException
*/
public function getDetail($activeId)
{
$model = static::detail($activeId);
if (empty($model) || $model['is_delete'] == true || $model['status'] == false) {
$this->error = '很抱歉,该砍价商品不存在或已下架';
return false;
}
return $model;
}
/**
* 获取用户是否正在参与改砍价活动,如果已参与则返回task_id
* @param $activeId
* @param bool $user
* @return bool|int
*/
public function getWhetherPartake($activeId, $user = false)
{
if ($user === false) {
return false;
}
return TaskModel::getHandByUser($activeId, $user['user_id']);
}
/**
* 累计活动销量(实际)
* @return int|true
* @throws \think\Exception
*/
public function setIncSales()
{
return $this->setInc('actual_sales');
}
}

102
source/application/api/model/dealer/Apply.php

@ -1,102 +0,0 @@
<?php
namespace app\api\model\dealer;
use app\common\model\dealer\Apply as ApplyModel;
/**
* 分销商申请模型
* Class Apply
* @package app\api\model\dealer
*/
class Apply extends ApplyModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'create_time',
'update_time',
];
/**
* 是否为分销商申请中
* @param $user_id
* @return bool
* @throws \think\exception\DbException
*/
public static function isApplying($user_id)
{
$detail = self::detail(['user_id' => $user_id]);
return $detail ? ((int)$detail['apply_status'] === 10) : false;
}
/**
* 提交申请
* @param $user
* @param $name
* @param $mobile
* @return bool
* @throws \think\exception\DbException
* @throws \think\exception\PDOException
*/
public function submit($user, $name, $mobile)
{
// 成为分销商条件
$config = Setting::getItem('condition');
// 数据整理
$data = [
'user_id' => $user['user_id'],
'real_name' => trim($name),
'mobile' => trim($mobile),
'referee_id' => Referee::getRefereeUserId($user['user_id'], 1),
'apply_type' => $config['become'],
'apply_time' => time(),
'wxapp_id' => self::$wxapp_id,
];
if ($config['become'] == 10) {
$data['apply_status'] = 10;
} elseif ($config['become'] == 20) {
$data['apply_status'] = 20;
}
return $this->add($user, $data);
}
/**
* 更新分销商申请信息
* @param $user
* @param $data
* @return bool
* @throws \think\exception\DbException
* @throws \think\exception\PDOException
*/
private function add($user, $data)
{
// 实例化模型
$model = self::detail(['user_id' => $user['user_id']]) ?: $this;
// 更新记录
$this->startTrans();
try {
// $data['create_time'] = time();
// 保存申请信息
$model->save($data);
// 无需审核,自动通过
if ($data['apply_type'] == 20) {
// 新增分销商用户记录
User::add($user['user_id'], [
'real_name' => $data['real_name'],
'mobile' => $data['mobile'],
'referee_id' => $data['referee_id']
]);
}
$this->commit();
return true;
} catch (\Exception $e) {
$this->error = $e->getMessage();
$this->rollback();
return false;
}
}
}

23
source/application/api/model/dealer/Capital.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model\dealer;
use app\common\model\dealer\Capital as CapitalModel;
/**
* 分销商资金明细模型
* Class Apply
* @package app\api\model\dealer
*/
class Capital extends CapitalModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'create_time',
'update_time',
];
}

116
source/application/api/model/dealer/Order.php

@ -1,116 +0,0 @@
<?php
namespace app\api\model\dealer;
use app\common\model\dealer\Order as OrderModel;
use app\common\service\Order as OrderService;
/**
* 分销商订单模型
* Class Apply
* @package app\api\model\dealer
*/
class Order extends OrderModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'update_time',
];
/**
* 获取分销商订单列表
* @param $user_id
* @param int $is_settled
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList($user_id, $is_settled = -1)
{
$is_settled > -1 && $this->where('is_settled', '=', !!$is_settled);
$data = $this->with(['user'])
->where('first_user_id|second_user_id|third_user_id', '=', $user_id)
->order(['create_time' => 'desc'])
->paginate(15, false, [
'query' => \request()->request()
]);
if ($data->isEmpty()) {
return $data;
}
// 整理订单信息
$with = ['goods' => ['image', 'refund'], 'address', 'user'];
return OrderService::getOrderList($data, 'order_master', $with);
}
/**
* 创建分销商订单记录
* @param $order
* @param int $order_type 订单类型 (10商城订单 20拼团订单)
* @return bool|false|int
* @throws \think\exception\DbException
*/
public static function createOrder(&$order, $order_type = 10)
{
// 分销订单模型
$model = new self;
// 分销商基本设置
$setting = Setting::getItem('basic');
// 是否开启分销功能
if (!$setting['is_open']) {
return false;
}
// 获取当前买家的所有上级分销商用户id
$dealerUser = $model->getDealerUserId($order['user_id'], $setting['level'], $setting['self_buy']);
// 非分销订单
if (!$dealerUser['first_user_id']) {
return false;
}
// 计算订单分销佣金
$capital = $model->getCapitalByOrder($order);
// 保存分销订单记录
return $model->save([
'user_id' => $order['user_id'],
'order_id' => $order['order_id'],
'order_type' => $order_type,
// 'order_no' => $order['order_no'], // 废弃
'order_price' => $capital['orderPrice'],
'first_money' => max($capital['first_money'], 0),
'second_money' => max($capital['second_money'], 0),
'third_money' => max($capital['third_money'], 0),
'first_user_id' => $dealerUser['first_user_id'],
'second_user_id' => $dealerUser['second_user_id'],
'third_user_id' => $dealerUser['third_user_id'],
'is_settled' => 0,
'wxapp_id' => $model::$wxapp_id
]);
}
/**
* 获取当前买家的所有上级分销商用户id
* @param $user_id
* @param $level
* @param $self_buy
* @return mixed
* @throws \think\exception\DbException
*/
private function getDealerUserId($user_id, $level, $self_buy)
{
$dealerUser = [
'first_user_id' => $level >= 1 ? Referee::getRefereeUserId($user_id, 1, true) : 0,
'second_user_id' => $level >= 2 ? Referee::getRefereeUserId($user_id, 2, true) : 0,
'third_user_id' => $level == 3 ? Referee::getRefereeUserId($user_id, 3, true) : 0
];
// 分销商自购
if ($self_buy && User::isDealerUser($user_id)) {
return [
'first_user_id' => $user_id,
'second_user_id' => $dealerUser['first_user_id'],
'third_user_id' => $dealerUser['second_user_id'],
];
}
return $dealerUser;
}
}

100
source/application/api/model/dealer/Referee.php

@ -1,100 +0,0 @@
<?php
namespace app\api\model\dealer;
use app\common\model\dealer\Referee as RefereeModel;
/**
* 分销商推荐关系模型
* Class Apply
* @package app\api\model\dealer
*/
class Referee extends RefereeModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [];
/**
* 创建推荐关系
* @param $user_id
* @param $referee_id
* @return bool
* @throws \think\Exception
* @throws \think\exception\DbException
*/
public static function createRelation($user_id, $referee_id)
{
// 分销商基本设置
$setting = Setting::getItem('basic');
// 是否开启分销功能
if (!$setting['is_open']) {
return false;
}
// 自分享
if ($user_id == $referee_id) {
return false;
}
// # 记录一级推荐关系
// 判断当前用户是否已存在推荐关系
if (self::isExistReferee($user_id)) {
return false;
}
// 判断推荐人是否为分销商
if (!User::isDealerUser($referee_id)) {
return false;
}
// 新增关系记录
$model = new self;
$model->add($referee_id, $user_id, 1);
// # 记录二级推荐关系
if ($setting['level'] >= 2) {
// 二级分销商id
$referee_2_id = self::getRefereeUserId($referee_id, 1, true);
// 新增关系记录
$referee_2_id > 0 && $model->add($referee_2_id, $user_id, 2);
}
// # 记录三级推荐关系
if ($setting['level'] == 3) {
// 三级分销商id
$referee_3_id = self::getRefereeUserId($referee_id, 2, true);
// 新增关系记录
$referee_3_id > 0 && $model->add($referee_3_id, $user_id, 3);
}
return true;
}
/**
* 新增关系记录
* @param $dealer_id
* @param $user_id
* @param int $level
* @return bool
* @throws \think\Exception
* @throws \think\exception\DbException
*/
private function add($dealer_id, $user_id, $level = 1)
{
// 新增推荐关系
$wxapp_id = self::$wxapp_id;
$create_time = time();
$this->insert(compact('dealer_id', 'user_id', 'level', 'wxapp_id', 'create_time'));
// 记录分销商成员数量
User::setMemberInc($dealer_id, $level);
return true;
}
/**
* 是否已存在推荐关系
* @param $user_id
* @return bool
* @throws \think\exception\DbException
*/
private static function isExistReferee($user_id)
{
return !!self::get(['user_id' => $user_id]);
}
}

22
source/application/api/model/dealer/Setting.php

@ -1,22 +0,0 @@
<?php
namespace app\api\model\dealer;
use app\common\model\dealer\Setting as SettingModel;
/**
* 分销商设置模型
* Class Setting
* @package app\api\model\dealer
*/
class Setting extends SettingModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'update_time',
];
}

51
source/application/api/model/dealer/User.php

@ -1,51 +0,0 @@
<?php
namespace app\api\model\dealer;
use app\common\model\dealer\User as UserModel;
/**
* 分销商用户模型
* Class User
* @package app\api\model\dealer
*/
class User extends UserModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'create_time',
'update_time',
];
/**
* 资金冻结
* @param $money
* @return false|int
*/
public function freezeMoney($money)
{
return $this->save([
'money' => $this['money'] - $money,
'freeze_money' => $this['freeze_money'] + $money,
]);
}
/**
* 累计分销商成员数量
* @param $dealer_id
* @param $level
* @return int|true
* @throws \think\Exception
* @throws \think\exception\DbException
*/
public static function setMemberInc($dealer_id, $level)
{
$fields = [1 => 'first_num', 2 => 'second_num', 3 => 'third_num'];
$model = static::detail($dealer_id);
return $model->setInc($fields[$level]);
}
}

99
source/application/api/model/dealer/Withdraw.php

@ -1,99 +0,0 @@
<?php
namespace app\api\model\dealer;
use app\common\exception\BaseException;
use app\common\model\dealer\Withdraw as WithdrawModel;
/**
* 分销商提现明细模型
* Class Withdraw
* @package app\api\model\dealer
*/
class Withdraw extends WithdrawModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'update_time',
];
/**
* 获取分销商提现明细
* @param $user_id
* @param int $apply_status
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList($user_id, $apply_status = -1)
{
$this->where('user_id', '=', $user_id);
$apply_status > -1 && $this->where('apply_status', '=', $apply_status);
return $this->order(['create_time' => 'desc'])
->paginate(15, false, [
'query' => \request()->request()
]);
}
/**
* 提交申请
* @param User $dealer
* @param $data
* @return false|int
* @throws BaseException
*/
public function submit($dealer, $data)
{
// 数据验证
$this->validation($dealer, $data);
// 新增申请记录
$this->save(array_merge($data, [
'user_id' => $dealer['user_id'],
'apply_status' => 10,
'wxapp_id' => self::$wxapp_id,
]));
// 冻结用户资金
$dealer->freezeMoney($data['money']);
return true;
}
/**
* 数据验证
* @param $dealer
* @param $data
* @throws BaseException
*/
private function validation($dealer, $data)
{
// 结算设置
$settlement = Setting::getItem('settlement');
// 最低提现佣金
if ($data['money'] <= 0) {
throw new BaseException(['msg' => '提现金额不正确']);
}
if ($dealer['money'] <= 0) {
throw new BaseException(['msg' => '当前用户没有可提现佣金']);
}
if ($data['money'] > $dealer['money']) {
throw new BaseException(['msg' => '提现金额不能大于可提现佣金']);
}
if ($data['money'] < $settlement['min_money']) {
throw new BaseException(['msg' => '最低提现金额为' . $settlement['min_money']]);
}
if (!in_array($data['pay_type'], $settlement['pay_type'])) {
throw new BaseException(['msg' => '提现方式不正确']);
}
if ($data['pay_type'] == '20') {
if (empty($data['alipay_name']) || empty($data['alipay_account'])) {
throw new BaseException(['msg' => '请补全提现信息']);
}
} elseif ($data['pay_type'] == '30') {
if (empty($data['bank_name']) || empty($data['bank_account']) || empty($data['bank_card'])) {
throw new BaseException(['msg' => '请补全提现信息']);
}
}
}
}

193
source/application/api/model/recharge/Order.php

@ -1,193 +0,0 @@
<?php
namespace app\api\model\recharge;
use app\common\model\recharge\Order as OrderModel;
use app\api\model\Setting as SettingModel;
use app\api\model\recharge\Plan as PlanModel;
use app\api\model\recharge\OrderPlan as OrderPlanModel;
use app\common\service\Order as OrderService;
use app\common\enum\recharge\order\PayStatus as PayStatusEnum;
use app\common\enum\recharge\order\RechargeType as RechargeTypeEnum;
use app\common\exception\BaseException;
/**
* 用户充值订单模型
* Class Order
* @package app\api\model\recharge
*/
class Order extends OrderModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
];
/**
* 获取订单列表
* @param $userId
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList($userId)
{
// 获取列表数据
return $this->where('user_id', '=', $userId)
->where('pay_status', '=', PayStatusEnum::SUCCESS)
->order(['create_time' => 'desc'])
->paginate(15, false, [
'query' => request()->request()
]);
}
/**
* 创建充值订单
* @param \app\api\model\User $user 当前用户信息
* @param int $planId 套餐id
* @param double $customMoney 自定义充值金额
* @return bool|false|int
* @throws BaseException
* @throws \think\exception\DbException
*/
public function createOrder($user, $planId = null, $customMoney = 0.00)
{
// 确定充值方式
$rechargeType = $planId > 0 ? RechargeTypeEnum::PLAN : RechargeTypeEnum::CUSTOM;
// 验证用户输入
if (!$this->validateForm($rechargeType, $planId, $customMoney)) {
$this->error = $this->error ?: '数据验证错误';
return false;
}
// 获取订单数据
$data = $this->getOrderData($user, $rechargeType, $planId, $customMoney);
// 记录订单信息
return $this->saveOrder($data);
}
/**
* 保存订单记录
* @param $data
* @return bool|false|int
*/
private function saveOrder($data)
{
// 写入订单记录
$this->save($data['order']);
// 记录订单套餐快照
if (!empty($data['plan'])) {
$PlanModel = new OrderPlanModel;
return $PlanModel->add($this['order_id'], $data['plan']);
}
return true;
}
/**
* 生成充值订单
* @param $user
* @param $rechargeType
* @param $planId
* @param $customMoney
* @return array
* @throws BaseException
* @throws \think\exception\DbException
*/
private function getOrderData($user, $rechargeType, $planId, $customMoney)
{
// 订单信息
$data = [
'order' => [
'user_id' => $user['user_id'],
'order_no' => 'RC' . OrderService::createOrderNo(),
'recharge_type' => $rechargeType,
'wxapp_id' => self::$wxapp_id,
],
'plan' => [] // 订单套餐快照
];
// 自定义金额充值
if ($rechargeType == RechargeTypeEnum::CUSTOM) {
$this->createDataByCustom($data, $customMoney);
}
// 套餐充值
if ($rechargeType == RechargeTypeEnum::PLAN) {
$this->createDataByPlan($data, $planId);
}
// 实际到账金额
$data['order']['actual_money'] = bcadd($data['order']['pay_price'], $data['order']['gift_money'], 2);
return $data;
}
/**
* 创建套餐充值订单数据
* @param $order
* @param $planId
* @return bool
* @throws BaseException
* @throws \think\exception\DbException
*/
private function createDataByPlan(&$order, $planId)
{
// 获取套餐详情
$planInfo = PlanModel::detail($planId);
if (empty($planInfo)) {
throw new BaseException(['msg' => '充值套餐不存在']);
}
$order['plan'] = $planInfo;
$order['order']['plan_id'] = $planInfo['plan_id'];
$order['order']['gift_money'] = $planInfo['gift_money'];
$order['order']['pay_price'] = $planInfo['money'];
return true;
}
/**
* 创建自定义充值订单数据
* @param $order
* @param $customMoney
* @return bool
*/
private function createDataByCustom(&$order, $customMoney)
{
// 用户支付金额
$order['order']['pay_price'] = $customMoney;
// 充值设置
$setting = SettingModel::getItem('recharge');
if ($setting['is_custom'] == false) {
return true;
}
// 根据自定义充值金额匹配满足的套餐
$PlanModel = new PlanModel;
$matchPlanInfo = $PlanModel->getMatchPlan($customMoney);
if (!empty($matchPlanInfo)) {
$order['plan'] = $matchPlanInfo;
$order['order']['plan_id'] = $matchPlanInfo['plan_id'];
$order['order']['gift_money'] = $matchPlanInfo['gift_money'];
}
return true;
}
/**
* 表单验证
* @param $rechargeType
* @param $planId
* @param $customMoney
* @return bool
*/
private function validateForm($rechargeType, $planId, $customMoney)
{
if (empty($planId) && $customMoney <= 0) {
$this->error = '请选择充值套餐或输入充值金额';
return false;
}
// 验证自定义的金额
if ($rechargeType == RechargeTypeEnum::CUSTOM && $customMoney <= 0) {
$this->error = '请选择充值套餐或输入充值金额';
return false;
}
return true;
}
}

32
source/application/api/model/recharge/OrderPlan.php

@ -1,32 +0,0 @@
<?php
namespace app\api\model\recharge;
use app\common\model\recharge\OrderPlan as OrderPlanModel;
/**
* 用户充值订单套餐快照模型
* Class OrderPlan
* @package app\api\model\recharge
*/
class OrderPlan extends OrderPlanModel
{
/**
* 新增记录
* @param $orderId
* @param $data
* @return false|int
*/
public function add($orderId, $data)
{
return $this->save([
'order_id' => $orderId,
'plan_id' => $data['plan_id'],
'plan_name' => $data['plan_name'],
'money' => $data['money'],
'gift_money' => $data['gift_money'],
'wxapp_id' => self::$wxapp_id
]);
}
}

73
source/application/api/model/recharge/Plan.php

@ -1,73 +0,0 @@
<?php
namespace app\api\model\recharge;
use app\common\model\recharge\Plan as PlanModel;
/**
* 用户充值订单模型
* Class Plan
* @package app\api\model\recharge
*/
class Plan extends PlanModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'is_delete',
'wxapp_id',
'create_time',
'update_time',
];
/**
* 获取器:充值金额
* @param $value
* @return int
*/
public function getMoneyAttr($value)
{
return ($value == $intValue = (int)$value) ? $intValue : $value;
}
/**
* 获取器:赠送金额
* @param $value
* @return int
*/
public function getGiftMoneyAttr($value)
{
return ($value == $intValue = (int)$value) ? $intValue : $value;
}
/**
* 获取可用的充值套餐列表
* @return false|\PDOStatement|string|\think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getList()
{
// 获取列表数据
return $this->where('is_delete', '=', 0)
->order(['sort' => 'asc', 'money' => 'desc', 'create_time' => 'desc'])
->select();
}
/**
* 根据自定义充值金额匹配满足的套餐
* @param $payPrice
* @return array|false|\PDOStatement|string|\think\Model
*/
public function getMatchPlan($payPrice)
{
return (new static)->where('money', '<=', $payPrice)
->where('is_delete', '=', 0)
->order(['money' => 'desc'])
->find();
}
}

50
source/application/api/model/sharing/Active.php

@ -1,50 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\exception\BaseException;
use app\common\model\sharing\Active as ActiveModel;
/**
* 拼团拼单模型
* Class Active
* @package app\api\model\sharing
*/
class Active extends ActiveModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
'update_time'
];
/**
* 新增拼单记录
* @param $data
* @return false|int
*/
public function add($data)
{
return $this->save($data);
}
/**
* 根据商品id获取进行中的拼单列表
* @param $goods_id
* @param int $limit
* @return false|\PDOStatement|string|\think\Collection
*/
public static function getActivityListByGoods($goods_id, $limit = 15)
{
return (new static)->with(['user'])
->where('goods_id', '=', $goods_id)
->where('status', '=', 10)
->limit($limit)
->select();
}
}

23
source/application/api/model/sharing/ActiveUsers.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\ActiveUsers as ActiveUsersModel;
/**
* 拼团拼单成员模型
* Class ActiveUsers
* @package app\api\model\sharing
*/
class ActiveUsers extends ActiveUsersModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
];
}

23
source/application/api/model/sharing/Category.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\Category as CategoryModel;
/**
* 拼团商品分类模型
* Class Category
* @package app\common\model\sharing
*/
class Category extends CategoryModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'update_time'
];
}

235
source/application/api/model/sharing/Comment.php

@ -1,235 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\exception\BaseException;
use app\common\model\sharing\Comment as CommentModel;
/**
* 拼团商品评价模型
* Class Comment
* @package app\api\model\sharing
*/
class Comment extends CommentModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'status',
'sort',
'order_id',
'goods_id',
'order_goods_id',
'is_delete',
'update_time'
];
/**
* 关联用户表
* @return \think\model\relation\BelongsTo
*/
public function user()
{
$module = self::getCalledModule() ?: 'common';
return $this->belongsTo("app\\{$module}\\model\\User")
->field(['user_id', 'nickName', 'avatarUrl']);
}
/**
* 获取指定商品评价列表
* @param $goods_id
* @param int $scoreType
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getGoodsCommentList($goods_id, $scoreType = -1)
{
// 筛选条件
$filter = [
'goods_id' => $goods_id,
'is_delete' => 0,
'status' => 1,
];
// 评分
$scoreType > 0 && $filter['score'] = $scoreType;
return $this->with(['user', 'OrderGoods', 'image.file'])
->where($filter)
->order(['sort' => 'asc', 'create_time' => 'desc'])
->paginate(15, false, [
'query' => request()->request()
]);
}
/**
* 获取指定评分总数
* @param $goods_id
* @return array|false|\PDOStatement|string|\think\Model
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getTotal($goods_id)
{
return $this->field([
'count(comment_id) AS `all`',
'count(score = 10 OR NULL) AS `praise`',
'count(score = 20 OR NULL) AS `review`',
'count(score = 30 OR NULL) AS `negative`',
])->where([
'goods_id' => $goods_id,
'is_delete' => 0,
'status' => 1
])->find();
}
/**
* 验证订单是否允许评价
* @param Order $order
* @return boolean
*/
public function checkOrderAllowComment($order)
{
// 验证订单是否已完成
if ($order['order_status']['value'] != 30) {
$this->error = '该订单未完成,无法评价';
return false;
}
// 验证订单是否已评价
if ($order['is_comment'] == 1) {
$this->error = '该订单已完成评价';
return false;
}
return true;
}
/**
* 根据已完成订单商品 添加评价
* @param Order $order
* @param \think\Collection|OrderGoods $goodsList
* @param $formJsonData
* @return boolean
* @throws \Exception
*/
public function addForOrder($order, $goodsList, $formJsonData)
{
// 生成 formData
$formData = $this->formatFormData($formJsonData);
// 生成评价数据
$data = $this->createCommentData($order['user_id'], $order['order_id'], $goodsList, $formData);
if (empty($data)) {
$this->error = '没有输入评价内容';
return false;
}
// 开启事务
$this->startTrans();
try {
// 记录评价内容
$result = $this->isUpdate(false)->saveAll($data);
// 记录评价图片
$this->saveAllImages($result, $formData);
// 更新订单评价状态
$isComment = count($goodsList) === count($data);
$this->updateOrderIsComment($order, $isComment, $result);
$this->commit();
return true;
} catch (\Exception $e) {
$this->rollback();
$this->error = $e->getMessage();
return false;
}
}
/**
* 更新订单评价状态
* @param Order $order
* @param $isComment
* @param $commentList
* @return array|false
* @throws \Exception
*/
private function updateOrderIsComment($order, $isComment, &$commentList)
{
// 更新订单商品
$orderGoodsData = [];
foreach ($commentList as $comment) {
$orderGoodsData[] = [
'order_goods_id' => $comment['order_goods_id'],
'is_comment' => 1
];
}
// 更新订单
$isComment && $order->save(['is_comment' => 1]);
return (new OrderGoods)->saveAll($orderGoodsData);
}
/**
* 生成评价数据
* @param $user_id
* @param $order_id
* @param $goodsList
* @param $formData
* @return array
* @throws BaseException
*/
private function createCommentData($user_id, $order_id, &$goodsList, &$formData)
{
$data = [];
foreach ($goodsList as $goods) {
if (!isset($formData[$goods['order_goods_id']])) {
throw new BaseException(['msg' => '提交的数据不合法']);
}
$item = $formData[$goods['order_goods_id']];
!empty($item['content']) && $data[$goods['order_goods_id']] = [
'score' => $item['score'],
'content' => $item['content'],
'is_picture' => !empty($item['uploaded']),
'sort' => 100,
'status' => 1,
'user_id' => $user_id,
'order_id' => $order_id,
'goods_id' => $item['goods_id'],
'order_goods_id' => $item['order_goods_id'],
'wxapp_id' => self::$wxapp_id
];
}
return $data;
}
/**
* 格式化 formData
* @param string $formJsonData
* @return array
*/
private function formatFormData($formJsonData)
{
return array_column(json_decode($formJsonData, true), null, 'order_goods_id');
}
/**
* 记录评价图片
* @param $commentList
* @param $formData
* @return bool
* @throws \Exception
*/
private function saveAllImages(&$commentList, &$formData)
{
// 生成评价图片数据
$imageData = [];
foreach ($commentList as $comment) {
$item = $formData[$comment['order_goods_id']];
foreach ($item['uploaded'] as $imageId) {
$imageData[] = [
'comment_id' => $comment['comment_id'],
'image_id' => $imageId,
'wxapp_id' => self::$wxapp_id
];
}
}
$model = new CommentImage;
return !empty($imageData) && $model->saveAll($imageData);
}
}

23
source/application/api/model/sharing/CommentImage.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\CommentImage as CommentImageModel;
/**
* 拼团商品图片模型
* Class GoodsImage
* @package app\api\model\sharing
*/
class CommentImage extends CommentImageModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
];
}

60
source/application/api/model/sharing/Goods.php

@ -1,60 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\Goods as GoodsModel;
/**
* 拼团商品模型
* Class Goods
* @package app\api\model\sharing
*/
class Goods extends GoodsModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'sales_initial',
'sales_actual',
'is_delete',
'wxapp_id',
'create_time',
'update_time'
];
/**
* 商品详情:HTML实体转换回普通字符
* @param $value
* @return string
*/
public function getContentAttr($value)
{
return htmlspecialchars_decode($value);
}
/**
* 根据商品id集获取商品列表
* @param $goodsIds
* @param null $status
* @return false|\PDOStatement|string|\think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getListByIds($goodsIds, $status = null)
{
// 筛选条件
$filter = ['goods_id' => ['in', $goodsIds]];
$status > 0 && $filter['goods_status'] = $status;
if (!empty($goodsIds)) {
$this->orderRaw('field(goods_id, ' . implode(',', $goodsIds) . ')');
}
// 获取商品列表数据
return $this->with(['category', 'image.file', 'sku', 'spec_rel.spec', 'delivery.rule'])
->where($filter)
->select();
}
}

23
source/application/api/model/sharing/GoodsImage.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\GoodsImage as GoodsImageModel;
/**
* 拼团商品图片模型
* Class GoodsImage
* @package app\api\model\sharing
*/
class GoodsImage extends GoodsImageModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
];
}

24
source/application/api/model/sharing/GoodsSku.php

@ -1,24 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\GoodsSku as GoodsSkuModel;
/**
* 拼团商品规格模型
* Class GoodsSku
* @package app\api\model\sharing
*/
class GoodsSku extends GoodsSkuModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
'update_time'
];
}

14
source/application/api/model/sharing/GoodsSpecRel.php

@ -1,14 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\GoodsSpecRel as GoodsSpecRelModel;
/**
* 拼团商品规格关系模型
* Class GoodsSpecRel
* @package app\api\model\sharing
*/
class GoodsSpecRel extends GoodsSpecRelModel
{
}

709
source/application/api/model/sharing/Order.php

@ -1,709 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\Order as OrderModel;
use app\api\model\Setting as SettingModel;
use app\api\model\store\Shop as ShopModel;
use app\api\model\UserCoupon as UserCouponModel;
use app\api\model\dealer\Order as DealerOrderModel;
use app\api\model\GoodsSku as GoodsSkuModel;
use app\api\model\sharing\Goods as GoodsModel;
use app\api\model\sharing\Setting as SharingSettingModel;
use app\api\model\sharing\OrderGoods as OrderGoodsModel;
use app\api\service\Payment as PaymentService;
use app\common\enum\order\PayStatus as PayStatusEnum;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\DeliveryType as DeliveryTypeEnum;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\service\delivery\Express as ExpressService;
use app\common\exception\BaseException;
/**
* 拼团订单模型
* Class Order
* @package app\api\model
*/
class Order extends OrderModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'update_time'
];
/**
* 订单确认
* @param \app\api\model\User $user
* @param int $order_type 订单类型 (10单独购买 20拼团)
* @param int $goods_id 商品id
* @param int $goods_num
* @param int $goods_sku_id
* @param int $delivery 配送方式
* @param int $pay_type 支付方式
* @param int $shop_id 自提门店id
* @return array
* @throws BaseException
* @throws \think\exception\DbException
* @throws \think\Exception
*/
public function getBuyNow(
$user,
$order_type,
$goods_id,
$goods_num,
$goods_sku_id,
$delivery,
$pay_type,
$shop_id = 0
)
{
// 商品信息
/* @var GoodsModel $goods */
$goods = GoodsModel::detail($goods_id);
// 判断商品是否下架
if (!$goods || $goods['is_delete'] || $goods['goods_status']['value'] != 10) {
throw new BaseException(['msg' => '很抱歉,商品信息不存在或已下架']);
}
// 商品sku信息
$goods['goods_sku'] = $goods->getGoodsSku($goods_sku_id);
// 判断商品库存
if ($goods_num > $goods['goods_sku']['stock_num']) {
$this->setError('很抱歉,商品库存不足');
}
// 返回的数据
$returnData = [];
// 商品单价 (根据order_type判断单买还是拼单)
// order_type:下单类型 10=>单独购买 20=>拼团
$goods['goods_price'] = $order_type == 10 ? $goods['goods_sku']['goods_price']
: $goods['goods_sku']['sharing_price'];
// 商品总价
$goods['total_num'] = $goods_num;
$goods['total_price'] = $goodsTotalPrice = bcmul($goods['goods_price'], $goods_num, 2);
// 商品详情
$goodsList = [$goods->toArray()];
// 处理配送方式
if ($delivery == DeliveryTypeEnum::EXPRESS) {
$this->orderExpress($returnData, $user, $goodsList, $goodsTotalPrice);
} elseif ($delivery == DeliveryTypeEnum::EXTRACT) {
$shop_id > 0 && $returnData['extract_shop'] = ShopModel::detail($shop_id);
}
// 可用优惠券列表
if (SharingSettingModel::getItem('basic')['is_coupon']) {
$returnData['coupon_list'] = UserCouponModel::getUserCouponList($user['user_id'], $goodsTotalPrice);
}
return array_merge([
'order_type' => $order_type, // 订单类型
'goods_list' => array_values($goodsList), // 商品详情
'order_total_num' => $goods_num, // 商品总数量
'order_total_price' => $goodsTotalPrice, // 商品总金额 (不含运费)
'order_pay_price' => $goodsTotalPrice, // 订单总金额 (含运费)
'delivery' => $delivery, // 配送类型
'coupon_list' => [], // 优惠券列表
'address' => $user['address_default'], // 默认地址
'exist_address' => !$user['address']->isEmpty(), // 是否存在收货地址
'express_price' => '0.00', // 配送费用
'intra_region' => true, // 当前用户收货城市是否存在配送规则中
'extract_shop' => [], // 自提门店信息
'pay_type' => $pay_type, // 支付方式
'has_error' => $this->hasError(),
'error_msg' => $this->getError(),
], $returnData);
}
/**
* 订单配送-快递配送
* @param $returnData
* @param $user
* @param $goodsList
* @param $goodsTotalPrice
*/
private function orderExpress(&$returnData, $user, $goodsList, $goodsTotalPrice)
{
// 当前用户收货城市id
$cityId = $user['address_default'] ? $user['address_default']['city_id'] : null;
// 初始化配送服务类
$ExpressService = new ExpressService(
static::$wxapp_id,
$cityId,
$goodsList,
OrderTypeEnum::SHARING
);
// 获取不支持当前城市配送的商品
$notInRuleGoods = $ExpressService->getNotInRuleGoods();
// 验证商品是否在配送范围
$intraRegion = $returnData['intra_region'] = $notInRuleGoods === false;
if ($intraRegion == false) {
$notInRuleGoodsName = $notInRuleGoods['goods_name'];
$this->setError("很抱歉,您的收货地址不在商品 [{$notInRuleGoodsName}] 的配送范围内");
} else {
// 计算配送金额
$ExpressService->setExpressPrice();
}
// 订单总运费金额
$expressPrice = $returnData['express_price'] = $ExpressService->getTotalFreight();
// 订单总金额 (含运费)
$returnData['order_pay_price'] = bcadd($goodsTotalPrice, $expressPrice, 2);
}
/**
* 创建新订单
* @param \app\api\model\User $user
* @param array $order 订单内容
* @param int $active_id 拼单id
* @param int $coupon_id 用户优惠券id
* @param string $remark 买家留言
* @return bool
* @throws \think\exception\DbException
*/
public function createOrder(
$user,
$order,
$active_id = null,
$coupon_id = null,
$remark = ''
)
{
// 如果是参与拼单,则记录拼单id
$order['active_id'] = $active_id > 0 ? $active_id : 0;
// 表单验证
if (!$this->validateOrderForm($user, $order)) {
return false;
}
$this->transaction(function () use ($order, $user, $coupon_id, $remark) {
// 设置订单优惠券信息
$this->setCouponPrice($order, $coupon_id);
// 记录订单信息
$this->add($user['user_id'], $order, $remark);
// 记录收货地址
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
$this->saveOrderAddress($user['user_id'], $order['address']);
}
// 保存订单商品信息
$this->saveOrderGoods($user['user_id'], $order);
// 更新商品库存 (针对下单减库存的商品)
$this->updateGoodsStockNum($order['goods_list']);
// 获取订单详情
$detail = self::getUserOrderDetail($this['order_id'], $user['user_id']);
// 记录分销商订单
if (SharingSettingModel::getItem('basic')['is_dealer']) {
DealerOrderModel::createOrder($detail, OrderTypeEnum::SHARING);
}
// 余额支付标记订单已支付
if ($order['pay_type'] == PayTypeEnum::BALANCE) {
$this->paymentByBalance($this['order_no']);
}
});
return true;
}
/**
* 构建微信支付请求
* @param \app\api\model\User $user
* @return array
* @throws BaseException
* @throws \think\exception\DbException
*/
public function paymentByWechat($user)
{
return PaymentService::wechat(
$user,
$this['order_id'],
$this['order_no'],
$this['pay_price'],
OrderTypeEnum::SHARING
);
}
/**
* 余额支付标记订单已支付
* @param string $orderNo 订单号
* @return bool
* @throws BaseException
* @throws \think\Exception
* @throws \think\exception\DbException
*/
public function paymentByBalance($orderNo)
{
// 获取订单详情
$model = new \app\task\model\sharing\Order;
$order = $model->payDetail($orderNo);
// 发起余额支付
$status = $order->paySuccess(PayTypeEnum::BALANCE);
if (!$status) {
$this->error = $order->error;
}
return $status;
}
/**
* 表单验证 (订单提交)
* @param \app\api\model\User $user 用户信息
* @param array $order 订单信息
* @return bool
* @throws \think\exception\DbException
*/
private function validateOrderForm($user, &$order)
{
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
if (empty($order['address'])) {
$this->error = '请先选择收货地址';
return false;
}
}
if ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
if (empty($order['extract_shop'])) {
$this->error = '请先选择自提门店';
return false;
}
}
// 余额支付时判断用户余额是否足够
if ($order['pay_type'] == PayTypeEnum::BALANCE) {
if ($user['balance'] < $order['order_pay_price']) {
$this->error = '用户余额不足,无法使用余额支付';
return false;
}
}
// 验证拼单id是否合法
if ($order['active_id'] > 0) {
// 拼单详情
$detail = Active::detail($order['active_id']);
if (empty($detail)) {
$this->error = '很抱歉,拼单不存在';
return false;
}
// 验证当前拼单是否允许加入新成员
if (!$detail->checkAllowJoin()) {
$this->error = $detail->getError();
return false;
}
}
return true;
}
/**
* 验证拼单是否允许加入
* @param $active_id
* @return bool
* @throws BaseException
* @throws \think\exception\DbException
*/
public function checkActiveIsAllowJoin($active_id)
{
// 拼单详情
$detail = Active::detail($active_id);
if (!$detail) {
throw new BaseException('很抱歉,拼单不存在');
}
// 验证当前拼单是否允许加入新成员
return $detail->checkAllowJoin();
}
/**
* 设置订单优惠券信息
* @param $order
* @param $coupon_id
* @return bool
* @throws BaseException
* @throws \think\exception\DbException
*/
private function setCouponPrice(&$order, $coupon_id)
{
if ($coupon_id > 0 && !empty($order['coupon_list'])) {
// 获取优惠券信息
$couponInfo = [];
foreach ($order['coupon_list'] as $coupon)
$coupon['user_coupon_id'] == $coupon_id && $couponInfo = $coupon;
if (empty($couponInfo)) throw new BaseException(['msg' => '未找到优惠券信息']);
// 计算订单金额 (抵扣后)
$orderTotalPrice = bcsub($order['order_total_price'], $couponInfo['reduced_price'], 2);
$orderTotalPrice <= 0 && $orderTotalPrice = '0.01';
// 记录订单信息
$order['coupon_id'] = $coupon_id;
$order['coupon_price'] = $couponInfo['reduced_price'];
$order['order_pay_price'] = bcadd($orderTotalPrice, $order['express_price'], 2);
// 设置优惠券使用状态
$model = UserCouponModel::detail($coupon_id);
$model->setIsUse();
return true;
}
$order['coupon_id'] = 0;
$order['coupon_price'] = 0.00;
return true;
}
/**
* 新增订单记录
* @param $user_id
* @param $order
* @param string $remark
* @return false|int
*/
private function add($user_id, &$order, $remark = '')
{
$data = [
'user_id' => $user_id,
'order_type' => $order['order_type'],
'active_id' => $order['active_id'],
'order_no' => $this->orderNo(),
'total_price' => $order['order_total_price'],
'coupon_id' => $order['coupon_id'],
'coupon_price' => $order['coupon_price'],
'pay_price' => $order['order_pay_price'],
'delivery_type' => $order['delivery'],
'pay_type' => $order['pay_type'],
'buyer_remark' => trim($remark),
'wxapp_id' => self::$wxapp_id,
];
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
$data['express_price'] = $order['express_price'];
} elseif ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
$data['extract_shop_id'] = $order['extract_shop']['shop_id'];
}
return $this->save($data);
}
/**
* 保存订单商品信息
* @param $user_id
* @param $order
* @return int
*/
private function saveOrderGoods($user_id, &$order)
{
// 订单商品列表
$goodsList = [];
// 订单商品实付款金额 (不包含运费)
$realTotalPrice = bcsub($order['order_pay_price'], $order['express_price'], 2);
foreach ($order['goods_list'] as $goods) {
/* @var Goods $goods */
// 计算商品实际付款价
$total_pay_price = $realTotalPrice * $goods['total_price'] / $order['order_total_price'];
$goodsList[] = [
'user_id' => $user_id,
'wxapp_id' => self::$wxapp_id,
'goods_id' => $goods['goods_id'],
'goods_name' => $goods['goods_name'],
'image_id' => $goods['image'][0]['image_id'],
'selling_point' => $goods['selling_point'],
'people' => $goods['people'],
'group_time' => $goods['group_time'],
'is_alone' => $goods['is_alone'],
'deduct_stock_type' => $goods['deduct_stock_type'],
'spec_type' => $goods['spec_type'],
'spec_sku_id' => $goods['goods_sku']['spec_sku_id'],
'goods_sku_id' => $goods['goods_sku']['goods_sku_id'],
'goods_attr' => $goods['goods_sku']['goods_attr'],
'content' => $goods['content'],
'goods_no' => $goods['goods_sku']['goods_no'],
'goods_price' => $goods['goods_sku']['goods_price'],
'line_price' => $goods['goods_sku']['line_price'],
'goods_weight' => $goods['goods_sku']['goods_weight'],
'total_num' => $goods['total_num'],
'total_price' => $goods['total_price'],
'total_pay_price' => sprintf('%.2f', $total_pay_price),
'is_ind_dealer' => $goods['is_ind_dealer'],
'dealer_money_type' => $goods['dealer_money_type'],
'first_money' => $goods['first_money'],
'second_money' => $goods['second_money'],
'third_money' => $goods['third_money'],
];
}
return $this->goods()->saveAll($goodsList);
}
/**
* 更新商品库存 (针对下单减库存的商品)
* @param $goods_list
* @throws \Exception
*/
private function updateGoodsStockNum($goods_list)
{
$deductStockData = [];
foreach ($goods_list as $goods) {
// 下单减库存
$goods['deduct_stock_type'] == 10 && $deductStockData[] = [
'goods_sku_id' => $goods['goods_sku']['goods_sku_id'],
'stock_num' => ['dec', $goods['total_num']]
];
}
!empty($deductStockData) && (new GoodsSkuModel)->isUpdate()->saveAll($deductStockData);
}
/**
* 记录收货地址
* @param $user_id
* @param $address
* @return false|\think\Model
*/
private function saveOrderAddress($user_id, $address)
{
if ($address['region_id'] == 0 && !empty($address['district'])) {
$address['detail'] = $address['district'] . ' ' . $address['detail'];
}
return $this->address()->save([
'user_id' => $user_id,
'wxapp_id' => self::$wxapp_id,
'name' => $address['name'],
'phone' => $address['phone'],
'province_id' => $address['province_id'],
'city_id' => $address['city_id'],
'region_id' => $address['region_id'],
'detail' => $address['detail'],
]);
}
/**
* 用户拼团订单列表
* @param $user_id
* @param string $type
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList($user_id, $type = 'all')
{
// 筛选条件
$filter = [];
// 订单数据类型
switch ($type) {
case 'all':
// 全部
break;
case 'payment';
// 待支付
$filter['pay_status'] = PayStatusEnum::PENDING;
break;
case 'sharing';
// 拼团中
$filter['active.status'] = 10;
break;
case 'delivery';
// 待发货
$this->where('IF ( (`order`.`order_type` = 20), (`active`.`status` = 20), TRUE)');
$filter['pay_status'] = 20;
$filter['delivery_status'] = 10;
break;
case 'received';
// 待收货
$filter['pay_status'] = 20;
$filter['delivery_status'] = 20;
$filter['receipt_status'] = 10;
break;
case 'comment';
$filter['order_status'] = 30;
$filter['is_comment'] = 0;
break;
}
return $this->with(['goods.image', 'active'])
->alias('order')
->field('order.*, active.status as active_status')
->join('sharing_active active', 'order.active_id = active.active_id', 'LEFT')
->where('user_id', '=', $user_id)
->where($filter)
->order(['create_time' => 'desc'])
->paginate(15, false, [
'query' => \request()->request()
]);
}
/**
* 取消订单
* @return bool|false|int
*/
public function cancel()
{
if ($this['delivery_status']['value'] == 20) {
$this->error = '已发货订单不可取消';
return false;
}
if ($this['order_type']['value'] == 20) {
$this->error = '拼团订单不允许取消';
return false;
}
$this->transaction(function () {
// 回退商品库存
(new OrderGoodsModel)->backGoodsStock($this['goods']);
// 更新订单状态
$this->save(['order_status' => $this['pay_status']['value'] == PayStatusEnum::SUCCESS ? 21 : 20]);
});
return true;
}
/**
* 确认收货
* @return bool
* @throws \think\exception\PDOException
*/
public function receipt()
{
// 验证订单是否合法
if ($this['delivery_status']['value'] == 10 || $this['receipt_status']['value'] == 20) {
$this->error = '该订单不合法';
return false;
}
$this->startTrans();
try {
// 更新订单状态
$this->save([
'receipt_status' => 20,
'receipt_time' => time(),
'order_status' => 30
]);
// 发放分销商佣金
DealerOrderModel::grantMoney($this, OrderTypeEnum::SHARING);
$this->commit();
return true;
} catch (\Exception $e) {
$this->error = $e->getMessage();
$this->rollback();
return false;
}
}
/**
* 获取订单总数
* @param $user_id
* @param string $type
* @return int|string
* @throws \think\Exception
*/
public function getCount($user_id, $type = 'all')
{
// 筛选条件
$filter = [];
// 订单数据类型
switch ($type) {
case 'all':
break;
case 'payment';
$filter['pay_status'] = PayStatusEnum::PENDING;
break;
case 'received';
$filter['pay_status'] = PayStatusEnum::SUCCESS;
$filter['delivery_status'] = 20;
$filter['receipt_status'] = 10;
break;
case 'comment';
$filter['order_status'] = 30;
$filter['is_comment'] = 0;
break;
}
return $this->where('user_id', '=', $user_id)
->where('order_status', '<>', 20)
->where($filter)
->count();
}
/**
* 订单详情
* @param $order_id
* @param $user_id
* @return array|false|\PDOStatement|string|\think\Model|static
* @throws BaseException
*/
public static function getUserOrderDetail($order_id, $user_id)
{
$order = (new static)->with(['goods' => ['image', 'refund'], 'address', 'express', 'extract_shop'])
->alias('order')
->field('order.*, active.status as active_status')
->join('sharing_active active', 'order.active_id = active.active_id', 'LEFT')
->where([
'order_id' => $order_id,
'user_id' => $user_id,
// 'order_status' => ['<>', 20]
])->find();
if (!$order) {
throw new BaseException(['msg' => '订单不存在']);
}
return $order;
}
/**
* 判断商品库存不足 (未付款订单)
* @param $goodsList
* @return bool
*/
public function checkGoodsStatusFromOrder(&$goodsList)
{
foreach ($goodsList as $goods) {
// 判断商品是否下架
if (!$goods['goods'] || $goods['goods']['goods_status']['value'] != 10) {
$this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 已下架');
return false;
}
// 付款减库存
if ($goods['deduct_stock_type'] == 20 && $goods['sku']['stock_num'] < 1) {
$this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 库存不足');
return false;
}
}
return true;
}
/**
* 当前订单是否允许申请售后
* @return bool
*/
public function isAllowRefund()
{
// 允许申请售后期限
$refund_days = SettingModel::getItem('trade')['order']['refund_days'];
if ($refund_days == 0) {
return false;
}
if (time() > $this['receipt_time'] + ((int)$refund_days * 86400)) {
return false;
}
if ($this['receipt_status']['value'] != 20) {
return false;
}
return true;
}
/**
* 判断当前订单是否允许核销
* @param static $order
* @return bool
*/
public function checkExtractOrder(&$order)
{
if (
$order['pay_status']['value'] == PayStatusEnum::SUCCESS
&& $order['delivery_type']['value'] == DeliveryTypeEnum::EXTRACT
&& $order['delivery_status']['value'] == 10
// 拼团订单验证拼单状态
&& ($order['order_type']['value'] == 20 ? $order['active']['status']['value'] == 20 : true)
) {
return true;
}
$this->setError('该订单不能被核销');
return false;
}
/**
* 设置错误信息
* @param $error
*/
private function setError($error)
{
empty($this->error) && $this->error = $error;
}
/**
* 是否存在错误
* @return bool
*/
public function hasError()
{
return !empty($this->error);
}
}

23
source/application/api/model/sharing/OrderAddress.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\OrderAddress as OrderAddressModel;
/**
* 拼团订单收货地址模型
* Class OrderAddress
* @package app\api\model
*/
class OrderAddress extends OrderAddressModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time',
];
}

35
source/application/api/model/sharing/OrderGoods.php

@ -1,35 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\OrderGoods as OrderGoodsModel;
/**
* 拼团订单商品模型
* Class OrderGoods
* @package app\api\model
*/
class OrderGoods extends OrderGoodsModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'content',
'wxapp_id',
'create_time',
];
/**
* 获取未评价的商品
* @param $order_id
* @return OrderGoods[]|false
* @throws \think\exception\DbException
*/
public static function getNotCommentGoodsList($order_id)
{
return self::all(['order_id' => $order_id, 'is_comment' => 0], ['orderM', 'image']);
}
}

171
source/application/api/model/sharing/OrderRefund.php

@ -1,171 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\OrderRefund as OrderRefundModel;
/**
* 售后单模型
* Class OrderRefund
* @package app\api\model\sharing
*/
class OrderRefund extends OrderRefundModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'update_time'
];
/**
* 追加字段
* @var array
*/
protected $append = [
'state_text', // 售后单状态文字描述
];
/**
* 售后单状态文字描述
* @param $value
* @param $data
* @return string
*/
public function getStateTextAttr($value, $data)
{
// 已完成
if ($data['status'] == 20) {
$text = [10 => '已同意退货并已退款', 20 => '已同意换货'];
return $text[$data['type']];
}
// 已取消
if ($data['status'] == 30) {
return '已取消';
}
// 已拒绝
if ($data['status'] == 10) {
// return '已拒绝';
return $data['type'] == 10 ? '已拒绝退货退款' : '已拒绝换货';
}
// 进行中
if ($data['status'] == 0) {
if ($data['is_agree'] == 0) {
return '等待审核中';
}
if ($data['type'] == 10) {
return $data['is_user_send'] ? '已发货,待平台确认' : '已同意退货,请及时发货';
}
}
return $value;
}
/**
* 获取用户售后单列表
* @param $user_id
* @param int $state
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList($user_id, $state = -1)
{
$state > -1 && $this->where('status', '=', $state);
return $this->with(['order_goods.image'])
->where('user_id', '=', $user_id)
->order(['create_time' => 'desc'])
->paginate(15, false, [
'query' => \request()->request()
]);
}
/**
* 用户发货
* @param $data
* @return false|int
*/
public function delivery($data)
{
if (
$this['type']['value'] != 10
|| $this['is_agree']['value'] != 10
|| $this['is_user_send'] != 0
) {
$this->error = '当前售后单不合法,不允许该操作';
return false;
}
if ($data['express_id'] <= 0) {
$this->error = '请选择物流公司';
return false;
}
if (empty($data['express_no'])) {
$this->error = '请填写物流单号';
return false;
}
return $this->save([
'is_user_send' => 1,
'send_time' => time(),
'express_id' => (int)$data['express_id'],
'express_no' => $data['express_no'],
]);
}
/**
* 新增售后单记录
* @param $user
* @param $goods
* @param $data
* @return bool
* @throws \Exception
*/
public function apply($user, $goods, $data)
{
$this->startTrans();
try {
// 新增售后单记录
$this->save([
'order_goods_id' => $data['order_goods_id'],
'order_id' => $goods['order_id'],
'user_id' => $user['user_id'],
'type' => $data['type'],
'apply_desc' => $data['content'],
'is_agree' => 0,
'status' => 0,
'wxapp_id' => self::$wxapp_id,
]);
// 记录凭证图片关系
if (isset($data['images']) && !empty($data['images'])) {
$this->saveImages($this['order_refund_id'], $data['images']);
}
$this->commit();
return true;
} catch (\Exception $e) {
$this->error = $e->getMessage();
$this->rollback();
return false;
}
}
/**
* 记录售后单图片
* @param $order_refund_id
* @param $images
* @return bool
* @throws \Exception
*/
private function saveImages($order_refund_id, $images)
{
// 生成评价图片数据
$data = [];
foreach (explode(',', $images) as $image_id) {
$data[] = [
'order_refund_id' => $order_refund_id,
'image_id' => $image_id,
'wxapp_id' => self::$wxapp_id
];
}
return !empty($data) && (new OrderRefundImage)->saveAll($data);
}
}

23
source/application/api/model/sharing/OrderRefundAddress.php

@ -1,23 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\OrderRefundAddress as OrderRefundAddressModel;
/**
* 售后单退货地址模型
* Class OrderRefundAddress
* @package app\api\model\sharing
*/
class OrderRefundAddress extends OrderRefundAddressModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
'create_time'
];
}

15
source/application/api/model/sharing/OrderRefundImage.php

@ -1,15 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\common\model\sharing\OrderRefundImage as OrderRefundImageModel;
/**
* 售后单图片模型
* Class OrderRefundImage
* @package app\api\model\sharing
*/
class OrderRefundImage extends OrderRefundImageModel
{
}

38
source/application/api/model/sharing/Setting.php

@ -1,38 +0,0 @@
<?php
namespace app\api\model\sharing;
use app\api\model\Setting as SettingModel;
use app\common\model\sharing\Setting as SharingSettingModel;
/**
* 拼团设置模型
* Class Setting
* @package app\api\model\sharing
*/
class Setting extends SharingSettingModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'update_time',
];
public static function getSetting()
{
// 订阅消息
$submsgList = [];
foreach (SettingModel::getItem('submsg')['sharing'] as $key => $item) {
$submsgList[$key] = $item['template_id'];
}
return [
// 基础设置
'basic' => static::getItem('basic'),
// 订阅消息
'order_submsg' => $submsgList,
];
}
}

131
source/application/api/model/store/Shop.php

@ -1,131 +0,0 @@
<?php
namespace app\api\model\store;
use app\common\model\store\Shop as ShopModel;
/**
* 商家门店模型
* Class Shop
* @package app\store\model\store
*/
class Shop extends ShopModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'is_delete',
'wxapp_id',
'create_time',
'update_time'
];
/**
* 获取门店列表
* @param null $is_check
* @param string $longitude
* @param string $latitude
* @param bool $limit
* @return array|false|\PDOStatement|string|\think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getList($is_check = null, $longitude = '', $latitude = '', $limit = false)
{
// 是否支持自提核销
$is_check && $this->where('is_check', '=', $is_check);
// 获取数量
$limit != false && $this->limit($limit);
// 获取门店列表数据
$data = $this->where('is_delete', '=', '0')
->where('status', '=', '1')
->order(['sort' => 'asc', 'create_time' => 'desc'])
->select();
// 根据距离排序
if (!empty($longitude) && !empty($latitude)) {
return $this->sortByDistance($data, $longitude, $latitude);
}
return $data;
}
/**
* 根据距离排序
* @param string $longitude
* @param string $latitude
* @param \think\Collection|false|\PDOStatement|string $data
* @return array
* @throws
*/
private function sortByDistance(&$data, $longitude, $latitude)
{
// 根据距离排序
$list = $data->isEmpty() ? [] : $data->toArray();
$sortArr = [];
foreach ($list as &$shop) {
// 计算距离
$distance = self::getDistance($longitude, $latitude, $shop['longitude'], $shop['latitude']);
// 排序列
$sortArr[] = $distance;
$shop['distance'] = $distance;
if ($distance >= 1000) {
$distance = bcdiv($distance, 1000, 2);
$shop['distance_unit'] = $distance . 'km';
} else
$shop['distance_unit'] = $distance . 'm';
}
// 根据距离排序
array_multisort($sortArr, SORT_ASC, $list);
return $list;
}
/**
* 获取两个坐标点的距离
* @param $ulon
* @param $ulat
* @param $slon
* @param $slat
* @return float
*/
private static function getDistance($ulon, $ulat, $slon, $slat)
{
// 地球半径
$R = 6378137;
// 将角度转为狐度
$radLat1 = deg2rad($ulat);
$radLat2 = deg2rad($slat);
$radLng1 = deg2rad($ulon);
$radLng2 = deg2rad($slon);
// 结果
$s = acos(cos($radLat1) * cos($radLat2) * cos($radLng1 - $radLng2) + sin($radLat1) * sin($radLat2)) * $R;
// 精度
$s = round($s * 10000) / 10000;
return round($s);
}
/**
* 根据门店id集获取门店列表
* @param $shopIds
* @return false|\PDOStatement|string|\think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getListByIds($shopIds)
{
// 筛选条件
$filter = ['shop_id' => ['in', $shopIds]];
if (!empty($shopIds)) {
$this->orderRaw('field(shop_id, ' . implode(',', $shopIds) . ')');
}
// 获取商品列表数据
return $this->with(['logo'])
->where('is_delete', '=', '0')
->where('status', '=', '1')
->where($filter)
->select();
}
}

65
source/application/api/model/store/shop/Clerk.php

@ -1,65 +0,0 @@
<?php
namespace app\api\model\store\shop;
use app\common\exception\BaseException;
use app\common\model\store\shop\Clerk as ClerkModel;
/**
* 商家门店店员模型
* Class Clerk
* @package app\api\model\store\shop
*/
class Clerk extends ClerkModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'is_delete',
'wxapp_id',
'create_time',
'update_time'
];
/**
* 店员详情
* @param $where
* @return static
* @throws BaseException
* @throws \think\exception\DbException
*/
public static function detail($where)
{
/* @var static $model */
$model = parent::detail($where);
if (!$model) {
throw new BaseException(['msg' => '未找到店员信息']);
}
return $model;
}
/**
* 验证用户是否为核销员
* @param $shop_id
* @return bool
*/
public function checkUser($shop_id)
{
if ($this['is_delete']) {
$this->error = '未找到店员信息';
return false;
}
if ($this['shop_id'] != $shop_id) {
$this->error = '当前店员不属于该门店,没有核销权限';
return false;
}
if (!$this['status']) {
$this->error = '当前店员状态已被禁用';
return false;
}
return true;
}
}

15
source/application/api/model/store/shop/ClerkRel.php

@ -1,15 +0,0 @@
<?php
namespace app\api\model\store\shop;
use app\common\model\store\shop\ClerkRel as ClerkRelModel;
/**
* 门店店员关系记录模型
* Class Clerk
* @package app\api\model\store\shop
*/
class ClerkRel extends ClerkRelModel
{
}

15
source/application/api/model/store/shop/Order.php

@ -1,15 +0,0 @@
<?php
namespace app\api\model\store\shop;
use app\common\model\store\shop\Order as OrderModel;
/**
* 商家门店核销订单记录模型
* Class Order
* @package app\api\model\store\shop
*/
class Order extends OrderModel
{
}

38
source/application/api/model/user/BalanceLog.php

@ -1,38 +0,0 @@
<?php
namespace app\api\model\user;
use app\common\model\user\BalanceLog as BalanceLogModel;
/**
* 用户余额变动明细模型
* Class BalanceLog
* @package app\api\model\user
*/
class BalanceLog extends BalanceLogModel
{
/**
* 隐藏字段
* @var array
*/
protected $hidden = [
'wxapp_id',
];
/**
* 获取账单明细列表
* @param $userId
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList($userId)
{
// 获取列表数据
return $this->where('user_id', '=', $userId)
->order(['create_time' => 'desc'])
->paginate(15, false, [
'query' => request()->request()
]);
}
}

30
source/application/api/model/wxapp/Formid.php

@ -1,30 +0,0 @@
<?php
namespace app\api\model\wxapp;
use app\common\model\wxapp\Formid as FormidModel;
/**
* form_id 模型
* Class Formid
* @package app\api\model\wxapp
*/
class Formid extends FormidModel
{
/**
* 新增form_id
* @param $user_id
* @param $form_id
* @return false|int
*/
public static function add($user_id, $form_id)
{
$model = new self;
return $model->save([
'user_id' => $user_id,
'form_id' => $form_id,
'expiry_time' => time() + (7 * 86400) - 10,
'wxapp_id' => self::$wxapp_id
]);
}
}

77
source/application/api/model/wxapp/LiveRoom.php

@ -1,77 +0,0 @@
<?php
namespace app\api\model\wxapp;
use app\common\model\wxapp\LiveRoom as LiveRoomModel;
use app\common\enum\live\LiveStatus as LiveStatusEnum;
/**
* 微信小程序直播间模型
* Class LiveRoom
* @package app\api\model\wxapp
*/
class LiveRoom extends LiveRoomModel
{
/**
* 隐藏的字段
* @var array
*/
protected $hidden = [
'is_delete',
'wxapp_id',
'create_time',
'update_time',
];
/**
* 获取直播间列表
* @return \think\Paginator
* @throws \think\exception\DbException
*/
public function getList()
{
// 直播间列表
// mix: 可设置live_status条件来显示不同直播状态的房间
$this->where('live_status', '<>', 107); // 已过期的不显示
$list = $this->where('is_delete', '=', 0)
->order([
'is_top' => 'desc',
'live_status' => 'asc',
'create_time' => 'desc'
])->paginate(15, false, [
'query' => \request()->request()
]);
// 整理api数据
foreach ($list as &$item) {
$item['live_status_text_1'] = LiveStatusEnum::data()[$item['live_status']]['name'];
$item['live_status_text_2'] = $item['live_status_text_1'];
$item['live_status'] == 101 && $item['live_status_text_1'] = '正在直播中';
$item['live_status'] == 102 && $item['live_status_text_1'] = $this->semanticStartTime($item->getData('start_time')) . ' 开播';
}
return $list;
}
/**
* 语义化开播时间
* @param $startTime
* @return string
*/
private function semanticStartTime($startTime)
{
// 转换为 YYYYMMDD 格式
$startDate = date('Ymd', $startTime);
// 获取今天的 YYYY-MM-DD 格式
$todyDate = date('Ymd');
// 获取明天的 YYYY-MM-DD 格式
$tomorrowDate = date('Ymd', strtotime('+1 day'));
// 使用IF当作字符串判断是否相等
if ($startDate == $todyDate) {
return date('今天H:i', $startTime);
} elseif ($startDate == $tomorrowDate) {
return date('明天H:i', $startTime);
}
// 常规日期格式
return date('m/d H:i', $startTime);
}
}

66
source/application/api/service/Payment.php

@ -1,66 +0,0 @@
<?php
namespace app\api\service;
use app\api\model\Wxapp as WxappModel;
//use app\api\model\WxappPrepayId as WxappPrepayIdModel;
use app\common\library\wechat\WxPay;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\order\PayType as PayTypeEnum;
class Payment
{
/**
* 构建订单支付参数
* @param $user
* @param $order
* @param $payType
* @return array
* @throws \app\common\exception\BaseException
* @throws \think\exception\DbException
*/
public static function orderPayment($user, $order, $payType)
{
if ($payType == PayTypeEnum::WECHAT) {
return self::wechat(
$user,
$order['order_id'],
$order['order_no'],
$order['pay_price'],
OrderTypeEnum::MASTER
);
}
return [];
}
/**
* 构建微信支付
* @param \app\api\model\User $user
* @param $orderId
* @param $orderNo
* @param $payPrice
* @param int $orderType
* @return array
* @throws \app\common\exception\BaseException
* @throws \think\exception\DbException
*/
public static function wechat(
$user,
$orderId,
$orderNo,
$payPrice,
$orderType = OrderTypeEnum::MASTER
)
{
// 统一下单API
$wxConfig = WxappModel::getWxappCache($user['wxapp_id']);
$WxPay = new WxPay($wxConfig);
$payment = $WxPay->unifiedorder($orderNo, $user['open_id'], $payPrice, $orderType);
// // 记录prepay_id
// $model = new WxappPrepayIdModel;
// $model->add($payment['prepay_id'], $orderId, $user['user_id'], $orderType);
return $payment;
}
}

874
source/application/api/service/order/Checkout.php

@ -1,874 +0,0 @@
<?php
namespace app\api\service\order;
use app\api\model\Order as OrderModel;
use app\api\model\User as UserModel;
use app\api\model\Goods as GoodsModel;
use app\api\model\Setting as SettingModel;
use app\api\model\store\Shop as ShopModel;
use app\api\model\UserCoupon as UserCouponModel;
use app\api\model\dealer\Order as DealerOrderModel;
use app\api\service\User as UserService;
use app\api\service\Payment as PaymentService;
use app\api\service\coupon\GoodsDeduct as GoodsDeductService;
use app\api\service\points\GoodsDeduct as PointsDeductService;
use app\api\service\order\source\checkout\Factory as CheckoutFactory;
use app\common\library\helper;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\DeliveryType as DeliveryTypeEnum;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\service\goods\source\Factory as StockFactory;
use app\common\enum\order\OrderSource as OrderSourceEnum;
use app\common\service\delivery\Express as ExpressService;
use app\common\exception\BaseException;
/**
* 订单结算台服务类
* Class Checkout
* @package app\api\service\order
*/
class Checkout
{
/* $model OrderModel 订单模型 */
public $model;
// 当前小程序id
private $wxapp_id;
/* @var UserModel $user 当前用户信息 */
private $user;
// 订单结算商品列表
private $goodsList = [];
// 错误信息
protected $error;
/**
* 订单结算api参数
* @var array
*/
private $param = [
'delivery' => null, // 配送方式
'shop_id' => 0, // 自提门店id
'linkman' => '', // 自提联系人
'phone' => '', // 自提联系电话
'coupon_id' => 0, // 优惠券id
'is_use_points' => 0, // 是否使用积分抵扣
'remark' => '', // 买家留言
'pay_type' => PayTypeEnum::WECHAT, // 支付方式
];
/**
* 订单结算的规则
* @var array
*/
private $checkoutRule = [
'is_user_grade' => true, // 会员等级折扣
'is_coupon' => true, // 优惠券抵扣
'is_use_points' => true, // 是否使用积分抵扣
'is_dealer' => true, // 是否开启分销
];
/**
* 订单来源
* @var array
*/
private $orderSource = [
'source' => OrderSourceEnum::MASTER,
'source_id' => 0,
];
/**
* 订单结算数据
* @var array
*/
private $orderData = [];
/**
* 构造函数
* Checkout constructor.
*/
public function __construct()
{
$this->model = new OrderModel;
$this->wxapp_id = OrderModel::$wxapp_id;
}
/**
* 设置结算台请求的参数
* @param $param
* @return array
*/
public function setParam($param)
{
$this->param = array_merge($this->param, $param);
return $this->getParam();
}
/**
* 获取结算台请求的参数
* @return array
*/
public function getParam()
{
return $this->param;
}
/**
* 订单结算的规则
* @param $data
* @return $this
*/
public function setCheckoutRule($data)
{
$this->checkoutRule = array_merge($this->checkoutRule, $data);
return $this;
}
/**
* 设置订单来源(普通订单、砍价订单、秒杀订单)
* @param $data
* @return $this
*/
public function setOrderSource($data)
{
$this->orderSource = array_merge($this->orderSource, $data);
return $this;
}
/**
* 订单确认-结算台
* @param $user
* @param $goodsList
* @return array
* @throws BaseException
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function onCheckout($user, $goodsList)
{
$this->user = $user;
$this->goodsList = $goodsList;
// 订单确认-立即购买
return $this->checkout();
}
/**
* 订单结算台
* @return array
* @throws BaseException
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function checkout()
{
// 整理订单数据
$this->orderData = $this->getOrderData();
// 验证商品状态, 是否允许购买
$this->validateGoodsList();
// 订单商品总数量
$orderTotalNum = helper::getArrayColumnSum($this->goodsList, 'total_num');
// 设置订单商品会员折扣价
$this->setOrderGoodsGradeMoney();
// 设置订单商品总金额(不含优惠折扣)
$this->setOrderTotalPrice();
// 当前用户可用的优惠券列表
$couponList = $this->getUserCouponList($this->orderData['order_total_price']);
// 计算优惠券抵扣
$this->setOrderCouponMoney($couponList, $this->param['coupon_id']);
// 计算可用积分抵扣
$this->setOrderPoints();
// 计算订单商品的实际付款金额
$this->setOrderGoodsPayPrice();
// 设置默认配送方式
!$this->param['delivery'] && $this->param['delivery'] = current(SettingModel::getItem('store')['delivery_type']);
// 处理配送方式
if ($this->param['delivery'] == DeliveryTypeEnum::EXPRESS) {
$this->setOrderExpress();
} elseif ($this->param['delivery'] == DeliveryTypeEnum::EXTRACT) {
$this->param['shop_id'] > 0 && $this->orderData['extract_shop'] = ShopModel::detail($this->param['shop_id']);
}
// 计算订单最终金额
$this->setOrderPayPrice();
// 计算订单积分赠送数量
$this->setOrderPointsBonus();
// 返回订单数据
return array_merge([
'goods_list' => array_values($this->goodsList), // 商品信息
'order_total_num' => $orderTotalNum, // 商品总数量
'coupon_list' => array_values($couponList), // 优惠券列表
'has_error' => $this->hasError(),
'error_msg' => $this->getError(),
], $this->orderData);
}
/**
* 计算订单可用积分抵扣
* @return bool
*/
private function setOrderPoints()
{
// 设置默认的商品积分抵扣信息
$this->setDefaultGoodsPoints();
// 积分设置
$setting = SettingModel::getItem('points');
// 条件:后台开启下单使用积分抵扣
if (!$setting['is_shopping_discount'] || !$this->checkoutRule['is_use_points']) {
return false;
}
// 条件:订单金额满足[?]元
if (helper::bccomp($setting['discount']['full_order_price'], $this->orderData['order_total_price']) === 1) {
return false;
}
// 计算订单商品最多可抵扣的积分数量
$this->setOrderGoodsMaxPointsNum();
// 订单最多可抵扣的积分总数量
$maxPointsNumCount = helper::getArrayColumnSum($this->goodsList, 'max_points_num');
// 实际可抵扣的积分数量
$actualPointsNum = min($maxPointsNumCount, $this->user['points']);
if ($actualPointsNum < 1) {
return false;
}
// 计算订单商品实际抵扣的积分数量和金额
$GoodsDeduct = new PointsDeductService($this->goodsList);
$GoodsDeduct->setGoodsPoints($maxPointsNumCount, $actualPointsNum);
// 积分抵扣总金额
$orderPointsMoney = helper::getArrayColumnSum($this->goodsList, 'points_money');
$this->orderData['points_money'] = helper::number2($orderPointsMoney);
// 积分抵扣总数量
$this->orderData['points_num'] = $actualPointsNum;
// 允许积分抵扣
$this->orderData['is_allow_points'] = true;
return true;
}
/**
* 计算订单商品最多可抵扣的积分数量
* @return bool
*/
private function setOrderGoodsMaxPointsNum()
{
// 积分设置
$setting = SettingModel::getItem('points');
foreach ($this->goodsList as &$goods) {
// 商品不允许积分抵扣
if (!$goods['is_points_discount']) continue;
// 积分抵扣比例
$deductionRatio = helper::bcdiv($setting['discount']['max_money_ratio'], 100);
// 最多可抵扣的金额
// !!!: 此处应该是优惠券打折后的价格
// bug: $totalPayPrice = $goods['total_price'];
$totalPayPrice = helper::bcsub($goods['total_price'], $goods['coupon_money']);
$maxPointsMoney = helper::bcmul($totalPayPrice, $deductionRatio);
// 最多可抵扣的积分数量
$goods['max_points_num'] = helper::bcdiv($maxPointsMoney, $setting['discount']['discount_ratio'], 0);
}
return true;
}
/**
* 设置默认的商品积分抵扣信息
* @return bool
*/
private function setDefaultGoodsPoints()
{
foreach ($this->goodsList as &$goods) {
// 最多可抵扣的积分数量
$goods['max_points_num'] = 0;
// 实际抵扣的积分数量
$goods['points_num'] = 0;
// 实际抵扣的金额
$goods['points_money'] = 0.00;
}
return true;
}
/**
* 整理订单数据(结算台初始化)
* @return array
*/
private function getOrderData()
{
// 系统支持的配送方式 (后台设置)
$deliveryType = SettingModel::getItem('store')['delivery_type'];
return [
// 配送类型
'delivery' => $this->param['delivery'] > 0 ? $this->param['delivery'] : $deliveryType[0],
// 默认地址
'address' => $this->user['address_default'],
// 是否存在收货地址
'exist_address' => $this->user['address_id'] > 0,
// 配送费用
'express_price' => 0.00,
// 当前用户收货城市是否存在配送规则中
'intra_region' => true,
// 自提门店信息
'extract_shop' => [],
// 是否允许使用积分抵扣
'is_allow_points' => false,
// 是否使用积分抵扣
'is_use_points' => $this->param['is_use_points'],
// 积分抵扣金额
'points_money' => 0.00,
// 赠送的积分数量
'points_bonus' => 0,
// 支付方式
'pay_type' => $this->param['pay_type'],
// 系统设置
'setting' => $this->getSetting(),
// 记忆的自提联系方式
'last_extract' => UserService::getLastExtract($this->user['user_id']),
];
}
/**
* 获取订单页面中使用到的系统设置
* @return array
*/
private function getSetting()
{
// 系统支持的配送方式 (后台设置)
$deliveryType = SettingModel::getItem('store')['delivery_type'];
// 积分设置
$pointsSetting = SettingModel::getItem('points');
// 订阅消息
$orderSubMsgList = [];
foreach (SettingModel::getItem('submsg')['order'] as $item) {
!empty($item['template_id']) && $orderSubMsgList[] = $item['template_id'];
}
return [
'delivery' => $deliveryType, // 支持的配送方式
'points_name' => $pointsSetting['points_name'], // 积分名称
'points_describe' => $pointsSetting['describe'], // 积分说明
'order_submsg' => $orderSubMsgList, // 订阅消息
];
}
/**
* 当前用户可用的优惠券列表
* @param $orderTotalPrice
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function getUserCouponList($orderTotalPrice)
{
// 是否开启优惠券折扣
if (!$this->checkoutRule['is_coupon']) {
return [];
}
return UserCouponModel::getUserCouponList($this->user['user_id'], $orderTotalPrice);
}
/**
* 验证订单商品的状态
* @return bool
*/
private function validateGoodsList()
{
$Checkout = CheckoutFactory::getFactory(
$this->user,
$this->goodsList,
$this->orderSource['source']
);
$status = $Checkout->validateGoodsList();
$status == false && $this->setError($Checkout->getError());
return $status;
}
/**
* 设置订单的商品总金额(不含优惠折扣)
*/
private function setOrderTotalPrice()
{
// 订单商品的总金额(不含优惠券折扣)
$this->orderData['order_total_price'] = helper::number2(helper::getArrayColumnSum($this->goodsList, 'total_price'));
}
/**
* 设置订单的实际支付金额(含配送费)
*/
private function setOrderPayPrice()
{
// 订单金额(含优惠折扣)
$this->orderData['order_price'] = helper::number2(helper::getArrayColumnSum($this->goodsList, 'total_pay_price'));
// 订单实付款金额(订单金额 + 运费)
$this->orderData['order_pay_price'] = helper::number2(helper::bcadd($this->orderData['order_price'], $this->orderData['express_price']));
}
/**
* 计算订单积分赠送数量
* @return bool
*/
private function setOrderPointsBonus()
{
// 初始化商品积分赠送数量
foreach ($this->goodsList as &$goods) {
$goods['points_bonus'] = 0;
}
// 积分设置
$setting = SettingModel::getItem('points');
// 条件:后台开启开启购物送积分
if (!$setting['is_shopping_gift']) {
return false;
}
// 设置商品积分赠送数量
foreach ($this->goodsList as &$goods) {
// 积分赠送比例
$ratio = $setting['gift_ratio'] / 100;
// 计算抵扣积分数量
$goods['points_bonus'] = !$goods['is_points_gift'] ? 0 : helper::bcmul($goods['total_pay_price'], $ratio, 0);
}
// 订单积分赠送数量
$this->orderData['points_bonus'] = helper::getArrayColumnSum($this->goodsList, 'points_bonus');
return true;
}
/**
* 计算订单商品的实际付款金额
* @return bool
*/
private function setOrderGoodsPayPrice()
{
// 商品总价 - 优惠抵扣
foreach ($this->goodsList as &$goods) {
// 减去优惠券抵扣金额
$value = helper::bcsub($goods['total_price'], $goods['coupon_money']);
// 减去积分抵扣金额
if ($this->orderData['is_allow_points'] && $this->orderData['is_use_points']) {
$value = helper::bcsub($value, $goods['points_money']);
}
$goods['total_pay_price'] = helper::number2($value);
}
return true;
}
/**
* 设置订单商品会员折扣价
* @return bool
*/
private function setOrderGoodsGradeMoney()
{
// 设置默认数据
helper::setDataAttribute($this->goodsList, [
// 标记参与会员折扣
'is_user_grade' => false,
// 会员等级抵扣的金额
'grade_ratio' => 0,
// 会员折扣的商品单价
'grade_goods_price' => 0.00,
// 会员折扣的总额差
'grade_total_money' => 0.00,
], true);
// 是否开启会员等级折扣
if (!$this->checkoutRule['is_user_grade']) {
return false;
}
// 会员等级状态
if (!(
$this->user['grade_id'] > 0 && !empty($this->user['grade'])
&& !$this->user['grade']['is_delete'] && $this->user['grade']['status']
)) {
return false;
}
// 计算抵扣金额
foreach ($this->goodsList as &$goods) {
// 判断商品是否参与会员折扣
if (!$goods['is_enable_grade']) {
continue;
}
// 商品单独设置了会员折扣
if ($goods['is_alone_grade'] && isset($goods['alone_grade_equity'][$this->user['grade_id']])) {
// 折扣比例
$discountRatio = helper::bcdiv($goods['alone_grade_equity'][$this->user['grade_id']], 10);
} else {
// 折扣比例
$discountRatio = helper::bcdiv($this->user['grade']['equity']['discount'], 10);
}
if ($discountRatio > 0) {
// 会员折扣后的商品总金额
$gradeTotalPrice = max(0.01, helper::bcmul($goods['total_price'], $discountRatio));
helper::setDataAttribute($goods, [
'is_user_grade' => true,
'grade_ratio' => $discountRatio,
'grade_goods_price' => helper::number2(helper::bcmul($goods['goods_price'], $discountRatio), true),
'grade_total_money' => helper::number2(helper::bcsub($goods['total_price'], $gradeTotalPrice)),
'total_price' => $gradeTotalPrice,
], false);
}
}
return true;
}
/**
* 设置订单优惠券抵扣信息
* @param array $couponList 当前用户可用的优惠券列表
* @param int $couponId 当前选择的优惠券id
* @return bool
* @throws BaseException
*/
private function setOrderCouponMoney($couponList, $couponId)
{
// 设置默认数据:订单信息
helper::setDataAttribute($this->orderData, [
'coupon_id' => 0, // 用户优惠券id
'coupon_money' => 0, // 优惠券抵扣金额
], false);
// 设置默认数据:订单商品列表
helper::setDataAttribute($this->goodsList, [
'coupon_money' => 0, // 优惠券抵扣金额
], true);
// 是否开启优惠券折扣
if (!$this->checkoutRule['is_coupon']) {
return false;
}
// 如果没有可用的优惠券,直接返回
if ($couponId <= 0 || empty($couponList)) {
return true;
}
// 获取优惠券信息
$couponInfo = helper::getArrayItemByColumn($couponList, 'user_coupon_id', $couponId);
if ($couponInfo == false) {
throw new BaseException(['msg' => '未找到优惠券信息']);
}
// 计算订单商品优惠券抵扣金额
$goodsListTemp = helper::getArrayColumns($this->goodsList, ['total_price']);
$CouponMoney = new GoodsDeductService;
$completed = $CouponMoney->setGoodsCouponMoney($goodsListTemp, $couponInfo['reduced_price']);
// 分配订单商品优惠券抵扣金额
foreach ($this->goodsList as $key => &$goods) {
$goods['coupon_money'] = $completed[$key]['coupon_money'] / 100;
}
// 记录订单优惠券信息
$this->orderData['coupon_id'] = $couponId;
$this->orderData['coupon_money'] = helper::number2($CouponMoney->getActualReducedMoney() / 100);
return true;
}
/**
* 订单配送-快递配送
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function setOrderExpress()
{
// 设置默认数据:配送费用
helper::setDataAttribute($this->goodsList, [
'express_price' => 0,
], true);
// 当前用户收货城市id
$cityId = $this->user['address_default'] ? $this->user['address_default']['city_id'] : null;
// 初始化配送服务类
$ExpressService = new ExpressService($cityId, $this->goodsList, OrderTypeEnum::MASTER);
// 验证商品是否在配送范围
$isIntraRegion = $ExpressService->isIntraRegion();
if ($cityId > 0 && $isIntraRegion == false) {
$notInRuleGoodsName = $ExpressService->getNotInRuleGoodsName();
$this->setError("很抱歉,您的收货地址不在商品 [{$notInRuleGoodsName}] 的配送范围内");
}
// 订单总运费金额
$this->orderData['intra_region'] = $isIntraRegion;
$this->orderData['express_price'] = $ExpressService->getDeliveryFee();
return true;
}
/**
* 创建新订单
* @param array $order 订单信息
* @return bool
* @throws \Exception
*/
public function createOrder($order)
{
// 表单验证
if (!$this->validateOrderForm($order, $this->param['linkman'], $this->param['phone'])) {
return false;
}
// 创建新的订单
$status = $this->model->transaction(function () use ($order) {
// 创建订单事件
return $this->createOrderEvent($order);
});
// 余额支付标记订单已支付
if ($status && $order['pay_type'] == PayTypeEnum::BALANCE) {
return $this->model->onPaymentByBalance($this->model['order_no']);
}
return $status;
}
/**
* 创建订单事件
* @param $order
* @return bool
* @throws BaseException
* @throws \think\exception\DbException
* @throws \Exception
*/
private function createOrderEvent($order)
{
// 新增订单记录
$status = $this->add($order, $this->param['remark']);
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
// 记录收货地址
$this->saveOrderAddress($order['address']);
} elseif ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
// 记录自提信息
$this->saveOrderExtract($this->param['linkman'], $this->param['phone']);
}
// 保存订单商品信息
$this->saveOrderGoods($order);
// 更新商品库存 (针对下单减库存的商品)
$this->updateGoodsStockNum($order);
// 设置优惠券使用状态
UserCouponModel::setIsUse($this->param['coupon_id']);
// 积分抵扣情况下扣除用户积分
if ($order['is_allow_points'] && $order['is_use_points'] && $order['points_num'] > 0) {
$describe = "用户消费:{$this->model['order_no']}";
$this->user->setIncPoints(-$order['points_num'], $describe);
}
// 获取订单详情
$detail = OrderModel::getUserOrderDetail($this->model['order_id'], $this->user['user_id']);
// 记录分销商订单
$this->checkoutRule['is_dealer'] && DealerOrderModel::createOrder($detail);
return $status;
}
/**
* 构建支付请求的参数
* @return array
* @throws BaseException
* @throws \think\exception\DbException
*/
public function onOrderPayment()
{
return PaymentService::orderPayment($this->user, $this->model, $this->param['pay_type']);
}
/**
* 表单验证 (订单提交)
* @param array $order 订单信息
* @param string $linkman 联系人
* @param string $phone 联系电话
* @return bool
*/
private function validateOrderForm(&$order, $linkman, $phone)
{
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
if (empty($order['address'])) {
$this->error = '您还没有选择配送地址';
return false;
}
}
if ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
if (empty($order['extract_shop'])) {
$this->error = '您还没有选择自提门店';
return false;
}
if (empty($linkman) || empty($phone)) {
$this->error = '您还没有填写联系人和电话';
return false;
}
}
// 余额支付时判断用户余额是否足够
if ($order['pay_type'] == PayTypeEnum::BALANCE) {
if ($this->user['balance'] < $order['order_pay_price']) {
$this->error = '您的余额不足,无法使用余额支付';
return false;
}
}
return true;
}
/**
* 当前订单是否存在和使用积分抵扣
* @param $order
* @return bool
*/
private function isExistPointsDeduction($order)
{
return $order['is_allow_points'] && $order['is_use_points'];
}
/**
* 新增订单记录
* @param $order
* @param string $remark
* @return false|int
*/
private function add($order, $remark = '')
{
// 当前订单是否存在和使用积分抵扣
$isExistPointsDeduction = $this->isExistPointsDeduction($order);
// 订单数据
$data = [
'user_id' => $this->user['user_id'],
'order_no' => $this->model->orderNo(),
'total_price' => $order['order_total_price'],
'order_price' => $order['order_price'],
'coupon_id' => $order['coupon_id'],
'coupon_money' => $order['coupon_money'],
'points_money' => $isExistPointsDeduction ? $order['points_money'] : 0.00,
'points_num' => $isExistPointsDeduction ? $order['points_num'] : 0,
'pay_price' => $order['order_pay_price'],
'delivery_type' => $order['delivery'],
'pay_type' => $order['pay_type'],
'buyer_remark' => trim($remark),
'order_source' => $this->orderSource['source'],
'order_source_id' => $this->orderSource['source_id'],
'points_bonus' => $order['points_bonus'],
'wxapp_id' => $this->wxapp_id,
];
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
$data['express_price'] = $order['express_price'];
} elseif ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
$data['extract_shop_id'] = $order['extract_shop']['shop_id'];
}
// 保存订单记录
return $this->model->save($data);
}
/**
* 保存订单商品信息
* @param $order
* @return int
*/
private function saveOrderGoods($order)
{
// 当前订单是否存在和使用积分抵扣
$isExistPointsDeduction = $this->isExistPointsDeduction($order);
// 订单商品列表
$goodsList = [];
foreach ($order['goods_list'] as $goods) {
/* @var GoodsModel $goods */
$item = [
'user_id' => $this->user['user_id'],
'wxapp_id' => $this->wxapp_id,
'goods_id' => $goods['goods_id'],
'goods_name' => $goods['goods_name'],
'image_id' => $goods['image'][0]['image_id'],
'deduct_stock_type' => $goods['deduct_stock_type'],
'spec_type' => $goods['spec_type'],
'spec_sku_id' => $goods['goods_sku']['spec_sku_id'],
'goods_sku_id' => $goods['goods_sku']['goods_sku_id'],
'goods_attr' => $goods['goods_sku']['goods_attr'],
'content' => $goods['content'],
'goods_no' => $goods['goods_sku']['goods_no'],
'goods_price' => $goods['goods_sku']['goods_price'],
'line_price' => $goods['goods_sku']['line_price'],
'goods_weight' => $goods['goods_sku']['goods_weight'],
'is_user_grade' => (int)$goods['is_user_grade'],
'grade_ratio' => $goods['grade_ratio'],
'grade_goods_price' => $goods['grade_goods_price'],
'grade_total_money' => $goods['grade_total_money'],
'coupon_money' => $goods['coupon_money'],
'points_money' => $isExistPointsDeduction ? $goods['points_money'] : 0.00,
'points_num' => $isExistPointsDeduction ? $goods['points_num'] : 0,
'points_bonus' => $goods['points_bonus'],
'total_num' => $goods['total_num'],
'total_price' => $goods['total_price'],
'total_pay_price' => $goods['total_pay_price'],
'is_ind_dealer' => $goods['is_ind_dealer'],
'dealer_money_type' => $goods['dealer_money_type'],
'first_money' => $goods['first_money'],
'second_money' => $goods['second_money'],
'third_money' => $goods['third_money'],
];
// 记录订单商品来源id
$item['goods_source_id'] = isset($goods['goods_source_id']) ? $goods['goods_source_id'] : 0;
$goodsList[] = $item;
}
return $this->model->goods()->saveAll($goodsList);
}
/**
* 更新商品库存 (针对下单减库存的商品)
* @param $order
* @return mixed
*/
private function updateGoodsStockNum($order)
{
return StockFactory::getFactory($this->model['order_source'])->updateGoodsStock($order['goods_list']);
}
/**
* 记录收货地址
* @param $address
* @return false|\think\Model
*/
private function saveOrderAddress($address)
{
if ($address['region_id'] == 0 && !empty($address['district'])) {
$address['detail'] = $address['district'] . ' ' . $address['detail'];
}
return $this->model->address()->save([
'user_id' => $this->user['user_id'],
'wxapp_id' => $this->wxapp_id,
'name' => $address['name'],
'phone' => $address['phone'],
'province_id' => $address['province_id'],
'city_id' => $address['city_id'],
'region_id' => $address['region_id'],
'detail' => $address['detail'],
]);
}
/**
* 保存上门自提联系人
* @param $linkman
* @param $phone
* @return false|\think\Model
*/
private function saveOrderExtract($linkman, $phone)
{
// 记忆上门自提联系人(缓存),用于下次自动填写
UserService::setLastExtract($this->model['user_id'], trim($linkman), trim($phone));
// 保存上门自提联系人(数据库)
return $this->model->extract()->save([
'linkman' => trim($linkman),
'phone' => trim($phone),
'user_id' => $this->model['user_id'],
'wxapp_id' => $this->wxapp_id,
]);
}
/**
* 设置错误信息
* @param $error
*/
protected function setError($error)
{
empty($this->error) && $this->error = $error;
}
/**
* 获取错误信息
* @return mixed
*/
public function getError()
{
return $this->error ?: '';
}
/**
* 是否存在错误
* @return bool
*/
public function hasError()
{
return !empty($this->error);
}
}

150
source/application/api/service/order/PaySuccess.php

@ -1,150 +0,0 @@
<?php
namespace app\api\service\order;
use think\Hook;
use app\api\service\Basics;
use app\api\model\User as UserModel;
use app\api\model\Order as OrderModel;
//use app\api\model\WxappPrepayId as WxappPrepayIdModel;
use app\api\model\user\BalanceLog as BalanceLogModel;
use app\common\service\goods\source\Factory as StockFactory;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\enum\user\balanceLog\Scene as SceneEnum;
/**
* 订单支付成功服务类
* Class PaySuccess
* @package app\api\service\order
*/
class PaySuccess extends Basics
{
// 订单模型
public $model;
// 当前用户信息
private $user;
/**
* 构造函数
* PaySuccess constructor.
* @param $orderNo
* @throws \think\exception\DbException
*/
public function __construct($orderNo)
{
// 实例化订单模型
$this->model = OrderModel::getPayDetail($orderNo);
if (!empty($this->model)) {
$this->wxappId = $this->model['wxapp_id'];
}
// 获取用户信息
$this->user = UserModel::detail($this->model['user_id']);
}
/**
* 获取订单详情
* @return OrderModel|null
*/
public function getOrderInfo()
{
return $this->model;
}
/**
* 订单支付成功业务处理
* @param $payType
* @param array $payData
* @return bool
*/
public function onPaySuccess($payType, $payData = [])
{
if (empty($this->model)) {
$this->error = '未找到该订单信息';
return false;
}
// 更新付款状态
$status = $this->updatePayStatus($payType, $payData);
// 订单支付成功行为
if ($status == true) {
Hook::listen('order_pay_success', $this->model, OrderTypeEnum::MASTER);
}
return $status;
}
/**
* 更新付款状态
* @param $payType
* @param array $payData
* @return bool
*/
private function updatePayStatus($payType, $payData = [])
{
// 验证余额支付时用户余额是否满足
if ($payType == PayTypeEnum::BALANCE) {
if ($this->user['balance'] < $this->model['pay_price']) {
$this->error = '用户余额不足,无法使用余额支付';
return false;
}
}
// 事务处理
$this->model->transaction(function () use ($payType, $payData) {
// 更新订单状态
$this->updateOrderInfo($payType, $payData);
// 累积用户总消费金额
$this->user->setIncPayMoney($this->model['pay_price']);
// 记录订单支付信息
$this->updatePayInfo($payType);
});
return true;
}
/**
* 更新订单记录
* @param $payType
* @param $payData
* @return false|int
* @throws \Exception
*/
private function updateOrderInfo($payType, $payData)
{
// 更新商品库存、销量
StockFactory::getFactory($this->model['order_source'])->updateStockSales($this->model['goods']);
// 整理订单信息
$order = [
'pay_type' => $payType,
'pay_status' => 20,
'pay_time' => time()
];
if ($payType == PayTypeEnum::WECHAT) {
$order['transaction_id'] = $payData['transaction_id'];
}
// 更新订单状态
return $this->model->save($order);
}
/**
* 记录订单支付信息
* @param $payType
* @throws \think\Exception
*/
private function updatePayInfo($payType)
{
// 余额支付
if ($payType == PayTypeEnum::BALANCE) {
// 更新用户余额
$this->user->setDec('balance', $this->model['pay_price']);
BalanceLogModel::add(SceneEnum::CONSUME, [
'user_id' => $this->user['user_id'],
'money' => -$this->model['pay_price'],
], ['order_no' => $this->model['order_no']]);
}
// 微信支付
if ($payType == PayTypeEnum::WECHAT) {
// 更新prepay_id记录
// WxappPrepayIdModel::updatePayStatus($this->model['order_id'], OrderTypeEnum::MASTER);
}
}
}

79
source/application/api/service/recharge/PaySuccess.php

@ -1,79 +0,0 @@
<?php
namespace app\api\service\recharge;
use app\api\service\Basics;
use app\api\model\User as UserModel;
use app\api\model\recharge\Order as OrderModel;
//use app\api\model\WxappPrepayId as WxappPrepayIdModel;
use app\api\model\user\BalanceLog as BalanceLogModel;
//use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\enum\user\balanceLog\Scene as SceneEnum;
use app\common\enum\recharge\order\PayStatus as PayStatusEnum;
class PaySuccess extends Basics
{
// 订单模型
public $model;
// 当前用户信息
private $user;
/**
* 构造函数
* PaySuccess constructor.
* @param $orderNo
* @throws \think\exception\DbException
*/
public function __construct($orderNo)
{
// 实例化订单模型
$this->model = OrderModel::getPayDetail($orderNo);
$this->wxappId = $this->model['wxapp_id'];
// 获取用户信息
$this->user = UserModel::detail($this->model['user_id']);
}
/**
* 获取订单详情
* @return OrderModel|null
*/
public function getOrderInfo()
{
return $this->model;
}
/**
* 订单支付成功业务处理
* @param int $payType 支付类型
* @param array $payData 支付回调数据
* @return bool
*/
public function onPaySuccess($payType, $payData)
{
return $this->model->transaction(function () use ($payType, $payData) {
// 更新订单状态
$this->model->save([
'pay_status' => PayStatusEnum::SUCCESS,
'pay_time' => time(),
'transaction_id' => $payData['transaction_id']
]);
// 累积用户余额
$this->user->setInc('balance', $this->model['actual_money']);
// 用户余额变动明细
BalanceLogModel::add(SceneEnum::RECHARGE, [
'user_id' => $this->user['user_id'],
'money' => $this->model['actual_money'],
'wxapp_id' => $this->wxappId,
], ['order_no' => $this->model['order_no']]);
// 更新prepay_id记录
if ($payType == PayTypeEnum::WECHAT) {
// WxappPrepayIdModel::updatePayStatus($this->model['order_id'], OrderTypeEnum::RECHARGE);
}
return true;
});
}
}

907
source/application/api/service/sharing/order/Checkout.php

@ -1,907 +0,0 @@
<?php
namespace app\api\service\sharing\order;
use app\api\model\sharing\Order as OrderModel;
use app\api\model\User as UserModel;
use app\api\model\Setting as SettingModel;
use app\api\model\sharing\Goods as GoodsModel;
use app\api\model\sharing\GoodsSku as GoodsSkuModel;
use app\api\model\sharing\Active as ActiveModel;
use app\api\model\sharing\Setting as SharingSettingModel;
use app\api\model\store\Shop as ShopModel;
use app\api\model\UserCoupon as UserCouponModel;
use app\api\model\dealer\Order as DealerOrderModel;
use app\api\service\User as UserService;
use app\api\service\Payment as PaymentService;
use app\api\service\coupon\GoodsDeduct as GoodsDeductService;
use app\api\service\points\GoodsDeduct as PointsDeductService;
use app\common\library\helper;
use app\common\enum\OrderType as OrderTypeEnum;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\enum\DeliveryType as DeliveryTypeEnum;
use app\common\enum\order\OrderSource as OrderSourceEnum;
use app\common\service\delivery\Express as ExpressService;
use app\common\exception\BaseException;
/**
* 订单结算台服务类
* Class Checkout
* @package app\api\service\order
*/
class Checkout
{
/* $model OrderModel 订单模型 */
public $model;
// 当前小程序id
private $wxapp_id;
/* @var UserModel $user 当前用户信息 */
private $user;
// 订单结算商品列表
private $goodsList = [];
// 错误信息
protected $error;
/**
* 订单结算api参数
* @var array
*/
private $param = [
'active_id' => 0, // 参与的拼单id
'delivery' => null, // 配送方式
'shop_id' => 0, // 自提门店id
'linkman' => '', // 自提联系人
'phone' => '', // 自提联系电话
'coupon_id' => 0, // 优惠券id
'is_use_points' => 0, // 是否使用积分抵扣
'remark' => '', // 买家留言
'pay_type' => PayTypeEnum::WECHAT, // 支付方式
'order_type' => 20, // 下单类型 10 => 单独购买,20 => 拼团
];
/**
* 订单结算的规则
* @var array
*/
private $checkoutRule = [
'is_user_grade' => true, // 会员等级折扣
'is_coupon' => true, // 优惠券抵扣
'is_use_points' => true, // 是否使用积分抵扣
'is_dealer' => true, // 是否开启分销
];
/**
* 订单来源
* @var array
*/
private $orderSource = [
'source' => OrderSourceEnum::MASTER,
'source_id' => 0,
];
/**
* 订单结算数据
* @var array
*/
private $orderData = [];
/**
* 构造函数
* Checkout constructor.
*/
public function __construct()
{
$this->model = new OrderModel;
$this->wxapp_id = OrderModel::$wxapp_id;
}
/**
* 设置结算台请求的参数
* @param $param
* @return array
*/
public function setParam($param)
{
$this->param = array_merge($this->param, $param);
return $this->getParam();
}
/**
* 获取结算台请求的参数
* @return array
*/
public function getParam()
{
return $this->param;
}
/**
* 订单结算的规则
* @param $data
*/
public function setCheckoutRule($data)
{
$this->checkoutRule = array_merge($this->checkoutRule, $data);
}
/**
* 设置订单来源(普通订单、砍价订单)
* @param $data
*/
public function setOrderSource($data)
{
$this->orderSource = array_merge($this->orderSource, $data);
}
/**
* 订单确认-砍价活动
* @param $user
* @param $goodsList
* @return array
* @throws BaseException
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function onCheckout($user, $goodsList)
{
$this->user = $user;
$this->goodsList = $goodsList;
// 订单确认-立即购买
return $this->checkout();
}
/**
* 订单结算台
* @return array
* @throws BaseException
* @throws \think\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function checkout()
{
// 整理订单数据
$this->orderData = $this->getOrderData();
// 验证商品状态, 是否允许购买
$this->validateGoodsList();
// 订单商品总数量
$orderTotalNum = helper::getArrayColumnSum($this->goodsList, 'total_num');
// 设置订单商品会员折扣价
$this->setOrderGoodsGradeMoney();
// 设置订单商品总金额(不含优惠折扣)
$this->setOrderTotalPrice();
// 当前用户可用的优惠券列表
$couponList = $this->getUserCouponList($this->orderData['order_total_price']);
// 计算优惠券抵扣
$this->setOrderCouponMoney($couponList, $this->param['coupon_id']);
// 计算可用积分抵扣
$this->setOrderPoints();
// 计算订单商品的实际付款金额
$this->setOrderGoodsPayPrice();
// 设置默认配送方式
!$this->param['delivery'] && $this->param['delivery'] = current(SettingModel::getItem('store')['delivery_type']);
// 处理配送方式
if ($this->param['delivery'] == DeliveryTypeEnum::EXPRESS) {
$this->setOrderExpress();
} elseif ($this->param['delivery'] == DeliveryTypeEnum::EXTRACT) {
$this->param['shop_id'] > 0 && $this->orderData['extract_shop'] = ShopModel::detail($this->param['shop_id']);
}
// 计算订单最终金额
$this->setOrderPayPrice();
// 计算订单积分赠送数量
$this->setOrderPointsBonus();
// 返回订单数据
return array_merge([
'goods_list' => array_values($this->goodsList), // 商品信息
'order_total_num' => $orderTotalNum, // 商品总数量
'coupon_list' => array_values($couponList), // 优惠券列表
'has_error' => $this->hasError(),
'error_msg' => $this->getError(),
], $this->orderData);
}
/**
* 计算订单可用积分抵扣
* @return bool
*/
private function setOrderPoints()
{
// 设置默认的商品积分抵扣信息
$this->setDefaultGoodsPoints();
// 积分设置
$setting = SettingModel::getItem('points');
// 条件:后台开启下单使用积分抵扣
if (!$setting['is_shopping_discount'] || !$this->checkoutRule['is_use_points']) {
return false;
}
// 条件:订单金额满足[?]元
if (helper::bccomp($setting['discount']['full_order_price'], $this->orderData['order_total_price']) === 1) {
return false;
}
// 计算订单商品最多可抵扣的积分数量
$this->setOrderGoodsMaxPointsNum();
// 订单最多可抵扣的积分总数量
$maxPointsNumCount = helper::getArrayColumnSum($this->goodsList, 'max_points_num');
// 实际可抵扣的积分数量
$actualPointsNum = min($maxPointsNumCount, $this->user['points']);
if ($actualPointsNum < 1) {
return false;
}
// 计算订单商品实际抵扣的积分数量和金额
$GoodsDeduct = new PointsDeductService($this->goodsList);
$GoodsDeduct->setGoodsPoints($maxPointsNumCount, $actualPointsNum);
// 积分抵扣总金额
$orderPointsMoney = helper::getArrayColumnSum($this->goodsList, 'points_money');
$this->orderData['points_money'] = helper::number2($orderPointsMoney);
// 积分抵扣总数量
$this->orderData['points_num'] = $actualPointsNum;
// 允许积分抵扣
$this->orderData['is_allow_points'] = true;
return true;
}
/**
* 计算订单商品最多可抵扣的积分数量
* @return bool
*/
private function setOrderGoodsMaxPointsNum()
{
// 积分设置
$setting = SettingModel::getItem('points');
foreach ($this->goodsList as &$goods) {
// 商品不允许积分抵扣
if (!$goods['is_points_discount']) continue;
// 积分抵扣比例
$deductionRatio = helper::bcdiv($setting['discount']['max_money_ratio'], 100);
// 最多可抵扣的金额
// !!!: 此处应该是优惠券打折后的价格
// bug: $totalPayPrice = $goods['total_price'];
$totalPayPrice = helper::bcsub($goods['total_price'], $goods['coupon_money']);
$maxPointsMoney = helper::bcmul($totalPayPrice, $deductionRatio);
// 最多可抵扣的积分数量
$goods['max_points_num'] = helper::bcdiv($maxPointsMoney, $setting['discount']['discount_ratio'], 0);
}
return true;
}
/**
* 设置默认的商品积分抵扣信息
* @return bool
*/
private function setDefaultGoodsPoints()
{
foreach ($this->goodsList as &$goods) {
// 最多可抵扣的积分数量
$goods['max_points_num'] = 0;
// 实际抵扣的积分数量
$goods['points_num'] = 0;
// 实际抵扣的金额
$goods['points_money'] = 0.00;
}
return true;
}
/**
* 整理订单数据(结算台初始化)
* @return array
*/
private function getOrderData()
{
// 系统支持的配送方式 (后台设置)
$deliveryType = SettingModel::getItem('store')['delivery_type'];
return [
// 订单类型
'order_type' => $this->param['order_type'],
// 配送类型
'delivery' => $this->param['delivery'] > 0 ? $this->param['delivery'] : $deliveryType[0],
// 默认地址
'address' => $this->user['address_default'],
// 是否存在收货地址
'exist_address' => $this->user['address_id'] > 0,
// 配送费用
'express_price' => 0.00,
// 当前用户收货城市是否存在配送规则中
'intra_region' => true,
// 自提门店信息
'extract_shop' => [],
// 是否允许使用积分抵扣
'is_allow_points' => false,
// 是否使用积分抵扣
'is_use_points' => $this->param['is_use_points'],
// 积分抵扣金额
'points_money' => 0.00,
// 赠送的积分数量
'points_bonus' => 0,
// 支付方式
'pay_type' => $this->param['pay_type'],
// 系统设置
'setting' => $this->getSetting(),
// 记忆的自提联系方式
'last_extract' => UserService::getLastExtract($this->user['user_id']),
// todo: 兼容处理
'deliverySetting' => $deliveryType,
];
}
/**
* 获取订单页面中使用到的系统设置
* @return array
*/
private function getSetting()
{
// 系统支持的配送方式 (后台设置)
$deliveryType = SettingModel::getItem('store')['delivery_type'];
// 积分设置
$pointsSetting = SettingModel::getItem('points');
// 订阅消息
$orderSubMsgList = [];
foreach (SettingModel::getItem('submsg')['order'] as $item) {
!empty($item['template_id']) && $orderSubMsgList[] = $item['template_id'];
}
return [
'delivery' => $deliveryType, // 支持的配送方式
'points_name' => $pointsSetting['points_name'], // 积分名称
'points_describe' => $pointsSetting['describe'], // 积分说明
'order_submsg' => $orderSubMsgList, // 订阅消息
];
}
/**
* 当前用户可用的优惠券列表
* @param $orderTotalPrice
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function getUserCouponList($orderTotalPrice)
{
// 是否开启优惠券折扣
if (!$this->checkoutRule['is_coupon'] || !SharingSettingModel::getItem('basic')['is_coupon']) {
return [];
}
return UserCouponModel::getUserCouponList($this->user['user_id'], $orderTotalPrice);
}
/**
* 验证订单商品的状态
*/
private function validateGoodsList()
{
foreach ($this->goodsList as $goods) {
// 判断商品是否下架
if ($goods['goods_status']['value'] != 10) {
$this->setError("很抱歉,商品 [{$goods['goods_name']}] 已下架");
}
// 判断商品库存
if ($goods['total_num'] > $goods['goods_sku']['stock_num']) {
$this->setError("很抱歉,商品 [{$goods['goods_name']}] 库存不足");
}
}
}
/**
* 设置订单的商品总金额(不含优惠折扣)
*/
private function setOrderTotalPrice()
{
// 订单商品的总金额(不含优惠券折扣)
$this->orderData['order_total_price'] = helper::number2(helper::getArrayColumnSum($this->goodsList, 'total_price'));
}
/**
* 设置订单的实际支付金额(含配送费)
*/
private function setOrderPayPrice()
{
// 订单金额(含优惠折扣)
$this->orderData['order_price'] = helper::number2(helper::getArrayColumnSum($this->goodsList, 'total_pay_price'));
// 订单实付款金额(订单金额 + 运费)
$this->orderData['order_pay_price'] = helper::number2(helper::bcadd($this->orderData['order_price'], $this->orderData['express_price']));
}
/**
* 计算订单积分赠送数量
* @return bool
*/
private function setOrderPointsBonus()
{
// 初始化商品积分赠送数量
foreach ($this->goodsList as &$goods) {
$goods['points_bonus'] = 0;
}
// 积分设置
$setting = SettingModel::getItem('points');
// 条件:后台开启开启购物送积分
if (!$setting['is_shopping_gift']) {
return false;
}
// 设置商品积分赠送数量
foreach ($this->goodsList as &$goods) {
// 积分赠送比例
$ratio = $setting['gift_ratio'] / 100;
// 计算抵扣积分数量
$goods['points_bonus'] = $goods['is_points_gift'] ? helper::bcmul($goods['total_pay_price'], $ratio, 0) : 0;
}
// 订单积分赠送数量
$this->orderData['points_bonus'] = helper::getArrayColumnSum($this->goodsList, 'points_bonus');
return true;
}
/**
* 计算订单商品的实际付款金额
* @return bool
*/
private function setOrderGoodsPayPrice()
{
// 商品总价 - 优惠抵扣
foreach ($this->goodsList as &$goods) {
// 减去优惠券抵扣金额
$value = helper::bcsub($goods['total_price'], $goods['coupon_money']);
// 减去积分抵扣金额
if ($this->orderData['is_allow_points'] && $this->orderData['is_use_points']) {
$value = helper::bcsub($value, $goods['points_money']);
}
$goods['total_pay_price'] = helper::number2($value);
}
return true;
}
/**
* 设置订单商品会员折扣价
* @return bool
*/
private function setOrderGoodsGradeMoney()
{
// 设置默认数据
helper::setDataAttribute($this->goodsList, [
// 标记参与会员折扣
'is_user_grade' => false,
// 会员等级抵扣的金额
'grade_ratio' => 0,
// 会员折扣的商品单价
'grade_goods_price' => 0.00,
// 会员折扣的总额差
'grade_total_money' => 0.00,
], true);
// 是否开启会员等级折扣
if (!$this->checkoutRule['is_user_grade']) {
return false;
}
// 会员等级状态
if (!(
$this->user['grade_id'] > 0 && !empty($this->user['grade'])
&& !$this->user['grade']['is_delete'] && $this->user['grade']['status']
)) {
return false;
}
// 计算抵扣金额
foreach ($this->goodsList as &$goods) {
// 判断商品是否参与会员折扣
if (!$goods['is_enable_grade']) {
continue;
}
// 商品单独设置了会员折扣
if ($goods['is_alone_grade'] && isset($goods['alone_grade_equity'][$this->user['grade_id']])) {
// 折扣比例
$discountRatio = helper::bcdiv($goods['alone_grade_equity'][$this->user['grade_id']], 10);
} else {
// 折扣比例
$discountRatio = helper::bcdiv($this->user['grade']['equity']['discount'], 10);
}
if ($discountRatio > 0) {
// 会员折扣后的商品总金额
$gradeTotalPrice = max(0.01, helper::bcmul($goods['total_price'], $discountRatio));
helper::setDataAttribute($goods, [
'is_user_grade' => true,
'grade_ratio' => $discountRatio,
'grade_goods_price' => helper::number2(helper::bcmul($goods['goods_price'], $discountRatio), true),
'grade_total_money' => helper::number2(helper::bcsub($goods['total_price'], $gradeTotalPrice)),
'total_price' => $gradeTotalPrice,
], false);
}
}
return true;
}
/**
* 设置订单优惠券抵扣信息
* @param array $couponList 当前用户可用的优惠券列表
* @param int $couponId 当前选择的优惠券id
* @return bool
* @throws BaseException
*/
private function setOrderCouponMoney($couponList, $couponId)
{
// 设置默认数据:订单信息
helper::setDataAttribute($this->orderData, [
'coupon_id' => 0, // 用户优惠券id
'coupon_money' => 0, // 优惠券抵扣金额
], false);
// 设置默认数据:订单商品列表
helper::setDataAttribute($this->goodsList, [
'coupon_money' => 0, // 优惠券抵扣金额
], true);
// 是否开启优惠券折扣
if (!$this->checkoutRule['is_coupon']) {
return false;
}
// 如果没有可用的优惠券,直接返回
if ($couponId <= 0 || empty($couponList)) {
return true;
}
// 获取优惠券信息
$couponInfo = helper::getArrayItemByColumn($couponList, 'user_coupon_id', $couponId);
if ($couponInfo == false) {
throw new BaseException(['msg' => '未找到优惠券信息']);
}
// 计算订单商品优惠券抵扣金额
$goodsListTemp = helper::getArrayColumns($this->goodsList, ['total_price']);
$CouponMoney = new GoodsDeductService;
$completed = $CouponMoney->setGoodsCouponMoney($goodsListTemp, $couponInfo['reduced_price']);
// 分配订单商品优惠券抵扣金额
foreach ($this->goodsList as $key => &$goods) {
$goods['coupon_money'] = $completed[$key]['coupon_money'] / 100;
}
// 记录订单优惠券信息
$this->orderData['coupon_id'] = $couponId;
$this->orderData['coupon_money'] = helper::number2($CouponMoney->getActualReducedMoney() / 100);
return true;
}
/**
* 订单配送-快递配送
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function setOrderExpress()
{
// 设置默认数据:配送费用
helper::setDataAttribute($this->goodsList, [
'express_price' => 0,
], true);
// 当前用户收货城市id
$cityId = $this->user['address_default'] ? $this->user['address_default']['city_id'] : null;
// 初始化配送服务类
$ExpressService = new ExpressService($cityId, $this->goodsList, OrderTypeEnum::SHARING);
// 验证商品是否在配送范围
$isIntraRegion = $ExpressService->isIntraRegion();
if ($cityId > 0 && $isIntraRegion == false) {
$notInRuleGoodsName = $ExpressService->getNotInRuleGoodsName();
$this->setError("很抱歉,您的收货地址不在商品 [{$notInRuleGoodsName}] 的配送范围内");
}
// 订单总运费金额
$this->orderData['intra_region'] = $isIntraRegion;
$this->orderData['express_price'] = $ExpressService->getDeliveryFee();
return true;
}
/**
* 创建新订单
* @param array $order 订单信息
* @return bool
* @throws \Exception
*/
public function createOrder($order)
{
// 如果是参与拼单,则记录拼单id
$order['active_id'] = $this->param['active_id'];
// 表单验证
if (!$this->validateOrderForm($order, $this->param['linkman'], $this->param['phone'])) {
return false;
}
// 创建新的订单
$status = $this->model->transaction(function () use ($order) {
// 创建订单事件
return $this->createOrderEvent($order);
});
// 余额支付标记订单已支付
if ($status && $order['pay_type'] == PayTypeEnum::BALANCE) {
return $this->model->onPaymentByBalance($this->model['order_no']);
}
return $status;
}
/**
* 创建订单事件
* @param $order
* @return bool
* @throws BaseException
* @throws \think\exception\DbException
* @throws \Exception
*/
private function createOrderEvent($order)
{
// 新增订单记录
$status = $this->add($order, $this->param['remark']);
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
// 记录收货地址
$this->saveOrderAddress($order['address']);
} elseif ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
// 记录自提信息
$this->saveOrderExtract($this->param['linkman'], $this->param['phone']);
}
// 保存订单商品信息
$this->saveOrderGoods($order);
// 更新商品库存 (针对下单减库存的商品)
$this->updateGoodsStockNum($order['goods_list']);
// 设置优惠券使用状态
UserCouponModel::setIsUse($this->param['coupon_id']);
// 积分抵扣情况下扣除用户积分
if ($order['is_allow_points'] && $order['is_use_points'] && $order['points_num'] > 0) {
$describe = "用户消费:{$this->model['order_no']}";
$this->user->setIncPoints(-$order['points_num'], $describe);
}
// 获取订单详情
$detail = OrderModel::getUserOrderDetail($this->model['order_id'], $this->user['user_id']);
// 记录分销商订单
if ($this->checkoutRule['is_dealer'] && SharingSettingModel::getItem('basic')['is_dealer']) {
DealerOrderModel::createOrder($detail, OrderTypeEnum::SHARING);
}
return $status;
}
/**
* 构建支付请求的参数
* @return array
* @throws BaseException
* @throws \think\exception\DbException
*/
public function onOrderPayment()
{
return PaymentService::orderPayment($this->user, $this->model, $this->param['pay_type']);
}
/**
* 表单验证 (订单提交)
* @param array $order 订单信息
* @param string $linkman 联系人
* @param string $phone 联系电话
* @return bool
* @throws \think\exception\DbException
*/
private function validateOrderForm(&$order, $linkman, $phone)
{
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
if (empty($order['address'])) {
$this->error = '您还没有选择配送地址';
return false;
}
}
if ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
if (empty($order['extract_shop'])) {
$this->error = '您还没有选择自提门店';
return false;
}
if (empty($linkman) || empty($phone)) {
$this->error = '您还没有填写联系人和电话';
return false;
}
}
// 余额支付时判断用户余额是否足够
if ($order['pay_type'] == PayTypeEnum::BALANCE) {
if ($this->user['balance'] < $order['order_pay_price']) {
$this->error = '您的余额不足,无法使用余额支付';
return false;
}
}
// 验证拼单id是否合法
if ($order['active_id'] > 0) {
// 拼单详情
$detail = ActiveModel::detail($order['active_id']);
if (empty($detail)) {
$this->error = '很抱歉,拼单不存在';
return false;
}
// 验证当前拼单是否允许加入新成员
if (!$detail->checkAllowJoin()) {
$this->error = $detail->getError();
return false;
}
}
return true;
}
/**
* 当前订单是否存在和使用积分抵扣
* @param $order
* @return bool
*/
private function isExistPointsDeduction($order)
{
return $order['is_allow_points'] && $order['is_use_points'];
}
/**
* 新增订单记录
* @param $order
* @param string $remark
* @return false|int
*/
private function add(&$order, $remark = '')
{
// 当前订单是否存在和使用积分抵扣
$isExistPointsDeduction = $this->isExistPointsDeduction($order);
// 订单数据
$data = [
'user_id' => $this->user['user_id'],
'order_type' => $order['order_type'],
'active_id' => $order['active_id'],
'order_no' => $this->model->orderNo(),
'total_price' => $order['order_total_price'],
'order_price' => $order['order_price'],
'coupon_id' => $order['coupon_id'],
'coupon_money' => $order['coupon_money'],
'points_money' => $isExistPointsDeduction ? $order['points_money'] : 0.00,
'points_num' => $isExistPointsDeduction ? $order['points_num'] : 0,
'pay_price' => $order['order_pay_price'],
'delivery_type' => $order['delivery'],
'pay_type' => $order['pay_type'],
'buyer_remark' => trim($remark),
// 'order_source' => $this->orderSource['source'],
// 'order_source_id' => $this->orderSource['source_id'],
'points_bonus' => $order['points_bonus'],
'wxapp_id' => $this->wxapp_id,
];
if ($order['delivery'] == DeliveryTypeEnum::EXPRESS) {
$data['express_price'] = $order['express_price'];
} elseif ($order['delivery'] == DeliveryTypeEnum::EXTRACT) {
$data['extract_shop_id'] = $order['extract_shop']['shop_id'];
}
// 保存订单记录
return $this->model->save($data);
}
/**
* 保存订单商品信息
* @param $order
* @return int
*/
private function saveOrderGoods(&$order)
{
// 当前订单是否存在和使用积分抵扣
$isExistPointsDeduction = $this->isExistPointsDeduction($order);
// 订单商品列表
$goodsList = [];
foreach ($order['goods_list'] as $goods) {
/* @var GoodsModel $goods */
$goodsList[] = [
'user_id' => $this->user['user_id'],
'wxapp_id' => $this->wxapp_id,
'goods_id' => $goods['goods_id'],
'goods_name' => $goods['goods_name'],
'image_id' => $goods['image'][0]['image_id'],
'people' => $goods['people'],
'group_time' => $goods['group_time'],
'is_alone' => $goods['is_alone'],
'deduct_stock_type' => $goods['deduct_stock_type'],
'spec_type' => $goods['spec_type'],
'spec_sku_id' => $goods['goods_sku']['spec_sku_id'],
'goods_sku_id' => $goods['goods_sku']['goods_sku_id'],
'goods_attr' => $goods['goods_sku']['goods_attr'],
'content' => $goods['content'],
'goods_no' => $goods['goods_sku']['goods_no'],
'goods_price' => $goods['goods_sku']['goods_price'],
'line_price' => $goods['goods_sku']['line_price'],
'goods_weight' => $goods['goods_sku']['goods_weight'],
'is_user_grade' => (int)$goods['is_user_grade'],
'grade_ratio' => $goods['grade_ratio'],
'grade_goods_price' => $goods['grade_goods_price'],
'grade_total_money' => $goods['grade_total_money'],
'coupon_money' => $goods['coupon_money'],
'points_money' => $isExistPointsDeduction ? $goods['points_money'] : 0.00,
'points_num' => $isExistPointsDeduction ? $goods['points_num'] : 0,
'points_bonus' => $goods['points_bonus'],
'total_num' => $goods['total_num'],
'total_price' => $goods['total_price'],
'total_pay_price' => $goods['total_pay_price'],
'is_ind_dealer' => $goods['is_ind_dealer'],
'dealer_money_type' => $goods['dealer_money_type'],
'first_money' => $goods['first_money'],
'second_money' => $goods['second_money'],
'third_money' => $goods['third_money'],
];
}
return $this->model->goods()->saveAll($goodsList);
}
/**
* 更新商品库存 (针对下单减库存的商品)
* @param $goods_list
* @throws \Exception
*/
private function updateGoodsStockNum($goods_list)
{
$deductStockData = [];
foreach ($goods_list as $goods) {
// 下单减库存
$goods['deduct_stock_type'] == 10 && $deductStockData[] = [
'goods_sku_id' => $goods['goods_sku']['goods_sku_id'],
'stock_num' => ['dec', $goods['total_num']]
];
}
!empty($deductStockData) && (new GoodsSkuModel)->isUpdate()->saveAll($deductStockData);
}
/**
* 记录收货地址
* @param $address
* @return false|\think\Model
*/
private function saveOrderAddress($address)
{
if ($address['region_id'] == 0 && !empty($address['district'])) {
$address['detail'] = $address['district'] . ' ' . $address['detail'];
}
return $this->model->address()->save([
'user_id' => $this->user['user_id'],
'wxapp_id' => $this->wxapp_id,
'name' => $address['name'],
'phone' => $address['phone'],
'province_id' => $address['province_id'],
'city_id' => $address['city_id'],
'region_id' => $address['region_id'],
'detail' => $address['detail'],
]);
}
/**
* 保存上门自提联系人
* @param $linkman
* @param $phone
* @return false|\think\Model
*/
private function saveOrderExtract($linkman, $phone)
{
// 记忆上门自提联系人(缓存),用于下次自动填写
UserService::setLastExtract($this->model['user_id'], trim($linkman), trim($phone));
// 保存上门自提联系人(数据库)
return $this->model->extract()->save([
'linkman' => trim($linkman),
'phone' => trim($phone),
'user_id' => $this->model['user_id'],
'wxapp_id' => $this->wxapp_id,
]);
}
/**
* 设置错误信息
* @param $error
*/
protected function setError($error)
{
empty($this->error) && $this->error = $error;
}
/**
* 获取错误信息
* @return mixed
*/
public function getError()
{
return $this->error;
}
/**
* 是否存在错误
* @return bool
*/
public function hasError()
{
return !empty($this->error);
}
}

152
source/application/api/service/sharing/order/PaySuccess.php

@ -1,152 +0,0 @@
<?php
namespace app\api\service\sharing\order;
use think\Hook;
use app\api\service\Basics;
use app\api\model\User as UserModel;
use app\api\model\sharing\Order as OrderModel;
use app\api\model\sharing\Goods as GoodsModel;
use app\api\model\sharing\Active as ActiveModel;
use app\api\model\user\BalanceLog as BalanceLogModel;
//use app\api\model\WxappPrepayId as WxappPrepayIdModel;
use app\common\enum\user\balanceLog\Scene as SceneEnum;
use app\common\enum\order\PayType as PayTypeEnum;
use app\common\enum\OrderType as OrderTypeEnum;
/**
* 订单支付成功服务类
* Class PaySuccess
* @package app\api\service\sharing\order
*/
class PaySuccess extends Basics
{
// 订单模型
public $model;
// 当前用户信息
private $user;
/**
* 构造函数
* PaySuccess constructor.
* @param $orderNo
* @throws \think\exception\DbException
*/
public function __construct($orderNo)
{
// 实例化订单模型
$this->model = OrderModel::getPayDetail($orderNo);
if (!empty($this->model)) {
$this->wxappId = $this->model['wxapp_id'];
}
// 获取用户信息
$this->user = UserModel::detail($this->model['user_id']);
}
/**
* 获取订单详情
* @return OrderModel|null
*/
public function getOrderInfo()
{
return $this->model;
}
/**
* 订单支付成功业务处理
* @param $payType
* @param array $payData
* @return bool
*/
public function onPaySuccess($payType, $payData = [])
{
if (empty($this->model)) {
$this->error = '未找到该订单信息';
return false;
}
// 更新付款状态
$status = $this->updatePayStatus($payType, $payData);
// 订单支付成功行为
if ($status == true) {
Hook::listen('order_pay_success', $this->model, OrderTypeEnum::SHARING);
}
return $status;
}
/**
* 更新付款状态
* @param $payType
* @param $payData
* @return bool
*/
private function updatePayStatus($payType, $payData)
{
// 验证余额支付时用户余额是否满足
if ($payType == PayTypeEnum::BALANCE) {
if ($this->user['balance'] < $this->model['pay_price']) {
$this->error = '用户余额不足,无法使用余额支付';
return false;
}
}
$this->model->transaction(function () use ($payType, $payData) {
// 更新商品库存、销量
(new GoodsModel)->updateStockSales($this->model['goods']);
// 更新拼单记录
$this->saveSharingActive($this->model['goods'][0]);
// 整理订单信息
$order = ['pay_type' => $payType, 'pay_status' => 20, 'pay_time' => time()];
if ($payType == PayTypeEnum::WECHAT) {
$order['transaction_id'] = $payData['transaction_id'];
}
// 更新订单状态
$this->model->save($order);
// 累积用户总消费金额
$this->user->setIncPayMoney($this->model['pay_price']);
// 余额支付
if ($payType == PayTypeEnum::BALANCE) {
// 更新用户余额
$this->user->setDec('balance', $this->model['pay_price']);
BalanceLogModel::add(SceneEnum::CONSUME, [
'user_id' => $this->user['user_id'],
'money' => -$this->model['pay_price'],
], ['order_no' => $this->model['order_no']]);
}
// 微信支付
if ($payType == PayTypeEnum::WECHAT) {
// 更新prepay_id记录
// WxappPrepayIdModel::updatePayStatus($this->model['order_id'], OrderTypeEnum::SHARING);
}
});
return true;
}
/**
* 更新拼单记录
* @param $goods
* @return bool
* @throws \app\common\exception\BaseException
* @throws \think\exception\DbException
*/
private function saveSharingActive($goods)
{
// 新增/更新拼单记录
if ($this->model['order_type']['value'] != 20) {
return false;
}
// 拼单模型
$ActiveModel = new ActiveModel;
// 参与他人的拼单, 更新拼单记录
if ($this->model['active_id'] > 0) {
$ActiveModel = $ActiveModel::detail($this->model['active_id']);
return $ActiveModel->onUpdate($this->model['user_id'], $this->model['order_id']);
}
// 自己发起的拼单, 新增拼单记录
$ActiveModel->onCreate($this->model['user_id'], $this->model['order_id'], $goods);
// 记录拼单id
$this->model['active_id'] = $ActiveModel['active_id'];
return true;
}
}
Loading…
Cancel
Save