小程序消息推送

小程序的消息推送很简单,主要把几个步骤理清就好了。

  • 在小程序的微信开发平台上配置服务器
  • 前端传递必要参数
  • 后端实现推送功能

一、配置

官方文档点这里
进入到微信平台,点开发=》开发设置=》消息推送的启用。

消息推送

配置

配置地址写可线上访问的,且必须要http或者https开头的,访问的位置是配置回调的php文件。内容如下:

<?php  
/** 
  * wechat php test 
  */  
  
//define your token
define("TOKEN", "weixin");  
$wechatObj = new wechatCallbackapiTest();  
$wechatObj->valid();  
  
class wechatCallbackapiTest  
{  
    public function valid()  
    {  
        $echoStr = $_GET["echostr"];  
  
        //valid signature , option  
        if($this->checkSignature()){  
            echo $echoStr;  
            exit;  
        }  
    }  
          
    private function checkSignature()  
    {  
        $signature = $_GET["signature"];  
        $timestamp = $_GET["timestamp"];  
        $nonce = $_GET["nonce"];      
                  
        $token = TOKEN;  
        $tmpArr = array($token, $timestamp, $nonce);  
        sort($tmpArr);  
        $tmpStr = implode( $tmpArr );  
        $tmpStr = sha1( $tmpStr );  
          
        if( $tmpStr == $signature ){  
            return true;  
        }else{  
            return false;  
        }  
    }  
} 

token是自己随便填的,AESkey最好直接使用后面的随机生成。
在提交后你可能会遇到“无效TOKEN”,那么可从以下几个地方检查:

  • 所填的域名是否可访问,最好另起一个窗口直接访问一下你所填的地址
  • 所填的Token和验证php文件中定义的token是否一致
  • 判断$tmpStr$signature是否一致后需要echo出结果

提交配置成功后再去模板消息那里添加自己需要做的需求推送模板,注意模板参数的顺序,在后端提交代码中顺序需要保证是一样的。

消息模板

二、代码的实现

推送这里可以分成普通的消息推送和订单支付的消息推送,当然,这里是我自己分的,原因是他们所需的formid的区别,看了文档会知道,普通的消息推送所需的formid是必须在前端的form标签中提交后获取到的,这也是必须参数。而支付订单的消息推送中的formid就可以不用前端那一步,因为它的formid是支付过程中生成的预支付id(prepay_id),所以下面只介绍普通的消息推送,知道了推送过程,支付的消息推送只需将其formid换成pripay_id就可以了。

前端

<form bindsubmit="formSubmit" report-submit="true">
      <button formType="submit">允许通知我</button>
</form>
formSubmit: function (e) {
    var that = this
    wx.request({
      url: "https://xxx/mobiletplus/index.php?act=login&op=send_wx",
      data: {
        "form_id": e.detail.formId,
        "customer_id": that.data.customer_id
      },
      method: 'POST',
      header: {
        'content-type': 'application/x-www-form-urlencoded'
      },
      success: function (res) {
        util.showSuccess("设置成功")
        //console.log(res.data)

      },
      fail: function (e) {
        util.showError("设置失败".e)
      }
    })
  },

拿到form_id后传到后端方法send_wx中实现功能
后端
所需参数:

  • touser=>open_id
  • templateId
  • formId
  • data

1.获取open_id(可参考我上一篇文章小程序授权登陆)
open_id在小程序授权登陆的时候产生,并存到数据库中

