2023-01-29 10:26:52 +08:00

469 lines
18 KiB
PHP
Raw Permalink 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
// 微信公众号基础类 需要安装redis
//杨星宇 除微信登录 微信支付
define("TOKEN", "mytoken");
class Wechatpush{
public $appid;
public $secret;
public $access_token;
function __construct($appid,$secret){
$this->appid = $appid;
$this->secret = $secret;
$this->valid();
$this->getaccess_token();
}
public function valid(){ //验证token
$echoStr = input('echostr');
if($this->checkSignature()){
echo $echoStr;
//exit;
}
}
private function checkSignature(){ //验证token
$signature = input("signature");
$timestamp = input("timestamp");
$nonce = input("nonce");
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
public function getaccess_token(){ //获取access_token 用redis来做中间token存储
$redis = new \Redis();
$redis->connect('127.0.0.1',6379);
$token = $redis->get($this->appid);
if($token){
$this->access_token = $token;
}else{
$token_access_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $this->appid . "&secret=" . $this->secret;
$res = file_get_contents($token_access_url); //获取文件内容或获取网络请求的内容
$result = json_decode($res, true); //接受一个 JSON 格式的字符串并且把它转换为 PHP 变量
if(isset($result['access_token'])){
//把access_token存入redis用 access_token expires_in 过期时间 来做过期时间
$result['expires_in'] = 3600;
$redis->setex($this->appid,$result['expires_in'],$result['access_token']);
$this->access_token = $result['access_token'];
}else{
$this->access_token = '';
}
}
}
//获取粉丝openid 一次最多拉取 1万条
public function getopenid(){
$url ="https://api.weixin.qq.com/cgi-bin/user/get?access_token=".$this->access_token;
$result = $this->https_request($url);
$info = json_decode($result,true);
if(isset($info['data'])){
$users = $info['data']['openid'];
}else{
$users = null;
}
return $users;
}
//获取所有全部粉丝openid 一次最多拉取 1万条 需要多次拉取 next_openid=列表最后一个openid
public function getopenidall($nextid=null){
$next_openid = empty($nextid)?null:"&next_openid=".$nextid;
$url ="https://api.weixin.qq.com/cgi-bin/user/get?access_token=".$this->access_token.$next_openid;
$result = $this->https_request($url);
$info = json_decode($result,true);
if(isset($info['data'])){
$users = $info['data']['openid'];
$endid = $info['next_openid'];
}else{
$users = null;
$endid = null;
}
$openidArr = array(
'users'=>$users,
'endid'=>$endid
);
return $openidArr;
}
//创建底部菜单 注意菜单名称如果是数组转json 需要 urlencode() 汉字 打包后 在解码
public function wechatnav($arr){
$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$this->access_token;
$jsondata = urldecode(json_encode($arr));
$ch = curl_init(); //创建一个请求
curl_setopt($ch,CURLOPT_URL,$url); //设置请求的url
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); // 将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($ch,CURLOPT_POST,1); //启用时会发送一个常规的POST请求类型为application/x-www-form-urlencoded就像表单提交的一样
curl_setopt($ch,CURLOPT_POSTFIELDS,$jsondata); //全部数据使用HTTP协议中的"POST"操作来发送。要发送文件,在文件名前面加上@前缀并使用完整路径。这个参数可以通过urlencoded后的字符串类似'para1=val1&para2=val2&...'或使用一个以字段名为键值字段数据为值的数组。如果value是一个数组Content-Type头将会被设置成multipart/form-data。
$output = curl_exec($ch); //执行请求
curl_close($ch); //关闭资源
return $output;
}
//查看底部菜单
public function getwechatnav(){
$url = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=".$this->access_token;
$data = $this->getHttp($url);
return $data;
}
public function deletenav(){ //删除底部菜单
return file_get_contents("https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=".$this->access_token);
}
//被动回复图文消息 注意Xml里面不能有编辑器换行或者空格 严格要求官方数据格式
//只能关注回复才能使用高级素材模式 否则会自动转成客服消息图文模式
public function transmitNews($object,$newsArray){
if(!is_array($newsArray)){
return "";
}
$itemTpl = "<item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>";
$item_str = "";
foreach ($newsArray as $item){
$item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
}
$xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str
</Articles>
</xml>";
$result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time(), count($newsArray));
echo $result;
}
//被动回复文本消息 注意Xml里面不能有编辑器换行或者空格 严格要求官方数据格式
public function transmitText($object,$content){
if (!isset($content) || empty($content)){
return "";
}
$xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time(),'text',$content);
echo $result;
}
//关注回复发送图片
public function transmitImage($object,$mediaId){
if (!isset($mediaId) || empty($mediaId)){
return "";
}
$xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Image>
<MediaId><![CDATA[%s]]></MediaId>
</Image>
</xml>";
$result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time(),'image',$mediaId);
echo $result;
}
//推送模板消息
public function pushTemplate($openids=array(),$data=array()){
$touser = $openids;
$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $this->access_token;
foreach ($touser as $value) {
$datapush = $this->getDataTemplateArray($value,$data);
$json_data = json_encode($datapush);//转化成json数组让微信可以接收
$res = $this->https_request($url, urldecode($json_data));//请求开始
$res = json_decode($res, true);
if ($res['errcode'] == 0 && $res['errcode'] == "ok"){
return 1;
}else{
return $res['errcode'];
}
}
}
//获取发送模板消息数据数组
public function getDataTemplateArray($openid,$data){
$data = array(
'touser' => $openid, //单个openid
'template_id' => $data['template'],
'url' => $data['link'],
'data' => array(
'first' => array(
'value' => $data['title'],
'color' => "#000"
),
'keyword1' => array(
'value' => $data['keyword1'],
'color' => $data['color2']
),
'keyword2' => array(
'value' => $data['keyword2'],
'color' => "#000"
),
'remark' => array(
'value' => $data['remark'],
'color' => $data['color3']
),
)
);
return $data;
}
public function getDataArrayKefu($value,$link){ //获取发送数据数组 发送文本客服消息
$data = array(
'touser' => $value, //要发送给用户的openid
'msgtype'=>'text',
'text' => array(
'content' =>$link
)
);
return $data;
}
public function getDataArrayKefuImg($value,$title,$description,$url,$imgurl){ //获取发送数据数组 发送图文客服消息
$data = '{
"touser":"'.$value.'",
"msgtype":"news",
"news":{
"articles": [
{
"title":"'.$title.'",
"description":"'.$description.'",
"url":"'.$url.'",
"picurl":"'.$imgurl.'"
}
]
}
}';
return $data;
}
//发送文本客服消息 text 需要urlencode编码一下
public function kefu($openids=array(),$text){
$touser = $openids;
$url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=". $this->access_token;
foreach ($touser as $value) {
$data = $this->getDataArrayKefu($value,$text);
$json_data = json_encode($data);//转化成json数组让微信可以接收
$res = $this->https_request($url, urldecode($json_data));//请求开始
$res = json_decode($res, true);
if ($res['errcode'] == 0 && $res['errcode'] == "ok"){
return '发送成功';
}else{
var_dump($res);
}
}
}
// 发送图文客服消息 openid 标题 描述 外链地址 图片地址
public function kefuImg($openids=array(),$title,$description,$linkurl,$imgurl){
$touser = $openids;
$url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=". $this->access_token;
foreach ($touser as $value) {
$data = $this->getDataArrayKefuImg($value,$title,$description,$linkurl,$imgurl);
$res = $this->https_request($url, $data);//请求开始
$res = json_decode($res, true);
if ($res['errcode'] == 0 && $res['errcode'] == "ok"){
return '发送成功';
}else{
var_dump($res);
}
}
}
//curl请求函数微信都是通过该函数请求
public function https_request($url, $data = null){
$curl = curl_init(); //创建请求
curl_setopt($curl, CURLOPT_URL, $url); //设置请求的URL
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);//禁用后cURL将终止从服务端进行验证。使用CURLOPT_CAINFO选项设置证书使用CURLOPT_CAPATH选项设置证书目录 如果CURLOPT_SSL_VERIFYPEER(默认值为2)被启用CURLOPT_SSL_VERIFYHOST需要被设置成TRUE否则设置为FALSE。
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);//1 检查服务器SSL证书中是否存在一个公用名(common name)。译者注:公用名(Common Name)一般来讲就是填写你将要申请SSL证书的域名 (domain)或子域名(sub domain)。2 检查公用名是否存在,并且是否与提供的主机名匹配
if (!empty($data)) {
curl_setopt($curl, CURLOPT_POST, 1); //设置为POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);//传递一个数组到CURLOPT_POSTFIELDScURL会把数据编码成 multipart/form-data而然传递一个URL-encoded字符串时数据会被编码成 application/x-www-form-urlencoded
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);//在启用CURLOPT_RETURNTRANSFER的时候返回原生的Raw输出。
$output = curl_exec($curl);//设置OK
curl_close($curl);
return $output;
}
// get请求
public function getHttp($url,$post_data=array()) {
$ch = curl_init($url);
$timeout = 6000;
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HEADER,0 );
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
$ret = curl_exec($ch);
curl_close($ch);
return $ret;
}
// 以下是高级群发 素材管理
// 上传图片 返回media_id
public function uploadImage($file,$type='image'){
$data = array('media' => new \CURLFile(realpath($file)));
$url = 'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token='.$this->access_token.'&type='.$type;
$res = $this->https_request($url,$data);//请求开始
$res = json_decode($res, true);
if (isset($res['errcode'])){
return 0;
}else{
return $res['media_id'];
}
}
// 上传图文消息内的图片获取URL $file 必须服务器绝对路径
public function getimg($file){
$data = array('media' => new \CURLFile(realpath($file)));
$url = 'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token='.$this->access_token;
$res = $this->https_request($url,$data);//请求开始
$res = json_decode($res, true);
if (isset($res['errcode'])){
return 0;
}else{
return $res['url'];
}
}
// 上传图文素材 返回素材的media_id
// 注意素材里的 文本需要 urlencode 编码 打包json后在 urldecode 数据才正确
// 编辑器里的文本需要 urlencode + htmlspecialchars(str_replace("\"", "'", $data['content'])) 然后 urldecode + htmlspecialchars_decode
// $data = 2维数组(必须)
public function upMaterial($data){
// $url = 'https://api.weixin.qq.com/cgi-bin/material/add_news?access_token='.$this->access_token;
$url = 'https://api.weixin.qq.com/cgi-bin/draft/add?access_token='.$this->access_token;
$news = array();
$news['articles'] = $data;
$news = json_encode($news);
$news = urldecode($news);
$news = htmlspecialchars_decode($news);
$res = $this->https_request($url,$news);//请求开始
$res = json_decode($res, true);
if (isset($res['errcode'])){
return null;
}else{
return $res['media_id'];
}
}
// 修改已经上传的图文素材 当个栏目修改
// 注意素材里的 文本需要 urlencode 编码 打包json后在 urldecode 数据才正确
// 编辑器里的文本需要 urlencode + htmlspecialchars(str_replace("\"", "'", $data['content'])) 然后 urldecode + htmlspecialchars_decode
// 正确时errcode的值应为0 $data = 一维数组 $media_id = 素材ID $index = 栏目所在素材位置
public function renewNews($data,$media_id,$index){
// $url = 'https://api.weixin.qq.com/cgi-bin/material/update_news?access_token='.$this->access_token;
$url = 'https://api.weixin.qq.com/cgi-bin/draft/update?access_token='.$this->access_token;
$news = array(
"media_id"=>$media_id,
"index"=>$index,
"articles"=>$data
);
$news = json_encode($news);
$news = urldecode($news);
$news = htmlspecialchars_decode($news);
$res = $this->https_request($url,urldecode($news));//请求开始
$res = json_decode($res, true);
if ($res['errcode']==0){
return 1;
}else{
return $res;
}
}
// 删除图文模板
public function delmd($media_id){
// $url = 'https://api.weixin.qq.com/cgi-bin/material/del_material?access_token='.$this->access_token;
$url = 'https://api.weixin.qq.com/cgi-bin/draft/delete?access_token='.$this->access_token;
$data = array('media_id'=>$media_id);
$data = json_encode($data);
$res = $this->https_request($url,$data);//请求开始
$res = json_decode($res, true);
if ($res['errcode']==0){
return 1;
}else{
return $res;
}
}
// 测试高级群发
public function ceshiPush($openid,$media_id){
$this->valid();
$this->getaccess_token();
$url = 'https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token='.$this->access_token;
$data = '{
"touser":"'.$openid.'",
"mpnews":{
"media_id":"'.$media_id.'"
},
"msgtype":"mpnews"
}';
$res = $this->https_request($url,$data);//请求开始
$res = json_decode($res, true);
if ($res['errcode']==0){
return '发送成功';
}else{
return $res['errmsg'];
}
}
// 开始高级群发 $openids = 一维数组 $media_id = 素材ID
public function advancedPush($openids,$media_id){
$url = 'https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token='.$this->access_token;
$openid = json_encode($openids);
$news = '{
"touser":'.$openid.',
"mpnews":{
"media_id":"'.$media_id.'"
},
"msgtype":"mpnews",
"send_ignore_reprint":1,
"is_to_all":"true"
}';
$res = $this->https_request($url,$news);//请求开始
$res = json_decode($res, true);
if ($res['errcode']==0){
return 1;
}else{
return $res['errmsg'];
}
}
}
?>