manghe/app/api/controller/Notify.php
2025-05-04 16:54:54 +08:00

2996 lines
126 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace app\api\controller;
use app\common\model\CardLevel;
use app\common\model\Goods;
use app\common\model\GoodsList;
use app\common\model\GoodsLock;
use app\common\model\ItemCard;
use app\common\model\Order;
use app\common\model\OrderList;
use app\common\model\OrderListSend;
use app\common\model\OrderSale;
use app\common\model\ProductOrder;
use app\common\model\ProductOrderList;
use app\common\model\ProfitPay;
use app\common\model\Shang;
use app\common\model\User;
use app\common\model\UserLevelCoupon;
use app\common\model\UserRecharge;
use app\common\model\Ads;
use think\facade\Db;
use think\facade\Request;
use app\common\model\CouponReceive as CouponReceiveModel;
use app\common\helper\ConfigHelper;
use app\common\service\RewardService;
/**
* Class Notify 同步处理
* @package app\index\controller
*/
class Notify extends Base
{
static $shang_prize_id = [10, 33];#抽奖赏品id
static $shang_give_first_id = 1;#赠送(FIRST赏)赏品id
static $shang_give_arr = [2, 3, 4];#赠送(LAST赏 最终赏 全局赏)赏品id
static $shang_give_w_id = 4;#赠送(全局赏)赏品id
static $shang_give_quan_id = 5;#赠送(拳王赏)赏品id
static $secretKey = null;
static $secretKeyAccount = null;
public function initialize()
{
// 获取微信支付配置
$wxpayConfig = \app\common\helper\WxPayHelper::getWxPayConfig();
$merchant = $wxpayConfig['merchant'];
// 使用随机商户的密钥
static::$secretKey = $merchant['keys'];
// 获取公众号密钥
static::$secretKeyAccount = getConfig('wechatofficialaccount')['keys'];
}
public function ceshi()
{
$order['goods_id'] = 18;
$order['num'] = 1;
$order['order_type'] = 3;
// dd(11);
$this->quan_prize_notice($order);
}
/**
* 特殊奖品开奖 拳王赏
* @param $order 订单信息
*/
protected function quan_prize_notice($order)
{
$res = [];
$goods_id = $order['goods_id'];
$num = $order['num'];
$order_type = $order['order_type'];
#盒子
$goods_info = Goods::field('prize_num,stock')->where(['id' => $goods_id])->find();
#特殊奖品存在where('goods_id', '=', $goods_id)
$special_prize = GoodsList::where('goods_id', '=', $goods_id)
->where('num', '=', $num)
->where('surplus_stock', '>', 0)
->where('shang_id', '=', self::$shang_give_quan_id)
->order('prize_num desc')
->select();
// dd($special_prize);
$user_ids = [];
foreach ($special_prize as $value) {
$surplus_give_stock = $value ? $value['surplus_stock'] : 0;
if ($value && $surplus_give_stock > 0) {
#符合条件的订单
$quan_prize_num = $value['prize_num'];
// dd($quan_prize_num);
// var_dump($quan_prize_num);
$prize_num_data = OrderList::field('id,user_id,count(`id`) as all_num')
->where('goods_id', '=', $goods_id)
->where('num', '=', $num)
->where('order_type', '=', $order_type)
->where('shang_id', '=', self::$shang_give_w_id)
->having('all_num', '>=', $quan_prize_num)
->group('user_id')
->select()->toArray();
$prize_num_data_arr = [];
foreach ($prize_num_data as $val) {
if ($val['all_num'] >= $quan_prize_num && !in_array($val['user_id'], $user_ids)) {
$prize_num_data_arr[] = $val;
}
}
// dd($prize_num_data_arr);
if ($prize_num_data_arr) {
// dd($prize_num_data);
#多个随机
shuffle($prize_num_data_arr);
$quan_prize_info = $prize_num_data_arr[0];
$user_id = $quan_prize_info['user_id'];
$user_ids[] = $quan_prize_info['user_id'];
$order_goods = [
'order_id' => 0,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => $num,
'shang_id' => $value['shang_id'],
'goodslist_id' => $value['id'],
'goodslist_title' => $value['title'],
'goodslist_imgurl' => $value['imgurl'],
'goodslist_price' => $value['price'],
'goodslist_money' => $value['money'],
'goodslist_type' => $value['goods_type'],
'goodslist_sale_time' => $value['sale_time'],
'addtime' => time(),
'prize_code' => $value['prize_code'],
'order_type' => $order_type,
'order_list_id' => 0,
];
// var_dump($order_goods);
#新增奖品列表
$res[] = OrderList::insert($order_goods);
#减少库存
$res[] = GoodsList::field('surplus_stock')
->where(['id' => $value['id']])
->dec('surplus_stock')
->update();
// var_dump($res);
}
}
}
#赏品
$goods_list_zd = GoodsList::where(['goods_id' => $goods_id])
->where(['num' => 1])
->select()->toArray();
if ($goods_list_zd) {
#循环数据
$save_sports_data = [];
$start_num = $goods_info['stock'] + 1;
for ($i = $start_num; $i <= $start_num; $i++) {
foreach ($goods_list_zd as $k => $v) {
unset($v['id']);
unset($v['num']);
$v['num'] = $i;
$v['surplus_stock'] = $v['stock'];
$save_sports_data[] = $v;
}
}
#添加赏品
$res[] = GoodsList::insertAll($save_sports_data);
#增加库存
$res[] = Goods::where(['id' => $goods_id])->inc('stock', 1)->update();
}
return $res;
}
/**
*
* 获取支付结果通知数据
* return array
*/
public function order_notify()
{
#获取通知的数据
$xml = file_get_contents("php://input");
if (empty($xml)) {
return false;
}
#转成数组
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
$sign = $data['sign'];
unset($data['sign']);
$newSign = $this->MakeSign($data);
$newSignAccount = $this->MakeSignAccount($data);
#验证签名
if ($sign == $newSign || $sign == $newSignAccount) {
//如果成功返回了
if ($data['return_code'] == 'SUCCESS' && $data['result_code'] == 'SUCCESS') {
$user = User::where('openid', $data['openid'])->find();
try {
// 使用profit_pay表记录支付信息而不是wxpay_log表
Db::name('profit_pay')->insert([
'user_id' => $user['id'],
'order_num' => $data['out_trade_no'],
'change_money' => isset($data['total_fee']) ? ($data['total_fee'] / 100) : 0,
'content' => $data['attach'] ? $data['attach'] : '微信支付',
'pay_type' => 1, // 1微信 2支付宝
'addtime' => time(),
]);
} catch (\Throwable $e) {
$this->CallbackSuccess();
}
$out_trade_no = $data['out_trade_no'];//订单号
$table = $data['attach'];#表名
if ($table == 'user_recharge') {#余额充值
$orderInfo = UserRecharge::where('order_num', '=', $out_trade_no)
->where(['status' => 1])
->find();
#这个订单存在状态对
if ($orderInfo && $orderInfo['status'] == 1) {
$user_id = $orderInfo['user_id'];
$money = $orderInfo['money'];
Db::startTrans();
#修改订单状态
$res[] = UserRecharge::field('status,pay_time')
->where(['id' => $orderInfo['id']])->update([
'status' => 2,
'pay_time' => time(),
]);
$res[] = User::changeMoney($user_id, $money, 2, '在线充值');
#记录微信支付
$res[] = ProfitPay::insert([
'user_id' => $user_id,
'order_num' => $out_trade_no,
'change_money' => $money,
'content' => '微信支付',
'pay_type' => 1,#1微信 2支付宝
'addtime' => time(),
]);
if (resCheck($res)) {
Db::commit();
} else {
Db::rollback();
}
}
} elseif ($table == 'order_yfs' || $table == 'order_lts' || $table == 'order_zzs' || $table == 'order_flw' || $table == 'order_scs') {#抽赏一番赏 擂台赏
$orderInfo = Order::where('order_num', '=', $out_trade_no)
->where('status', '=', 0)
->find();
#这个订单存在状态对
if ($orderInfo && $orderInfo['status'] == 0) {
$user_id = $orderInfo['user_id'];
$price = $orderInfo['price'];
Db::startTrans();
try {
#开盒子
$res[] = $this->drawprize_notice($user_id, $orderInfo['id'], $orderInfo['goods_id'], $orderInfo['num']);
$this->wx_gf_fahuo($user_id, $orderInfo['order_num']);
#广告收益回调
if (!empty($orderInfo['click_id']) && !empty($orderInfo['ad_id'])) {
$order_ad_num = Order::where('user_id', '=', $user_id)->where('status', '=', 1)->where('ad_id', '>', 0)->where('click_id', '>', 0)->where('price', '>', 0)->count();
if ($order_ad_num <= 1) {
$this->ad_notify($orderInfo['ad_id'], $orderInfo['click_id']);
}
}
} catch (\Throwable $e) {
Db::rollback();
#卡单了
Order::field('kd_is')->where(['id' => $orderInfo['id']])
->update(['kd_is' => 1]);
#通知微信
$this->CallbackSuccess();
}
#记录微信支付
$res[] = ProfitPay::insert([
'user_id' => $user_id,
'order_num' => $out_trade_no,
'change_money' => $price,
'content' => '购买盒子' . $orderInfo['goods_title'],
'pay_type' => 1,#1微信 2支付宝
'addtime' => time(),
]);
if (resCheck($res)) {
Db::commit();
} else {
Db::rollback();
}
} else {
$tempOrder = Order::where('order_num', '=', $out_trade_no)
->find();
if ($tempOrder) {
// 作废订单支付
$tempOrder->status = 3;
$tempOrder->save();
}
}
} elseif ($table == 'order_wxs' || $table == 'order_fbs') {#抽赏无限赏
$orderInfo = Order::where('order_num', '=', $out_trade_no)
->where('status', '=', 0)
->find();
#这个订单存在状态对
if ($orderInfo && $orderInfo['status'] == 0) {
$user_id = $orderInfo['user_id'];
$price = $orderInfo['price'];
Db::startTrans();
$res[] = $this->infinite_drawprize_notice($user_id, $orderInfo['id'], $orderInfo['goods_id']);
#记录微信支付
$res[] = ProfitPay::insert([
'user_id' => $user_id,
'order_num' => $out_trade_no,
'change_money' => $price,
'content' => '购买盒子' . $orderInfo['goods_title'],
'pay_type' => 1,#1微信 2支付宝
'addtime' => time(),
]);
$this->wx_gf_fahuo($user_id, $orderInfo['order_num']);
#广告收益回调
if (!empty($orderInfo['click_id']) && !empty($orderInfo['ad_id'])) {
$order_ad_num = Order::where('user_id', '=', $user_id)->where('status', '=', 1)->where('ad_id', '>', 0)->where('click_id', '>', 0)->where('price', '>', 0)->count();
if ($order_ad_num <= 1) {
$this->ad_notify($orderInfo['ad_id'], $orderInfo['click_id']);
}
}
if (resCheck($res)) {
Db::commit();
} else {
Db::rollback();
}
}
} elseif ($table == 'order_ckj') {#抽赏抽卡机
$orderInfo = Order::where('order_num', '=', $out_trade_no)
->where('status', '=', 0)
->where('order_type', '=', 4)
->find();
#这个订单存在状态对
if ($orderInfo && $orderInfo['status'] == 0) {
$user_id = $orderInfo['user_id'];
$price = $orderInfo['price'];
Db::startTrans();
$res[] = $this->cardextractor_drawprize_notice($user_id, $orderInfo['id'], $orderInfo['goods_id']);
#记录微信支付
$res[] = ProfitPay::insert([
'user_id' => $user_id,
'order_num' => $out_trade_no,
'change_money' => $price,
'content' => '购买盒子' . $orderInfo['goods_title'],
'pay_type' => 1,#1微信 2支付宝
'addtime' => time(),
]);
$this->wx_gf_fahuo($user_id, $orderInfo['order_num']);
if (resCheck($res)) {
Db::commit();
} else {
Db::rollback();
}
}
} elseif ($table == 'order_list_send') {#背包发货
$orderInfo = OrderListSend::where('send_num', '=', $out_trade_no)
->where('status', '=', 0)
->find();
#这个订单存在状态对
if ($orderInfo && $orderInfo['status'] == 0) {
$user_id = $orderInfo['user_id'];
$freight = $orderInfo['freight'];
Db::startTrans();
$res[] = $this->reward_order_handle($user_id, $orderInfo['id']);
#记录微信支付
$res[] = ProfitPay::insert([
'user_id' => $user_id,
'order_num' => $out_trade_no,
'change_money' => $freight,
'content' => '背包发货',
'pay_type' => 1,#1微信 2支付宝
'addtime' => time(),
]);
$this->wx_gf_fahuo($user_id, $orderInfo['order_num']);
if (resCheck($res)) {
Db::commit();
} else {
Db::rollback();
}
}
} elseif ($table == 'order_js') {
}
}
}
$this->CallbackSuccess();
}
/*
广告推广
*/
public function ad_notify($ads_id, $click_id)
{
$tencent_ad = Ads::where('id', $ads_id)->find();
if (!empty($tencent_ad)) {
$result = tencent_ad_attribution($click_id, 1, $tencent_ad['account_id'], $tencent_ad['access_token'], $tencent_ad['user_action_set_id']);
dump($result);
}
}
/**
* 生成签名
* @return 签名
*/
public function MakeSign($params)
{
//签名步骤一:按字典序排序数组参数
ksort($params);
$string = $this->ToUrlParams($params);
//签名步骤二在string后加入KEY
$string = $string . "&key=" . static::$secretKey;
//签名步骤三MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
/**
* 生成签名
* @return 签名
*/
public function MakeSignAccount($params)
{
//签名步骤一:按字典序排序数组参数
ksort($params);
$string = $this->ToUrlParams($params);
//签名步骤二在string后加入KEY
$string = $string . "&key=" . static::$secretKeyAccount;
//签名步骤三MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
/**
* 将参数拼接为url: key=value&key=value
* @param $params
* @return string
*/
public function ToUrlParams($params)
{
$string = '';
if (!empty($params)) {
$array = array();
foreach ($params as $key => $value) {
$array[] = $key . '=' . $value;
}
$string = implode("&", $array);
}
return $string;
}
/**
* 接收通知成功后应答输出XML数据
* @param string $xml
*/
public function CallbackSuccess()
{
exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
}
/**
* 接收通知成功后应答输出XML数据
* @param string $xml
*/
public function CallbackSuccess_new($payment_type)
{
if ($payment_type == "zfbpay") {
exit('success');
} else {
exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
}
}
/**
* 抽赏开始抽赏======================================================
* @param int $user_id 会员id
* @param int $order_id 订单ID
* @param int $goods_id 盒子id
* @param int $num 盒子箱号
*/
public function drawprize_notice($user_id = 0, $order_id = 0, $goods_id = 0, $num = 0)
{
$res = [];
$order = Order::where(['id' => $order_id])
->where(['user_id' => $user_id])
->where(['goods_id' => $goods_id])
->where(['num' => $num])
->where(['status' => 0])
->where('order_type', 'in', [1, 3, 5, 6, 11, 15, 10])
->find();
if ($order) {
#改变状态
$res[] = Order::field('status,pay_time')
->where(['id' => $order['id']])
->update([
'status' => 1,
'pay_time' => time(),
]);
#扣余额
if ($order['use_money'] > 0) {
$res[] = User::changeMoney($order['user_id'], -$order['use_money'], 3, '购买盒子' . $order['goods_title']);
}
#扣吧唧币
if ($order['use_integral'] > 0) {
$res[] = User::changeIntegral($order['user_id'], -$order['use_integral'], 2, '购买盒子' . $order['goods_title']);
}
#扣积分
if ($order['use_score'] > 0) {
$res[] = User::changeScore($order['user_id'], -$order['use_score'], 2, '购买盒子' . $order['goods_title']);
}
# 扣货币2
if ($order['use_money2'] > 0) {
$res[] = User::changeMoney2($order['user_id'], -$order['use_money2'], 2, '购买盒子' . $order['goods_title']);
}
#判断一下优惠券
if (!empty($order['coupon_id'])) {
$coupon = CouponReceiveModel::where(['id' => $order['coupon_id'], 'status' => 0])->update(['status' => 1]);
}
#分销奖励
$res[] = User::distribution($order);
#分销奖励
if ($order['order_type'] == 15) {
$res[] = $this->ordinary_prize_notice_flw($order);
} elseif ($order['order_type'] == 10) {
$res[] = $this->infinite_shangchengshang($order);
} else {
#普通奖品==========================================================
$res[] = $this->ordinary_prize_notice($order);
#普通奖品==========================================================
#判断是否发积分 发券
$res[] = User::is_integral_coupon($order);
//升级欧气值
if ($order['price'] > 0) {
User::ou_qi_level_up($order['user_id'], $order['price']);
}
#特殊奖品**********************************************************
#普通奖品余量信息
$goodslist = GoodsList::field('sum(`stock`) as stock, sum(`surplus_stock`) as surplus_stock')
->where('goods_id', '=', $goods_id)
->where('num', '=', $num)
->where('shang_id', 'between', self::$shang_prize_id)
->where('goods_list_id', '=', 0)
->find();
// var_dump($goodslist['surplus_stock']);
#普通赏销量数量
$sale_count = $goodslist['stock'] - $goodslist['surplus_stock'];
#普通奖品一半
$first_count = floor($goodslist['stock'] / 2);
#FIRST
if ($order['order_type'] != 3 && $sale_count >= $first_count) {
$res[] = $this->special_first_notice($order, $first_count);
}
#LAST赏 全局赏 拳王赏
if ($goodslist['surplus_stock'] <= 0) {
// var_dump($goodslist['surplus_stock']);
$res[] = $this->special_prize_notice($order, $first_count);
// var_dump($res);
#擂台赏
if ($order['order_type'] == 3) {
$res[] = $this->quan_prize_notice($order);
}
#增加盒子库存
$goods = Goods::field('id,stock,sale_stock')
->where(['id' => $goods_id])
->find();
$save_update = [];
$goods_sale_stock = $goods['sale_stock'] + 1;
if ($goods_sale_stock >= $goods['stock']) {
$save_update['status'] = 3;
}
$save_update['sale_stock'] = $goods_sale_stock;
$res[] = Goods::field('id,status,sale_stock')
->where(['id' => $goods_id])
->update($save_update);
}
}
#特殊奖品**********************************************************
} else {
$res[] = 0;
}
return $res;
}
/**
* 普通奖品开奖
* @param $order 订单信息
*/
protected function ordinary_prize_notice($order)
{
$user_id = $order['user_id'];
$order_id = $order['id'];
$goods_id = $order['goods_id'];
$num = $order['num'];
$order_type = $order['order_type'];
#抽奖数量
$prize_num = $order['prize_num'];
#普通奖品信息
$ordinary_prize = GoodsList::where('goods_id', '=', $goods_id)
->where('num', '=', $num)
->where('shang_id', 'between', self::$shang_prize_id)
->where('goods_list_id', '=', 0)
->order('sort desc,shang_id asc')
->select()->toArray();
if (!$ordinary_prize) {
$res[] = 0;
return $res;
}
$res[] = $this->ordinary_prize_notice_box($ordinary_prize, $prize_num, $order_id, $user_id, $goods_id, $order_type, $num);
return $res;
}
/**
* 普通奖品开奖宝箱
* @param mixed $ordinary_prize
* @param mixed $prize_num
* @param mixed $order_id
* @param mixed $user_id
* @param mixed $goods_id
* @param mixed $order_type
* @param mixed $num
* @return array<array|GoodsList|int>
*/
protected function ordinary_prize_notice_box($ordinary_prize, $prize_num, $order_id, $user_id, $goods_id, $order_type, $num)
{
$res = [];
try {
// 过滤掉库存为0的奖品
$valid_prizes = array_filter($ordinary_prize, function ($item) {
return $item['surplus_stock'] > 0;
});
if (empty($valid_prizes)) {
return [0]; // 没有有效奖品
}
// 创建权重数组用于加权随机
$weights = [];
foreach ($valid_prizes as $index => $prize) {
$weights[$index] = $prize['surplus_stock'];
}
// 开普通奖品
for ($i = 0; $i < $prize_num; $i++) {
// 检查是否还有可抽奖品
if (empty($weights) || array_sum($weights) <= 0) {
break;
}
// 使用加权随机算法选择奖品
$selected_index = $this->weightedRandom($weights);
$ordinary_prize_info = $valid_prizes[$selected_index];
// 减少权重以反映库存变化
$weights[$selected_index]--;
// 如果权重为0则从数组中移除
if ($weights[$selected_index] <= 0) {
unset($weights[$selected_index]);
unset($valid_prizes[$selected_index]);
}
$order_goods_info = [
'order_id' => $order_id,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => $num,
'shang_id' => $ordinary_prize_info['shang_id'],
'goodslist_id' => $ordinary_prize_info['id'],
'goodslist_title' => $ordinary_prize_info['title'],
'goodslist_imgurl' => $ordinary_prize_info['imgurl'],
'goodslist_price' => $ordinary_prize_info['price'],
'goodslist_money' => $ordinary_prize_info['money'],
'goodslist_type' => $ordinary_prize_info['goods_type'],
'goodslist_sale_time' => $ordinary_prize_info['sale_time'],
'addtime' => time(),
'prize_code' => isset($ordinary_prize_info['prize_code']) ? $ordinary_prize_info['prize_code'] : '',
'order_type' => $order_type,
'parent_goods_list_id' => $ordinary_prize_info['goods_list_id'],
'source' => 1, // 标记来源为抽奖
];
// 插入订单商品记录
$res[] = OrderList::insert($order_goods_info);
// 减少库存
$res[] = GoodsList::where(['id' => $ordinary_prize_info['id']])
->dec('surplus_stock')
->update();
// 赠送货币
if (isset($ordinary_prize_info['doubling']) && $ordinary_prize_info['doubling'] > 1) {
$bei = $ordinary_prize_info['doubling'] - 1;
$change_money = $ordinary_prize_info['money'] * $bei * 100;
$res[] = User::changeIntegral($user_id, $change_money, 6, '抽中翻倍赏-' . $ordinary_prize_info['title'] . '赠送');
}
if (isset($ordinary_prize_info['reward_id']) && $ordinary_prize_info['reward_id'] != '') {
RewardService::sendReward($user_id, $ordinary_prize_info['reward_id'], '抽中' . $ordinary_prize_info['title']);
}
// RewardService::sendReward($user['user_id'], $prize['reward_id'], $goods_title . '开奖');
// 处理宝箱奖品
if ($ordinary_prize_info['goods_type'] == 4) {
// 查找宝箱奖品
$goodslist_1 = GoodsList::where(['goods_id' => $goods_id])
->where('goods_list_id', '=', $ordinary_prize_info['id'])
->select()->toArray();
if (!empty($goodslist_1)) {
$box_res = $this->ordinary_prize_notice_box($goodslist_1, 1, $order_id, $user_id, $goods_id, $order_type, $num);
$res = array_merge($res, $box_res);
}
}
}
return $res;
} catch (\Exception $e) {
// 记录错误日志
trace('抽奖异常: ' . $e->getMessage(), 'error');
// 抛出异常,让外层事务处理回滚
throw $e;
}
}
/**
* 加权随机算法
* @param array $weights 权重数组
* @return int 选中的索引
*/
private function weightedRandom(array $weights)
{
$sum = array_sum($weights);
$rand = random_int(1, $sum);
foreach ($weights as $index => $weight) {
$rand -= $weight;
if ($rand <= 0) {
return $index;
}
}
return array_key_first($weights); // 防止浮点数精度问题导致无法选中
}
/**
* 福利屋购买
* @param $order 订单信息
*/
protected function ordinary_prize_notice_flw($order)
{
$user_id = $order['user_id'];
$order_id = $order['id'];
$goods_id = $order['goods_id'];
$order_type = $order['order_type'];
$goods_price = $order['goods_price'];
#入库奖品
$save_order_goods = [];
#开普通奖品
$save_order_goods[] = [
'order_id' => $order_id,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => 0,
'source' => 3,
'shang_id' => 0,
'goodslist_id' => 0,
'goodslist_title' => '',
'goodslist_imgurl' => '',
'goodslist_price' => $goods_price,
'goodslist_money' => 0,
'goodslist_type' => 3,
'goodslist_sale_time' => '',
'addtime' => time(),
'prize_code' => '',
'order_type' => $order_type,
];
if ($save_order_goods) {
#新增奖品列表
$res[] = OrderList::insertAll($save_order_goods);
}
return $res;
}
/**
* 特殊奖品开奖 FIRST
* @param $order 订单信息
* @param $first_count
*/
protected function special_first_notice($order, $first_count)
{
$res = [];
$goods_id = $order['goods_id'];
$num = $order['num'];
$order_type = $order['order_type'];
#特殊奖品存在
$special_prize = GoodsList::where('goods_id', '=', $goods_id)
->where('num', '=', $num)
->where('surplus_stock', '>', 0)
->where('shang_id', '=', self::$shang_give_first_id)
->find();
#剩余数量
$surplus_give_stock = $special_prize ? $special_prize['surplus_stock'] : 0;
if ($special_prize && $surplus_give_stock > 0) {
#所有奖品信息
$all_order_list = OrderList::where('goods_id', '=', $goods_id)
->where('num', '=', $num)
->where('order_type', '=', $order_type)
->where('shang_id', 'between', self::$shang_prize_id)
->order('id asc')
->limit((int) $first_count)
->select()->toArray();
shuffle($all_order_list);
shuffle($all_order_list);
$prize_info = $all_order_list[0];
$user_id = $prize_info['user_id'];
#特殊赏中奖订单id
$order_list_id = $prize_info['id'];
#中奖奖项
$order_goods = [
'order_id' => 0,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => $num,
'shang_id' => $special_prize['shang_id'],
'goodslist_id' => $special_prize['id'],
'goodslist_title' => $special_prize['title'],
'goodslist_imgurl' => $special_prize['imgurl'],
'goodslist_price' => $special_prize['price'],
'goodslist_money' => $special_prize['money'],
'goodslist_type' => $special_prize['goods_type'],
'goodslist_sale_time' => $special_prize['sale_time'],
'addtime' => time(),
'prize_code' => $special_prize['prize_code'],
'order_type' => $order_type,
'order_list_id' => $order_list_id,
];
#增加销量
$res[] = GoodsList::field('surplus_stock')
->where(['id' => $special_prize['id']])
->dec('surplus_stock')
->update();
#新增奖品列表
$res[] = OrderList::insert($order_goods);
} else {
$res[] = 1;
}
return $res;
}
/**
* 特殊奖品开奖 LAST 最终赏 全局赏
* @param $order 订单信息
* @param $first_count
*/
protected function special_prize_notice($order, $first_count)
{
$res = [];
$goods_id = $order['goods_id'];
$num = $order['num'];
$order_type = $order['order_type'];
#特殊奖品存在
$special_prize = GoodsList::where('goods_id', '=', $goods_id)
->where('num', '=', $num)
->where('surplus_stock', '>', 0)
->where('shang_id', 'in', self::$shang_give_arr)
->where('goods_list_id', '=', 0)
->select()->toArray();
$surplus_give_stock = $special_prize ? array_sum(array_column($special_prize, 'surplus_stock')) : 0;
if ($special_prize && $surplus_give_stock > 0) {
#所有奖品信息
$all_order_list = OrderList::field('id,user_id')
->where('goods_id', '=', $goods_id)
->where('num', '=', $num)
->where('order_type', '=', $order_type)
->where('shang_id', 'between', self::$shang_prize_id)
->order('id asc')
->select()->toArray();
$order_goods = [];
foreach ($special_prize as $k => $v) {
if ($v['shang_id'] == 4) {#全局赏
for ($surplus_stock_i = 0; $surplus_stock_i < $v['surplus_stock']; $surplus_stock_i++) {
$overall_order_list = $all_order_list;
shuffle($overall_order_list);
shuffle($overall_order_list);
$prize_info = $overall_order_list[0];
$user_id = $prize_info['user_id'];
#特殊赏中奖订单id
$order_list_id = $prize_info['id'];
#中奖奖项
$ordinary_prize_info = $v;
$order_goods_temp = [
'order_id' => 0,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => $num,
'shang_id' => $ordinary_prize_info['shang_id'],
'goodslist_id' => $ordinary_prize_info['id'],
'goodslist_title' => $ordinary_prize_info['title'],
'goodslist_imgurl' => $ordinary_prize_info['imgurl'],
'goodslist_price' => $ordinary_prize_info['price'],
'goodslist_money' => $ordinary_prize_info['money'],
'goodslist_type' => $ordinary_prize_info['goods_type'],
'goodslist_sale_time' => $ordinary_prize_info['sale_time'],
'addtime' => time(),
'prize_code' => $ordinary_prize_info['prize_code'],
'order_type' => $order_type,
'order_list_id' => $order_list_id,
'parent_goods_list_id' => $ordinary_prize_info['goods_list_id'],
];
$res[] = OrderList::insert($order_goods_temp);
#减少库存
$res[] = GoodsList::field('surplus_stock')
->where(['id' => $ordinary_prize_info['id']])
->dec('surplus_stock')
->update();
if (isset($ordinary_prize_info['reward_id']) && $ordinary_prize_info['reward_id'] != '') {
RewardService::sendReward($user_id, $ordinary_prize_info['reward_id'], '抽中' . $ordinary_prize_info['title']);
}
# 宝箱处理
if ($ordinary_prize_info['goods_type'] == 4) {
# 查找宝箱奖品
$goodslist_1 = GoodsList::where(['goods_id' => $goods_id])
->where('goods_list_id', '=', $ordinary_prize_info['id'])
->select()->toArray();
if ($goodslist_1) {
$res[] = $this->ordinary_prize_notice_box($goodslist_1, 1, 0, $user_id, $goods_id, $order_type, $num);
}
}
}
} else {
if ($v['shang_id'] == 2) {#LAST赏
$last_order_list = array_slice($all_order_list, (int) $first_count);
shuffle($last_order_list);
shuffle($last_order_list);
$prize_info = $last_order_list[0];
#中奖用户id
$user_id = $prize_info['user_id'];
#特殊赏中奖订单id
$order_list_id = $prize_info['id'];
#中奖奖项
$ordinary_prize_info = $v;
} elseif ($v['shang_id'] == 3) {#最终赏
$end_order_list = $all_order_list;
$prize_info = end($end_order_list);
#中奖用户id
$user_id = $prize_info['user_id'];
#特殊赏中奖订单id
$order_list_id = $prize_info['id'];
#中奖奖项
$ordinary_prize_info = $v;
}
$order_goods_temp = [
'order_id' => 0,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => $num,
'shang_id' => $ordinary_prize_info['shang_id'],
'goodslist_id' => $ordinary_prize_info['id'],
'goodslist_title' => $ordinary_prize_info['title'],
'goodslist_imgurl' => $ordinary_prize_info['imgurl'],
'goodslist_price' => $ordinary_prize_info['price'],
'goodslist_money' => $ordinary_prize_info['money'],
'goodslist_type' => $ordinary_prize_info['goods_type'],
'goodslist_sale_time' => $ordinary_prize_info['sale_time'],
'addtime' => time(),
'prize_code' => $ordinary_prize_info['prize_code'],
'order_type' => $order_type,
'order_list_id' => $order_list_id,
'parent_goods_list_id' => $ordinary_prize_info['goods_list_id'],
];
$res[] = OrderList::insert($order_goods_temp);
#减少库存
$res[] = GoodsList::field('surplus_stock')
->where(['id' => $ordinary_prize_info['id']])
->dec('surplus_stock')
->update();
## 判断是否有奖励
if (isset($ordinary_prize_info['reward_id']) && $ordinary_prize_info['reward_id'] != '') {
RewardService::sendReward($user_id, $ordinary_prize_info['reward_id'], '抽中' . $ordinary_prize_info['title']);
}
# 宝箱处理
if ($ordinary_prize_info['goods_type'] == 4) {
# 查找宝箱奖品
$goodslist_1 = GoodsList::where(['goods_id' => $goods_id])
->where('goods_list_id', '=', $ordinary_prize_info['id'])
->select()->toArray();
if ($goodslist_1) {
$res[] = $this->ordinary_prize_notice_box($goodslist_1, 1, 0, $user_id, $goods_id, $order_type, $num);
}
}
}
}
#新增奖品列表
// $res[] = OrderList::insertAll($order_goods);
} else {
$res[] = 1;
}
return $res;
}
/**
* 无限赏开始抽赏======================================================
* @param int $user_id 会员id
* @param int $order_id 订单ID
* @param int $box_id 盲盒id
*/
public function infinite_drawprize_notice($user_id = 0, $order_id = 0, $goods_id = 0, $num = 0)
{
// if()
$res = [];
$order = Order::where(['id' => $order_id])
->where(['user_id' => $user_id])
->where(['goods_id' => $goods_id])
->where(['num' => $num])
->where(['status' => 0])
->find();
if ($order == null && $num == 0) {
$order = Order::where(['id' => $order_id])
->where(['user_id' => $user_id])
->where(['goods_id' => $goods_id])
->where(['num' => 1])
->where(['status' => 0])
->find();
if ($order != null) {
$order_type1 = $order['order_type'];
if ($order_type1 == 10) {
$num = 1;
}
}
}
if ($order) {
#改变状态
$res[] = Order::field('status,pay_time')
->where(['id' => $order['id']])
->update([
'status' => 1,
'pay_time' => time(),
]);
#扣余额
if ($order['use_money'] > 0) {
$res[] = User::changeMoney($order['user_id'], -$order['use_money'], 3, '购买盒子' . $order['goods_title']);
}
#扣货币1
if ($order['use_integral'] > 0) {
$res[] = User::changeIntegral($order['user_id'], -$order['use_integral'], 2, '购买盒子' . $order['goods_title']);
}
#
if ($order['use_money2'] > 0) {
$res[] = User::changeMoney2($order['user_id'], -$order['use_money2'], 2, '购买盒子' . $order['goods_title']);
}
#判断一下优惠券
if (!empty($order['coupon_id'])) {
$coupon = CouponReceiveModel::where(['id' => $order['coupon_id'], 'status' => 0])->update(['status' => 1]);
}
#分销奖励
$res[] = User::distribution($order);
#分销奖励
#开奖==================================================
if ($order['order_type'] == 10) {
$res[] = $this->infinite_shangchengshang($order);
}
if ($order['order_type'] == 17) {
$res[] = $this->infinite_drawprize_tesu($order);
} else {
$res[] = $this->infinite_drawprize($order);
}
#开奖==================================================
#判断是否发积分 发券
$res[] = User::is_integral_coupon($order);
#判断是否发积分
//升级欧气值
if ($order['price'] > 0) {
User::ou_qi_level_up($order['user_id'], $order['price']);
}
} else {
$res[] = 0;
}
return $res;
}
/**
* 无限赏开奖逻辑
* @param $order 订单信息
*/
protected function infinite_drawprize_tesu($order = [])
{
$user_id = $order['user_id'];#用户ID
$order_id = $order['id'];#订单ID
$goods_id = $order['goods_id'];#盒子ID
$prize_num = $order['prize_num'];#抽奖数量
$order_type = $order['order_type'];#订单类型
$whe = [];
$whe[] = ['id', '=', $order['goods_id']];
$infinite_goods = Goods::getInfo($whe, 'type');
$where = [];
$where[] = ['goods_id', '=', $goods_id];
$where[] = ['num', '=', 0];
$where[] = ['real_pro', '>', 0];
//普通
$where[] = ['lian_ji_type', '=', 0];
$where[] = ['goods_list_id', '=', 0];
#查找奖品
$goodslist = GoodsList::field('id,shang_id,real_pro,stock')
->where($where)
->select()->toArray();
if ($goodslist) {
$res[] = $this->infinite_drawprize_tesu_box($goodslist, $prize_num, $order_id, $user_id, $goods_id, $order_type);
} else {
$res[] = 0;
}
return $res;
}
/**
* 抽出奖品
* @param $order 订单信息
*/
protected function infinite_drawprize_tesu_box($goodslist, $prize_num, $order_id, $user_id, $goods_id, $order_type)
{
// 计算总概率
$totalProbability = array_sum(array_column($goodslist, 'real_pro'));
//获取今天凌晨时间
$todayMidnight = strtotime('today');
// 构建概率区间
$probabilityRanges = [];
$currentRange = 0;
foreach ($goodslist as $good) {
// if ($good['stock'] <= 0) {
// continue;
// }
#判断今日库存
$user_quanju_count = OrderList::field('id')
->where('goods_id', '=', $goods_id)
->where('parent_goods_list_id', '=', 0)
->where('addtime', '>=', $todayMidnight)
->count();
// if ($user_quanju_count >= $good['stock']) {
// continue;
// }
$rangeStart = $currentRange;
$currentRange += $good['real_pro'];
$probabilityRanges[] = [
'id' => $good['id'],
'start' => $rangeStart,
'end' => $currentRange
];
}
$multiple = ConfigHelper::getInfiniteMultiple();
for ($i = 0; $i < $prize_num; $i++) {
// 生成随机数 (保持与原始方法相同的精度100000)
$maxRand = (int) ($totalProbability * $multiple);
$random = random_int(0, $maxRand) / $multiple;
// 查找中奖奖品
$prize_id = null;
foreach ($probabilityRanges as $range) {
if ($random >= $range['start'] && $random < $range['end']) {
$prize_id = $range['id'];
break;
}
}
// 获取奖品信息
$prize_info = GoodsList::where(['id' => $prize_id])->find();
#编号
$luck_no = OrderList::field('id')
->where('goods_id', '=', $goods_id)
->where('num', '=', 0)
->where('order_type', '=', $order_type)
->order('id desc')
->value('luck_no');
$luck_no++;
$doubling = $prize_info['doubling'];
if (!$doubling) {
$doubling = 0;
}
#新增记录
$save_prize_info = [
'order_id' => $order_id,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => 0,
'doubling' => $doubling,
'shang_id' => $prize_info['shang_id'],
'goodslist_id' => $prize_info['id'],
'goodslist_title' => $prize_info['title'],
'goodslist_imgurl' => $prize_info['imgurl'],
'goodslist_price' => $prize_info['price'],
'goodslist_money' => $prize_info['money'],
'goodslist_type' => $prize_info['goods_type'],
'goodslist_sale_time' => $prize_info['sale_time'],
'addtime' => time(),
'prize_code' => $prize_info['prize_code'],
'order_type' => $order_type,
'luck_no' => $luck_no,
'parent_goods_list_id' => $prize_info['goods_list_id'],
];
#入库===
$res[] = OrderList::insert($save_prize_info);
# 赠送货币
if ($prize_info['doubling'] > 1) {
$bei = $prize_info['doubling'] - 1;
$change_money = $prize_info['money'] * $bei * 100;
$res[] = User::changeIntegral($user_id, $change_money, 6, '抽中翻倍赏-' . $prize_info['title'] . '赠送');
}
if (isset($prize_info['reward_id']) && $prize_info['reward_id'] != '') {
RewardService::sendReward($user_id, $prize_info['reward_id'], '抽中' . $prize_info['title']);
}
# 宝箱
if ($prize_info['goods_type'] == 4) {
# 查找宝箱奖品
$goodslist_1 = GoodsList::where(['goods_id' => $goods_id])
->where('goods_list_id', '=', $prize_info['id'])
->select()->toArray();
// $res[] = $this->infinite_drawprize_box($order);
$res[] = $this->infinite_drawprize_tesu_box($goodslist_1, 1, $order_id, $user_id, $goods_id, $order_type);
}
}
return $res;
}
/**
* 无限赏开奖逻辑
* @param $order 订单信息
*/
protected function infinite_drawprize($order = [])
{
$user_id = $order['user_id'];#用户ID
$order_id = $order['id'];#订单ID
$goods_id = $order['goods_id'];#盒子ID
$prize_num = $order['prize_num'];#抽奖数量
// $order_type = $order['order_type'];#订单类型
$whe = [];
$whe[] = ['id', '=', $order['goods_id']];
$infinite_goods = Goods::getInfo($whe, '*');
$where = [];
$where[] = ['goods_id', '=', $goods_id];
$where[] = ['num', '=', 0];
$where[] = ['real_pro', '>', 0];
if ($infinite_goods['type'] == 9 && $order['is_mibao'] == 1) {
//秘宝池
$where[] = ['lian_ji_type', '=', 1];
} else {
//普通
$where[] = ['lian_ji_type', '=', 0];
}
$where[] = ['goods_list_id', '=', 0];
#查找奖品
$goodslist = GoodsList::field('id,shang_id,real_pro,title,price,money')
->where($where)
->select()->toArray();
if ($goodslist) {
$res[] = $this->infinite_drawprize_box($goodslist, $prize_num, $user_id, $goods_id, $infinite_goods, $order);
// 更新Redis中盒子的热度值增加本次抽奖次数
$this->updateGoodsHeat($goods_id, $prize_num);
//去除秘宝池次数
if ($infinite_goods['type'] == 9 && $order['is_mibao'] == 1) {
User::where('id', $user_id)->dec('mb_number', $prize_num)->update();
}
//计算怒气值
$this->rage($goods_id, $order_id, $user_id);
//领主
$this->ling_zhu($order, $order_id);
//连击赏
if ($infinite_goods['type'] == 9 && $order['is_mibao'] == 0) {
$this->lian_ji($order, $order_id);
}
} else {
$res[] = 0;
}
return $res;
}
/**
* 抽出奖品
* @param $order 订单信息
*/
protected function infinite_drawprize_box1($goodslist, $prize_num, $user_id, $goods_id, $infinite_goods, $order)
{
$order_id = $order['id'];
$order_type = $order['order_type'];
// 计算总概率
$totalProbability = array_sum(array_column($goodslist, 'real_pro'));
// 构建概率区间
$probabilityRanges = [];
$currentRange = 0;
foreach ($goodslist as $good) {
$rangeStart = $currentRange;
$currentRange += $good['real_pro'];
$probabilityRanges[] = [
'id' => $good['id'],
'start' => $rangeStart,
'end' => $currentRange
];
}
//获取抽奖倍数100000
$multiple = ConfigHelper::getInfiniteMultiple();
$lingzhu_shang_id = 0;
if (!$infinite_goods) {
$infinite_goods = Goods::getInfo(['id' => $goods_id], 'type,lingzhu_is,lingzhu_fan,lingzhu_shang_id,king_user_id');
}
if ($infinite_goods != null && $infinite_goods['type'] == 8 && $infinite_goods['lingzhu_is'] == 1) {
$lingzhu_shang_id = $infinite_goods['lingzhu_shang_id'];
}
for ($i = 0; $i < $prize_num; $i++) {
// 生成随机数 (保持与原始方法相同的精度100000)
$maxRand = (int) ($totalProbability * $multiple);
$random = random_int(0, $maxRand) / $multiple;
// 查找中奖奖品
$prize_id = null;
foreach ($probabilityRanges as $range) {
if ($random >= $range['start'] && $random < $range['end']) {
$prize_id = $range['id'];
break;
}
}
// 获取奖品信息
$prize_info = GoodsList::where(['id' => $prize_id])->find();
#编号
$luck_no = OrderList::field('id')
->where('goods_id', '=', $goods_id)
->where('num', '=', 0)
->where('order_type', '=', $order_type)
->order('id desc')
->value('luck_no');
$luck_no++;
$doubling = $prize_info['doubling'];
if (!$doubling) {
$doubling = 0;
}
$lingzhu = $prize_info['is_lingzhu'];
if ($infinite_goods['type'] == 8) {
//如果是领主赏,则去查询一下。是否为领主
if ($lingzhu_shang_id > 0 && $lingzhu == 0) {
if ($lingzhu_shang_id == $prize_info['shang_id']) {
$lingzhu = 1;
}
}
}
#新增记录
$save_prize_info = [
'order_id' => $order_id,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => 0,
'doubling' => $doubling,
'shang_id' => $prize_info['shang_id'],
'goodslist_id' => $prize_info['id'],
'goodslist_title' => $prize_info['title'],
'goodslist_imgurl' => $prize_info['imgurl'],
'goodslist_price' => $prize_info['price'],
'goodslist_money' => $prize_info['money'],
'goodslist_type' => $prize_info['goods_type'],
'goodslist_sale_time' => $prize_info['sale_time'],
'addtime' => time(),
'prize_code' => $prize_info['prize_code'],
'order_type' => $order_type,
'luck_no' => $luck_no,
'parent_goods_list_id' => $prize_info['goods_list_id'],
'is_lingzhu' => $lingzhu,
];
#入库===
$res[] = OrderList::insert($save_prize_info);
# 赠送货币
if ($prize_info['doubling'] > 1) {
$bei = $prize_info['doubling'] - 1;
$change_money = $prize_info['money'] * $bei * 100;
$res[] = User::changeIntegral($user_id, $change_money, 6, '抽中翻倍赏-' . $prize_info['title'] . '赠送');
}
if (isset($prize_info['reward_id']) && $prize_info['reward_id'] != '') {
RewardService::sendReward($user_id, $prize_info['reward_id'], '抽中' . $prize_info['title']);
}
# 宝箱
if ($prize_info['goods_type'] == 4) {
# 查找宝箱奖品
$goodslist_1 = GoodsList::where(['goods_id' => $goods_id])
->where('goods_list_id', '=', $prize_info['id'])
->select()->toArray();
// $res[] = $this->infinite_drawprize_box($order);
$res[] = $this->infinite_drawprize_box($goodslist_1, 1, $user_id, $goods_id, $infinite_goods, $order);
}
}
return $res;
}
/**
* 无限抽奖箱:每次抽奖重新随机排序并构建概率区间
*
* @param array $goodslist 奖品列表(每个奖品需要包含 real_pro 字段作为概率)
* @param int $prize_num 抽奖次数
* @param int $order_id 订单ID
* @param int $user_id 用户ID
* @param int $goods_id 商品ID
* @param int $order_type 订单类型
* @param array|null $infinite_goods 商品扩展信息(用于领主赏判断)
* @return array 抽奖结果集合
*/
protected function infinite_drawprize_box($goodslist, $prize_num, $user_id, $goods_id, $infinite_goods, $order)
{
// 记录抽奖总开始时间
$total_start_time = microtime(true);
// 记录抽奖出货总金额
$total_prize_money = 0;
$order_id = $order['id'];//订单id
$order_type = $order['order_type'];//订单类型
$order_num = $order['order_num'];//订单编号
$res = []; // 保存每次抽奖结果
$multiple = ConfigHelper::getInfiniteMultiple(); // 获取随机倍数例如100000
// 将赏品列表转换为map格式以id为键便于快速查找
$shang_list_array = Shang::field('id,title')->select()->toArray();
$shang_list = [];
foreach ($shang_list_array as $shang) {
$shang_list[$shang['id']] = $shang['title'];
}
$lingzhu_shang_id = 0; // 初始化领主赏上级ID
if (!$infinite_goods) {
$infinite_goods = Goods::getInfo(['id' => $goods_id], '*');
}
if ($infinite_goods != null && $infinite_goods['type'] == 8 && $infinite_goods['lingzhu_is'] == 1) {
$lingzhu_shang_id = $infinite_goods['lingzhu_shang_id'];
}
// 创建日志数据集合数组
$log_data_collection = [];
// 循环抽奖指定次数
for ($i = 0; $i < $prize_num; $i++) {
// 记录单次抽奖开始时间
$single_start_time = microtime(true);
// 用于记录日志的数据
$log_data = [
'draw_num' => $i + 1,
'user_id' => $user_id,
'box_id' => $goods_id,
'order_num' => $order_num,
'probability_ranges' => []
];
// 1. 每次抽奖前,随机打乱奖品列表
$shuffledGoodsList = $goodslist;
shuffle($shuffledGoodsList);
// 2. 重新计算总概率和构建新的概率区间
$totalProbability = array_sum(array_column($shuffledGoodsList, 'real_pro'));
$probabilityRanges = [];
$currentRange = 0;
foreach ($shuffledGoodsList as $good) {
$rangeStart = $currentRange;
$currentRange += $good['real_pro'];
$probabilityRanges[] = [
'id' => $good['id'],
'start' => $rangeStart,
'end' => $currentRange
];
// 收集奖品区间分布数据用于日志
// 判断$good中是否已包含需要的信息
if (isset($good['title']) && isset($good['price'])) {
$log_data['probability_ranges'][] = [
'id' => $good['id'],
'title' => $good['title'],
'price' => $good['price'],
'money' => $good['money'],
'start' => $rangeStart,
'shang_id' => $good['shang_id'],
'shang_title' => isset($shang_list[$good['shang_id']]) ? $shang_list[$good['shang_id']] : '未知',
'end' => $currentRange,
'real_pro' => $good['real_pro']
];
} else {
// 如果没有,才查询数据库
$good_info = GoodsList::where(['id' => $good['id']])->field('id,title,price,money,real_pro,shang_id')->find();
if ($good_info) {
$log_data['probability_ranges'][] = [
'id' => $good['id'],
'title' => $good_info['title'],
'price' => $good_info['price'],
'money' => $good_info['money'],
'shang_id' => $good_info['shang_id'],
'shang_title' => isset($shang_list[$good_info['shang_id']]) ? $shang_list[$good_info['shang_id']] : '未知',
'start' => $rangeStart,
'end' => $currentRange,
'real_pro' => $good_info['real_pro']
];
}
}
}
// 3. 随机生成一个数,根据区间确定中奖奖品
$maxRand = (int) ($totalProbability * $multiple);
$random = random_int(0, $maxRand) / $multiple;
// 记录随机数
$log_data['random'] = $random;
$prize_id = null;
foreach ($probabilityRanges as $range) {
if ($random >= $range['start'] && $random < $range['end']) {
$prize_id = $range['id'];
break;
}
}
if (!$prize_id) {
// 记录日志 - 未中奖
$log_data['prize_id'] = 0;
$log_data['prize_title'] = '未中奖';
// 计算单次抽奖耗时
$single_end_time = microtime(true);
$log_data['execution_time'] = round(($single_end_time - $single_start_time) * 1000, 2); // 毫秒
// 收集日志数据而不是立即写入
$log_data_collection[] = $log_data;
continue; // 防止异常空抽
}
// 4. 获取中奖奖品详细信息
$prize_info = GoodsList::where(['id' => $prize_id])->find();
if (!$prize_info) {
// 记录日志 - 奖品信息不存在
$log_data['prize_id'] = $prize_id;
$log_data['prize_title'] = '奖品信息不存在';
// 计算单次抽奖耗时
$single_end_time = microtime(true);
$log_data['execution_time'] = round(($single_end_time - $single_start_time) * 1000, 2); // 毫秒
// 收集日志数据而不是立即写入
$log_data_collection[] = $log_data;
continue;
}
// 累加中奖金额到总金额
$total_prize_money += (float) $prize_info['money'];
$log_data['prize_money'] = $prize_info['money'];
// 5. 处理编号
$luck_no = OrderList::field('luck_no')
->where('goods_id', '=', $goods_id)
->where('num', '=', 0)
->where('order_type', '=', $order_type)
->order('id desc')
->value('luck_no');
$luck_no = $luck_no ? $luck_no + 1 : 1;
// 6. 处理翻倍赏
$doubling = $prize_info['doubling'] ?? 0;
// 7. 判断是否是领主赏
$lingzhu = $prize_info['is_lingzhu'] ?? 0;
if ($infinite_goods['type'] == 8) {
if ($lingzhu_shang_id > 0 && $lingzhu == 0) {
if ($lingzhu_shang_id == $prize_info['shang_id']) {
$lingzhu = 1;
}
}
}
// 记录日志数据
$log_data['prize_id'] = $prize_info['id'];
$log_data['prize_title'] = $prize_info['title'];
$log_data['doubling'] = $doubling;
$log_data['is_lingzhu'] = $lingzhu;
$log_data['is_king'] = isset($infinite_goods['king_user_id']) && $infinite_goods['king_user_id'] == $user_id ? 1 : 0;
$log_data['is_box'] = $prize_info['goods_type'] == 4 ? 1 : 0;
$log_data['shang_id'] = $prize_info['shang_id'];
$log_data['shang_title'] = isset($shang_list[$prize_info['shang_id']]) ? $shang_list[$prize_info['shang_id']] : '未知';
// 8. 组装抽奖记录
$save_prize_info = [
'order_id' => $order_id,
'user_id' => $user_id,
'status' => 0, // 0未操作
'goods_id' => $goods_id,
'num' => 0,
'doubling' => $doubling,
'shang_id' => $prize_info['shang_id'],
'goodslist_id' => $prize_info['id'],
'goodslist_title' => $prize_info['title'],
'goodslist_imgurl' => $prize_info['imgurl'],
'goodslist_price' => $prize_info['price'],
'goodslist_money' => $prize_info['money'],
'goodslist_type' => $prize_info['goods_type'],
'goodslist_sale_time' => $prize_info['sale_time'],
'addtime' => time(),
'prize_code' => $prize_info['prize_code'],
'order_type' => $order_type,
'luck_no' => $luck_no,
'parent_goods_list_id' => $prize_info['goods_list_id'],
'is_lingzhu' => $lingzhu,
];
// 9. 插入中奖记录到订单表
$res[] = OrderList::insert($save_prize_info);
// 10. 如果中奖是翻倍赏,赠送货币积分
if ($doubling > 1) {
$bei = $doubling - 1;
$change_money = $prize_info['money'] * $bei * 100;
$res[] = User::changeIntegral($user_id, $change_money, 6, '抽中翻倍赏-' . $prize_info['title'] . '赠送');
$log_data['doubling_res'] = '翻倍赠送UU币:' . $change_money;
}
// 11. 如果奖品绑定了额外奖励,发放奖励
if (isset($prize_info['reward_id']) && $prize_info['reward_id'] != '') {
$reward_res = RewardService::sendReward($user_id, $prize_info['reward_id'], '抽中' . $prize_info['title']);
$log_data['reward_res'] = $reward_res;
}
// 计算单次抽奖耗时
$single_end_time = microtime(true);
$log_data['execution_time'] = round(($single_end_time - $single_start_time) * 1000, 2); // 毫秒
// 收集日志数据而不是立即写入
$log_data_collection[] = $log_data;
// 12. 如果抽到宝箱奖品,需要继续递归抽奖
if ($prize_info['goods_type'] == 4) {
$goodslist_1 = GoodsList::where(['goods_id' => $goods_id])
->where('goods_list_id', '=', $prize_info['id'])
->select()
->toArray();
if (!empty($goodslist_1)) {
$box_result = $this->infinite_drawprize_box($goodslist_1, 1, $user_id, $goods_id, $infinite_goods, $order);
// 将子抽奖的总金额加到当前总金额中
if (isset($box_result['total_prize_money'])) {
$total_prize_money += $box_result['total_prize_money'];
}
$res[] = $box_result;
}
}
}
// 计算总耗时
$total_end_time = microtime(true);
$total_execution_time = round(($total_end_time - $total_start_time) * 1000, 2); // 毫秒
// 抽奖循环结束后,统一写入日志
if (!empty($log_data_collection)) {
try {
$this->recordDrawLog($log_data_collection, $infinite_goods, $order, $total_execution_time, $total_prize_money);
} catch (\Exception $e) {
// 记录异常信息,但不影响主流程
\think\facade\Log::error('记录抽奖日志异常:' . $e->getMessage());
}
}
// 将总金额添加到返回结果中,以便递归调用时能够累加子抽奖的金额
$res['total_prize_money'] = $total_prize_money;
return $res;
}
/**
* 记录抽奖日志Markdown 格式)
* @param array $data_collection 抽奖数据集合
* @param array $goods 商品信息
* @param array $order 订单信息
* @param float $total_execution_time 总执行时间(毫秒)
* @param float $total_prize_money 总出货金额
* @return void
*/
protected function recordDrawLog($data_collection, $goods, $order, $total_execution_time = 0, $total_prize_money = 0)
{
// 如果数据集合为空,直接返回
if (empty($data_collection)) {
return;
}
try {
// 获取第一条数据,用于确定日志文件路径
// $first_data = $data_collection[0];
$goods_id = $goods['id'];
$goods_title = $goods['title'];
$goods_price = $goods['price'];
$order_num = $order['order_num'];
// 日志目录格式:./draw_log/{box_id}/
$log_dir = "./draw_log/{$goods_id}";
if (!is_dir($log_dir)) {
mkdir($log_dir, 0755, true);
}
// 日志文件路径
$log_file = $log_dir . '/' . $order_num . '.md';
// 是否为新文件,写入标题
$is_new_file = !file_exists($log_file);
// 构建完整的日志内容
$full_log_content = '';
$full_log_content .= "# 抽奖日志 - 盒子名称: {$goods_title} - 订单号: {$order_num} - 盒子ID: {$goods_id} - 盒子价格: {$goods_price} " . PHP_EOL . PHP_EOL;
// 添加订单详情信息
$full_log_content .= "## 订单详情" . PHP_EOL;
$full_log_content .= "- **订单总金额**: {$order['order_total']}" . PHP_EOL;
$full_log_content .= "- **订单折扣金额**: {$order['order_zhe_total']}" . PHP_EOL;
$full_log_content .= "- **微信支付**: {$order['price']}" . PHP_EOL;
$full_log_content .= "- **钻石支付**: {$order['use_money']}" . PHP_EOL;
$full_log_content .= "- **UU币支付**: {$order['use_integral']}" . PHP_EOL;
$full_log_content .= "- **达达卷支付**: {$order['use_money2']}" . PHP_EOL;
$full_log_content .= "- **优惠券ID**: {$order['coupon_id']}" . PHP_EOL;
$full_log_content .= "- **是否首抽五折**: " . ($order['is_shou_zhe'] == 1 ? '是' : '否') . PHP_EOL;
$full_log_content .= "- **抽奖数量**: {$order['prize_num']}" . PHP_EOL;
$full_log_content .= "- **下单时间**: " . date('Y-m-d H:i:s', $order['addtime']) . PHP_EOL;
if (!empty($order['pay_time'])) {
$full_log_content .= "- **付款时间**: " . date('Y-m-d H:i:s', $order['pay_time']) . PHP_EOL;
}
$full_log_content .= "- **是否为福利屋**: " . ($order['is_flw'] == 1 ? '是' : '否') . PHP_EOL;
$full_log_content .= "- **支付类型**: " . ($order['pay_type'] == 1 ? '微信' : ($order['pay_type'] == 2 ? '支付宝' : '其他')) . PHP_EOL;
$full_log_content .= PHP_EOL;
// 添加总执行时间信息和出货总金额
$full_log_content .= "## 抽奖总耗时: {$total_execution_time} 毫秒" . PHP_EOL;
$full_log_content .= "## 本次抽奖出货总金额: {$total_prize_money}" . PHP_EOL . PHP_EOL;
// 处理每条抽奖记录
foreach ($data_collection as $data) {
// 当前时间
$now = date('Y-m-d H:i:s');
$full_log_content .= "## 第 {$data['draw_num']} 次抽奖 - {$now}" . PHP_EOL;
$full_log_content .= "- **用户ID**: {$data['user_id']}" . PHP_EOL;
$full_log_content .= "- **随机数**: {$data['random']}" . PHP_EOL;
$full_log_content .= "- **执行时间**: {$data['execution_time']} 毫秒" . PHP_EOL;
// 获取中奖ID方便后续在表格中标红
$winning_prize_id = isset($data['prize_id']) && $data['prize_id'] > 0 ? $data['prize_id'] : 0;
// 中奖信息
if ($winning_prize_id) {
$full_log_content .= "- **中奖ID**: {$data['prize_id']}" . PHP_EOL;
$full_log_content .= "- **商品名**: {$data['prize_title']}" . PHP_EOL;
if (isset($data['prize_money'])) {
$full_log_content .= "- **奖品金额**: {$data['prize_money']}" . PHP_EOL;
}
if (isset($data['shang_id']) && isset($data['shang_title'])) {
$full_log_content .= "- **赏ID**: {$data['shang_id']}" . PHP_EOL;
$full_log_content .= "- **赏名称**: {$data['shang_title']}" . PHP_EOL;
}
} else {
$full_log_content .= "- **未中奖或奖品信息异常**" . PHP_EOL;
}
// 奖品翻倍
if (isset($data['doubling']) && $data['doubling'] > 0) {
$full_log_content .= "- **奖品翻倍**: {$data['doubling']}" . PHP_EOL;
if (isset($data['doubling_res'])) {
$full_log_content .= "- **翻倍奖励**: {$data['doubling_res']}" . PHP_EOL;
}
} else {
$full_log_content .= "- **奖品翻倍**: 无" . PHP_EOL;
}
// 领主等信息
$full_log_content .= "- **是否领主赏**: " . (isset($data['is_lingzhu']) && $data['is_lingzhu'] == 1 ? "" : "") . PHP_EOL;
$full_log_content .= "- **是否领主**: " . (isset($data['is_king']) && $data['is_king'] == 1 ? "" : "") . PHP_EOL;
$full_log_content .= "- **是否宝箱**: " . (isset($data['is_box']) && $data['is_box'] == 1 ? "" : "") . PHP_EOL;
// 发放奖励结果
if (isset($data['reward_res'])) {
$full_log_content .= "- **发放奖励结果**: " . (is_string($data['reward_res']) ? $data['reward_res'] : json_encode($data['reward_res'], JSON_UNESCAPED_UNICODE)) . PHP_EOL;
}
// 奖品区间分布表格
if (!empty($data['probability_ranges'])) {
$full_log_content .= PHP_EOL . "### 奖品区间分布" . PHP_EOL;
$full_log_content .= "| 奖品ID | 名称 | 价格 | 金额 | 概率 | 区间范围 | 赏ID | 赏名称 |" . PHP_EOL;
$full_log_content .= "|--------|------|------|------|------|-----------|------|--------|" . PHP_EOL;
foreach ($data['probability_ranges'] as $range) {
$start = $range['start'];
$end = $range['end'];
$shang_id = $range['shang_id'] ?? 0;
$shang_title = $range['shang_title'] ?? '未知';
$money = $range['money'] ?? 0;
// 判断是否是中奖奖品,如果是,则把名称变成红色
$title = $range['title'];
if ($winning_prize_id && $winning_prize_id == $range['id']) {
$title = "<span style=\"color:red\">{$title}</span>";
}
$full_log_content .= "| {$range['id']} | {$title} | {$range['price']} | {$money} | {$range['real_pro']} | {$start} ~ {$end} | {$shang_id} | {$shang_title} |" . PHP_EOL;
}
}
$full_log_content .= PHP_EOL . "---" . PHP_EOL . PHP_EOL;
}
// 一次性写入所有日志内容
file_put_contents($log_file, $full_log_content, $is_new_file ? FILE_APPEND : (FILE_APPEND | LOCK_EX));
} catch (\Exception $e) {
// 捕获异常,防止影响主流程
\think\facade\Log::error('记录抽奖日志异常:' . $e->getMessage());
}
}
/**
* 商城赏
* @param $order 订单信息
*/
protected function infinite_shangchengshang($order = [])
{
$user_id = $order['user_id'];#用户ID
$order_id = $order['id'];#订单ID
$goods_id = $order['goods_id'];#盒子ID
$prize_num = $order['prize_num'];#抽奖数量
$order_type = $order['order_type'];#订单类型
$whe = [];
$whe[] = ['id', '=', $order['goods_id']];
$infinite_goods = Goods::getInfo($whe, 'type');
$num = 1;
$where = [];
$where[] = ['goods_id', '=', $goods_id];
$where[] = ['num', '=', $num];
#查找奖品
$goodslist = GoodsList::field('id,shang_id,real_pro,surplus_stock')
->where($where)
->select()->toArray();
if ($goodslist) {
#组合中奖商品
$all_goods_id = [];
foreach ($goodslist as $value) {
$surplus_stock = $value['surplus_stock'];
for ($i = 1; $i <= $surplus_stock; $i++) {
$all_goods_id[] = $value['id'];
}
}
for ($i = 0; $i < $prize_num; $i++) {
$prize_id = $all_goods_id[0];
$prize_info = GoodsList::where(['id' => $prize_id])->find();
$prize_info_surplus_stock = $prize_info['surplus_stock'];
$prize_info['surplus_stock'] = $prize_info_surplus_stock - 1;
if ($prize_info_surplus_stock < 0) {
$res[] = 0;
return;
}
$prize_info->save();
#编号
$luck_no = OrderList::field('id')
->where('goods_id', '=', $goods_id)
->where('num', '=', $num)
->where('order_type', '=', $order_type)
->order('id desc')
->value('luck_no');
$luck_no++;
#新增记录
$save_prize_info = [
'order_id' => $order_id,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => $num,
'shang_id' => $prize_info['shang_id'],
'goodslist_id' => $prize_info['id'],
'goodslist_title' => $prize_info['title'],
'goodslist_imgurl' => $prize_info['imgurl'],
'goodslist_price' => $prize_info['price'],
'goodslist_money' => $prize_info['money'],
'goodslist_type' => $prize_info['goods_type'],
'goodslist_sale_time' => $prize_info['sale_time'],
'addtime' => time(),
'prize_code' => $prize_info['prize_code'],
'order_type' => $order_type,
'luck_no' => $luck_no,
];
#入库===
$res[] = OrderList::insert($save_prize_info);
}
} else {
$res[] = 0;
}
return $res;
}
//计算怒气值
public function rage($goods_id, $order_id, $user_id)
{
$order_list = OrderList::field('id')->where(['order_id' => $order_id])->find();
if (!$order_list) {
return false;
}
try {
$goods = Goods::field('id')->field('rage_is,rage,item_card_id')->where(['id' => $goods_id])->find();
if ($goods['rage_is'] == 1 && $goods['rage'] > 0 && $goods['item_card_id'] > 0) {
$order = Order::field('order_total')->where(['id' => $order_id])->find();
if ($order['order_total'] > 0) {
//获取奖品总价值
$out_price_sum = OrderList::where(['order_id' => $order_id])->sum('goodslist_money');
$rage_number = bcsub($order['order_total'], "$out_price_sum", 2);
$user_rage = Db::name('user_rage')->field('id,rage')->where(['user_id' => $user_id, 'goods_id' => $goods_id])->find();
if ($user_rage) {
$rage_number2 = bcadd((string) ($user_rage['rage']), "$rage_number", 2);
if ($rage_number2 >= $goods['rage']) {
//赠送道具卡
$item_card = ItemCard::field('id,title')->where(['id' => $goods['item_card_id']])->find();
if ($item_card) {
Db::name('user_item_card')->insert(['user_id' => $user_id, 'item_card_id' => $item_card['id'], 'title' => $item_card['title'], 'status' => 1, 'addtime' => time(), 'updatetime' => time()]);
}
Db::name('user_rage')->where(['user_id' => $user_id, 'goods_id' => $goods_id])->update(['rage' => 0, 'updatetime' => time()]);
} else {
Db::name('user_rage')->where(['user_id' => $user_id, 'goods_id' => $goods_id])->update(['rage' => $rage_number2, 'updatetime' => time()]);
}
} else {
Db::name('user_rage')->insert(['user_id' => $user_id, 'goods_id' => $goods_id, 'rage' => $rage_number, 'addtime' => time(), 'updatetime' => time()]);
}
}
}
} catch (\Exception $e) {
}
}
//领主
public function ling_zhu($order, $order_id)
{
//是否开启领主模式
$whe = [];
$whe[] = ['id', '=', $order['goods_id']];
$infinite_goods = Goods::getInfo($whe, 'type,lingzhu_is,lingzhu_fan,lingzhu_shang_id,king_user_id');
if ($infinite_goods['type'] != 8) {
return false;
}
if ($infinite_goods['lingzhu_is'] == 1) {
$whe2 = [];
$whe2[] = ['order_id', '=', $order_id];
$order_list = OrderList::getAllList($whe2, 'id,shang_id,user_id,goods_id,is_lingzhu', 'id asc');
foreach ($order_list as $k => $v) {
if ($v['shang_id'] == $infinite_goods['lingzhu_shang_id'] || $v['is_lingzhu'] == 1) {
// 查找当前池子是否有领主
if ($infinite_goods['king_user_id'] != 0) {
Db::name('goods_king_rank')->where([['user_id', '=', $infinite_goods['king_user_id']], ['goods_id', '=', $v['goods_id']]])->order('id', 'desc')->limit(1)->update(['end_time' => time()]);
}
//新的领主
Goods::where(['id' => $v['goods_id']])->update(['king_user_id' => $v['user_id']]);
//多少发晋升领主
$luck_no = OrderList::where([['goods_id', '=', $v['goods_id']], ['id', '<=', $v['id']]])->count();
$rank = [
'user_id' => $v['user_id'],
'goods_id' => $v['goods_id'],
'count' => $luck_no,
'order_list_id' => $v['id'],
'addtime' => time(),
];
$result = Db::name('goods_king_rank')->insert($rank);
} else {
// 查找当前池子是否有领主
$infinite_goods = Goods::getInfo($whe, 'lingzhu_is,lingzhu_fan,lingzhu_shang_id,king_user_id');
if ($infinite_goods['king_user_id'] != 0) {
$king_user_id = $infinite_goods['king_user_id'];
Db::name('goods_king_rank')->where([['user_id', '=', $infinite_goods['king_user_id']], ['goods_id', '=', $v['goods_id']]])->order('id', 'desc')->limit(1)->inc('z_nums', 1)->update();
$king_money = $infinite_goods['lingzhu_fan'];
if ($king_money && $king_money > 0) {
Db::name('goods_king_rank')->where([['user_id', '=', $infinite_goods['king_user_id']], ['goods_id', '=', $v['goods_id']]])->order('id', 'desc')->limit(1)->inc('money', floatval($king_money))->update();
// User::changeIntegral($infinite_goods['king_user_id'], $king_money, 4, '领主收益');
User::changeIntegral($infinite_goods['king_user_id'], $king_money, 4, '领主收益');
}
}
}
}
}
}
//连击赏
public function lian_ji($order, $order_id)
{
//是否是连击赏
$whe = [];
$whe[] = ['id', '=', $order['goods_id']];
$infinite_goods = Goods::getInfo($whe, 'type,lian_ji_num,lian_ji_shang_id');
if ($infinite_goods['type'] != 9) {
return false;
}
if ($order['is_mibao'] == 1) {
//减少秘宝池次数
User::field('mb_number')->where(['id' => $order['user_id']])->dec('mb_number', $order['prize_num'])->update();
}
$whe2 = [];
$whe2[] = ['order_id', '=', $order_id];
$order_list = OrderList::getAllList($whe2, 'id,shang_id,goods_id,user_id', 'id asc');
foreach ($order_list as $k => $v) {
//是否已有连击
$user_goods_lian_ji = Db::name('user_goods_lian_ji')->where([['user_id', '=', $v['user_id']], ['goods_id', '=', $v['goods_id']]])->whereNull('deltime')->order('id', 'desc')->find();
if ($v['shang_id'] == $infinite_goods['lian_ji_shang_id']) {
if ($infinite_goods['lian_ji_num'] != 0 && $infinite_goods['lian_ji_shang_id'] != 0) {
if ($user_goods_lian_ji) {
Db::name('user_goods_lian_ji')->field('number,updatetime')->where([['user_id', '=', $v['user_id']], ['goods_id', '=', $v['goods_id']]])->whereNull('deltime')->order('id', 'desc')->inc('number', 1)->update(['updatetime' => time()]);
//连击次数是否满足条件
$lian_ji_number = Db::name('user_goods_lian_ji')->where([['user_id', '=', $v['user_id']], ['goods_id', '=', $v['goods_id']]])->whereNull('deltime')->order('id', 'desc')->limit(1)->value('number');
if ($lian_ji_number && $lian_ji_number >= $infinite_goods['lian_ji_num']) {
//赠送秘宝池次数
User::field('mb_number')->where(['id' => $v['user_id']])->inc('mb_number', 1)->update();
//清空连击次数
Db::name('user_goods_lian_ji')->field('number,updatetime')->where([['user_id', '=', $v['user_id']], ['goods_id', '=', $v['goods_id']]])->whereNull('deltime')->order('id', 'desc')->update(['number' => 0, 'updatetime' => time()]);
}
} else {
Db::name('user_goods_lian_ji')->insert(['user_id' => $v['user_id'], 'goods_id' => $v['goods_id'], 'number' => 1, 'addtime' => time(), 'updatetime' => time()]);
}
}
} else {
if ($user_goods_lian_ji) {
Db::name('user_goods_lian_ji')->field('number,updatetime')->where([['user_id', '=', $v['user_id']], ['goods_id', '=', $v['goods_id']]])->whereNull('deltime')->order('id', 'desc')->update(['number' => 0, 'updatetime' => time()]);
} else {
Db::name('user_goods_lian_ji')->insert(['user_id' => $v['user_id'], 'goods_id' => $v['goods_id'], 'number' => 0, 'addtime' => time(), 'updatetime' => time()]);
}
}
}
}
/**
* 抽卡机抽奖逻辑
* @param int $user_id
* @param int $order_id
* @param int $goods_id
*/
public function cardextractor_drawprize_notice($user_id = 0, $order_id = 0, $goods_id = 0)
{
$res = [];
// dd(11);
$order = Order::where(['id' => $order_id])
->where(['user_id' => $user_id])
->where(['goods_id' => $goods_id])
->where(['num' => 0])
->where(['status' => 0])
->where(['order_type' => 4])
->find();
// dd($order);
if ($order) {
#改变状态
$res[] = Order::field('status,pay_time')
->where(['id' => $order['id']])
->update([
'status' => 1,
'pay_time' => time(),
]);
#扣余额
if ($order['use_money'] > 0) {
$res[] = User::changeMoney($order['user_id'], -$order['use_money'], 3, '购买盒子' . $order['goods_title']);
}
#扣货币1
if ($order['use_integral'] > 0) {
$res[] = User::changeIntegral($order['user_id'], -$order['use_integral'], 2, '购买盒子' . $order['goods_title']);
}
//扣除货币2
if ($order['use_money2'] > 0) {
$res[] = User::changeMoney2($order['user_id'], -$order['use_money2'], 2, '购买盒子' . $order['goods_title']);
}
#判断一下优惠券
if (!empty($order['coupon_id'])) {
$coupon = CouponReceiveModel::where(['id' => $order['coupon_id'], 'status' => 0])->update(['status' => 1]);
}
#判断是否发积分 发券
$res[] = User::is_integral_coupon($order);
#判断是否发积分
#分销奖励
$res[] = User::distribution($order);
#分销奖励
#开奖==================================================
$res[] = $this->cardextractor_drawprize($order);
#开奖==================================================
} else {
$res[] = 0;
}
return $res;
}
/**
* 抽卡机开奖
* @param array $order
*/
public function cardextractor_drawprize($order = [])
{
$user_id = $order['user_id'];#用户ID
$order_id = $order['id'];#订单ID
$goods_id = $order['goods_id'];#盒子ID
$prize_num = $order['prize_num'];#抽奖数量
$order_type = $order['order_type'];#订单类型
$prize_card_set = $order['prize_card_set'] ? json_decode($order['prize_card_set'], true) : '';#抽卡机必出设置
// dd($order);
#排除必出等级卡条件
$shang_where = [];
// dd(11111);
#必出卡等级
$set_prize_shang = [];
if ($prize_card_set && isset($prize_card_set['shang_id']) && isset($prize_card_set['shang_count'])) {
// dd($prize_card_set['shang_count']);
// foreach ($prize_card_set as $set_key => $set_value) {
for ($seti = 1; $seti <= $prize_card_set['shang_count']; $seti++) {
$set_prize_shang[] = $prize_card_set['shang_id'];
}
// }
// dd($set_prize_shang);
#排除必出等级卡条件
$shang_where[] = ['id', 'not in', array_unique($set_prize_shang)];
#减去必出数量
$prize_num = $prize_num - count($set_prize_shang);
}
// dd($shang_where);
#卡等级随机
$shang = CardLevel::field('id,title')
// ->where('goods_id', '=', $goods_id)
// ->where('pro', '>', 0)
->where($shang_where)
->select()->toArray();
// dd(1111)
// dd($shang);
if ($shang) {
#卡等级随机
$all_shang_id = [];
foreach ($shang as $shang_value) {
// $real_shang_pro = $shang_value['pro'] * 100;
// for ($is = 1; $is <= $real_shang_pro; $is++) {
$goods = GoodsList::where('shang_id', $shang_value['id'])->where('goods_id', '=', $goods_id)->find();
if ($goods) {
$all_shang_id[] = $shang_value['id'];
}
// }
}
// dd($all_shang_id);
#中奖卡等级
$prize_shang = [];
for ($i = 0; $i < $prize_num; $i++) {
#随机打乱
shuffle($all_shang_id);
shuffle($all_shang_id);
$prize_shang[] = $all_shang_id[0];
}
// dd($prize_shang);
$prize_shang = array_merge($prize_shang, $set_prize_shang);
shuffle($prize_shang);
$save_prize_data = [];
// dd($prize_shang);
#根据卡等级中奖奖品
foreach ($prize_shang as $prize_shang_id) {
#查找奖品
$goodslist = GoodsList::field('id,shang_id,real_pro,special_stock')
->where('goods_id', '=', $goods_id)
->where('shang_id', '=', $prize_shang_id)
->where('num', '=', 0)
->where('real_pro', '>', 0)
->where('special_stock = -100 OR special_stock > 0')
->select()->toArray();
if (empty($goodslist)) {
$res[] = 0;
return $res;
}
// dd($goodslist);
if ($goodslist) {
#组合中奖商品
$all_goods_id = [];
foreach ($goodslist as $value) {
$real_pro = $value['real_pro'] * 100;
for ($i = 1; $i <= $real_pro; $i++) {
$all_goods_id[] = $value['id'];
}
}
#随机打乱
shuffle($all_goods_id);
shuffle($all_goods_id);
$prize_id = $all_goods_id[0];
$prize_info = GoodsList::where(['id' => $prize_id])->find();
$save_prize_data[] = [
'order_id' => $order_id,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => 0,
'shang_id' => $prize_info['shang_id'],
'goodslist_id' => $prize_info['id'],
'goodslist_title' => $prize_info['title'],
'goodslist_imgurl' => $prize_info['imgurl'],
'goodslist_price' => $prize_info['price'],
'goodslist_money' => $prize_info['money'],
'goodslist_type' => $prize_info['goods_type'],
'goodslist_sale_time' => $prize_info['sale_time'],
'addtime' => time(),
'prize_code' => $prize_info['prize_code'],
'order_type' => $order_type,
];
if ($prize_info['special_stock'] >= 1) {
#减少库存
$res[] = GoodsList::field('special_stock')
->where(['id' => $prize_info['id']])
->dec('special_stock')
->update();
}
} else {
$res[] = $prize_shang_id;
}
}
#入库===
$res[] = OrderList::insertAll($save_prize_data);
} else {
$res[] = 0;
}
return $res;
}
/**
* 背包发货订单处理
* @param int $user_id 用户id
* @param int $order_id 订单id
*/
public function reward_order_handle($user_id = 0, $order_id = 0)
{
$res = [];
$send_info = OrderListSend::where(['user_id' => $user_id])
->where('user_id', '=', $user_id)
->where('id', '=', $order_id)
->where('status', '=', 0)#0待支付 1待发货 2待收货 3已完成
->find();
if ($send_info) {
#改变订单状态
$res[] = OrderListSend::field('id,status,pay_time')
->where('id', '=', $order_id)
->update([
'status' => 1,#0待支付 1待发货 2待收货 3已完成
'pay_time' => time(),#支付时间
]);
#改变赏品信息
$res[] = OrderList::field('id,status,send_num,choice_time')
->where('user_id', '=', $user_id)
->where('status', '=', 0)
->where('goodslist_type', '=', 1)
->where('send_num', '=', $send_info['send_num'])
->update([
'status' => 2,
'choice_time' => time(),
]);
} else {
$res[] = 0;
}
return $res;
}
public function order_notify7()
{
$testxml = file_get_contents("php://input");
$jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
$result = json_decode($jsonxml, true);//转成数组,
// wri($result['out_trade_no'], '秒杀商城回调--' . $result['out_trade_no']);
if ($result) {
//如果成功返回了
$out_trade_no = $result['out_trade_no'];
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
// writelog($out_trade_no, "秒杀商城支付成功--");
Db::startTrans();
$res[] = $this->order_update($out_trade_no, 7);
if (resCheck($res)) {
Db::commit();
} else {
Db::rollback();
}
}
}
$html = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
die($html);
}
public static function order_update($order_num, $type)
{
$res = [];
$order_info = Db::name('kk_order')
->where(['order_no' => $order_num])
->where(['status' => 0])#0待付款 1待发货 2待收货 3确认收货
->find();
if ($order_info) {
#改变订单状态
$res[] = Db::name('kk_order')->field('id,status,pay_time')
->where(['id' => $order_info['id']])
->update([
'status' => 1,#0待付款 1待发货 2待收货 3确认收货
'pay_time' => time(),#支付时间
]);
if ($order_info['money'] > 0) {
// dd($order_info['user_id']);
User::changeMoney($order_info['user_id'], '-' . $order_info['money'], 7);
}
if ($order_info['integral'] > 0) {
User::changeIntegral($order_info['user_id'], '-' . $order_info['integral'], 4);
}
$goods_data = Db::name('kk_order_good')
->field('id,goods_id,goods_num,goods_spec_id')
->where(['order_id' => $order_info['id']])
->select()->toArray();
foreach ($goods_data as $k => $v) {
#加销量
Db::name('kk_product')
->field('id,sale_num')
->where('id', $v['goods_id'])
->inc('sale_num', $v['goods_num'])
->update();
#减库存
Db::name('kk_product_spec')
->field('id,stock')
->where('id', $v['goods_spec_id'])
->dec('stock', $v['goods_num'])
->update();
}
} else {
$res[] = 0;
}
return $res;
}
/**
* 抽奖券======================================================
* @param int $user_id 会员id
* @param int $order_id 订单ID
* @param int $box_id 盲盒id
*/
public function draw_drawprize_notice($user_id = 0, $order_id = 0, $goods_id = 0)
{
$res = [];
$order = Order::where(['id' => $order_id])
->where(['user_id' => $user_id])
->where(['goods_id' => $goods_id])
->where(['num' => 0])
->where(['status' => 0])
->where(['order_type' => 7])
->find();
if ($order) {
#改变状态
$res[] = Order::field('status,pay_time')
->where(['id' => $order['id']])
->update([
'status' => 1,
'pay_time' => time(),
]);
#扣抽奖券
if ($order['use_draw'] > 0) {
$res[] = User::changeDraw($order['user_id'], -$order['use_draw'], 3, '抽奖券消费' . $order['goods_title']);
}
#开奖==================================================
$res[] = $this->draw_drawprize($order);
#开奖==================================================
// 更新Redis中盒子的热度值
$this->updateGoodsHeat($goods_id, $order['prize_num']);
} else {
$res[] = 0;
}
return $res;
}
/**
* 无限赏开奖逻辑
* @param $order 订单信息
*/
protected function draw_drawprize($order = [])
{
$user_id = $order['user_id'];#用户ID
$order_id = $order['id'];#订单ID
$goods_id = $order['goods_id'];#盒子ID
$prize_num = $order['prize_num'];#抽奖数量
$order_type = $order['order_type'];#订单类型
#查找奖品
$goodslist = GoodsList::field('id,shang_id,real_pro')
->where('goods_id', '=', $goods_id)
->where('num', '=', 0)
->where('real_pro', '>', 0)
->select()->toArray();
if ($goodslist) {
#组合中奖商品
$all_goods_id = [];
foreach ($goodslist as $value) {
$real_pro = $value['real_pro'] * 100;
for ($i = 1; $i <= $real_pro; $i++) {
$all_goods_id[] = $value['id'];
}
}
for ($i = 0; $i < $prize_num; $i++) {
#随机打乱
shuffle($all_goods_id);
shuffle($all_goods_id);
$prize_id = $all_goods_id[0];
$prize_info = GoodsList::where(['id' => $prize_id])->find();
#编号
$luck_no = OrderList::field('id')
->where('goods_id', '=', $goods_id)
->where('num', '=', 0)
->where('order_type', '=', $order_type)
->order('id desc')
->value('luck_no');
$luck_no++;
#新增记录
$save_prize_info = [
'order_id' => $order_id,
'user_id' => $user_id,
'status' => 0,#0未操作 1选择兑换 2选择发货
'goods_id' => $goods_id,
'num' => 0,
'shang_id' => $prize_info['shang_id'],
'goodslist_id' => $prize_info['id'],
'goodslist_title' => $prize_info['title'],
'goodslist_imgurl' => $prize_info['imgurl'],
'goodslist_price' => $prize_info['price'],
'goodslist_money' => $prize_info['money'],
'goodslist_type' => $prize_info['goods_type'],
'goodslist_sale_time' => $prize_info['sale_time'],
'addtime' => time(),
'prize_code' => $prize_info['prize_code'],
'order_type' => $order_type,
'luck_no' => $luck_no,
];
#入库===
$res[] = OrderList::insert($save_prize_info);
}
} else {
$res[] = 0;
}
return $res;
}
/**
* 道具卡======================================================
* @param int $user_id 会员id
* @param int $order_id 订单ID
* @param int $box_id 盲盒id
*/
public function item_card_notice($user_id = 0, $order_id = 0, $goods_id = 0)
{
$res = [];
$order = Order::where(['id' => $order_id])
->where(['user_id' => $user_id])
->where(['goods_id' => $goods_id])
->where(['num' => 0])
->where(['status' => 0])
->find();
if ($order) {
#改变状态
$res[] = Order::field('status,pay_time')
->where(['id' => $order['id']])
->update([
'status' => 1,
'pay_time' => time(),
]);
#扣道具卡
if ($order['use_item_card'] > 0) {
$res[] = Db::name('user_item_card')->where(['user_id' => $user_id, 'status' => 1])->order('id asc')->limit($order['use_item_card'])->update(['status' => 2, 'order_id' => $order_id, 'updatetime' => time()]);
}
#开奖==================================================
$res[] = $this->draw_drawprize($order);
#开奖==================================================
// 更新Redis中盒子的热度值
$this->updateGoodsHeat($goods_id, $order['prize_num']);
} else {
$res[] = 0;
}
return $res;
}
public function wx_gf_fahuo($user_id, $order_num)
{
$user = Db::name('user')->where('id', $user_id)->find();
$mp = new \app\common\server\platform\MiniProgramPlatform();
$mp->post_order($user, $order_num);
// //微信官方发货
// $wxServer = new \app\common\server\Wx($this->app);
// $access_token = $wxServer->get_access_token();
// $open_id = Db::name('user')->where('id', $user_id)->value('openid');
// $pay = new \app\api\controller\Pay();
// $pay->post_order($open_id, $access_token, $order_num);
// $wxServer->post_order($open_id, $access_token, $order_num);
}
/**
* 商城赏======================================================
* @param int $user_id 会员id
* @param int $order_id 订单ID
* @param int $box_id 盲盒id
*/
public function infinite_shangchengshang_notice($user_id = 0, $order_id = 0, $goods_id = 0, $num = 0)
{
$res = [];
$order = Order::where(['id' => $order_id])
->where(['user_id' => $user_id])
->where(['goods_id' => $goods_id])
->where(['num' => $num])
->where(['status' => 0])
->find();
if ($order == null && $num == 0) {
$order = Order::where(['id' => $order_id])
->where(['user_id' => $user_id])
->where(['goods_id' => $goods_id])
->where(['num' => 1])
->where(['status' => 0])
->find();
if ($order != null) {
$order_type1 = $order['order_type'];
if ($order_type1 == 10) {
$num = 1;
}
}
}
if ($order) {
#改变状态
$res[] = Order::field('status,pay_time')
->where(['id' => $order['id']])
->update([
'status' => 1,
'pay_time' => time(),
]);
#扣余额
if ($order['use_money'] > 0) {
$res[] = User::changeMoney($order['user_id'], -$order['use_money'], 3, '购买盒子' . $order['goods_title']);
}
#扣货币
if ($order['use_integral'] > 0) {
$res[] = User::changeIntegral($order['user_id'], -$order['use_integral'], 2, '购买盒子' . $order['goods_title']);
}
#扣货币2
if ($order['use_money2'] > 0) {
$res[] = User::changeMoney2($order['user_id'], -$order['use_money2'], 2, '购买盒子' . $order['goods_title']);
}
$res[] = $this->infinite_shangchengshang($order);
} else {
$res[] = 0;
}
return $res;
}
/**
* 更新Redis中盒子的热度值
*
* @param int $goods_id 盒子ID
* @param int $prize_num 本次抽奖次数
* @return bool 更新结果
*/
private function updateGoodsHeat($goods_id, $prize_num)
{
try {
// 获取Redis实例
$redis = (new \app\common\server\RedisHelper())->getRedis();
$cacheKey = "order_goods_count:{$goods_id}";
// 获取当前热度值
$current_heat = $redis->get($cacheKey);
// 如果缓存不存在,先从数据库获取
if ($current_heat === false) {
$current_heat = \app\common\model\OrderList::where('goods_id', '=', $goods_id)
->where('shang_id', 'between', [34, 38])
->where('parent_goods_list_id', '=', 0)
->count();
} else {
// 转为整数
$current_heat = intval($current_heat);
}
// 计算新的热度值
$new_heat = $current_heat + $prize_num;
// 更新Redis缓存设置5分钟过期时间
$redis->set($cacheKey, $new_heat, 300);
return true;
} catch (\Exception $e) {
// 发生异常时记录日志
\think\facade\Log::error("更新盒子热度值失败:" . $e->getMessage());
return false;
}
}
/**
* 新的支付结果通知处理方法(通过路径参数接收)
* @param string|null $payment_type 支付方式
* @param string|null $order_type 赏品类型(order_yfs, order_lts等)
* @param int|null $user_id 用户ID
* @param string|null $order_num 订单号
* @param int|null $timestamp 支付时间戳
* @param string|null $sign 加密验签
* @return void
*/
public function order_notify_new($payment_type = null, $order_type = null, $user_id = null, $order_num = null, $timestamp = null, $sign = null)
{
$rawContent = Request::getContent(); // 返回原始字符串
// 记录接收到的参数
writelog('pay_notify_log', json_encode([
'method' => 'order_notify_new',
'payment_type' => $payment_type,
'order_type' => $order_type,
'user_id' => $user_id,
'order_num' => $order_num,
'timestamp' => $timestamp,
'sign' => $sign,
'time' => date('Y-m-d H:i:s'),
'psot' => $rawContent
]));
// 验证所有必要参数是否存在
if (empty($payment_type) || empty($order_type) || empty($user_id) || empty($order_num) || empty($timestamp) || empty($sign)) {
writelog('pay_notify_error', "缺少必要参数: payment_type={$payment_type}, order_type={$order_type}, user_id={$user_id}, order_num={$order_num}, timestamp={$timestamp}, sign={$sign}");
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
// 验证时间戳允许6小时的误差
if (abs(time() - intval($timestamp)) > 21600) {
writelog('pay_notify_error', "时间戳验证失败超出6小时的有效期: " . $timestamp);
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
if ($payment_type == "zfbpay") {
$postData = request()->post();
$h5 = new \app\common\server\platform\H5Platform();
$zfb_result = $h5->verify($order_num, $postData);
if (!$zfb_result) {
writelog('pay_notify_error', "支付宝支付验证失败: " . $order_num);
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
}
// 获取Redis实例
$redis = (new \app\common\server\RedisHelper())->getRedis();
$lockKey = "pay_notify_lock:{$order_num}";
// 尝试获取锁过期时间为5分钟
if (!$redis->setnx($lockKey, time())) {
// 如果锁已存在,检查是否已经超时
$lockTime = $redis->get($lockKey);
if ($lockTime && time() - $lockTime < 300) {
// 锁未超时,说明订单正在处理中,直接返回成功
writelog('pay_notify_info', "订单 {$order_num} 正在处理中,跳过重复请求");
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
// 锁已超时,可以强制获取
$redis->set($lockKey, time(), 300);
} else {
// 成功获取锁,设置过期时间
$redis->expire($lockKey, 300);
}
try {
// 从订单通知表中获取随机字符串
$orderNotify = \app\common\model\OrderNotify::getByOrderNo($order_num);
if (!$orderNotify) {
writelog('pay_notify_error', "未找到订单通知记录: " . $order_num);
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
$nonce_str = $orderNotify['nonce_str'];
if (empty($nonce_str)) {
writelog('pay_notify_error', "订单 {$order_num} 没有关联的随机字符串");
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
// 验证签名
$data = [
'payment_type' => $payment_type,
'order_type' => $order_type,
'user_id' => $user_id,
'order_num' => $order_num,
'timestamp' => $timestamp,
'nonce_str' => $nonce_str // 使用从数据库中获取的随机字符串
];
if (!verifyPayNotifySign($data, $sign)) {
writelog('pay_notify_error', "签名验证失败: " . json_encode($data));
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
$price = 0;
// 开始处理支付
Db::startTrans();
try {
$res = [];
// 更新订单通知状态为处理中
\app\common\model\OrderNotify::updateStatus($orderNotify['id'], 1, '回调处理中');
if ($order_type == 'order_list_send') {
// 背包发货处理逻辑
$orderInfo = OrderListSend::where('send_num', '=', $order_num)
->where('status', '=', 0)
->find();
if (!$orderInfo) {
writelog('pay_notify_error', "未找到发货订单或状态错误: " . $order_num);
\app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '未找到发货订单或状态错误');
Db::rollback();
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
$user_id = $orderInfo['user_id'];
$freight = $orderInfo['freight'];
$res[] = $this->reward_order_handle($user_id, $orderInfo['id']);
// 记录微信支付
$res[] = ProfitPay::insert([
'user_id' => $user_id,
'order_num' => $order_num,
'change_money' => $freight,
'content' => '背包发货',
'pay_type' => $payment_type == 'alipay' ? 2 : 1,
'addtime' => time(),
]);
// 微信官方公众号发货通知
if ($payment_type == "wxpay") {
$this->wx_gf_fahuo($user_id, $order_num);
}
} else {
// 普通盒子订单处理逻辑
$orderInfo = Order::where('order_num', '=', $order_num)
->find();
if (!$orderInfo) {
writelog('pay_notify_error', "未找到订单: " . $order_num);
\app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '未找到订单');
Db::rollback();
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
// 检查订单状态
if ($orderInfo['status'] != 0) {
writelog('pay_notify_error', "订单状态不正确: " . $order_num . ", 状态: " . $orderInfo['status']);
\app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '订单状态不正确');
Order::where(['order_num' => $order_num])->update(['kd_is' => 1]);
Db::rollback();
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
// 验证用户ID是否一致
if ($orderInfo['user_id'] != $user_id) {
writelog('pay_notify_error', "用户ID不匹配: 通知中的用户ID={$user_id}, 订单中的用户ID={$orderInfo['user_id']}");
\app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '用户ID不匹配');
Order::where(['order_num' => $order_num])->update(['kd_is' => 1]);
Db::rollback();
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
$price = $orderInfo['price'];
// 根据订单类型执行不同的处理逻辑
if (in_array($order_type, ['order_wxs', 'order_fbs'])) {
// 无限赏处理
$res[] = $this->infinite_drawprize_notice($user_id, $orderInfo['id'], $orderInfo['goods_id'], $orderInfo['num']);
} elseif (in_array($order_type, ['order_yfs', 'order_lts', 'order_zzs', 'order_flw', 'order_scs'])) {
// 一番赏、擂台赏等处理
$res[] = $this->drawprize_notice($user_id, $orderInfo['id'], $orderInfo['goods_id'], $orderInfo['num']);
} elseif ($order_type == 'order_ckj') {
// 抽卡机处理
$res[] = $this->cardextractor_drawprize_notice($user_id, $orderInfo['id'], $orderInfo['goods_id']);
} else {
writelog('pay_notify_error', "不支持的订单类型: " . $order_type);
\app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '不支持的订单类型');
Db::rollback();
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
return;
}
// 微信官方公众号发货通知
if ($payment_type == "wxpay") {
$this->wx_gf_fahuo($user_id, $orderInfo['order_num']);
}
// 记录支付信息
$res[] = Db::name('profit_pay')->insert([
'user_id' => $user_id,
'order_num' => $order_num,
'change_money' => $price,
'content' => '购买盒子' . $orderInfo['goods_title'],
'pay_type' => $payment_type == 'alipay' ? 2 : 1,
'addtime' => time(),
]);
}
if (resCheck($res)) {
Db::commit();
writelog('pay_notify_success', "支付成功处理完成: " . $order_num);
\app\common\model\OrderNotify::updateStatus($orderNotify['id'], 1, '支付处理成功');
} else {
Db::rollback();
writelog('pay_notify_error', "支付处理失败,可能存在业务逻辑错误: " . $order_num);
\app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '支付处理失败,业务逻辑错误');
}
} catch (\Exception $e) {
Db::rollback();
writelog('pay_notify_error', "支付处理异常: " . $e->getMessage() . ", 订单号: " . $order_num);
try {
// 标记订单为卡单状态
if ($order_type == 'order_list_send') {
OrderListSend::where(['send_num' => $order_num])->update(['kd_is' => 1]);
} else {
Order::where(['order_num' => $order_num])->update(['kd_is' => 1]);
}
\app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '支付处理异常: ' . $e->getMessage());
} catch (\Exception $ex) {
writelog('pay_notify_error', "更新卡单状态异常: " . $ex->getMessage());
}
}
// 无论处理结果如何,都释放锁并返回成功,避免重复通知
$redis->del($lockKey);
$this->CallbackSuccess_new($payment_type); // 返回成功
} catch (\Exception $e) {
// 处理外层异常(如锁获取失败等)
writelog('pay_notify_error', "处理订单异常: " . $e->getMessage() . ", 订单号: " . $order_num);
$this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知
}
}
public function test_notify_url()
{
// 测试生成支付通知URL
$payment_type = 'wxpay';
$order_type = 'order_wxs';
$user_id = 123;
$order_num = 'MH_' . date('YmdHis') . random_int(1000, 9999);
$nonce_str = getRandStr(16);
try {
// 生成URL
$notify_url = generatePayNotifyUrl($payment_type, $order_type, $user_id, $order_num, $nonce_str);
// 解析URL以提取参数和签名
$url_parts = parse_url($notify_url);
$path_parts = explode('/', trim($url_parts['path'], '/'));
// 路径格式应该是: notify/payment_type/order_type/user_id/order_num/timestamp/sign
$extracted_payment_type = $path_parts[1] ?? '';
$extracted_order_type = $path_parts[2] ?? '';
$extracted_user_id = $path_parts[3] ?? '';
$extracted_order_num = $path_parts[4] ?? '';
$extracted_timestamp = $path_parts[5] ?? '';
$extracted_sign = $path_parts[6] ?? '';
// 重新构建验证数据
$verify_data = [
'payment_type' => $extracted_payment_type,
'order_type' => $extracted_order_type,
'user_id' => $extracted_user_id,
'order_num' => $extracted_order_num,
'timestamp' => $extracted_timestamp,
'nonce_str' => $nonce_str
];
// 验证签名
$is_valid = verifyPayNotifySign($verify_data, $extracted_sign);
// 返回测试结果
return json([
'original' => [
'payment_type' => $payment_type,
'order_type' => $order_type,
'user_id' => $user_id,
'order_num' => $order_num,
'nonce_str' => $nonce_str
],
'generated_url' => $notify_url,
'extracted' => [
'payment_type' => $extracted_payment_type,
'order_type' => $extracted_order_type,
'user_id' => $extracted_user_id,
'order_num' => $extracted_order_num,
'timestamp' => $extracted_timestamp,
'sign' => $extracted_sign
],
'is_valid' => $is_valid,
'message' => '支付通知URL测试成功'
]);
} catch (\Exception $e) {
return json([
'error' => $e->getMessage(),
'message' => '生成支付通知URL失败请确保提供了所有必要参数'
]);
}
}
}