在支付完成後我們會調用回調地址,發送模板消息。具體做法如下;
之前我們有定義過一個回調地址,具體的實現方式是在你支付完成後,他會自動請求執行這個回調文件。
下面我們來寫一個上述的回調文件paymentresult.php。
當支付完成後,服務器會自動返回一些支付後的參數給我們,所以我們要使用file_get_contents(“php://input”)方式去獲取。
具體如下:
<?php
$post = file_get_contents("php://input");
/**支付成功返回示例 詳見 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_7&index=7**
$post = '<xml>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<attach><![CDATA[支付測試]]></attach>
<bank_type><![CDATA[CFT]]></bank_type>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
<openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
<out_trade_no><![CDATA[1409811653]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
<sub_mch_id><![CDATA[10000100]]></sub_mch_id>
<time_end><![CDATA[20140903131540]]></time_end>
<total_fee>1</total_fee>
<coupon_fee_0><![CDATA[10]]></coupon_fee_0>
<coupon_count><![CDATA[1]]></coupon_count>
<coupon_type><![CDATA[CASH]]></coupon_type>
<coupon_id><![CDATA[10000]]></coupon_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
</xml>';
**支付成功返回示例結束**/
if($post){
file_put_contents('wxpay_log.txt',$post);
$data = getTheEscapedXml($post);
if($data['RETURN_CODE'] == 'SUCCESS'){//此時返回了正確的數據,可以保存到數據庫了
echo 'SUCCESS';//先返回,後保存數據,防止後續邏輯處理過多造成網絡超時
$result = json_encode($data);
//保存支付結果信息並且發送模板消息
savePaymentInformation($result);
}
$str='<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>';
// echo 'SUCCESS';
}else{
file_put_contents('wxpay_log.txt','error,回調錯誤');
savePaymentErrorInformation();
echo 'ERROR';
echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[Callback error]]></return_msg></xml>';
}
//保存微信支付數據
function savePaymentInformation($result){
$database = require_once '../config/ind_db.php';//引入數據庫配置
$db_user = $database['username']; //數據庫賬號
$db_pass = $database['password']; //數據庫密碼
//拼接數據庫主機信息
$dbh = $database['dsn'];
try {
//開始連接數據庫
$dbh = new PDO($dbh,$db_user,$db_pass);
//設置字符集
$dbh -> query('set names utf8');
$time = time();
$sql="INSERT INTO szdato_qyx_wxpay_callback(
pay_info,
add_time,
create_date)
VALUES(
'{$result}',
'{$time}',
'{$time}')";
$dbh->exec($sql);
//更新訂單信息
$data = json_decode($result);
$attach_id = $data->ATTACH;//訂單id
if(!$attach_id){
echo 'attach_id錯誤,未找到訂單。';exit;
}
//查詢該訂單
$sql = "select * from szdato_level_order where id={$attach_id}";
$res = $dbh->query($sql);
$level_order = $res ->fetch();
$user_id = $level_order['user_id'];
$addtime = time();
$endtime = strtotime($level_order['vip_end_time']);
$member_id = $level_order['member_id'];
$remarks = '購買成功,時長:'.$level_order['opening_time'] . ',' . '付款金額:' . $level_order['pay_price'];
$store_id = $level_order['store_id'];
//保存會員信息
$sql="INSERT INTO szdato_qyx_user_member(
user_id,
addtime,
endtime,
vip_end_time,
member_id,
remarks)
VALUES(
'{$user_id}',
'{$addtime}',
'{$endtime}',
'{$level_order['vip_end_time']}',
'{$member_id}',
'{$remarks}')";
$dbh->exec($sql);
//更新付款狀態
$pay_time = strtotime($data->TIME_END);//支付完成時間 格式爲yyyyMMddHHmmss,如2009年12月25日9點10分10秒錶示爲20091225091010。
$transaction_id = $data->TRANSACTION_ID;//微信訂單號
$sql="UPDATE szdato_level_order SET
is_pay=1,
pay_time={$pay_time},
transaction_id={$transaction_id},
addtime={$addtime}
WHERE id={$attach_id}";
$dbh->exec($sql);
//發送模板消息
$prepay_id = $level_order['prepay_id'];
$formid = $prepay_id;
if($store_id == 8){
$template_id = 'KlrWgWw0nB6IUDgOR4Dh3_MDQDJM3PtfMOSk5700b94';//趣預習模板ID
}else{
$template_id = 'unRS6hK8jh9EU5iWimEVbRfrzvU2m4HvKob_2y67EmA';//微課隨聲聽模板ID
}
$page = 'pages/index/index';
$open_id = $data->OPENID;
if(!$open_id||!$formid)die('failed!');
$key1 = $data->OUT_TRADE_NO;//訂單號out_trade_no
$pe = $data->TOTAL_FEE/1;
$pe = round($pe/100,2);
$key2 = $pe.'';//支付金額total_fee
$key3 = date('Y-m-d H:i:s');//下單時間
$key4 = 'VIP會員';//物品名稱
$access_token = get_access_token();
$url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token='.$access_token;
$data = array(//這裏一定要按照微信給的格式
"touser"=>$open_id,
"template_id"=>$template_id,
"page"=>$page,
"form_id"=>$formid,
"data"=>array(
"keyword1"=>array(
"value"=>$key1,
),
"keyword2"=>array(
"value"=>$key2,
),
"keyword3"=>array(
"value"=>$key3,
),
"keyword4"=>array(
"value"=>$key4,
)
),
"emphasis_keyword"=>"keyword2.DATA",//需要進行加大的消息
);
$tempinfo = http_request_json($url,$data);//將data數組轉換爲json數據
if(json_decode($tempinfo)->errcode){
$tips = '模板信息發送失敗' ;
$template_info = '錯誤代碼:[' . $tempinfo->errcode . ']' . $tempinfo->errmsg;
$time = time();
$sql9="INSERT INTO szdato_qyx_tempinfo_callback(
template_info,
tips,
create_date)
VALUES(
'{$template_info}',
'{$tips}',
'{$time}')";
$dbh->exec($sql9);
file_put_contents('wxpay_log_sendtempInfo.txt','錯誤代碼:' . $tempinfo->errcode . $tempinfo->errmsg);
}else{
$tips = '模板信息發送成功' ;
$template_info = json_encode($data['data']);
$time = time();
$sql10="INSERT INTO szdato_qyx_tempinfo_callback(
template_info,
tips,
create_date)
VALUES(
'{$template_info}',
'{$tips}',
'{$time}')";
$dbh->exec($sql10);
file_put_contents('wxpay_log_sendtempInfo.txt','模板信息發送成功,發送時間:' . date('Y-m-d H:i:s',time()));
}
} catch (PDOException $e) {
//連接失敗錯誤提示
die('error:'.$e->getMessage());
}
}
//轉義xml 到數組
function getTheEscapedXml($xml){
$p = xml_parser_create();//創建 XML 解析器
xml_parse_into_struct($p, $xml, $vals, $index);
xml_parser_free($p);
$data = "";
foreach ($index as $key=>$value) {
if($key == 'xml' || $key == 'XML') continue;
$tag = $vals[$value[0]]['tag'];
$value = $vals[$value[0]]['value'];
$data[$tag] = $value;
}
return $data;
}
//保存錯誤的支付信息
function savePaymentErrorInformation(){
$database = require_once '../config/ind_db.php';//引入數據庫配置
$db_user = $database['username']; //數據庫賬號
$db_pass = $database['password']; //數據庫密碼
//拼接數據庫主機信息
$dbh = $database['dsn'];
try {
//開始連接數據庫
$dbh = new PDO($dbh,$db_user,$db_pass);
//設置字符集
$dbh -> query('set names utf8');
$time = time();
$result = '支付回調notify_url請求錯誤,會員數據保存失敗!';
$sql="INSERT INTO szdato_qyx_wxpay_callback(pay_info,add_time,create_date)VALUES('{$result}','{$time}','{$time}')";
$dbh->exec($sql);
} catch (PDOException $e) {
//連接失敗錯誤提示
die('error:'.$e->getMessage());
}
}
//獲取access_token
function get_access_token(){
$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxdda3d40e074e4e7d&secret=f50fb02c140c4fcfe11b8279f6217863';
$ass_key = http_request_json($url);
$access_token = json_decode($ass_key)->access_token;
return $access_token;
}
/**
* 網絡請求curl
* @param $url $url 微信接口
* @param null $data $data 可以是數組,也可以是json字符串
* @param string $type
* @return mixed 返回的是json字符串
*/
function http_request_json($url,$data = null,$type = 'json'){
if ($type == 'json') {
$data = json_encode($data);//對數組進行json編碼
$header = array("Content-type: application/json;charset=UTF-8", "Accept: application/json", "Cache-Control: no-cache", "Pragma: no-cache");
}
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
if (!empty($data)) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
$res = curl_exec($curl);
if (curl_errno($curl)) {
echo 'Error+' . curl_error($curl);
}
curl_close($curl);
return $res;
}
以上回調文件會在支付成功(或者某個事件觸發)後發送模板消息,模板消息的ID還需要在微信後臺去設置一個模板的樣式。
下面我們來看一下小程序的模板消息與公衆號的模板消息有什麼不同。
模板消息以服務通知的方式通知到你,而公衆號的是直接發送公衆號消息。