$json=$this->_getUserInfo();
$data['openid']=empty($json->openid)?$json->openId:$json->openid;
private function _getUserInfo(){
        require_once(dirname(dirname(__FILE__)).DS."resource".DS.'wxBizDataCrypt.php');
        $code = $_REQUEST['code'];
        $appId = $_REQUEST['appID'];
        $appSecret = $_REQUEST['appSecret'];
        $grant_type="authorization_code";
        $url_get = 'https://api.weixin.qq.com/sns/jscode2session?appid='.$appId.'&secret='.$appSecret.'&js_code='.$code.'&grant_type='.$grant_type;
        try{
            $json=json_decode($this->curlGet($url_get));
            if (!$json->errmsg){
                $sessionKey = $json->session_key;
                $encryptedData=$_REQUEST['encrypted'];
                $iv=$_REQUEST['iv'];
                $appID=$_REQUEST['appID'];
                $pc = new WXBizDataCrypt($appID, $sessionKey);
                $errCode = $pc->decryptData($encryptedData, $iv, $data );
                if ($errCode == 0) {
                    return json_decode($data);
                } else {
                    throw new Exception($errCode);
                }
            }else {
                throw new Exception('获取session_key发生错误:错误代码'.$json->errcode.',微信返回错误信息:'.$json->errmsg);
            }
        }
        catch(Exception $e){
            output_error($e->getMessage());
        }
    }

private function curlGet($url,$method='get',$data=''){
        $ch = curl_init();
        $header=array();
        $header[] = "Accept-Charset: utf-8";
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $temp = curl_exec($ch);
        curl_close($ch);
        return $temp;
    }

2.获取access_token

$access_token = $this->get_wxmini_access_token()->access_token;
public function get_wxmini_access_token(){
        $grant_type="client_credential";
        $url_get="https://api.weixin.qq.com/cgi-bin/token?grant_type=".$grant_type."&appid=".$this->appid."&secret=".$this->appSecret;
        try{
            $data = json_decode($this->curlGet($url_get));
            return $data;
        }
        catch(Exception $e){
            output_error($e->getMessage());
        }
    }
private function curlGet($url,$method='get',$data=''){
        $ch = curl_init();
        $header=array();
        $header[] = "Accept-Charset: utf-8";
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $temp = curl_exec($ch);
        curl_close($ch);
        return $temp;
    }

3.获取$url

$url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token='.$access_token;  //此处变量插入字符串不能使用{}!!!

4.$data的结构

$data = array(
                "touser"=>$openid,
                "template_id"=>$template_id,
                "page"=>$page,
                "form_id"=>$form_id,
                //"page"=>$page,
                "data"=>array(
                  "keyword1"=>array(
                      "value"=>$key1,
                      "color"=>"#173177"
                   ),
                   "keyword2"=>array(
                       "value"=>$key2,
                       "color"=>"#173177"
                   ),
                   "keyword3"=>array(
                       "value"=>$key3,
                       "color"=>"#173177"
                   ),
             ),
            );

5.send_wx

public function send_wx($form_id,$template_id,$page,$openid,$send_data){
        $access_token = $this->get_wxmini_access_token()->access_token;
        if(!empty($access_token)) {
            $url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token='.$access_token;  //此处变量插入字符串不能使用{}!!!
            /*
             * $send_data格式严格按照下面的形式
             * array(
             *      "keyword1"=>array(
             *          "value"=>$key1,
             *          "color"=>"#173177"
             *       ),
             *       "keyword2"=>array(
             *           "value"=>$key2,
             *           "color"=>"#173177"
             *       ),
             *       "keyword3"=>array(
             *           "value"=>$key3,
             *           "color"=>"#173177"
             *       ),
             * ),
             * */
            $data = array(
                "touser"=>$openid,
                "template_id"=>$template_id,
                "page"=>$page,
                "form_id"=>$form_id,
                //"page"=>$page,
                "data"=>$send_data,
            );
            $result = $this->curlPost($url,$data,'json');
            $arr = array('ret'=>1,
                'msg'=>'success',
                'data'=>array('result'=>$result),
            );
        } else {
            $arr = array('ret'=>0,'msg'=>'ACCESS TOKEN为空!');
        }
        echo json_encode($arr);
    }

三、微信小程序的支付功能

