确短信发送

This commit is contained in:
ASUS 2025-09-18 17:38:47 +08:00
parent 060fb1ae5c
commit c9589602eb
4 changed files with 276 additions and 52 deletions

View File

@ -9,7 +9,20 @@ class IndexController
{
public function index(Request $request)
{
return '哈啰';
$url = 'http://192.168.1.31/market/admin/coupon/grant';
$res = http_post($url, [
'userId' => 1,
'couponId' => 1,
'num' => 1,
'shopId' => 1,
]);
p($res);
// $data = \app\model\MessagePushTask::send_push_msg();
// $data = \app\model\MessagePushTask::send_sms_msg();
return json($data);
}
public function view(Request $request)

View File

@ -51,3 +51,48 @@ function uniqueMultidimensionalArray($array, $k = 'user_id') {
// 重新索引数组从0开始的连续数字键
return array_values($unique);
}
if(!function_exists('http_post')) {
function http_post($url, $data, $headers = [], $timeout = 30, $contentType = 'application/json')
{
// 初始化cURL
$ch = curl_init();
// 处理请求数据
if ($contentType === 'application/json') {
$data = json_encode($data);
} elseif (is_array($data)) {
$data = http_build_query($data);
}
// 设置请求头
$defaultHeaders = [
"Content-Type: $contentType",
"Content-Length: " . strlen($data)
];
$headers = array_merge($defaultHeaders, $headers);
// 设置cURL选项
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// 执行请求
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
// 关闭cURL
curl_close($ch);
// 处理错误
if ($response === false) {
return $error;
}
return $response;
}
}

View File

@ -9,10 +9,12 @@ use EasyWeChat\Factory;
class MessagePushTask
{
public static function send_msg()
// 推送模版消息
public static function send_push_msg()
{
// 查询任务
$event_list = Db::name('tb_push_event')->where(['status' => 0])->select();
// 查询模版任务
$event_list = Db::name('tb_push_event')->where(['status' => 0, 'push_type' => 1])->select()->toArray();
if($event_list) {
try {
Db::startTrans();
@ -23,23 +25,30 @@ class MessagePushTask
foreach ($res as $rk => &$rv) {
if(empty($rv['open_id'])) {
unset($res[$rk]);
}else {
$rv['push_event_id'] = $event['id'];
$rv['template_id'] = $event['template_id'];
$rv['keyword1'] = $event['keyword1'];
$rv['keyword2'] = $event['keyword2'];
$rv['keyword3'] = $event['keyword3'];
$rv['keyword4'] = $event['keyword4'];
$rv['keyword5'] = $event['keyword5'];
}
$rv['push_event_id'] = $event['id'];
$rv['template_id'] = $event['template_id'];
$rv['keyword1'] = $event['keyword1'];
$rv['keyword2'] = $event['keyword2'];
$rv['keyword3'] = $event['keyword3'];
$rv['keyword4'] = $event['keyword4'];
$rv['keyword5'] = $event['keyword5'];
}
$user_list = uniqueMultidimensionalArray($res);
// 需要接收推送的用户 准备发送
foreach ($user_list as $k => $user) {
$data = [
'thing2' => $user['keyword1'],
'amount3' => $user['keyword2'],
'time6' => $user['keyword3'],
];
$user_push_list_res_id = Db::name('tb_user_push_event')->insertGetId([
'push_event_id' => $user['push_event_id'],
'user_id' => $user['user_id'],
'create_time' => date("Y-m-d H:i:s"),
'content' => json_encode($data),
]);
if($user_push_list_res_id) {
$app = Factory::officialAccount([
@ -47,11 +56,7 @@ class MessagePushTask
'secret' => config('cons.secret'),
'response_type' => 'array',
]);
$data = [
'thing2' => $user['keyword1'],
'amount3' => $user['keyword2'],
'time6' => $user['keyword3'],
];
// 正式推送
$push = $app->template_message->send([
'touser' => $user['open_id'],
@ -61,6 +66,11 @@ class MessagePushTask
Log::info('用户-' . $user['user_id'] . ' 推送模版ID'. $user['template_id'] .' 内容:' . json_encode($data, 256) . ' 推送结果:' . json_encode($push));
if($push['errcode'] == 0) {
Db::name('tb_user_push_event')->where(['id' => $user_push_list_res_id])->update(['update_time' => date("Y-m-d H:i:s"), 'status' => 1]);
// 送券
if(isset($event['coupon'])) {
$coupon = json_decode($event['coupon'], true);
self::sendUserCoupon($event['shop_id'], $user['user_id'], $coupon['id'], $coupon['num']);
}
}else {
Db::name('tb_user_push_event')->where(['id' => $user_push_list_res_id])->update(['update_time' => date("Y-m-d H:i:s"), 'status' => -1, 'error' => json_encode($push)]);
}
@ -81,6 +91,117 @@ class MessagePushTask
}
// 推送短信消息
public static function send_sms_msg()
{
// 查询短信任务
$event_list = Db::name('tb_push_event')->where(['status' => 0, 'push_type' => 2])->select()->toArray();
if($event_list) {
try {
Db::startTrans();
foreach ($event_list as $k => $event) {
Db::name('tb_push_event')->where(['id' => $event['id']])->update(['status' => 1, 'start_time' => date('Y-m-d H:i:s')]);
$res = self::getPullInfoUser($event);
if($res) {
foreach ($res as $rk => &$rv) {
if(empty($rv['phone'])) {
unset($res[$rk]);
}else {
$rv['push_event_id'] = $event['id'];
$rv['sms_sign'] = $event['sms_sign'];
$rv['sms_code'] = $event['sms_code'];
$rv['sms_content'] = $event['sms_content'];
}
}
$user_list = uniqueMultidimensionalArray($res);
// 需要接收推送的用户 准备发送
foreach ($user_list as $k => $user) {
// 查询商家短信余额
$sms_shop = Db::name('tb_shop_sms_money')->where(['shop_id' => $event['shop_id']])->find();
if (!$sms_shop) {
$sms_shop_res_id = Db::name('tb_shop_sms_money')->insertGetId([
'shop_id' => $user['push_event_id'],
'create_time' => date("Y-m-d H:i:s"),
]);
log::info('商户' . $event['shop_id'] . '不存在或余额不足,停止发送');
continue 2;
} else {
// 一条短信的价格
$one_sms_price = config('cons.sms_price');
if($sms_shop['money'] < $one_sms_price) {
log::info('商户' . $event['shop_id'] . '余额不足,停止发送');
continue 2;
}else {
$user_push_list_res_id = Db::name('tb_user_push_event')->insertGetId([
'push_event_id' => $user['push_event_id'],
'user_id' => $user['user_id'],
'create_time' => date("Y-m-d H:i:s"),
'content' => json_encode($user),
]);
if ($user_push_list_res_id) {
// 发送短信空位置
Log::info('用户-' . $user['user_id'] . ' 短信发送ID' . $user['template_id'] . ' 内容:' . json_encode($data, 256) . ' 推送结果:' . json_encode($push));
if ($push['errcode'] == 0) {
Db::name('tb_user_push_event')->where(['id' => $user_push_list_res_id])->update(['update_time' => date("Y-m-d H:i:s"), 'status' => 1]);
// 加入明细
$tb_shop_sms_money = Db::name('tb_shop_sms_money_detail')->insertGetId([
'shop_id' => $event['shop_id'],
'type' => 2,
'money' => $one_sms_price,
'create_time' => date("Y-m-d H:i:s"),
]);
if($tb_shop_sms_money) {
// 扣掉余额
Db::name('tb_shop_sms_money')->where([
'shop_id' => $event['shop_id'],
])->dec('money', $one_sms_price)->update();
}
// 送券
if(isset($event['coupon'])) {
$coupon = json_decode($event['coupon'], true);
self::sendUserCoupon($event['shop_id'], $user['user_id'], $coupon['id'], $coupon['num']);
}
} else {
Db::name('tb_user_push_event')->where(['id' => $user_push_list_res_id])->update(['update_time' => date("Y-m-d H:i:s"), 'status' => -1, 'error' => json_encode($push)]);
}
}
sleep(1);
}
}
}
Db::name('tb_push_event')->where(['id' => $event['id']])->update(['status' => 2, 'send_time' => date('Y-m-d H:i:s')]);
}
}
Db::commit();
}catch (\Exception $e) {
Log::info('执行出错--' . $e->getMessage());
Db::rollback();
}
}
Log::info('没有推送任务可执行');
return true;
}
/**
* 找到可以接收订阅消息的用户
* @param $type类型 1按次数发送 2自定义 3按标签
@ -90,12 +211,15 @@ class MessagePushTask
{
$user_arr = [];
switch ($event['type']) {
// 按可接收次数发送(模版推送)/全部绑定手机用户(短信推送)
case 1;
$user_arr = self::getPullInfoUserToNumber($event);
break;
// 自定义
case 2;
$user_arr = self::getPullInfoUserToCustom($event);
break;
// 按标签
case 3;
$user_arr = self::getPullInfoUserToLabel($event);
break;
@ -108,13 +232,19 @@ class MessagePushTask
public static function getPullInfoUserToNumber($event)
{
$user_num = [];
if($event['can_send_times'] > 0) {
if($event['push_type'] == 1 && $event['can_send_times'] > 0) {
$user_num = Db::name('tb_user_push_event_num')->alias('upen')->where('upen.num', '>=', $event['can_send_times'])
->join('tb_user_info u', 'upen.user_id = u.id')
->field('upen.user_id as user_id, upen.open_id as open_id')
->select()
->toArray();
}
if($event['push_type'] == 2) {
$user_num = Db::name('tb_user_info')->where('phone', '<>', '')
->field('id as user_id, wechat_ac_open_id as open_id, phone')
->select()
->toArray();
}
return $user_num;
}
@ -131,21 +261,21 @@ class MessagePushTask
// 未知
if($gender == 0) {
$gender_data_res = Db::name('tb_user_info')->whereNotIn('sex', [0,1])
->field('id as user_id, wechat_ac_open_id as open_id')
->field('id as user_id, wechat_ac_open_id as open_id, phone')
->select()
->toArray();
}
// 男
if($gender == 1) {
$gender_data_res = Db::name('tb_user_info')->where('sex', 1)
->field('id as user_id, wechat_ac_open_id as open_id')
->field('id as user_id, wechat_ac_open_id as open_id, phone')
->select()
->toArray();
}
// 女
if($gender == 2) {
$gender_data_res = Db::name('tb_user_info')->where('sex', 0)
->field('id as user_id, wechat_ac_open_id as open_id')
->field('id as user_id, wechat_ac_open_id as open_id, phone')
->select()
->toArray();
}
@ -174,7 +304,7 @@ class MessagePushTask
->leftJoin('tb_order_info o', 'u.id = o.user_id')
->where('o.user_id', 'null')
->distinct()
->field('u.id as user_id, u.wechat_ac_open_id as open_id')
->field('u.id as user_id, u.wechat_ac_open_id as open_id, u.phone as phone')
->select()
->toArray();
}
@ -189,7 +319,7 @@ class MessagePushTask
// 筛选出订单数量为1的用户
->having('COUNT(o.id) = 1')
// 选择需要的用户字段,同时查询订单数量(可选)
->field('u.id as user_id, u.wechat_ac_open_id as open_id')
->field('u.id as user_id, u.wechat_ac_open_id as open_id, u.phone as phone')
->select()
->toArray();
}
@ -203,7 +333,7 @@ class MessagePushTask
->group('u.id')
// 筛选出订单数量为1的用户
->having('COUNT(o.id) BETWEEN 2 AND 5')
->field('u.id as user_id, u.wechat_ac_open_id as open_id')
->field('u.id as user_id, u.wechat_ac_open_id as open_id, u.phone as phone')
->select()
->toArray();
}
@ -217,7 +347,7 @@ class MessagePushTask
->group('u.id')
// 筛选出订单数量为1的用户
->having('COUNT(o.id) >= 5')
->field('u.id as user_id, u.wechat_ac_open_id as open_id')
->field('u.id as user_id, u.wechat_ac_open_id as open_id, u.phone as phone')
->select()
->toArray();
}
@ -246,7 +376,7 @@ class MessagePushTask
->join('tb_order_info o', 'u.id = o.user_id')
->where('o.create_time', '>=', date('Y-m-d 00:00:00'))
->where('o.create_time', '<=', date('Y-m-d 23:59:59'))
->field('u.id as user_id, u.wechat_ac_open_id as open_id')
->field('u.id as user_id, u.wechat_ac_open_id as open_id, u.phone as phone')
->distinct()
->select()
->toArray();
@ -258,7 +388,7 @@ class MessagePushTask
->join('tb_order_info o', 'u.id = o.user_id')
->where('o.create_time', '>=', date('Y-m-d 00:00:00', strtotime('-1 day')))
->where('o.create_time', '<=', date('Y-m-d 23:59:59', strtotime('-1 day')))
->field('u.id as user_id, u.wechat_ac_open_id as open_id')
->field('u.id as user_id, u.wechat_ac_open_id as open_id, u.phone as phone')
->distinct()
->select()
->toArray();
@ -272,7 +402,7 @@ class MessagePushTask
->leftJoin('tb_order_info o', 'u.id = o.user_id')
->where('o.create_time', '>=', $twoWeeksAgo)
->where('o.id', 'null')
->field('u.id as user_id, u.wechat_ac_open_id as open_id')
->field('u.id as user_id, u.wechat_ac_open_id as open_id, u.phone as phone')
->distinct()
->select()
->toArray();
@ -289,7 +419,7 @@ class MessagePushTask
->group('u.id')
// 筛选最后下单时间在30天前到15天前之间的用户
->having('MAX(o.create_time) >="'. $startTime .'" AND MAX(o.create_time) <= "' . $endTime . '"')
->field('u.id as user_id, u.wechat_ac_open_id as open_id')
->field('u.id as user_id, u.wechat_ac_open_id as open_id, u.phone as phone')
->select()
->toArray();
}
@ -305,7 +435,7 @@ class MessagePushTask
// 筛选最后下单时间在1个月前及更早
->having('MAX(o.create_time) <= "' . $oneMonthAgo . '"')
// ->field('u.id as user_id, u.wechat_ac_open_id as open_id, MAX(o.create_time) as last_order_time')
->field('u.id as user_id, u.wechat_ac_open_id as open_id')
->field('u.id as user_id, u.wechat_ac_open_id as open_id, u.phone as phone')
->select()
->toArray();
}
@ -329,21 +459,52 @@ class MessagePushTask
// 非会员
if($vip == 0) {
$vip_data_res = Db::name('tb_user_info')->whereNotIn('is_vip', 0)
->field('id as user_id, wechat_ac_open_id as open_id')
->field('id as user_id, wechat_ac_open_id as open_id,phone')
->select()
->toArray();
}
// 会员
if($vip == 1) {
$vip_data_res = Db::name('tb_user_info')->where('is_vip', 1)
->field('id as user_id, wechat_ac_open_id as open_id')
->select()
->toArray();
if($event['push_type'] == 1) {
$vip_data_res = Db::name('tb_user_info')->where('is_vip', 1)
->field('id as user_id, wechat_ac_open_id as open_id,phone')
->select()
->toArray();
}
// 推送类型为短信推送
if($event['push_type'] == 2) {
// 全部会员
if($event['vip_lavel'] == 0) {
$vip_data_res = Db::name('tb_user_info')->where('is_vip', 1)
->field('id as user_id, wechat_ac_open_id as open_id,phone')
->select()
->toArray();
}
// 仅限等级
if($event['vip_lavel'] == 1) {
$vip_data_res = Db::name('tb_user_info')->where(['is_vip' => 1, 'member_level_id' => $event['vip_lavel_id']])
->field('id as user_id, wechat_ac_open_id as open_id,phone')
->select()
->toArray();
}
// 以上等级
if($event['vip_lavel'] == 2) {
// 找到会员详情
$vip_config_info = Db::name('tb_member_level_config')->where(['id' => $event['vip_lavel_id']])->find();
if($vip_config_info) {
$vip_config_info = Db::name('tb_member_level_config')->where('experience_value', '>', $vip_config_info['experience_value'])->column('id');
if($vip_config_info) {
$vip_data_res = Db::name('tb_user_info')->where(['is_vip' => 1])->whereIn('member_level_id', $vip_config_info)
->field('id as user_id, wechat_ac_open_id as open_id,phone')
->select()
->toArray();
}
}
}
}
}
if($vip_data_arr) {
$vip_data_arr = array_merge($vip_data_arr, $vip_data_res);
}else {
$vip_data_arr = $vip_data_res;
}
@ -372,7 +533,7 @@ class MessagePushTask
// 已绑定
if($telphone == 1) {
$telphone_data_res = Db::name('tb_user_info')->where('phone', '<>', '')
->field('id as user_id, wechat_ac_open_id as open_id')
->field('id as user_id, wechat_ac_open_id as open_id, phone')
->select()
->toArray();
}
@ -401,7 +562,7 @@ class MessagePushTask
->column('user_id');
if($label) {
$data_arr = Db::name('tb_user_info')->whereIn('id', $label)
->field('id as user_id, wechat_ac_open_id as open_id')
->field('id as user_id, wechat_ac_open_id as open_id, phone')
->select()
->toArray();
}
@ -410,23 +571,27 @@ class MessagePushTask
// 给用户送送优惠券
public static function sendUserCoupon(int | array $user_id, $coupon_id, $number = 1)
public static function sendUserCoupon($shop_id, int | array $user_id, $coupon_id, $number = 1)
{
try {
Db::startTrans();
if(is_int($user_id)) {
}elseif (is_array($user_id)) {
}
Db::commit();
return true;
}catch (\Exception $e) {
Db::rollback();
Log::info('用户送券异常-->' . $e->getMessage());
if ($number === null || $number <= 0) {
Log::info('推送用户送券发放数量不能小于0');
return false;
}
$url = 'http://192.168.1.31/market/admin/coupon/grant';
$res = http_post($url, [
'userId' => $user_id,
'couponId' => $coupon_id,
'num' => $number,
'shopId' => $shop_id,
]);
Log::info('发券:' . $res);
$res = json_decode($res, true);
if($res['code'] == 200) {
Log::info('userId:' . $user_id . ' couponId:' . $coupon_id . ' shopId:' . $shop_id . '发券成功');
}else {
Log::info('userId:' . $user_id . ' couponId:' . $coupon_id . ' shopId:' . $shop_id . '发券失败' . ' 信息:' . $res['msg']);
}
return true;
}

View File

@ -5,4 +5,5 @@
return [
'app_id' => 'wx1fb600d0f5ea6279', // 银收客czg
'secret' => 'b4c0534c9b5e6c84a7fe5c2078dff876',
'sms_price' => 0.055, // 短信发送价格
];