初识小程序

消息订阅的实现

2020-10-12  本文已影响0人  洗耳恭听_kai

引言:去年五月份的时候总结过微信小程序消息推送的功能,然后最近重新做这个的时候发现没有消息推送这个东西了,后来知道今年微信官方把消息推送改到了消息订阅里去了,其实原理都差不多,都是在小程序端获取用户同意后,在后台传相关的模板id信息,再通过url发送到对应的用户

image.png

一、效果

image.png image.png

二、获取模板id

这里和前面的消息推送是一样的,只不过改成了在“消息订阅”里添加了。如果需要自己定义一些消息模板,可以点击跳转到最后一页,然后在下面有几个小字,点进去可以自己配置一些模式。

三、实现

小程序端

支付成功后:

if(res.data.code == 1000){
       wx.showModal({
                    title: '提示',
                    content: '支付成功',
                    success: function (res) {
                      //消息订阅
                      var touser = uid
                      var tmplId = 'G8f87i7GxuuKjEG7TkOTWJ69zPMJtxxxx'
                      var page = 'pages/index/index'
                      var content = _this.data.orderid
                      app.toggleSubscribe(touser,tmplId,page,content)
                      app.openPage('member/mine_order?type=2')
                    }
                  })
        }
//消息订阅
  toggleSubscribe: function (touser,tmplId,page,content) {
    var that = this;
    wx.getSetting({
      withSubscriptions: true,
      success(res) {
        console.log(res.subscriptionsSetting)   //这里可以看到每一项的授权状态,当用户没授权时,即使withSubscriptions开启了true,也是不会输出订阅状态的,所以直接让弹出授权框就得了
        if (wx.requestSubscribeMessage) {
          wx.requestSubscribeMessage({
            tmplIds: [tmplId],  //数组(多条订阅)
            success: function (res) { //成功
              console.log('订阅授权成功后的打印:')
              console.log(res);
              that.reqPost('Buy','sendSubscribeMessage',{
                touser: touser,
                template_id: tmplId,
                page : page,
                content: content
              },function(res){
                console.log('订阅消息请求成功')
              })
            },
            fail: function (res) {
              console.log(res);
            }
          })
        } else {
          wx.showToast({
            title: '请更新您微信版本,来获取订阅消息功能',
            icon: 'none'
          });
        }

      }
    });
  },

注:传递的参数tmplIds需要是数组的类型,不然会报错,一个模板id也要放到数组里

后端

