引言:去年五月份的時(shí)候總結(jié)過(guò)微信小程序消息推送的功能众羡,然后最近重新做這個(gè)的時(shí)候發(fā)現(xiàn)沒(méi)有消息推送這個(gè)東西了暴拄,后來(lái)知道今年微信官方把消息推送改到了消息訂閱里去了,其實(shí)原理都差不多,都是在小程序端獲取用戶同意后,在后臺(tái)傳相關(guān)的模板id信息粪摘,再通過(guò)url發(fā)送到對(duì)應(yīng)的用戶
一、效果
二阀湿、獲取模板id
這里和前面的消息推送是一樣的赶熟,只不過(guò)改成了在“消息訂閱”里添加了瑰妄。如果需要自己定義一些消息模板陷嘴,可以點(diǎn)擊跳轉(zhuǎn)到最后一頁(yè),然后在下面有幾個(gè)小字间坐,點(diǎn)進(jìn)去可以自己配置一些模式灾挨。
三、實(shí)現(xiàn)
小程序端
支付成功后:
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) //這里可以看到每一項(xiàng)的授權(quán)狀態(tài)竹宋,當(dāng)用戶沒(méi)授權(quán)時(shí)劳澄,即使withSubscriptions開(kāi)啟了true,也是不會(huì)輸出訂閱狀態(tài)的蜈七,所以直接讓彈出授權(quán)框就得了
if (wx.requestSubscribeMessage) {
wx.requestSubscribeMessage({
tmplIds: [tmplId], //數(shù)組(多條訂閱)
success: function (res) { //成功
console.log('訂閱授權(quán)成功后的打用氚巍:')
console.log(res);
that.reqPost('Buy','sendSubscribeMessage',{
touser: touser,
template_id: tmplId,
page : page,
content: content
},function(res){
console.log('訂閱消息請(qǐng)求成功')
})
},
fail: function (res) {
console.log(res);
}
})
} else {
wx.showToast({
title: '請(qǐng)更新您微信版本,來(lái)獲取訂閱消息功能',
icon: 'none'
});
}
}
});
},
注:傳遞的參數(shù)tmplIds需要是數(shù)組的類型飒硅,不然會(huì)報(bào)錯(cuò)砂缩,一個(gè)模板id也要放到數(shù)組里
后端
/*
* 訂閱消息
*/
/**
* Notes:獲取accessToken
* @return mixed
* @throws \think\Exception
* @throws \think\exception\PDOException
*/
public function getAccessToken($touser)
{
//當(dāng)前時(shí)間戳
$now_time = strtotime(date('Y-m-d H:i:s',time())) ;
//失效時(shí)間
$timeout = 7200 ;
//判斷access_token是否過(guò)期
$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'] ;
//保存到數(shù)據(jù)庫(kù)
$insert = ['access_token' => $access_token ,'update_time' => $now_time,'uid'=>$touser] ;
Db::name('takeout_access_token')->insert($insert);
return $access_token;
}
//未查找到就為過(guò)期
$access_token = Db::name('takeout_access_token')->where('uid',$touser)
->where('update_time' ,'>',$before_time)
->value('access_token');
//如果過(guò)期
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'] ;
//更新數(shù)據(jù)庫(kù)
$update = ['access_token' => $access_token ,'update_time' => $now_time] ;
Db::name('takeout_access_token')->where('uid',$touser)->update($update) ;
}
return $access_token ;
}
//發(fā)送訂閱消息
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'];
//請(qǐng)求url
$url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=' . $access_token ;
//發(fā)送內(nèi)容
$data = [] ;
//接收者(用戶)的 openid
$data['touser'] = $openid ;
//所需下發(fā)的訂閱模板id
$data['template_id'] = $template_id ;
//點(diǎn)擊模板卡片后的跳轉(zhuǎn)頁(yè)面浑玛,僅限本小程序內(nèi)的頁(yè)面挟冠。支持帶參數(shù),(示例index?foo=bar)。該字段不填則模板無(wú)跳轉(zhuǎn)涯曲。
if(!empty($page)){
$data['page'] = $page ;
}
//模板內(nèi)容雀监,格式形如 { "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);
//跳轉(zhuǎn)小程序類型:developer為開(kāi)發(fā)版双吆;trial為體驗(yàn)版;formal為正式版;默認(rèn)為正式版
$data['miniprogram_state'] = 'formal' ;
return self::curlPost($url,json_encode($data)) ;
}
//發(fā)送post請(qǐng)求
protected function curlPost($url,$data)
{
$ch = curl_init();
$params[CURLOPT_URL] = $url; //請(qǐng)求url地址
$params[CURLOPT_HEADER] = FALSE; //是否返回響應(yīng)頭信息
$params[CURLOPT_SSL_VERIFYPEER] = false;
$params[CURLOPT_SSL_VERIFYHOST] = false;
$params[CURLOPT_RETURNTRANSFER] = true; //是否將結(jié)果返回
$params[CURLOPT_POST] = true;
$params[CURLOPT_POSTFIELDS] = $data;
curl_setopt_array($ch, $params); //傳入curl參數(shù)
$content = curl_exec($ch); //執(zhí)行
curl_close($ch); //關(guān)閉連接
return $content;
}
注意:需要注意的幾點(diǎn)好乐,第一個(gè)是accessToken是會(huì)過(guò)期的匾竿,所以需要每次判斷一下。第二個(gè)是需要傳用戶的openid曹宴,這樣才能知道推送到的是哪個(gè)微信用戶搂橙。第二個(gè)是消息內(nèi)容中的key需要和模板消息里的key一致,否則發(fā)送不成功
特別說(shuō)明:支付的消息訂閱是可以在form中直接成功笛坦,但其他的需要有bintap綁定事件才能訂閱成功区转,否則會(huì)報(bào)錯(cuò):errMsg: "requestSubscribeMessage:fail can only be invoked by user TAP gesture
我的做法是:
tosend:function(){
var that = this
wx.showModal({
title: '申請(qǐng)成功',
content: '需要平臺(tái)審核才能登陸,登陸賬戶為當(dāng)前申請(qǐng)的手機(jī)號(hào)版扩,初始密碼為123456',
confirmText:'確定',
success: function (res) {
if (res.confirm) {
console.log('用戶點(diǎn)擊確定')
that.toggleSubscribe() //在這里進(jìn)行消息訂閱
} else if (res.cancel) {
console.log('用戶點(diǎn)擊取消')
return
}
}
})
},
1废离、在需要的地方調(diào)用這個(gè)就行了。
2礁芦、其實(shí)有很多情況是小程序這邊給用戶跳出訂閱的彈窗蜻韭,授權(quán)訂閱后,后臺(tái)需要做一些業(yè)務(wù)上的審核柿扣,然后再主動(dòng)去發(fā)送訂閱消息到對(duì)應(yīng)的用戶肖方,比如審核結(jié)果類的業(yè)務(wù)。所以未状,我的意思是大致的邏輯是:小程序端給授權(quán)俯画,微信那邊應(yīng)該是根據(jù)openid來(lái)對(duì)應(yīng)的判斷用戶是否有授權(quán)此訂閱,然后我們后臺(tái)就可以進(jìn)行消息的推送了司草。