php实现小程序定时推送消息

之前工作需求,需要开发微信小程序,现在一段时间没做都快忘记了,今天记录一下!!!
首先,小程序的定时推送消息是有限制的,如果用户主动触发小程序1次,小程序可在7天内向用户主动推送1条模版消息,如果用户通过小程序完成支付,小程序可在7天内向用户主动推送3条模版消息,对于这句话的理解就是:用户触发一次,就会向后台发送一个formid来向用户推送模板消息,但是这个formid有效期只有7天,且只能使用一次。那么如何推送消息?又有什么要求呢?
首先,讲讲要求,想要推送模板消息,就需要用户的openid小程序的accesstoken触发表单的formid

01、获取用户的openid

官方文档说可以通过用户登录向后台发送 res.code 到后台换取 openId, sessionKey, unionId,利用提供的组件wx.login({}),直接上代码:
前端代码发送code给后台,返回openid,全局app.js
小程序代码:

wx.login({
      success: res => {
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
        var code = res.code;
        if (code) {
          wx.request({
            url: ‘后台地址’,
            method: "POST",
            data: {
              code: code,
            },
            header: {
              'Content-Type': 'application/x-www-form-urlencoded'
            },
            success(res) {
              that.globalData.openid = res.data.openid;//存储到全局
            }
          })
        } else {
          console.log('获取code失败')
        }
      }
    })

后台PHP代码:

$code = $_POST['code'];//接收前端code

$APPID = "APPID";//小程序后台管理提供的id
$APPSECRET =  "APPSECRET";//小程序后台管理提供的秘钥,很重要,首次生成后记好,不要随便更改,如果重新生成秘钥后,需要修改已发布的项目,否则会报错
 
 /**
  *  openid
  */ 
function getOpenId($APPID,$APPSECRET,$code) {
	//$url是小程序提供的接口
    $url = "https://api.weixin.qq.com/sns/jscode2session?appid=".$APPID."&secret=".$APPSECRET."&js_code=".$code."&grant_type=authorization_code";
    $res = httpRequest($url);
    $res = json_decode($res,true);
    return $res;
}

/**
 * curl获取指定网页内容
 */
 function httpRequest($url, $data='', $method='GET'){
    $curl = curl_init();  
    curl_setopt($curl, CURLOPT_URL, $url);  
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);  
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);  
    curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);  
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);  
    curl_setopt($curl, CURLOPT_AUTOREFERER, 1);  
    if($method=='POST')
    {
        curl_setopt($curl, CURLOPT_POST, 1); 
        if ($data != '')
        {
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);  
        }
    }

    curl_setopt($curl, CURLOPT_TIMEOUT, 30);  
    curl_setopt($curl, CURLOPT_HEADER, 0);  
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);  
    $result = curl_exec($curl);  
    curl_close($curl);  
    return json_decode($result,true);
  } 

02、获取小程序的accesstoken

注意:目前小程序的access_token有效期期是2小时,也就是7200秒,所以需要定时刷新,重复刷新会导致上次获取的 access_token 失效,建议开发者统一获取和刷新 access_token,不应该各自去刷新,否则容易造成冲突,导致 access_token 覆盖而影响业务;
php获取accesstoken:

  /**
   * 获取accessToken
   */
function accessToken($APPID,$APPSECRET) {
    $tokenFile = __DIR__."xxxx.txt";//存储access_token的文件
    //缓存文件名
    $data = json_decode(file_get_contents($tokenFile));
    //判断时间是否过期或不存在
    if ($data->expire_time < time() || !$data->expire_time) {
    	//小程序提供的获取accesstoken的接口
        $access_token = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$APPID."&secret=".$APPSECRET;
        $res = httpRequest($access_token);
        $res = json_decode($res,true);
        $access_token = $res['access_token'];
        if ($access_token) {
        	//设置过期时间
            $jsonstr['expire_time'] = time() + 7000;
            //设置 $access_token
            $jsonstr['access_token'] = $access_token;
            $fp = fopen($tokenFile, "w");//打开文件
            fwrite($fp, json_encode($jsonstr));//写入文件
            fclose($fp);//关闭文件
        }
    } else {
    	//未过期直接从文件中读取accesstoken
        $access_token = $data->access_token;
    }
    return $access_token;
}

