Files
BESCMS/dayrui/App/Weixin/Models/Weixin.php
T

701 lines
25 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php namespace Phpcmf\Model\Weixin;
class Weixin extends \Phpcmf\Model
{
// 发送通知
public function send_notice($value, $siteid, $error) {
$content = [];
if (isset($value['config']['weixin']['tpl_content']) && is_array($value['config']['weixin']['tpl_content'])) {
$content = $value['config']['weixin']['tpl_content'];
if (!$content) {
$error[] = $debug = '自定义通知内容参数tpl_content不存在';
CI_DEBUG && log_message('debug', '通知任务('.$value['name'].')微信执行失败:'.$debug);
}
} else {
$rt = \Phpcmf\Service::L('notice')->_get_tpl_content($siteid, $value['name'], 'weixin', $value['data']);
if (!$rt['code']) {
$error[] = $rt['msg'];
CI_DEBUG && log_message('debug', '通知任务('.$value['name'].')执行失败:'.$rt['msg']);
} else {
$xml = \Phpcmf\Service::L('notice')->_xml_array($rt['msg']);
if (!$xml || !isset($xml['xml']) || !$xml['xml']) {
$error[] = $debug = 'xml解析失败,检查文件格式是否正确:'.$value['name'].'.html';
CI_DEBUG && log_message('debug', '通知任务('.$value['name'].')微信执行失败:'.$debug.'<br>'.$rt['msg']);
} else {
$content = $xml['xml'];
}
}
}
if ($content) {
$rt = \Phpcmf\Service::M('member')->weixin_template($value['data']['uid'], $content['id'], $content['param'], $content['url']);
if (!$rt['code']) {
$error[] = $debug = '微信消息执行错误:'.$rt['msg'];
CI_DEBUG && log_message('debug', '通知任务('.$value['name'].')微信执行失败:'.$debug);
} else {
// 成功
unset($value['config']['weixin']);
}
}
return [$error, $value];
}
// 获取微信表名
public function wxtable($name) {
return weixin_wxtable($name);
}
// 获取配置信息
public function get_config($name) {
$data = $this->db->table(weixin_wxtable('weixin'))->where('name', $name)->get()->getRowArray();
if ($data) {
$data = dr_string2array($data['value']);
return $data;
} else {
$this->db->table(weixin_wxtable('weixin'))->insert([
'name' => $name,
'value' => '',
]);
return [];
}
}
// 存储配置信息
public function save_config($name, $post) {
$rt = $this->db->table(weixin_wxtable('weixin'))->replace([
'name' => $name,
'value' => dr_array2string($post),
]);
if ($rt->connID->error) {
return dr_return_data(0, $this->table.': '.$rt->connID->error);
}
return dr_return_data(1);
}
// 上传图文消息内的图片获取URL
public function get_file_media_id($access_token, $type, $filename) {
// 查询本地库
$rt = $this->table(weixin_wxtable('media_id'))->where('file', md5($filename))->getRow();
if ($rt) {
return dr_return_data(1, 'ok', $rt);
}
$id = dr_get_file($filename, true);
if (!$id) {
return dr_return_data(0, '文件不存在');
}
$file = WRITEPATH.'temp/sync_'.md5($id).'.'.substr(strrchr($id, '.'), 1);;
$c = dr_catcher_data($id);
if (!$c) {
return dr_return_data(0, '无法获取文件内容:'.$id);
}
$rt = file_put_contents($file, $c);
if (!$rt) {
return dr_return_data(0, '本地文件写入失败:'.$id);
} elseif (!is_file($file)) {
return dr_return_data(0, '本地文件不存在');
}
$rt = ihttp_request(
'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token='.$access_token,
[
'type' => 'image',
'media' => '@' . $file
]
);
if ($rt['code']) {
// 更新到媒体表
$save = [
'file' => md5($filename),
'url' => $rt['data']['url'],
'media_id' => $rt['data']['media_id'],
];
$this->table(weixin_wxtable('media_id'))->insert($save);
}
return $rt;
}
// 同步素材到服务器
public function sync_content($access_token, $t, $return = 0) {
if (!$t['media_id'] || $return) {
// 图文素材
$url = 'https://api.weixin.qq.com/cgi-bin/draft/add?access_token='.$access_token;
$param = [
'articles' => [
]
];
$value = dr_string2array($t['content']);
for ($i = 1; $i<=9; $i++) {
if (!$value['title_'.$i]) {
break;
}
if (!$value['thumb_'.$i]) {
return dr_return_data(0, '素材['.$t['title'].'] 第'.$i.'个内容缺少封面图片');
}
$cache = [];
$content = htmlspecialchars_decode($value['content_'.$i]);
if (preg_match_all("/(src)=([\"|']?)([^ \"'>]+\.(gif|jpg|jpeg|png))\\2/i", $content, $imgs)) {
foreach ($imgs[3] as $image) {
if (!isset($cache[$image])) {
$tmp = WRITEPATH.'temp/sync_'.md5($image).'.'.substr(strrchr($image, '.'), 1);;
if (strpos($image, '/') === 0 && is_file(WEBPATH.$image)) {
$file = file_get_contents(WEBPATH.$image);
} else {
$file = dr_catcher_data($image);
}
if ($file && file_put_contents($tmp, $file)) {
$cache[$image] = 1;
$rt = ihttp_request(
'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token='.$access_token,
[
'media' => '@' . $tmp
]
);
// 更新到内容
$rt['code'] && $content = str_replace($image, $rt['data']['url'], $content);
}
}
}
}
$rt = $this->get_file_media_id($access_token, 'thumb', $value['thumb_'.$i]);
if (!$rt['code']) {
$rt['msg'] = $value['thumb_'.$i].' - 附件上传失败:'.$rt['msg'];
return $rt;
}
$thumb_id = $rt['data']['media_id'];
$param['articles'][] = [
"title" => $value['title_'.$i],
"thumb_media_id" => $thumb_id,
"author" => $value['author_'.$i],
"digest" => dr_strcut($value['description_'.$i], 50),
"content" => $content,
"show_cover_pic" => 1,
"content_source_url" => html_entity_decode($value['url_'.$i])
];
}
if (!count($param['articles'])) {
return dr_return_data(0, '素材['.$t['title'].'] 资源信息为空无法同步');
}
$rt = wx_post_https_json_data($url, $param);
if (!$rt['code']) {
return $rt;
}
$media_id = $rt['data']['media_id'];
if ($return) {
return dr_return_data(1, $media_id);
}
} else {
$media_id = $t['media_id'];
}
if (!$t['publish_id']) {
// 发布内容
$rt = wx_post_https_json_data(
'https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token='.$access_token,
[
'media_id' => $media_id
]
);
if (!$rt['code']) {
$this->table(weixin_wxtable('content'))->update($t['id'], [
'media_id' => $media_id
]);
return $rt;
}
// 存储
$this->table(weixin_wxtable('content'))->update($t['id'], [
'media_id' => $media_id,
'publish_id' => $rt['data']['publish_id'],
]);
} else {
// 查询结果
$rt = wx_post_https_json_data(
'https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token='.$access_token,
[
'publish_id' => $t['publish_id']
]
);
if (!$rt['code']) {
return $rt;
}
$this->table(weixin_wxtable('content'))->update($t['id'], [
'status' => $rt['data']['publish_status'],
'article_id' => $rt['data']['article_id']
]);
}
return dr_return_data(1, 'ok');
}
// 高级群发
public function sendall($groupid, $data)
{
$rt = weixin_get_access_token();
if (!$rt['code']) {
return $rt;
}
// 将内容转成为草稿箱
$rs = $this->sync_content($rt['msg'], $data, 1);
if (!$rs['code']) {
return $rs;
}
$param = [
'msgtype' => 'mpnews',
'mpnews' => [
'media_id' => $rs['msg']
],
];
if ($groupid) {
$param['filter'] = [
'is_to_all' => false,
'tag_id' => $groupid,
];
} else {
$param['filter'] = [
'is_to_all' => true,
];
}
$rt = wx_post_https_json_data(
'https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token='.$rt['msg'],
$param
);
if (!$rt['code']) {
return $rt;
}
return dr_return_data(1, 'ok');
}
// 客服群发 文本内容
public function send_for_text($groupid, $data)
{
$param = [
'msgtype' => 'text',
'text' => [
'content' => $data
],
];
if ($groupid) {
if (strlen($groupid) > 5) {
// 指定粉丝
$user = [
[
'openid' => $groupid,
]
];
} else {
// 粉丝组
$user = $this->table(weixin_wxtable('user'))->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->where('`groupids` like "%\"'.$groupid.'\"%"')->getAll();
}
} else {
// 全部粉丝
$user = $this->table(weixin_wxtable('user'))->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->getAll();
}
if (!$user) {
return dr_return_data(0, '48小时内互动的粉丝不存在');
}
return $this->_save_send_data($user, $param);
}
// 客服群发 内容模块
public function send_for_module($dir, $ids) {
$data = $this->table_site($dir)->where_in('id', $ids)->getAll(9);
if (!$data) {
return dr_return_data(0, '模块内容不存在');
}
$param = [
'msgtype' => 'news',
'news' => [
'articles' => []
],
];
foreach ($data as $t) {
$param['news']['articles'][] = [
"title" => $t['title'],
"description" => $t['description'],
"picurl" => dr_get_file($t['thumb'], true),
"url" => dr_url_prefix($t['url'], $dir)
];
}
$user = $this->table(weixin_wxtable('user'))->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->getAll();
if (!$user) {
return dr_return_data(0, '粉丝信息不存在');
}
return $this->_save_send_data($user, $param);
}
// 客服群发 内容素材
public function send_for_content($groupid, $data)
{
$param = [
'msgtype' => 'mpnewsarticle',
'mpnewsarticle' => [
'article_id' => $data['article_id']
],
];
if ($groupid) {
if (strlen($groupid) > 5) {
// 指定粉丝
$user = [
[
'openid' => $groupid,
]
];
} else {
// 粉丝组
$user = $this->table(weixin_wxtable('user'))->where('groupid', $groupid)->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->getAll();
}
} else {
// 全部粉丝
$user = $this->table(weixin_wxtable('user'))->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->getAll();
}
if (!$user) {
return dr_return_data(0, '48小时内互动的粉丝不存在');
} elseif (!$param) {
return dr_return_data(0, '未知的tid类别信息:'.$data['tid']);
}
return $this->_save_send_data($user, $param);
}
// 存储客服消息发送记录表
private function _save_send_data($user, $param) {
$id = (int)substr(SYS_TIME - rand(0, 9999), 0, 10);
foreach ($user as $t) {
$rt = $this->table(weixin_wxtable('send'))->insert([
'cid' => $id,
'openid' => $t['openid'],
'status' => 0,
'content' => dr_array2string($param)
]);
if (!$rt['code']) {
return $rt;
}
}
return dr_return_data($id, 'ok');
}
// 存储客户端消息
public function save_message($data)
{
$rt = $this->table(weixin_wxtable('message'))->insert([
'tid' => $data['MsgType'],
'openid' => $data['FromUserName'],
'nickname' => '',
'headimgurl' => '',
'status' => 0,
'content' => dr_array2string($data),
'inputtime' => $data['CreateTime'],
]);
if (!$rt['code']) {
log_message('error', '微信消息存储失败:'.$rt['msg']);
}
}
// 更新统计数据
public function update_count_fans() {
return $this->table(weixin_wxtable('count_fans'))->order_by('id desc')->getAll(10, 'date');
$seven_days = array(
date('Ymd', strtotime('-1 days')),
date('Ymd', strtotime('-2 days')),
date('Ymd', strtotime('-3 days')),
date('Ymd', strtotime('-4 days')),
date('Ymd', strtotime('-5 days')),
date('Ymd', strtotime('-6 days')),
date('Ymd', strtotime('-7 days')),
);
// 本周数据
$week_stat_fans = $this->table(weixin_wxtable('count_fans'))->where_in('date', $seven_days)->getAll(0, 'date');
$stat_update_yes = false;
foreach ($seven_days as $sevens) {
if (empty($week_stat_fans[$sevens]) || $week_stat_fans[$sevens]['cumulate'] <=0) {
$stat_update_yes = true;
break;
}
}
if (empty($stat_update_yes)) {
return $week_stat_fans;
}
$rt = weixin_get_access_token();
if ($rt['code']) {
$access_token = $rt['msg'];
$url = 'https://api.weixin.qq.com/datacube/getusersummary?access_token='.$access_token;
$rt = wx_post_https_json_data($url, [
"begin_date" => date('Y-m-d', strtotime('-7 days')),
"end_date" => date('Y-m-d', strtotime('-1 days')),
]);
if ($rt['code']) {
$summary = $rt['data'];
}
$url = 'https://api.weixin.qq.com/datacube/getusercumulate?access_token='.$access_token;
$rt = wx_post_https_json_data($url, [
"begin_date" => date('Y-m-d', strtotime('-7 days')),
"end_date" => date('Y-m-d', strtotime('-1 days')),
]);
if ($rt['code']) {
$cumulate = $rt['data'];
}
$result = [];
if (!empty($summary['list'])) {
foreach ($summary['list'] as $row) {
$key = str_replace('-', '', $row['ref_date']);
$result[$key]['new'] = intval($result[$key]['new']) + $row['new_user'];
$result[$key]['cancel'] = intval($result[$key]['cancel']) + $row['cancel_user'];
}
}
if (!empty($cumulate['list'])) {
foreach ($cumulate['list'] as $row) {
$key = str_replace('-', '', $row['ref_date']);
$result[$key]['cumulate'] = $row['cumulate_user'];
}
}
foreach ($result as $i => $t) {
$this->table(weixin_wxtable('count_fans'))->replace([
'new' => (int)$t['new'],
'cancel' => (int)$t['cancel'],
'cumulate' => (int)$t['cumulate'],
'date' => $i,
]);
}
return $result;
}
return $week_stat_fans;
}
/**
* 发送微信通知模板
*
* $uid 会员id
* $id 微信模板id
* $data 通知内容
* $url 详细地址
* $color top颜色
*/
public function send_template($uid, $id, $data, $url = '', $color = '') {
$rt = weixin_get_access_token();
if (!$rt['code']) {
return dr_return_data(0, $rt['msg']);
}
if (is_array($uid)) {
$error = [];
foreach ($uid as $u) {
$oauth = $this->db->table('member_oauth')->where('uid', $u)->where('oauth', 'wechat')->get()->getRowArray();
if (!$oauth) {
$error[] = 'uid'.$u.')未绑定账号';
continue;
}
$rs = wx_post_https_json_data('https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$rt['msg'], [
'touser' => $oauth['oid'],
'template_id' => $id,
'url' => $url,
'topcolor' => $color,
'data' => $data,
]);
if (!$rs['code']) {
$error[] = $rs['msg'];
}
}
if (dr_count($error) == dr_count($uid)) {
return dr_return_data(0, implode('', $error));
} else {
return dr_return_data(1, '发送成功');
}
} else {
$oauth = $this->db->table('member_oauth')->where('uid', $uid)->where('oauth', 'wechat')->get()->getRowArray();
if (!$oauth) {
return dr_return_data(0, 'uid'.$uid.')未绑定账号');
}
return wx_post_https_json_data('https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$rt['msg'], [
'touser' => $oauth['oid'],
'template_id' => $id,
'url' => $url,
'topcolor' => $color,
'data' => $data,
]);
}
}
/**
* 发送微信订阅通知
*
* $uid 会员id
* $id 所需下发的订阅模板id
* $data 通知内容
* $url 详细地址
*/
public function send_biz($uid, $id, $data, $url = '') {
$oauth = $this->db->table('member_oauth')->where('uid', $uid)->where('oauth', 'wechat')->get()->getRowArray();
if (!$oauth) {
return dr_return_data(0, 'uid'.$uid.')未绑定账号');
}
$rt = weixin_get_access_token();
if (!$rt['code']) {
return dr_return_data(0, $rt['msg']);
}
return wx_post_https_json_data('https://api.weixin.qq.com/cgi-bin/message/subscribe/bizsend?access_token='.$rt['msg'], [
'touser' => $oauth['oid'],
'template_id' => $id,
'page' => $url,
'data' => $data,
]);
}
// 缓存
public function cache($siteid = SITE_ID)
{
$table = \Phpcmf\Service::M()->dbprefix('app_weixin');
if (!\Phpcmf\Service::M()->is_table_exists($table)) {
\Phpcmf\Service::M('table')->create_table(
$table,
[
'id' => 'int(10) NOT NULL AUTO_INCREMENT COMMENT \'id\'',
'name' => 'varchar(200) NOT NULL COMMENT \'公众号名称\'',
],
[
'PRIMARY KEY (`id`)',
],
'多公众号表'
);
}
$mr = \Phpcmf\Service::M()->table('app_weixin')->get(1);
if (!$mr) {
\Phpcmf\Service::M()->table('app_weixin')->replace([
'id' => 1,
'name' => '默认公众号'
]);
}
$alls = $this->table('app_weixin')->getAll();
$more_cache = [];
foreach ($alls as $more) {
$more_cache[$more['id']] = $more['name'];
/////////////////////////
$data = $this->table(weixin_wxtable('weixin', $more['id']))->getAll();
$cache = [];
if ($data) {
foreach ($data as $t) {
$value = dr_string2array($t['value']);
$cache[$t['name']] = $value;
}
}
$kws = [];
$data = $this->table(weixin_wxtable('reply', $more['id']))->getAll();
if ($data) {
foreach ($data as $t) {
$arr = explode(',', $t['keyword']);
if ($arr) {
foreach ($arr as $kw) {
$kws[$kw] = $t['id'];
}
}
}
uksort($kws, function ($a, $b) {
return strlen($b) - strlen($a);
});
}
\Phpcmf\Service::L('cache')->set_file('weixin-kws'.($more['id'] > 1 ? '_more_'.$more['id'] : ''), $kws);
$table = $this->dbprefix(weixin_wxtable('template', $more['id']));
if (!\Phpcmf\Service::M()->is_table_exists($table)) {
\Phpcmf\Service::M('table')->create_table(
$table,
[
'id' => 'int(10) NOT NULL AUTO_INCREMENT COMMENT \'id\'',
'title' => 'varchar(200) NOT NULL COMMENT \'主题\'',
'groupid' => 'int(10) NOT NULL COMMENT \'发送标签组\'',
'counts' => 'int(10) NOT NULL COMMENT \'发送数\'',
'content' => 'text NOT NULL COMMENT \'消息内容\'',
'template' => 'varchar(200) NOT NULL COMMENT \'模板ID\'',
'url' => 'varchar(200) NOT NULL COMMENT \'url\'',
'color' => 'varchar(200) NOT NULL COMMENT \'主题颜色\'',
'inputtime' => 'int(10) NOT NULL COMMENT \'录入时间\'',
],
[
'PRIMARY KEY (`id`)',
'KEY `inputtime` (`inputtime`)',
],
'微信模板消息记录表'
);
}
$table = $this->dbprefix(weixin_wxtable('user', $more['id']));
\Phpcmf\Service::M()->query('UPDATE `'.$table.'` SET `subscribe`=`subscribe_time` where `subscribe`=1');
$table = $this->dbprefix(weixin_wxtable('content', $more['id']));
$t = \Phpcmf\Service::M('table');
$m = \Phpcmf\Service::M();
if (!$m->is_field_exists($table, 'nums')) {
$t->add_field($table, 'nums', 'tinyint(2)', 'DEFAULT \'0\'', '');
}
if (!$m->is_field_exists($table, 'status')) {
$t->add_field($table, 'status', 'tinyint(2)', 'DEFAULT \'0\'', '');
}
if (!$m->is_field_exists($table, 'publish_id')) {
$t->add_field($table, 'publish_id', 'varchar(255)', 'DEFAULT \'\'', '');
}
if (!$m->is_field_exists($table, 'article_id')) {
$t->add_field($table, 'article_id', 'varchar(255)', 'DEFAULT \'\'', '');
}
\Phpcmf\Service::L('cache')->set_file('weixin'.($more['id'] > 1 ? '_more_'.$more['id'] : ''), $cache);
/// ////////////////////////
}
\Phpcmf\Service::L('cache')->set_file('app_weixin', count($more_cache) == 1 ? '' : $more_cache);
return;
}
}