getPaySetting(); //规则列表 $rule_list = (new PayWarningRule)->getPaySetting(); $settingInfo['whitelist_channel'] = empty($settingInfo['whitelist_channel']) ? [] : explode(',', $settingInfo['whitelist_channel']); //功能状态开启并且有设置预警规则时 if (isset($settingInfo['status']) && $settingInfo['status'] == 1 && !in_array($channel_id, $settingInfo['whitelist_channel']) && count($rule_list) > 0) { $this->payTimesOverLimit($rule_list, $member_id, $channel_id, $game_id, $amount); } } /** * 充值预警是否超过限制次数 * * @param $rule_list array 规则列表 * */ public function payTimesOverLimit($rule_list, $member_id, $channel_id, $game_id, $amount) { foreach ($rule_list as $v) { $key = 'clearable_pay_warning:channelid:' . $channel_id . 'gameid:' . $game_id . 'member_id:' . $member_id . 'ruleid:' . $v['id'] . 'amount_' . $amount; //包含6元 if ($v['is_six']) { if ($v['min_amount'] <= $amount && $amount <= $v['max_amount']) { $res = $this->setRedisByRule($key, $v['order_count'], $v['warning_time'], $member_id, $game_id); } } //不包含6元 else { if ($amount != 6 && $v['min_amount'] <= $amount && $amount <= $v['max_amount']) { $res = $this->setRedisByRule($key, $v['order_count'], $v['warning_time'], $member_id, $game_id); } } } } /** * 满足规则时,设置redis缓存计数 * * @param $key string redis的key * @param $times int 累加次数 * @param $expire int redis有效期 * @param $member_id int 玩家ID * @param $game_id int 游戏ID * */ public function setRedisByRule($key, $times, $expire, $member_id, $game_id) { if (empty($key)) { return false; } $times = (int)$times; $expire = (int)$expire * 60; //规则中设置的预警时间阈值 $redis = Cache::store('default')->handler(); $value = $redis->incr($key); //充值次数 //超过预警规则的次数时 if ($times <= $value) { $redis->del($key); //发送预警邮件 $this->sendWarningMail($member_id, $game_id); return true; //代表可以发送邮件 } //首次时 else if ('1' == $value) { $redis->expire($key, $expire); } return false; } /** * 发送预警邮件 * */ public function sendWarningMail($member_id, $game_id) { //配置信息 $settingInfo = (new PaySetting)->getPaySetting(); //用户名 $username = (new Members())->where(['id' => $member_id])->value('username'); //游戏名称 $game_name = (new Game())->where(['id' => $game_id])->value('name'); /* //发送邮件 (new Mail())->sendMail("{$username}账号 在 {$game_name} 充值存在异常,请及时核实,时间:".date('Y-m-d H:i:s'), explode(';',$settingInfo['emails'])); */ $template = $username . " 账号在游戏 " . $game_name . " 充值存在异常,请及时核实,时间:" . date('Y-m-d H:i:s'); $ddurl = Env::get('dingtalk.warning_url'); $result = curlDD($template, $ddurl, true); } //----------------------------------------------------------------------------------// /** * 计算订单各项支付金额 * * @param $amount :订单总金额 * @param $coin_amount :专属币余额 * @param $ptb_amount :使用平台币金额 * * @return $result array */ public function calPayAmount($amount, $ptb_amount = 0,$discount = 1) { $result['real_amount'] = 0; // 实际支付金额 $result['real_ptb'] = 0; // 使用平台币的金额 $result['real_coin'] = 0; // 真实平台币 // 先计算折扣后的应付总额 $discounted_amount = round(bcmul((string)$amount, (string)$discount, 3), 2); // 确保最小支付 0.01 if($amount != 0 && $discounted_amount < 0.01){ $discounted_amount = 0.01; } // 如果专属币大于等于折扣后的总额 if ($ptb_amount > 0 && bccomp((string)$ptb_amount, $discounted_amount, 2) >= 0) { $result['real_ptb'] = $discounted_amount; $result['real_amount'] = 0; $result['pay_amount'] = $result['real_ptb']; } else { $diff = bcsub($discounted_amount, $ptb_amount, 2); $result['real_amount'] = $diff; // 四舍五入到 2 位 $result['real_ptb'] = $ptb_amount; $result['pay_amount'] = round(bcadd($diff, $ptb_amount, 3), 2); } $result['real_coin'] = 0; return $result; } /** * 专属币相关数据更新处理 * * @param array $coinInfo 使用的平台币信息 * @param array $payData 消费的订单信息 * */ public function saveCoinData($coinInfo, $payData) { $userCoinInfo = model('MemberZscoin')->field('id,userid,username,game_id,amount,status')->where(['userid' => $coinInfo['userid'], 'game_id' => $coinInfo['game_id']])->find(); if (!empty($userCoinInfo)) { $coinData = array(); $coinData['amount'] = Db::raw("amount-" . $payData['real_ptb']); $coinData['update_time'] = time(); $result = model('MemberZscoin')->where(['id' => $userCoinInfo['id'], 'userid' => $userCoinInfo['userid'], 'game_id' => $userCoinInfo['game_id'], 'amount' => ['>=', $payData['real_ptb']]])->update($coinData); if (!$result) { throw new Exception("用户游戏平台币账户金额变动失败"); } $coinDetData = array(); $coinDetData['userid'] = $payData['userid']; $coinDetData['username'] = $payData['username']; $coinDetData['game_id'] = $payData['gameid']; $coinDetData['type'] = 3; $coinDetData['prev_amount'] = $userCoinInfo['amount']; $coinDetData['change_amount'] = -$payData['real_ptb']; $coinDetData['after_amount'] = $coinDetData['prev_amount'] - $payData['real_ptb']; $coinDetData['out_orderid'] = $payData['orderid']; $coinDetData['create_time'] = time(); $coinDetData['update_time'] = time(); $insertDetId = model('MemberZscoinDet')->insertGetId($coinDetData); if (!$insertDetId) { throw new Exception("添加用户游戏平台币变动明细失败"); } } else { throw new Exception("游戏平台币账户余额不足"); } } /** * 计算订单各项支付金额 * * @param $amount string 订单总金额 * @param $coin_amount double 平台币余额 * @param $discount double 折扣 * * @return $result array */ public function calCoinPayAmount($amount, $coin_amount = 0,$discount = 1) { $result['real_amount'] = 0; // 实际支付金额 $result['real_ptb'] = 0; // 使用平台币的金额 $result['real_coin'] = 0; // 专属平台币 // 先计算折扣后的应付总额 $discounted_amount = round(bcmul((string)$amount, (string)$discount, 3), 2); // 确保最小支付 0.01 if($amount != 0 && $discounted_amount < 0.01){ $discounted_amount = 0.01; } // 如果平台币大于等于折扣后的金额,则支付平台币,否则使用 平台币+第三方支付 if ($amount > 0 && bccomp((string)$coin_amount, $discounted_amount, 2) >= 0) { $result['real_ptb'] = 0; $result['real_coin'] = $discounted_amount; $result['real_amount'] = 0; $result['pay_amount'] = $result['real_coin']; } else { $diff = bcsub($discounted_amount, $coin_amount, 2); $result['real_ptb'] = 0; $result['real_amount'] = $diff; $result['real_coin'] = $coin_amount; $result['pay_amount'] = round(bcadd($diff, $coin_amount, 3), 2); } // dump($result); return $result; } /** * 平台币相关数据更新处理 * * @param array $members 使用的平台币信息 * @param array $payInfo 消费的订单信息 * */ public function saveCoinPayData($members, $payInfo) { $membersModel = new Members(); $amount = priceFormat($members['amount'] - $payInfo['real_coin']); if($amount<0){ return false; } $coinData = [ 'userid' => $payInfo['userid'], 'orderid' => $payInfo['orderid'], 'start_amount' => $members['amount'], 'amount' => '-'.$payInfo['real_coin'], 'result_amount' => $amount, 'type' => 2, 'remarks' => '平台币使用', 'create_time' => NOW_TIMESTAMP ]; $memberCoinInfoModel = new MemberCoinInfo(); if (!$memberCoinInfoModel->insertGetId($coinData)) { return false; } if (!$membersModel->where('id', $payInfo['userid'])->update(['amount' => $amount])) { return false; } return true; } /** * 代金券使用状态修改 * @param $payData * @return bool */ public function saveCouponData($payData){ if($payData['real_amount']>0){ if(model('common/CouponMember')->where(['id'=>$payData['coupon_member_id'],'is_use'=>1,'examine'=>2,'state'=>1])->update(['is_use'=>2,'use_time'=>time()])){ return true; }else{ return false; } }else{ if(model('common/CouponMember')->where(['id'=>$payData['coupon_member_id'],'is_use'=>1,'examine'=>2,'state'=>1])->update(['is_use'=>3,'use_time'=>time()])){ return true; }else{ return false; } } } }