微信小程序模板消息实现(PHP+小程序)

  • Post author:
  • Post category:php


参考官方文档和部分资料,总结小程序模板消息推送以及相关注意事项,楼主踩过的坑,特来与大家分享。

一、开发准备:

1. 在微信公众平台 – 小程序的模板中心申请消息模板


Laravel


Laravel

二、实现原理:

文档示例:小程序 + 接口(PHP)

小程序部分:

话不多说,先上效果图:


Laravel

示例代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18


<form bindsubmit=


"formSubmit"


report-submit=


'true'


>




<view


class


=


"btn-area"


><button formType=


"submit"


>Submit</button></view>


</form>


formSubmit:


function


(e) {




console.log(


'form发生了submit事件,formId为:'


, e.detail)




var


that =


this


;




wx.request({




url:


'https://api.XXX.com/sendTemplateMessage.api'


,




data: {




uid: uid,




formId: e.detail.formId




},




method:


'post'


,




header: {



'content-type'


:


'application/x-www-form-urlencoded'


},


//使用这种方式后台才能实现获取到数据




success:


function


(res) {




console.log(


"发送模板:"


+ res.data)




}




})

注意事项:

小程序通 submit 点击事件获 formid 在安卓和 IOS 是不一样的,安卓系统中为 13 位时间戳,而 IOS 系统中为 32 位字符串,在做接口请求时,不需要做额外处理。

安卓系统


Laravel


IOS系统



Laravel

PHP 接口部分:

1. 根据微信公众平台 —  设置  —  消息推送 — URL (服务器地址),在 PHP 项目配置入口文件,实现请求分发。

2. 验证入口文件,传递 token 令牌(消息推送的 token),进行 Signature 签名有效性验证,完成之后才能进行消息模板的服务器 URL 地址配置。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45


<?php




define(


'SS_START_TIME'


, microtime(true));




define(


'RUN_SS'


, true);




require


'../ss/ss.php'


;




$ss


=


new


ss(


'xcx'


);




$ss


->execute(


'xcx'


,


'valid'


,


'xcx'


);


?>


<?php




// 小程序验证入口文件




public


function


xcx(){




$type


=


$token


;


//Token(令牌)




if


(


$this


->checkSignature(


$type


) && isset(


$_GET


[


'echostr'


])){




echo


$_GET


[


'echostr'


];




exit


();




}




}




/**




* 校验微信加密签名




* [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) bool




*/




private


function


checkSignature(


$type


=


''


){




// 微信服务器配置Token




$token


=


$type


;




// 1.将timestamp,token,nonce按字典序排序




$timestamp


=


$_GET


[


'timestamp'


];




$nonce


=


$_GET


[


'nonce'


];




$signature


=


$_GET


[


'signature'


];




$arr


=


array


(


$timestamp


,


$token


,


$nonce


);




sort(


$arr


, SORT_STRING);




// 2.拼接为字符串并sha1加密




$tmpStr


= implode(


$arr


);




$tmpStr


= sha1(


$tmpStr


);




// 3.与signature对比判断是否来自微信服务器




if


(


$tmpStr


==


$signature


){




return


true;




}


else


{




return


false;




}




}


?>

可在 https://mp.weixin.qq.com/debug/ 调试获取 access_token


Laravel

3. 微信公众平台 – 设置 – 开发设置配置消息推送(需要先将入口文件上传服务器)


Laravel

4. 在微信公众平台获取相关参数:

AppID (小程序 ID)、AppSecret (小程序密钥)、Token (令牌)、TemplateId(模板 id)、EncodingAESKey (消息加密密钥)

4.1  小程序模板接口

复制代码

/*
     *小程序模板消息
     *@param uid 用户id
     *$param template_id 模板id
     *@param form_id 表单提交场景下formId(只能用一次)
     *@param emphasis_keyword 消息加密密钥
    */
    public function sendTemplateMessage($uid,$form_id,$template_id){
        // 检验uid合法性 防止非法越界
        $nickname = "nickname";  // 用户昵称
        // 此openid为小程序的openid切勿与微信自动登录的openid混淆
        $xcx_open['openid'] = "用户openid";
        // openid可以通过PHP接口或者小程序获取
        if ($xcx_open['openid']) {
            $temp_msg = array(
                'touser' => "{$xcx_open['openid']}",
                'template_id' => "{$template_id}",
                'page' => "/pages/index/index",
                'form_id' => "{$form_id}",
                'data' => array(
                    'keyword1' => array(
                        'value' => "{$nickname}",
                    ),
                    'keyword2' => array(
                        'value' => date('Y-m-d H:i:s', time()),
                    ),
                    'keyword3' => array(
                        'value' => "好友已完成测试,快去看看吧!",
                    ),
                    'keyword4' => array(
                        'value' => "你收到1封新信件,快去看看吧~",
                    ),
                ),
                'emphasis_keyword'=> "{$emphasis_keyword}"
            );
            $res = $this->sendXcxTemplateMsg(json_encode($temp_msg));
            echo "<pre>";var_dump($res);exit;
        }
    }

复制代码

4.2 发送小程序模板消息

复制代码

  /**
     * 发送小程序模板消息
     * @param $data
     * [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) array
    */
    public function sendXcxTemplateMsg($data,$appid = "",$appsecret = "")
    {
        // 具体模板格式参考公众平台申请的template_id
        if (!$appid || !$appsecret)
        {
            $appid        = '';    //小程序id
            $appsecret    = '';    //小程序秘钥 
        }
        $access_token = $this->getXcxAccessToken($appid,$appsecret);
        $url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token={$access_token}";
        return $this->http_request($url, $data);
    }

复制代码

请求数据格式如下:

复制代码

{
  "touser": "OPENID",
  "template_id": "TEMPLATE_ID",
  "page": "index",
  "form_id": "FORMID",
  "data": {
      "keyword1": {
          "value": "339208499"
      },
      "keyword2": {
          "value": "2015年01月05日 12:30"
      },
      "keyword3": {
          "value": "腾讯微信总部"
      } ,
      "keyword4": {
          "value": "广州市海珠区新港中路397号"
      }
  },
  "emphasis_keyword": "keyword1.DATA"
}

复制代码

4.3 获取 access_token

复制代码

/**
     * 获取微信接口调用凭证
     * @param string $appid
     * @param string $appsecret
     * [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) mixed
    */
    public function getXcxAccessToken($appid = '', $appsecret = '')
    {
        if (!$appid || !$appsecret)
        {
            $appid        = '';
            $appsecret    = '';
        }

        // 缓存获取
        $cache = &factory::cache();
        if (!$cache->get($appid.'xcx_access_token'))
        {
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
            $res = $this->http_request($url);
            // access_token设置到缓存中
            $cache->set($appid.'xcx_access_token', $res['access_token'], 7000);
            return $res['access_token'];
        }

        return $cache->get($appid.'xcx_access_token');
    }

复制代码

4.4 CURL 模拟 HTTP 请求(POST)`

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26


/**




* curl模拟http请求GET/POST




* @param $url




* @param null $data




* [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) array




*/




public


function


http_request(


$url


,


$data


= null)




{




$ch


= curl_init();




curl_setopt(


$ch


, CURLOPT_URL,


$url


);




// 以文件流形式返回




curl_setopt(


$ch


, CURLOPT_RETURNTRANSFER, 1);




if


(!


empty


(


$data


))




{




// POST请求




curl_setopt(


$ch


, CURLOPT_POST, 1);




curl_setopt(


$ch


, CURLOPT_POSTFIELDS,


$data


);




}




$output


= curl_exec(


$ch


);




curl_close(


$ch


);




// 返回数组




return


json_decode(


$output


, true);




}

传递参数:根据定义接口传递相关参数,用户 uid  通过 uid 获取 openid,此 openid 为小程序的 openid, formId 为表单提交场景下,为 submit 事件带上的 formId,formid 在安卓和 ios 下的数据格式和长度不一致,而且小程序获取 formid 只支持真机调试。

接口调试:errcode 的合法值

值 说明

40037 template_id 不正确

41028 form_id 不正确,或者过期

41029 form_id 已被使用

41030 page 不正确

45009 接口调用超过限额(目前默认每个帐号日调用限额为 100 万)

请求成功:

1

2

3

4

5

6

7

8


{




"state"


: 1,




"data"


: {




"errcode"


: 0,




"errmsg"


:


"ok"




},




"info"


:


"successful!"


}

至此,推送功能完整实现!