feat(robot): 增加商户余额监控和订单查询功能

- 新增商户余额监控功能,支持异步消息提醒
- 添加订单查询功能,可查询当天和最近一周的订单
- 实现携转检测功能,可查询手机号是否携转及新旧运营商
- 优化机器人自动回复逻辑,支持多种查询命令
This commit is contained in:
mzeros 2025-01-08 16:05:57 +08:00
parent 991222546d
commit 25439b988e
6 changed files with 369 additions and 159 deletions

View File

@ -15,6 +15,7 @@
namespace app\merchant\controller;
use app\gateway\service\RedisService;
use think\admin\Controller;
use app\merchant\service\MerchantLogService;
use app\merchant\service\MerchantService;
@ -253,6 +254,20 @@ class Merchant extends Controller
}
if (MerchantLogService::instance()->add($data['mid'], $data['num'], $data['account_type'],$data['type'],$data['desc']) !== false) {
sysoplog('修改金额', '修改金额:'.$data['num'].'元,类型为:'. $data['account_type']);
if(sysconf('queue') == 1){
#此处判断是否开启异步做消息提醒
try{
$redisService = RedisService::getInstance();
$redis_data =$data;
$redis_data['time'] = date('Y-m-d H:i:s');
$redisService->push('merchant_recharge_msg', $redis_data);
}catch (\Exception $e){
}
}
/*
$info = MerchantService::instance()->getInfo($data['mid']);
MerchantService::instance()->get($info['appid'], false);

View File

@ -2,6 +2,7 @@
namespace app\merchant\controller;
use app\gateway\service\RedisService;
use think\admin\Controller;
use app\merchant\service\PercentService;
@ -228,7 +229,9 @@ class Percent extends Controller
$update['rule'] = $rule;
}
$this->app->db->name('merchant_percent')->where(['id' => $info['id']])->update($update);
}
}
//PercentService::instance()->get($mid, $product_key, false);

View File

@ -1060,82 +1060,20 @@ class Test extends Core
ini_set('memory_limit', '1024M');
$this->redis();
$channelService = ChannelService::instance();
$RobotService = new WxWorkBot($this->app);
$channelList = $channelService->db()->where(['status'=>1])->whereLike('other_data','%Monitor_Balance_status%')->select()->toArray();
$merchantService = MerchantService::instance();
$RobotService = new WeChatBotC($this->app);
$channelList_num = count($channelList);
$merchantsList = $merchantService->db()->where(['merchant_type'=>1,'status'=>1])->whereLike('other_param','%Monitor_Balance_status%')->select()->toArray();
$merchantsList_num = count($merchantsList);
$count_sum = 0;
$mid = 1;
$merchantMid1 = array_filter($merchantsList, function($merchant) use ($mid) {
return $merchant['id'] == $mid;
});
$day = date('Y-m-d', strtotime('-1 day'));
$tip_info=[];
$key = '41b42bd4-c9f9-4617-9531-0a358dd97a82';
foreach($channelList as $channel) {
$other_param = json_decode($channel['other_data'],true);
if(!$other_param){
continue;
}
$Monitor_Balance = $other_param['Monitor_Balance'] ?? null;
if(!$Monitor_Balance){
continue;
}
try{
$account_data = $channelService->call('account', $channel['id'], $day);
if (is_array($account_data) && isset($account_data['account'])) {
$balance = $account_data['account'];
if( $balance <= $Monitor_Balance){
$count_sum ++;
$this->redis->set('Check_channel_account-'.$channel['id'],1);
$tip_info[] = $channel['name']."<font color=\"comment\">余额不足,只剩下</font>:<font color=\"info\">".$balance."</font>";
$Monitor_Balance_TOP = $other_param['Monitor_Balance_TOP'] ?? null;
if($Monitor_Balance_TOP && $balance <= $Monitor_Balance_TOP){
if(!$this->redis->get('Check_channel_account_TOP-'.$channel['id'])){
$count_sum ++;
$this->redis->set('Check_channel_account_TOP-'.$channel['id'],1);
$tip_info[] = $channel['name']."<font color=\"comment\">余额不足,只剩下</font>:<font color=\"info\">".$balance."</font>";
}
}
}else{
if($this->redis->get('Check_channel_account-'.$channel['id'])){
$count_sum ++;
$this->redis->delete('Check_channel_account-'.$channel['id']);
$tip_info[] = $channel['name']."<font color=\"comment\">余额已经恢复,现在余额为</font>:<font color=\"info\">".$balance."</font>";
}
if($this->redis->get('Check_channel_account_TOP-'.$channel['id'])){
$this->redis->delete('Check_channel_account_TOP-'.$channel['id']);
}
}
}
}catch (\Exception $e){
}
}
if(!empty($tip_info)){
$errorMsg = "渠道余额监控预警<font color=\"warning\">".$count_sum ."列</font>,请相关同事注意。\n
>";
$errorMsg .= implode(">", $tip_info);
$errorMsgs =$RobotService->send_markdown($errorMsg,$key);
}
var_dump($errorMsgs);
// 获取第一个匹配的元素
$merchantMid1 = reset($merchantMid1);
var_dump($merchantMid1);
}

View File

@ -3,7 +3,12 @@
namespace app\private_api\controller\robotApi;
use app\channel\service\ChannelService;
use app\core\Service;
use app\gateway\service\RedisService;
use app\merchant\service\MerchantService;
use app\merchant\service\OrderLastweekHistoryService;
use app\order\service\OrderService;
use dever\Log;
use think\exception\HttpResponseException;
use app\robot\controller\WeChatBot as WeChatBotC;
use app\robot\service\WeChatService;
@ -56,51 +61,267 @@ class WeChatBot extends Core
{
$RobotService = new WeChatBotC($this->app);
$data = input();
if(isset($data['token'])){
$robotInfo = $this->getRobotInfo($data['token']);
if($robotInfo){
$this->robotInfo = $robotInfo;
}else{
return $this->response(['code'=>-1,'msg'=>'机器人不存在']);
}
}else{
return $this->response(['code'=>-1,'msg'=>'参数错误']);
}
// if(isset($data['token'])){
// $robotInfo = $this->getRobotInfo($data['token']);
// if($robotInfo){
// $this->robotInfo = $robotInfo;
// }else{
// return $this->response(['code'=>-1,'msg'=>'机器人不存在']);
// }
// }else{
// return $this->response(['code'=>-1,'msg'=>'参数错误']);
// }
# 判断是否为群组
if($data['is_group']){
$roomid = $data['roomid'];
if($roomid == '47576792968@chatroom' && str_contains($data['xml'],'wxid_9iv1hha8g3ok29')){
$AllContacts = $RobotService->get_all_contacts();
// var_dump($AllContacts);die;
$Contacts_array = json_decode($AllContacts,true);
$acc = $Contacts_array['data']['contacts'];
// var_dump($acc);die;
$ac = '';
foreach ($acc as $k=>$v){
if($v['wxid'] == $data['sender']){
$ac = $v['name'];
// Log::write('robot', 'wechat', $data);
// if($roomid == '47576792968@chatroom' && str_contains($data['xml'],'wxid_9iv1hha8g3ok29')){
// $AllContacts = $RobotService->get_all_contacts();
//// var_dump($AllContacts);die;
// $Contacts_array = json_decode($AllContacts,true);
// $acc = $Contacts_array['data']['contacts'];
//// var_dump($acc);die;
// $ac = '';
// foreach ($acc as $k=>$v){
// if($v['wxid'] == $data['sender']){
// $ac = $v['name'];
// }
// }
//// var_dump($data['sender']);die;
// return $RobotService->send_text('测试自动回复 @'.$ac,$data['roomid'],$data['sender']);
// }
// if($roomid == '47576792968@chatroom' && str_contains($data['xml'],'wxid_9iv1hha8g3ok29')){
// $AllContacts = $RobotService->get_all_contacts();
//// var_dump($AllContacts);die;
// $Contacts_array = json_decode($AllContacts,true);
// $acc = $Contacts_array['data']['contacts'];
//// var_dump($acc);die;
// $ac = '';
// foreach ($acc as $k=>$v){
// if($v['wxid'] == $data['sender']){
// $ac = $v['name'];
// }
// }
//// var_dump($data['sender']);die;
// return $RobotService->send_text('测试自动回复 @'.$ac,$data['roomid'],$data['sender']);
// }
if( str_contains($data['xml'],'wxid_9iv1hha8g3ok29')){
$merchantService = MerchantService::instance();
$check_merchant = $merchantService->db()->whereLike('other_param', '%'.$roomid.'%')->findOrEmpty();
if($check_merchant){
$AllContacts = $RobotService->get_all_contacts();
$Contacts_array = json_decode($AllContacts,true);
$acc = $Contacts_array['data']['contacts'];
$ac = '';
foreach ($acc as $k=>$v){
if($v['wxid'] == $data['sender']){
$ac = $v['name'];
}
}
}
// var_dump($data['sender']);die;
return $RobotService->send_text('测试自动回复 @'.$ac,$data['roomid'],$data['sender']);
}
if($roomid == '47576792968@chatroom' && str_contains($data['xml'],'wxid_9iv1hha8g3ok29')){
$AllContacts = $RobotService->get_all_contacts();
// var_dump($AllContacts);die;
$Contacts_array = json_decode($AllContacts,true);
$acc = $Contacts_array['data']['contacts'];
// var_dump($acc);die;
$ac = '';
foreach ($acc as $k=>$v){
if($v['wxid'] == $data['sender']){
$ac = $v['name'];
if($roomid == '47576792968@chatroom'){
if(str_starts_with($data['content'], '@发财-庚辰小秘通知 ') ||str_starts_with($data['content'], '@发财-庚辰小秘 通知 ')||str_starts_with($data['content'], '@发财-庚辰小秘通知全部 ')){
$newString = strstr($data['content'], '通知全部 ');
if ($newString) {
$newString = substr($newString, strlen('通知全部 '));
}else{
$newString = strstr($data['content'], '通知 ');
if ($newString) {
$newString = substr($newString, strlen('通知 '));
}else{
$this->response(['code'=>1]);
}
}
$merchantsList = $merchantService->db()->where(['merchant_type'=>1,'status'=>1])->whereLike('other_param','%Monitor_Balance_status%')->select()->toArray();
if(!$merchantsList)return $this->response(['code'=>1]);
$tip_info=[];
$num = 0;
foreach ($merchantsList as $merchant){
$other_param = json_decode($merchant['other_param'],true);
$roomids = $other_param['QYWX_roomid'];
$sender = $other_param['QYWX_sender'];
if($roomid == $data['roomid']){
continue;
}
$acm = '';
foreach ($acc as $k=>$v){
if($v['wxid'] == $sender){
$acm = $v['name'];
}
}
$RobotService->send_text("通知 \n ".$newString."\n 时间:".date('Y-m-d H:i:s')."\n @".$acm,$roomids,$sender);
$tip_info[]=$merchant['name'];
$num++;
}
$merchant_name = implode("\n", $tip_info);
return $RobotService->send_text('通知完毕 共通知了'.$num."个商户:\n".$merchant_name.'@'.$ac,$data['roomid'],$data['sender']);
}
if(str_ends_with($data['content'], '余额') ){
$channelService = ChannelService::instance();
$channelList = $channelService->db()->where(['status'=>1])->whereLike('other_data','%Monitor_Balance_status%')->select()->toArray();
if(!$channelList)return $RobotService->send_text('暂无可查询渠道@'.$ac,$data['roomid'],$data['sender']);
$count_sum= 0;
$day = date('Y-m-d', strtotime('-1 day'));
$tip_info=[];
foreach($channelList as $channel) {
$other_param = json_decode($channel['other_data'], true);
if (!$other_param) {
continue;
}
$Monitor_Balance = $other_param['Monitor_Balance'] ?? null;
if (!$Monitor_Balance) {
continue;
}
try {
$account_data = $channelService->call('account', $channel['id'], $day);
if (is_array($account_data) && isset($account_data['account'])) {
$balance = $account_data['account'];
$tip_info[]='渠道:['.$channel['name']."] \n余额:【".$balance.'】元';
$count_sum++;
}
}catch (\Exception $e){
}
}
if(!$tip_info)return $RobotService->send_text('暂无可查询渠道@'.$ac,$data['roomid'],$data['sender']);
$errorMsg = implode("\n", $tip_info);
return $RobotService->send_text("渠道余额查询完毕,共查询了".$count_sum."个渠道:\n".$errorMsg."\n@".$ac,$data['roomid'],$data['sender']);
}
}
if(str_ends_with($data['content'], '余额') || str_ends_with($data['content'],'查余额')){
return $RobotService->send_text("商户[".$check_merchant['name']."] : \n 余额为:".$check_merchant['account_surplus']." @".$ac,$data['roomid'],$data['sender']);
}
if(str_starts_with($data['content'], '@发财-庚辰小秘1')||str_starts_with($data['content'], '@发财-庚辰小秘 1')){
$newString = strstr($data['content'], '1');
if (preg_match('/\b1[3-9]\d{9}\b/', $newString)) {
// Log::write('Robot', 'wechat', $data);
#查询订单
$msg = [];
$orderService = OrderService::instance();
$order = $orderService->db()->field('cid,pid,mid,order_id,merchant_order_id,param,account,cash,status,channel_callback_at,create_at')->where(['account'=>$newString,'mid'=>$check_merchant['id']])->select()->toArray();
if(!$order){
$orderLastweekHistoryService = OrderLastweekHistoryService::instance();
$order = $orderLastweekHistoryService->db()->field('cid,pid,mid,order_id,merchant_order_id,param,account,cash,status,channel_callback_at,create_at')->where(['account'=>$newString,'mid'=>$check_merchant['id']])->select()->toArray();
}
if(!$order)return $RobotService->send_text("手机号格式正确,但是未找到订单,暂时支持当天和最近一周的订单筛选,更多请前往后台查询 @".$ac,$data['roomid'],$data['sender']);
if (count($order) == 1) {
$orders = $order[0];
$infos =$orderService->getOrderInfo($orders['cid'],$orders['mid'],$orders['pid']);
$msg = [
'系统订单号:' . $orders['order_id'],
'产品:' . $infos['p']['name']??'',
'商户订单号:' . $orders['merchant_order_id'],
'手机号:' . $orders['account'],
'订单金额:' . $orders['cash'],
'订单状态:' . ($orders['status'] == 2 ? '成功' : ($orders['status'] == 3 ? '失败' : '处理中')),
'订单时间:' . $orders['create_at'],
];
if(str_contains($orders['param'], 'mnp_isp_array')){
$param_data = json_decode($orders['param'],true);
if($param_data['mnp_isp_array']['old_isp'] == $param_data['mnp_isp_array']['new_isp']){
$msg[] = '携转检测:未携转';
}else{
$msg[] = '携转检测:已携转';
$isp_name = [
1=>'移动',
2=>'联通',
3=>'电信',
];
$msg[] = '旧运营商:'.$isp_name[$param_data['mnp_isp_array']['old_isp']??0] ?? '';
$msg[] = '新运营商:'.$isp_name[$param_data['mnp_isp_array']['new_isp']??0] ?? '';
}
}
if(isset($orders['channel_callback_at']) && $orders['channel_callback_at']){
$msg[] = '完成时间:'.$orders['channel_callback_at'];
}
$m_msg= implode("\n", $msg);
return $RobotService->send_text("已为您查询到订单信息:\n".$m_msg." \n@".$ac, $data['roomid'], $data['sender']);
} else {
return $RobotService->send_text("手机号格式正确,查询到多条订单,暂时只支持单条查询,更多请前往后台查询 @".$ac,$data['roomid'],$data['sender']);
// foreach ($order as $singleOrder) {
// // 在这里处理每一条订单数据
// // 例如:$RobotService->send_text("订单信息: " . $singleOrder['some_field'], $data['roomid'], $data['sender']);
// }
}
}
}
if(str_starts_with($data['content'], '@发财-庚辰小秘检测 ')||str_starts_with($data['content'], '@发财-庚辰小秘 检测 ')){
$newString = strstr($data['content'], '1');
if (!preg_match('/\b1[3-9]\d{9}\b/', $newString)) return $RobotService->send_text("暂时只支持手机号码检测,其他请联系管理员 @".$ac,$data['roomid'],$data['sender']);
$settingPhoneMNPStatus = sysconf('settingPhoneMNPStatus');
if ($settingPhoneMNPStatus == 1) {
$mnp_cid = sysconf('PhoneMnp_cid');
$param = [
'mobile' => $newString,
];
if ($mnp_cid) {
$mnp_array = ChannelService::instance()->call('phone_mnp', $mnp_cid, $param);
if (is_array($mnp_array) && isset($mnp_array['new_isp'])) {
$msg = [
'手机号:' . $newString,
'是否携转:' . ($mnp_array['new_isp'] == $mnp_array['old_isp'] ? '否' : '是'),
'旧运营商:' . ($mnp_array['old_isp'] == 1 ? '移动' : ($mnp_array['old_isp'] == 2 ? '联通' : '电信')),
'新运营商:' . ($mnp_array['new_isp'] == 1 ? '移动' : ($mnp_array['new_isp'] == 2 ? '联通' : '电信')),
];
$m_msg= implode("\n", $msg);
return $RobotService->send_text("已经为您查询到手机号信息:\n".$m_msg." \n@".$ac, $data['roomid'], $data['sender']);
}
}
}
$isp = Service::instance()->isp($newString);
$msg = [
'手机号:' . $newString,
'是否携转:' . '未携转或者无法查询',
'运营商:' . ($isp == 1 ? '移动' : ($isp == 2 ? '联通' : '电信')),
];
$m_msg= implode("\n", $msg);
return $RobotService->send_text("已经为您查询到手机号信息:\n".$m_msg." \n@", $data['roomid'], $data['sender']);
}
return $RobotService->send_text('测试自动回复 @'.$ac,$data['roomid'],$data['sender']);
}
// var_dump($data['sender']);die;
return $RobotService->send_text('测试自动回复 @'.$ac,$data['roomid'],$data['sender']);
}
$this->response(['code'=>1]);
}

View File

@ -4,6 +4,7 @@ namespace app\queue\command\monitor;
use app\channel\service\ChannelService;
use app\gateway\service\RedisService;
use app\merchant\service\OrderService;
use app\robot\controller\WxWorkBot;
use think\admin\Command;
use think\console\Input;
@ -37,7 +38,7 @@ class ChannelOrderStatusMonitor extends Command
$RobotService = new WxWorkBot($this->app);
$channelList = $channelService->db()->where(['status'=>1])->whereLike('other_data','%Monitor_OrderStatus_status%')->select()->toArray();
if(!$channelList) $this->setQueueSuccess("未找到支持监控余额的渠道");
if(!$channelList) $this->setQueueSuccess("未找到支持监控订单的渠道");
$channelList_num = count($channelList);
$count_sum = 0;
@ -45,7 +46,7 @@ class ChannelOrderStatusMonitor extends Command
$day = date('Y-m-d', strtotime('-1 day'));
$tip_info=[];
$key = '41b42bd4-c9f9-4617-9531-0a358dd97a82';
// $key = '41b42bd4-c9f9-4617-9531-0a358dd97a82';
foreach($channelList as $channel) {
@ -53,53 +54,21 @@ class ChannelOrderStatusMonitor extends Command
if(!$other_param){
continue;
}
$Monitor_Balance = $other_param['Monitor_Balance'] ?? null;
if(!$Monitor_Balance){
$roomid = $other_param['QYWX_roomid']??null;
if(!$roomid || $other_param['Monitor_OrderStatus_status'] !=1){
continue;
}
$sender = $other_param['QYWX_sender']??null;
try{
$account_data = $channelService->call('account', $channel['id'], $day);
if (is_array($account_data) && isset($account_data['account'])) {
$balance = $account_data['account'];
if( $balance <= $Monitor_Balance){
if(!$this->redis->get('Check_channel_account-'.$channel['id'])){
$count_sum ++;
$this->redis->set('Check_channel_account-'.$channel['id'],1);
$tip_info[] = $channel['name']."<font color=\"comment\">余额不足,只剩下</font>:<font color=\"info\">".$balance."</font>";
}
$Monitor_Balance_TOP = $other_param['Monitor_Balance_TOP'] ?? null;
if($Monitor_Balance_TOP && $balance <= $Monitor_Balance_TOP){
if(!$this->redis->get('Check_channel_account_TOP-'.$channel['id'])){
$count_sum ++;
$this->redis->set('Check_channel_account_TOP-'.$channel['id'],1);
$tip_info[] = $channel['name']."<font color=\"comment\">余额不足,只剩下</font>:<font color=\"info\">".$balance."</font>";
}
}
}else{
if($this->redis->get('Check_channel_account-'.$channel['id'])){
$count_sum ++;
$this->redis->delete('Check_channel_account-'.$channel['id']);
$tip_info[] = $channel['name']."<font color=\"comment\">余额已经恢复,现在余额为</font>:<font color=\"info\">".$balance."</font>";
}
if($this->redis->get('Check_channel_account_TOP-'.$channel['id'])){
$this->redis->delete('Check_channel_account_TOP-'.$channel['id']);
}
}
}
}catch (\Exception $e){
if(isset($other_param['Monitor_OrderStatus_OrderFailRate'])){
$orderFailRate = $this->orderFailRate($channel,$other_param['Monitor_OrderStatus_OrderFailRate']);
}
}
if(!empty($tip_info)){
@ -116,6 +85,22 @@ class ChannelOrderStatusMonitor extends Command
}
#获取订单失败率
public function orderFailRate($channel,$rate)
{
$OrderService = OrderService::instance();
$cur = time();
$time = 300;
$whereRaw = $cur . '-unix_timestamp(create_at) >=' . $time;
return $OrderService->db()->whereRaw('status = 4 and ' . $whereRaw)->order('id asc')->select();
return true;
// $this->redis->set('queue:channel:order:status:monitor:success', $msg);
}
protected function redis()
{
if (!$this->redis) {

View File

@ -44,6 +44,7 @@ class MerchantBalanceMonitor extends Command
$count_sum = 0;
foreach($merchantsList as $merchants) {
$other_param = json_decode($merchants['other_param'],true);
if(!$other_param){
@ -57,10 +58,6 @@ class MerchantBalanceMonitor extends Command
$sender = $other_param['QYWX_sender'];
if($merchants['account_surplus'] <= $Monitor_Balance){
#进入预警流程
@ -80,7 +77,7 @@ class MerchantBalanceMonitor extends Command
$RobotService->send_text('余额预警: 您的账户现在只剩下'.$merchants['account_surplus'].'元,低于预警'.$Monitor_Balance.'元,请及时充值, @'.$ac,$roomid,$sender);
$this->setQueueProgress("预警 {$merchants['name']} 余额成功", $count_sum / $merchantsList_num * 100);
}
if($merchants['account_surplus'] <= 500){
if($merchants['account_surplus'] <= 5000){
if(!$this->redis->get('Check_merchant_account-TOP-'.$merchants['id'])){
$count_sum ++;
if(!isset($ac)){
@ -122,9 +119,60 @@ class MerchantBalanceMonitor extends Command
}
}
}
$wh = true;
$add_msg_count = 0;
#添加余额消息预警
while($wh) {
try{
$datas = $this->redis->pop('merchant_recharge_msg');
if($datas) {
$wh = true;
$mid = $datas['mid']??null;
if($mid){
$merchantMid = array_filter($merchantsList, function($merchant) use ($mid) {
return $merchant['id'] == $mid;
});
// 获取第一个匹配的元素
$merchantMid = reset($merchantMid);
$ac = '';
$other_params = json_decode($merchantMid['other_param'],true);
$roomid = $other_params['QYWX_roomid']??null;
$sender = $other_params['QYWX_sender']??null;
if($roomid){
if(!isset($acc)){
$AllContacts = $RobotService->get_all_contacts();
$Contacts_array = json_decode($AllContacts,true);
$acc = $Contacts_array['data']['contacts'];
}
foreach ($acc as $k=>$v){
if($v['wxid'] == $sender){
$ac = $v['name'];
}
}
$RobotService->send_text("余额预警: \n 检测到您的账户余额有变动,\n 变动金额为:".$datas['num']."元, \n 变动描述:".$datas['desc']." \n 变动款时间:".$datas['time']." \n 请关注账户 @".$ac,$roomid,$sender);
$add_msg_count++;
}
}
// 根据mid=1的数据定义为变量
}else{
$wh = false;
}
}catch (\Exception $e){
$wh = false;
}
}
$this->setQueueSuccess("共处理 {$merchantsList_num} 个商家, 完成{$count_sum} 个查询处理!");
$this->setQueueSuccess("共处理 {$merchantsList_num} 个商家, 完成{$count_sum} 个查询处理!和{$add_msg_count} 个加款消息预警!");
}