| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- <?php
- /**
- * 玩家充值相关公共业务逻辑类
- *
- */
- namespace app\common\logic;
- use app\common\model\MemberCoinInfo;
- use think\Cache;
- use app\common\library\Mail;
- use app\common\model\Members;
- use app\common\model\Game;
- use app\common\model\PaySetting;
- use app\common\model\PayWarningRule;
- use think\Db;
- use think\Env;
- use think\Exception;
- class Pay
- {
- /**
- * 设置充值预警的redis信息
- *
- * @param $member_id int 玩家ID
- * @param $channel_id int 渠道ID
- * @param $game_id int 游戏ID
- * @param $amount 充值金额
- *
- */
- public function payWarning($member_id, $channel_id, $game_id, $amount)
- {
- //配置信息
- $settingInfo = (new PaySetting)->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;
- }
- }
- }
- }
|