在支付完成后我们会调用回调地址,发送模板消息。具体做法如下;
之前我们有定义过一个回调地址,具体的实现方式是在你支付完成后,他会自动请求执行这个回调文件。
下面我们来写一个上述的回调文件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还需要在微信后台去设置一个模板的样式。
下面我们来看一下小程序的模板消息与公众号的模板消息有什么不同。
模板消息以服务通知的方式通知到你,而公众号的是直接发送公众号消息。