372 lines
14 KiB
Plaintext
372 lines
14 KiB
Plaintext
<?php
|
||
|
||
class OrderController extends Controller
|
||
{
|
||
/**
|
||
* 下单计算金额
|
||
*/
|
||
public function infinite_ordermoney()
|
||
{
|
||
$user = $this->getUser();
|
||
$params = $this->getRequestParams();
|
||
|
||
$goods = $this->getGoods($params['goods_id']);
|
||
if (!$goods || $goods['status'] != 1) return $this->renderError("盒子不存在或已下架");
|
||
|
||
$goodsExtend = GoodsExtend::getGoodsExtendByGoodsId($goods['id'], $goods['type']);
|
||
if (!$goodsExtend) return $this->renderError("盒子类型配置不存在");
|
||
|
||
if (($res = $this->checkGlobalLimit($goods, $user['id'], $params['prize_num'])) !== true) return $res;
|
||
if (($res = $this->checkDailyLimit($goods, $user['id'], $params['prize_num'])) !== true) return $res;
|
||
if (($res = $this->checkConsumptionLimit($goods, $user)) !== true) return $res;
|
||
|
||
$priceInfo = $this->calculatePriceInfo($goods, $goodsExtend, $user, $params);
|
||
return $this->renderSuccess("请求成功", $priceInfo);
|
||
}
|
||
|
||
/**
|
||
* 下单
|
||
*/
|
||
public function infinite_orderbuy()
|
||
{
|
||
$user = $this->getUser();
|
||
if (empty($user['mobile'])) return $this->renderError('请先绑定手机号', [], -9);
|
||
|
||
$params = $this->getRequestParams();
|
||
$goods = $this->getGoods($params['goods_id']);
|
||
if (!$goods || $goods['status'] != 1) return $this->renderError("盒子不存在或已下架");
|
||
|
||
$goodsExtend = GoodsExtend::getGoodsExtendByGoodsId($goods['id'], $goods['type']);
|
||
if (!$goodsExtend) return $this->renderError("盒子类型配置不存在");
|
||
|
||
if (!in_array($goods['type'], [2, 8, 9, 10, 16, 17])) return $this->renderError("非法请求");
|
||
|
||
if (($res = $this->checkGlobalLimit($goods, $user['id'], $params['prize_num'])) !== true) return $res;
|
||
if (($res = $this->checkDailyLimit($goods, $user['id'], $params['prize_num'])) !== true) return $res;
|
||
if (($res = $this->checkConsumptionLimit($goods, $user)) !== true) return $res;
|
||
|
||
if (!$this->checkGoodsPrize($goods, $params)) return $this->renderError('暂无奖品信息');
|
||
|
||
$priceInfo = $this->calculatePriceInfo($goods, $goodsExtend, $user, $params);
|
||
|
||
if (!$this->acquireLock($user['id'])) return $this->renderError("当前操作太快了,请等待");
|
||
|
||
$orderResult = $this->createOrderAndPay($user, $goods, $params, $priceInfo);
|
||
$this->releaseLock($user['id']);
|
||
|
||
return $orderResult;
|
||
}
|
||
|
||
// ================= 工具方法 =================
|
||
|
||
private function getRequestParams()
|
||
{
|
||
return [
|
||
'goods_id' => request()->param('goods_id/d', 0),
|
||
'prize_num' => request()->param('prize_num/d', 0),
|
||
'use_money_is' => request()->param('use_money_is/d', 0),
|
||
'use_integral_is' => request()->param('use_integral_is/d', 0),
|
||
'use_money2_is' => request()->param('use_money2_is/d', 0),
|
||
'coupon_id' => request()->param('coupon_id'),
|
||
'is_mibao' => request()->param('is_mibao/d', 0),
|
||
'ad_id' => request()->header('adid'),
|
||
];
|
||
}
|
||
|
||
private function getGoods($goodsId)
|
||
{
|
||
return Goodsmodel::field('id,title,imgurl_detail,type,price,status,is_shou_zhe,choujiang_xianzhi,quanju_xiangou,daily_xiangou')
|
||
->where(['id' => $goodsId])->find();
|
||
}
|
||
|
||
private function checkGlobalLimit($goods, $userId, $buyCount)
|
||
{
|
||
if ($goods['quanju_xiangou'] <= 0) return true;
|
||
|
||
$userCount = OrderList::where('goods_id', $goods['id'])
|
||
->where('user_id', $userId)->where('parent_goods_list_id', 0)->count();
|
||
|
||
if ($userCount >= $goods['quanju_xiangou']) {
|
||
return $this->renderError("当前限购{$goods['quanju_xiangou']}次");
|
||
}
|
||
|
||
if ($userCount + $buyCount > $goods['quanju_xiangou']) {
|
||
$allow = $goods['quanju_xiangou'] - $userCount;
|
||
return $this->renderError("购买超出限制,还允许购买{$allow}次");
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
private function checkDailyLimit($goods, $userId, $buyCount)
|
||
{
|
||
if ($goods['daily_xiangou'] <= 0) return true;
|
||
|
||
$todayMidnight = strtotime('today');
|
||
$userTodayCount = OrderList::where('goods_id', $goods['id'])
|
||
->where('user_id', $userId)
|
||
->where('parent_goods_list_id', 0)
|
||
->where('addtime', '>=', $todayMidnight)
|
||
->count();
|
||
|
||
if ($userTodayCount >= $goods['daily_xiangou']) {
|
||
return $this->renderError("今日限购{$goods['daily_xiangou']}次");
|
||
}
|
||
|
||
if ($userTodayCount + $buyCount > $goods['daily_xiangou']) {
|
||
$allow = $goods['daily_xiangou'] - $userTodayCount;
|
||
return $this->renderError("购买超出限制,今日还允许购买{$allow}次");
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
private function checkConsumptionLimit($goods, $user)
|
||
{
|
||
if (empty($goods['choujiang_xianzhi']) || $goods['choujiang_xianzhi'] <= 0) return true;
|
||
|
||
$userId = $user['id'];
|
||
$userPrice = Order::where('user_id', $userId)->where('status', 1)->sum('price');
|
||
|
||
if ($userPrice < $goods['choujiang_xianzhi']) {
|
||
if ($user['istest'] > 0) {
|
||
$userPrice = Order::where('user_id', $userId)->where('status', 1)->sum('order_zhe_total');
|
||
}
|
||
if ($userPrice < $goods['choujiang_xianzhi']) {
|
||
return $this->renderError("消费满{$goods['choujiang_xianzhi']}元可参与 已消费" . round($userPrice, 2) . "元");
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
private function checkGoodsPrize($goods, $params)
|
||
{
|
||
$where = [['goods_id', '=', $goods['id']]];
|
||
|
||
if ($goods['type'] == 10) {
|
||
$where[] = ['shang_id', 'between', [10, 33]];
|
||
$where[] = ['num', '=', 1];
|
||
} else {
|
||
$where[] = ['num', '=', 0];
|
||
$where[] = ['real_pro', '>', 0];
|
||
$where[] = ['shang_id', 'between', self::$shang_prize_id];
|
||
}
|
||
|
||
if ($goods['type'] == 9 && $params['is_mibao'] == 1) {
|
||
$where[] = ['lian_ji_type', '=', 1];
|
||
}
|
||
|
||
return GoodsList::where($where)->find();
|
||
}
|
||
|
||
private function acquireLock($userId)
|
||
{
|
||
$redis = (new \app\common\server\RedisHelper())->getRedis();
|
||
$key = "kpw_infinite_orderbuy_{$userId}";
|
||
if ($redis->get($key)) return false;
|
||
$redis->set($key, 1, 3);
|
||
return true;
|
||
}
|
||
|
||
private function releaseLock($userId)
|
||
{
|
||
$redis = (new \app\common\server\RedisHelper())->getRedis();
|
||
$key = "kpw_infinite_orderbuy_{$userId}";
|
||
$redis->del($key);
|
||
}
|
||
|
||
/**
|
||
* 金额计算逻辑,包括首抽折扣、优惠券、三种抵扣方式
|
||
*/
|
||
private function calculatePriceInfo($goods, $goodsExtend, $user, $params)
|
||
{
|
||
$prizeNum = intval($params['prize_num']);
|
||
$boxPrice = $goods['price'];
|
||
|
||
// 首抽五折逻辑
|
||
$shouZhePrice = 0;
|
||
if (!in_array($goods['type'], [5, 10])) {
|
||
$isChou = Order::where([['user_id', '=', $user['id']], ['status', '=', 1]])->find();
|
||
$isChou2 = Order::where([['is_shou_zhe', '=', 1], ['status', '=', 1], ['user_id', '=', $user['id']]])->find();
|
||
if (!$isChou && !$isChou2 && $goods['is_shou_zhe'] == 1) {
|
||
$shouZhePrice = bcmul((string)$boxPrice, '0.5', 2);
|
||
}
|
||
}
|
||
|
||
$goods['shou_zhe_price'] = $shouZhePrice;
|
||
|
||
// 初始总价
|
||
$price = bcmul((string)$boxPrice, (string)$prizeNum, 2);
|
||
$price = bcsub($price, (string)$shouZhePrice, 2);
|
||
$orderTotal = $orderZheTotal = $price;
|
||
|
||
// 抵扣处理
|
||
$useMoney = 0;
|
||
$useIntegral = 0;
|
||
$useMoney2 = 0;
|
||
$couponPrice = 0;
|
||
$zhe = 0;
|
||
$iszhifu = 0;
|
||
|
||
// 优惠券抵扣
|
||
if ($shouZhePrice <= 0 && !empty($params['coupon_id']) && $goodsExtend['pay_coupon'] == 1) {
|
||
$coupon = CouponReceiveModel::where([
|
||
'id' => $params['coupon_id'],
|
||
'status' => 0,
|
||
'user_id' => $user['id']
|
||
])->where('man_price', '<=', $price)->where('end_time', '>', time())->find();
|
||
|
||
if ($coupon) {
|
||
$couponPrice = $coupon['price'];
|
||
$price = bcsub($price, (string)$couponPrice, 2);
|
||
}
|
||
}
|
||
|
||
if ($price < 0) $price = '0.00';
|
||
$orderZheTotal = $price;
|
||
|
||
// 余额抵扣
|
||
if ($params['use_money_is'] == 1 && $goodsExtend['pay_balance'] == 1) {
|
||
if ($goodsExtend['is_deduction'] == 1) {
|
||
$useMoney = min($user['money'], $price);
|
||
$price = bcsub($price, (string)$useMoney, 2);
|
||
} else if ($user['money'] >= $price) {
|
||
$useMoney = $price;
|
||
$price = '0.00';
|
||
$iszhifu++;
|
||
} else {
|
||
return $this->renderError('金额不足');
|
||
}
|
||
}
|
||
|
||
// 积分抵扣(1:100)
|
||
if ($params['use_integral_is'] == 1 && $goodsExtend['pay_currency'] == 1) {
|
||
$priceInIntegral = bcmul($price, '100', 0);
|
||
if ($goodsExtend['is_deduction'] == 1) {
|
||
$useIntegral = min($user['integral'], $priceInIntegral);
|
||
$price = bcsub($price, bcdiv((string)$useIntegral, '100', 2), 2);
|
||
} else if ($user['integral'] >= $priceInIntegral) {
|
||
$useIntegral = $priceInIntegral;
|
||
$price = '0.00';
|
||
$iszhifu++;
|
||
} else {
|
||
return $this->renderError('金额不足');
|
||
}
|
||
}
|
||
|
||
// 货币2抵扣
|
||
if ($params['use_money2_is'] == 1 && $goodsExtend['pay_currency2'] == 1) {
|
||
$priceInCurrency2 = bcmul($price, '100', 0);
|
||
if ($goodsExtend['is_deduction'] == 1) {
|
||
$useMoney2 = min($user['money2'] ?? 0, $priceInCurrency2);
|
||
$price = bcsub($price, bcdiv((string)$useMoney2, '100', 2), 2);
|
||
} else if (($user['money2'] ?? 0) >= $priceInCurrency2) {
|
||
$useMoney2 = $priceInCurrency2;
|
||
$price = '0.00';
|
||
$iszhifu++;
|
||
} else {
|
||
return $this->renderError('金额不足');
|
||
}
|
||
}
|
||
|
||
// 支付方式校验
|
||
if ($goodsExtend['is_deduction'] == 0 && $iszhifu == 0 && $goodsExtend['pay_wechat'] == 0) {
|
||
return $this->renderError('请选择支付方式');
|
||
}
|
||
|
||
return [
|
||
'goods' => $goods,
|
||
'order_total' => round(floatval($orderTotal), 2),
|
||
'order_zhe_total' => round($orderZheTotal, 2),
|
||
'zhe' => round($zhe, 2),
|
||
'price' => round($price, 2),
|
||
'integral' => round($user['integral'], 2),
|
||
'use_integral' => round($useIntegral, 2),
|
||
'use_integral_money' => round($useIntegral / 100, 2),
|
||
'money' => round($user['money'], 2),
|
||
'use_money' => round($useMoney, 2),
|
||
'score' => $user['money2'] ?? 0,
|
||
'use_score' => $useMoney2,
|
||
'coupon_id' => $params['coupon_id'] ?? 0,
|
||
'coupon_price' => round($couponPrice, 2),
|
||
'goods_extend' => $goodsExtend,
|
||
'prize_num' => $prizeNum
|
||
];
|
||
}
|
||
|
||
|
||
private function createOrderAndPay($user, $goods, $params, $priceInfo)
|
||
{
|
||
Db::startTrans();
|
||
try {
|
||
$num = ($goods['type'] == 10) ? 1 : 0;
|
||
$orderNum = create_order_no('MH_', 'order', 'order_num');
|
||
|
||
$orderId = Order::insertGetId([
|
||
'user_id' => $user['id'],
|
||
'order_num' => $orderNum,
|
||
'order_total' => $priceInfo['order_total'],
|
||
'order_zhe_total' => $priceInfo['order_zhe_total'],
|
||
'price' => $priceInfo['price'],
|
||
'use_money' => $priceInfo['use_money'],
|
||
'use_integral' => $priceInfo['use_integral'],
|
||
'use_money2' => $priceInfo['use_score'],
|
||
'use_score' => 0,
|
||
'zhe' => $priceInfo['zhe'],
|
||
'goods_id' => $goods['id'],
|
||
'num' => $num,
|
||
'goods_price' => $goods['price'],
|
||
'goods_title' => $goods['title'],
|
||
'goods_imgurl' => $goods['imgurl_detail'],
|
||
'prize_num' => $params['prize_num'],
|
||
'status' => 0,
|
||
'pay_type' => 1,
|
||
'order_type' => $goods['type'],
|
||
'addtime' => time(),
|
||
'coupon_id' => $priceInfo['coupon_id'],
|
||
'use_coupon' => $priceInfo['coupon_price'],
|
||
'is_mibao' => $params['is_mibao'],
|
||
'is_shou_zhe' => $goods['shou_zhe_price'] > 0 ? 1 : 0,
|
||
'ad_id' => $params['ad_id'],
|
||
'click_id' => $user['click_id'] ?? ''
|
||
]);
|
||
|
||
// 是否需要支付
|
||
if ($priceInfo['price'] > 0) {
|
||
$body = '购买盒子' . $goods['title'];
|
||
$attach = $goods['type'] == 16 ? 'order_fbs' : 'order_wxs';
|
||
$payRes = (new Pay())->wxCreateOrder($orderNum, $priceInfo['price'], $user['openid'], $body, $attach);
|
||
|
||
if ($payRes['status'] != 1) {
|
||
Db::rollback();
|
||
return $this->renderError('下单失败');
|
||
}
|
||
|
||
Db::commit();
|
||
return $this->renderSuccess('下单成功', [
|
||
'status' => 1,
|
||
'order_num' => $orderNum,
|
||
'res' => $payRes['data']
|
||
]);
|
||
} else {
|
||
// 0元单直接开奖
|
||
$res = (new Notify($this->app))->infinite_drawprize_notice($user['id'], $orderId, $goods['id'], $num);
|
||
if (!$res) {
|
||
Db::rollback();
|
||
return $this->renderError('开奖失败');
|
||
}
|
||
|
||
Db::commit();
|
||
return $this->renderSuccess('下单成功', [
|
||
'status' => 0,
|
||
'order_num' => $orderNum
|
||
]);
|
||
}
|
||
} catch (\Throwable $e) {
|
||
Db::rollback();
|
||
return $this->renderError('系统异常: ' . $e->getMessage());
|
||
}
|
||
}
|
||
}
|