$token = accessToken($APPID,$APPSECRET);

03、获取表单的formid

既然是表单的id,当然就是form+button了,直接上代码
小程序代码:

//wxml代码
<form bindsubmit="getformid" report-submit="{{true}}">
   <button formType="submit" bindtap='close' data-title='hb' class='HB_des'>取消</button>
</form>

//js代码
  //获取用户唯一标识 formid,推送模板消息
  getformid: function (e) {
    if (e.detail.formId != "the formId is a mock one") {
        var formId_str = e.detail.formId;
        wx.request({
          url: '后台地址',
          method: 'POST',
          header: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          data: {
            formid: formId_str,
            openid: app.globalData.openid,//用户id,上面获取
            expire: parseInt(new Date().getTime() / 1000) + 604800,//计算7天后的过期时间时间戳-秒,存储需要
          },
          success: function (res) {
            console.log('成功');
            console.log(res);
          },
          fail: function (err) {
            console.log('request fail ', err);
          },
        })
    }
  },

该获取的都获取了,现在来PHP推送模板消息

$formid= $_POST['formid'];
$openid= $_POST['openid'];
$token= $_POST['token'];//accesstoken不需要返回前端,在后直接使用,这里为了方便,获取请看上文

/**
 * 发送模板消息
 */ 
function sendTemMsg($formid,$openid,$token){
	//小程序提供发布模板的接口
    $url='https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token='.$token;
    $temid='Dwme7pfbGkfh87394p0tkOrYhKpMbeok27CFP3-BDjU';//小程序后台管理模板id,下文介绍
    $page='pages/index/index';//小程序首页
    //以下提供的模板样式,根据项目需求,手动添加
    $data = array(
        "touser"=>$openid,
        "template_id"=>$temid,
        "page"=>$page,
        "form_id"=>$formid,
        "data"=>array(
            "keyword1"=>array(
                "value"=>'自定义内容',
                "color"=>"#173177"
            ),
            "keyword2"=>array(
                "value"=>'好文章分享!',
                "color"=>"#173177"
            ),
            "keyword3"=>array(
                "value"=>'好文章分享!',
                "color"=>"#173177"
            ),
            // "keyword4"=>array(
            //     "value"=>'北京',
            //     "color"=>"#173177"
            // ),
        ),
        // "emphasis_keyword"=>"keyword1.DATA",//需要进行加大的消息
    );
    $jsondata=json_encode($data);
    $res=httpRequest($url, $jsondata,'POST');
    if($res){
    	//推送模板消息成功
        return json_encode(array('state'=>4,'msg'=>$res));
    }else{
        return json_encode(array('state'=>5,'msg'=>$res));
    }
}

if($formid){
    echo sendTemMsg($formid,$openid,$token);
}else{
    echo '返回数据失败';
}

到这里推送模板消息基本就结束啦!当用户触发的时候就可以向用户推送消息了,新手可能不知道上图中的小程序后台管理模板是什么,现在解释一下,小程序后台管理模板,需要登入微信公众号平台https://mp.weixin.qq.com,找到模板消息栏目–>进行自定义模板–》完成后就会生成自定义模板ID,如下图:模板

04、进阶模块定时推送消息-----对上面代码进行改造

以下内容用于正常推送消息,不能乱用否则影响用户体验
当我们有业务需求,需要向用户定时推送,一天只能推送一次,那么我们就可以搜集formid,但是formid有效期是7天,一个只能使用一次,所有我们只需要收集7个就好,现在有两种方法:
**方法一:**所有和用户交互的地方使用form+button进行改造,到时工作量有点大,正常情况也不需要那么多的formid。
**方法二:**就是form+button相互嵌套进行改造,嵌套个7层,调整样式,也能获得7个formid.
这里使用的是方法二,代码走起