/*
     * 订阅消息
     */
    /**
     * Notes:获取accessToken
     * @return mixed
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    public function getAccessToken($touser)
    {
        //当前时间戳
        $now_time = strtotime(date('Y-m-d H:i:s',time())) ;

        //失效时间
        $timeout = 7200 ;

        //判断access_token是否过期
        $before_time = $now_time - $timeout ;

        //判断是否为首次
        $is_e = Db::name('takeout_access_token')->where('uid',$touser)->find();
        if(empty($is_e)){
            //获取新的access_token
            $appid  = 'wx5cf756xxxxxxx';
            $secret = "d32237266522xxxxxxxx";
            $url    = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret;
            $res = json_decode(file_get_contents($url),true);

            $access_token = $res['access_token'] ;

            //保存到数据库
            $insert = ['access_token' => $access_token ,'update_time' => $now_time,'uid'=>$touser] ;
            Db::name('takeout_access_token')->insert($insert);

            return $access_token;
        }
        //未查找到就为过期
        $access_token = Db::name('takeout_access_token')->where('uid',$touser)
            ->where('update_time' ,'>',$before_time)
            ->value('access_token');

        //如果过期
        if( !$access_token ) {

            //获取新的access_token
            $appid  = 'wx5cf756xxxxx';
            $secret = "d322372665220765xxxx";
            $url    = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret;
            $res = json_decode(file_get_contents($url),true);

            $access_token = $res['access_token'] ;

            //更新数据库
            $update = ['access_token' => $access_token ,'update_time' => $now_time] ;
            Db::name('takeout_access_token')->where('uid',$touser)->update($update) ;
        }

        return $access_token ;
    }

    //发送订阅消息
    public function sendSubscribeMessage()
    {
        $touser = $_POST['touser'];
        $template_id = $_POST['template_id'];
        $page = isset($_POST['page'])?$_POST['page']:'';
        $content = $_POST['content'];
        //access_token
        $access_token = self::getAccessToken($touser) ;
        //查找openid
        $openid = Db::name('users')->where('id',$touser)->find()['openid'];

        //请求url
        $url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=' . $access_token ;

        //发送内容
        $data = [] ;

        //接收者(用户)的 openid
        $data['touser'] = $openid ;

        //所需下发的订阅模板id
        $data['template_id'] = $template_id ;

        //点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
        if(!empty($page)){
            $data['page'] = $page ;
        }

        //模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } }
//        $data['data'] = [
//            "phrase10"=>[
//                'value' => '123456'
//            ],
//            "name8"=>[
//                'value' => '123456'
//            ],
//        ];
        //获取到订单信息
        $orderid = $content;
        $orderinfo = Db::name('order')->where('id',$orderid)->find();
        $data['data'] = [
            "character_string3"=>[
                'value' => $orderinfo['order_no']
            ],
            "amount1"=>[
                'value' => $orderinfo['money']
            ],
            "time2"=>[
                'value' => empty(date('Y-m-d H:i:s',$orderinfo['pay_time']))?date('Y-m-d H:i:s',time()):date('Y-m-d H:i:s',$orderinfo['pay_time'])
            ]
        ];
        var_dump($data);

        //跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
        $data['miniprogram_state'] = 'formal' ;

        return self::curlPost($url,json_encode($data)) ;
    }
    //发送post请求
    protected function curlPost($url,$data)
    {
        $ch = curl_init();
        $params[CURLOPT_URL] = $url;    //请求url地址
        $params[CURLOPT_HEADER] = FALSE; //是否返回响应头信息
        $params[CURLOPT_SSL_VERIFYPEER] = false;
        $params[CURLOPT_SSL_VERIFYHOST] = false;
        $params[CURLOPT_RETURNTRANSFER] = true; //是否将结果返回
        $params[CURLOPT_POST] = true;
        $params[CURLOPT_POSTFIELDS] = $data;
        curl_setopt_array($ch, $params); //传入curl参数
        $content = curl_exec($ch); //执行
        curl_close($ch); //关闭连接
        return $content;
    }

注意:需要注意的几点,第一个是accessToken是会过期的,所以需要每次判断一下。第二个是需要传用户的openid,这样才能知道推送到的是哪个微信用户。第二个是消息内容中的key需要和模板消息里的key一致,否则发送不成功

特别说明:支付的消息订阅是可以在form中直接成功,但其他的需要有bintap绑定事件才能订阅成功,否则会报错:errMsg: "requestSubscribeMessage:fail can only be invoked by user TAP gesture

我的做法是:

tosend:function(){
    var that = this
    wx.showModal({
     title: '申请成功',
     content: '需要平台审核才能登陆,登陆账户为当前申请的手机号,初始密码为123456',
     confirmText:'确定',
     success: function (res) {
       if (res.confirm) {
         console.log('用户点击确定')
         that.toggleSubscribe()  //在这里进行消息订阅
       } else if (res.cancel) {
         console.log('用户点击取消')
         return
       }
     }
   })
 },

1、在需要的地方调用这个就行了。
2、其实有很多情况是小程序这边给用户跳出订阅的弹窗,授权订阅后,后台需要做一些业务上的审核,然后再主动去发送订阅消息到对应的用户,比如审核结果类的业务。所以,我的意思是大致的逻辑是:小程序端给授权,微信那边应该是根据openid来对应的判断用户是否有授权此订阅,然后我们后台就可以进行消息的推送了。

上一篇 下一篇

猜你喜欢

热点阅读