对于app中的微信支付功能可以看我前面写的微信支付爬坑
那在这里的微信小程序的支付功能简单说一下就可以了,参考代码即可。主要说的是注意事项。

  • 首先,我们需要在小程序对于账号的微信公共平台找到微信支付这个tab


    微信小程序支付

    如图可见,2是我们小程序的appid,3是我们需要关联的商户号。所以我们得需要一个开通了的商户号。

  • 关联商户号,如果关联失败的原因可能是因为:此小程序之前关联过别的商户号,如果关联过别的商户号,则再关联新的商户号的时候,新的商户号中费率必须和之前关联过的那个商户号的费率相同,否则会关联失败。这里我也是被坑了挺长时间。一开始反驳回来说的是一个费率为广告流量的,一个是销售的。我本来以为是说的是我的小程序是广告流量的,我在想我的类目明明是海淘啊,怎么会审核说我的是广告流量业务的。后来才发现,原来他指的是这个小程序之前关联过的商户号的业务是广告流量的。如果碰到这样的情况,是无法在线修改和删除之前关联过的商户号的(目前是,不代表以后会不能)。那我打客服电话咨询,他说只能迁移小程序。所以我这边用的是新申请的小程序。
  • prepay_id为空。待关联成功后,点支付的功能时发现prepay_id预支付id为空。可能的原因是:商户号不对;没有openid;缺少JSAPI支付功能;我碰到的原因就是这个JSAPI没有开通。需要到对应的商户号下面开通,开通需要管理员的短信验证码。
  • 支付相关后台代码
    wxmini表示的是小程序
public function payOp(){
        $app_id=empty($_REQUEST['appID'])?"wx3ee49988xxxx4":$_REQUEST['appID'];
        $mch_id='xxxx';
        $app_key='xxx';
        $openid=$_REQUEST['openid'];
        // order_info
        $orderIds=$_REQUEST['orderIds'];
        if(empty($orderIds)){
            output_error("网络繁忙");
        }
        $orderIds=getRandChar(5)."_".$orderIds;
        $order_amount=(float)$_REQUEST['order_amount'];
//        $order_info=Model("order")->getOrderInfo(array("order_id"=>$order_id));
//        if(empty($order_info)){
//            output_error("网络繁忙");
//        }
        // get prepay id
        $prepay_id = $this->generatePrepayId($app_id, $mch_id, $app_key,$orderIds,$order_amount,$openid);
        // re-sign it
        if($_REQUEST['platform'] == "wxmini"){
            $response = array(
                'appId' => $app_id,
                'timeStamp' => ''.time(),
                'nonceStr' => $this->generateNonce(),
                'package' => 'prepay_id='.$prepay_id,
                'signType' => 'MD5'
            );
            $response['paySign'] = $this->calculateSign($response, $app_key);
        }
        else{
            $response = array(
                'appid'     => $app_id,
                'partnerid' => $mch_id,
                'prepayid'  => $prepay_id,
                'package'   => 'Sign=WXPay',
                'noncestr'  => $this->generateNonce(),
                'timestamp' => time(),
            );
            $response['sign'] = $this->calculateSign($response, $app_key);
        }
        output_data(array('response'=>$response,'prepay_id'=>$prepay_id));
    }
    /**
     * Generate a nonce string
     *
     * @link https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=4_3
     */
    function generateNonce(){
        return md5(uniqid('', true));
    }
    /**
     * Get a sign string from array using app key
     *
     * @link https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=4_3
     */
    function calculateSign($arr, $key){
        ksort($arr);
        $buff = "";
        foreach ($arr as $k => $v) {
            if ($k != "sign" && $k != "key" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return strtoupper(md5($buff . "&key=" . $key));
    }
    /**
     * Get xml from array
     */
    function getXMLFromArray($arr){
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= sprintf("<%s>%s</%s>", $key, $val, $key);
            } else {
                $xml .= sprintf("<%s><![CDATA[%s]]></%s>", $key, $val, $key);
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

好了,对于小程序的消息推送功能就总结完了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容