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数据 * @param string $xml */ public function CallbackSuccess_new($payment_type) { if ($payment_type == "zfbpay") { exit('success'); } else { exit(''); } } /** * 抽赏开始抽赏====================================================== * @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 */ 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 = "{$title}"; } $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 = ""; 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); } } elseif ($order_type == 'order_product') { // 钻石订单处理逻辑 $diamondOrder = \app\common\model\DiamondOrder::where('order_no', '=', $order_num) ->where('status', '=', \app\common\model\DiamondOrder::STATUS_PENDING) ->find(); if (!$diamondOrder) { writelog('pay_notify_error', "未找到钻石订单或状态错误: " . $order_num); \app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '未找到钻石订单或状态错误'); Db::rollback(); $this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知 return; } // 验证用户ID是否一致 if ($diamondOrder['user_id'] != $user_id) { writelog('pay_notify_error', "用户ID不匹配: 通知中的用户ID={$user_id}, 钻石订单中的用户ID={$diamondOrder['user_id']}"); \app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '用户ID不匹配'); Db::rollback(); $this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知 return; } $price = $diamondOrder['amount_paid']; // 查询钻石商品信息 $diamondProduct = \app\common\model\DiamondProducts::where('id', '=', $diamondOrder['diamond_id'])->find(); if (!$diamondProduct) { writelog('pay_notify_error', "未找到钻石商品: " . $diamondOrder['diamond_id']); \app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '未找到钻石商品'); Db::rollback(); $this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知 return; } $reward_log = ''; if ($diamondProduct['base_reward'] == "") { writelog('pay_notify_error', "商品没有设置基础奖励: " . $diamondOrder['diamond_id']); \app\common\model\OrderNotify::updateStatus($orderNotify['id'], 2, '商品没有设置基础奖励'); Db::rollback(); $this->CallbackSuccess_new($payment_type); // 返回成功避免重复通知 return; } // 给用户钱包加钻石 $reward_res = RewardService::sendReward($user_id, $diamondProduct['base_reward'], '购买商品' . $diamondProduct['name']); if ($reward_res) { foreach ($reward_res['data'] as $item) { $reward_log .= $item['msg'] . ','; } // implode(',', $reward_res['data']); } //判断商品是否开启首充 if ($diamondProduct['is_first'] == 1) { //判断是否有首充 $diamond_order_count = \app\common\model\DiamondOrder::where('user_id', $user_id) ->where('status', '=', 'success')->count(); if ($diamond_order_count == 0 && $diamondProduct['first_bonus_reward'] != '') { $reward_res = RewardService::sendReward($user_id, $diamondProduct['first_bonus_reward'], '首充赠送'); foreach ($reward_res['data'] as $item) { $reward_log .='首充赠送' . $item['msg'] . ','; } // $reward_log = '首充赠送' . implode(',', $reward_res['data']); } } //判断$reward_log结尾是否是,号,是的话,去除 if(substr($reward_log, -1) == ','){ $reward_log = substr($reward_log, 0, -1); } // 更新订单状态为支付成功 $res[] = $diamondOrder->save([ 'status' => \app\common\model\DiamondOrder::STATUS_SUCCESS, 'paid_at' => date('Y-m-d H:i:s'), 'reward_log' => '支付成功,' . $reward_log ]); // 记录支付信息 $res[] = Db::name('profit_pay')->insert([ 'user_id' => $user_id, 'order_num' => $order_num, 'change_money' => $price, 'content' => '购买钻石' . $diamondProduct['name'], 'pay_type' => $payment_type == 'alipay' ? 2 : 1, 'addtime' => time(), ]); } 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]); } elseif ($order_type == 'order_product') { // 钻石订单处理异常,标记为失败状态 \app\common\model\DiamondOrder::where(['order_no' => $order_num]) ->update([ 'status' => \app\common\model\DiamondOrder::STATUS_FAILED, 'reward_log' => '支付处理异常: ' . $e->getMessage() ]); } 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失败,请确保提供了所有必要参数' ]); } } }