小程序的消息推送很簡單,主要把幾個步驟理清就好了。
- 在小程序的微信開發(fā)平臺上配置服務器
- 前端傳遞必要參數(shù)
- 后端實現(xiàn)推送功能
一、配置
官方文檔點這里
進入到微信平臺,點開發(fā)=》開發(fā)設置=》消息推送的啟用。


配置地址寫可線上訪問的,且必須要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出結果
提交配置成功后再去模板消息那里添加自己需要做的需求推送模板,注意模板參數(shù)的順序,在后端提交代碼中順序需要保證是一樣的。

二、代碼的實現(xiàn)
推送這里可以分成普通的消息推送和訂單支付的消息推送,當然,這里是我自己分的,原因是他們所需的formid的區(qū)別,看了文檔會知道,普通的消息推送所需的formid是必須在前端的form標簽中提交后獲取到的,這也是必須參數(shù)。而支付訂單的消息推送中的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中實現(xiàn)功能
后端
所需參數(shù):
- touser=>open_id
- templateId
- formId
- data
1.獲取open_id(可參考我上一篇文章小程序授權登陸)
open_id在小程序授權登陸的時候產生,并存到數(shù)據庫中
$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發(fā)生錯誤:錯誤代碼'.$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是我們需要關聯(lián)的商戶號。所以我們得需要一個開通了的商戶號。
- 關聯(lián)商戶號,如果關聯(lián)失敗的原因可能是因為:此小程序之前關聯(lián)過別的商戶號,如果關聯(lián)過別的商戶號,則再關聯(lián)新的商戶號的時候,新的商戶號中費率必須和之前關聯(lián)過的那個商戶號的費率相同,否則會關聯(lián)失敗。這里我也是被坑了挺長時間。一開始反駁回來說的是一個費率為廣告流量的,一個是銷售的。我本來以為是說的是我的小程序是廣告流量的,我在想我的類目明明是海淘啊,怎么會審核說我的是廣告流量業(yè)務的。后來才發(fā)現(xiàn),原來他指的是這個小程序之前關聯(lián)過的商戶號的業(yè)務是廣告流量的。如果碰到這樣的情況,是無法在線修改和刪除之前關聯(lián)過的商戶號的(目前是,不代表以后會不能)。那我打客服電話咨詢,他說只能遷移小程序。所以我這邊用的是新申請的小程序。
- prepay_id為空。待關聯(lián)成功后,點支付的功能時發(fā)現(xiàn)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;
}
好了,對于小程序的消息推送功能就總結完了。