//wxml代码
        <form bindsubmit="getformid" report-submit="{{true}}" class='HB_form'>
          <button formType="submit" class='HB_btn'>
            <form bindsubmit="getformid" report-submit="{{true}}">
              <button formType="submit" class='HB_btn'>
                <form bindsubmit="getformid" report-submit="{{true}}">
                  <button formType="submit" class='HB_btn'>
                    <form bindsubmit="getformid" report-submit="{{true}}">
                      <button formType="submit" class='HB_btn'>
                        <form bindsubmit="getformid" report-submit="{{true}}">
                          <button formType="submit" class='HB_btn'>
                            <form bindsubmit="getformid" report-submit="{{true}}">
                              <button formType="submit" class='HB_btn'>
                                <form bindsubmit="getformid" report-submit="{{true}}">
                                  <button formType="submit" bindtap='close' data-title='hb' class='HB_des'>获取formid</button>
                                </form>
                              </button>
                            </form>
                          </button>
                        </form>
                      </button>
                    </form>
                  </button>
                </form>
              </button>
            </form>
          </button>
        </form>
        
//wxss代码
.HB_form{
  position: relative;
  height: 44px;
  width: 100%;
  display: inline-block;
}
.HB_btn {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 0;
  border-radius:0;
  padding: 0;
  line-height: 0px;
  overflow: visible;
}

.HB_des {
  position: absolute;
  top: 0;
  left: 0;
  border-radius:0;
  line-height: 44px;
  padding: 0;
  width: 100%;
}

这样做的目的就是利用点击穿透,点击1次相当于点击7次,就能获得7个formid,然后在在发送给后台存储
改造js

//js代码
  //获取用户唯一标识 formid,推送模板消息
  getformid: function (e) {
    if (e.detail.formId != "the formId is a mock one") {
      this.data.formids.push(e.detail.formId);
      if (this.data.formids.length == 7) {
        var formId_arr = this.data.formids;
        var formId_str = JSON.stringify(formId_arr);
        this.data.formids = [];
        wx.request({
          url: '后台地址',
          method: 'POST',
          header: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          data: {
            formid: formId_str,//获取的formid数组
            openid: app.globalData.openid,//用户id
            expire: parseInt(new Date().getTime() / 1000) + 604800,//计算7天后的过期时间时间戳-秒
          },
          success: function (res) {
            console.log('成功');
            console.log(res);
          },
          fail: function (err) {
            console.log('request fail ', err);
          },
        })
      }
    }
  },

//PHP代码
//php存储formid代码
$formid= $_POST['formid'];//表单ID-数组
$openid= $_POST['openid'];//用户ID
$expire= $_POST['expire'];//7天后的过期时间

if($openid){
	//以键值对的方式进行存储formid和过期时间,方便判断formid是否过期
    $arr=array($expire=>$formid);
    $data=json_encode($arr);
    //存储到数据库,根据项目的数据库进行存储
    $aa=redis()->hset('formid', $openid, $data);
    echo $aa;//插入成功返回1,替换成功或失败返回0
}else{
    echo '没有openid';
	$aa=redis()->hgetall('formid');
	var_dump($aa);
}

实现定时发送需要Linux服务器上使用CronTab定时执行php

定时读取数据库的formid来推送消息
001、php定时脚本

//读取数据库中formid
$aa=redis()->hgetall('formid');
if($aa){
    foreach ( $aa as $key_openid => $value) {
        $openid=$key_openid;
        $arr=json_decode($value,true);//获取用户id对应的formid和过期时间
        foreach($arr as $key_time=>$value_formid){
            $expire=$key_time;
            $formid_arr=json_decode($value_formid,true);//获取formid
            if($expire>time() && count($formid_arr,0)>0){//查看是否过期
                $formid=array_shift($formid_arr);//读取并删除第一个formid
                sendTemMsg($formid,$openid,$token);//下发模板消息,sendTemMsg函数见上文
                if($formid_arr){//判断是否还有formid,有就重新存储,没有就删除对应用户,清理内存
                    $formid_str=json_encode($formid_arr);
                    $jsonarr=array($expire=>$formid_str);
                    $data=json_encode($jsonarr);
                    redis()->hset('formid', $openid, $data);
                    break 1; 
                }else{
                    redis()->hdel('formid',$openid);
                    break 1;
                }
            }
        }
    }
}

Linux服务器上使用CronTab定时执行php
首先,进入命令行模式,在命令行中键入:

 crontab -e
 00 * * * * lynx -dump https://www.yourdomain.com/script.php

至于这些代码解释自行百度,推荐以下文章有解释CronTab定时执行php
设置定时任务:
https://blog.csdn.net/zalan01408980/article/details/80555492
PHP实现定时任务的几种方法:
https://www.cnblogs.com/starFeeling/p/6751921.html

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值