因为项目原因,最近刚在项目中接入了支付宝的支付,故将支付过程记录下来以备查看。
项目背景:该项目为手机WAP项目,所以接入的是支付宝的手机网站支付类型。
首先,在支付宝官方下载SDK和DEMO:
https://docs.open.alipay.com/203/105910/
在pay.php中引入相关类文件和配置,如下,同时提交相关订单信息
<?php
/* ** 功能:支付宝手机网站支付接口(alipay.trade.wap.pay)接口调试入口页面* 版本:2.0* 修改日期:2016-11-01* 说明:* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。请确保项目文件有可写权限,不然打印不了日志。*/header("Content-type: text/html; charset=utf-8");include_once("../../../include/config.inc.php");
require_once dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'service/AlipayTradeService.php';
require_once dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'buildermodel/AlipayTradeWapPayContentBuilder.php';
require dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'./../config.php';//接收支付数据
$order_data = trim(get_param("orderDa")); //订单数据
if($order_data == "" ){$mssage = "数据不能为空";showinfo($mssage,'' ,3);exit;
}
$result_order = json_decode(uc_authcode(base64_decode($order_data), 'DECODE', ADMIN_KEY),true);//商户订单号,商户网站订单系统中唯一订单号,必填
$out_trade_no = $result_order['WIDout_trade_no'];//订单名称,必填
$subject = $result_order['WIDsubject'];//付款金额,必填
$total_amount = $result_order['WIDtotal_amount'];//商品描述,可空
$body = $result_order['WIDbody'];//超时时间
$timeout_express="1m";//验证数据
$pay_md5 = $result_order['infoPy']; //订单验证if($out_trade_no==''){$mssage = "订单号不能为空";showinfo($mssage,'' ,3);exit;
}
if($total_amount=='' || $total_amount==0){$mssage = "订单金额不能为空";showinfo($mssage,'' ,3);exit;
}//购买商品
if($result_order['flag']=='paycard'){//检测是否有订单号$where = " and o_orderid = '".$out_trade_no."' and o_totalprice='".$total_amount."' and o_status=4 ";$info = get_info($GLOBALS["conn"],"game_order",array(),$where);if( empty($info) ){$mssage = "没有此订单!";showinfo($mssage,'' ,3);exit;}
//验证数据$p_arr = array( 'uid'=>$info['o_playerid'], 'uorder'=>$info['o_orderid'], 'uprice'=>$info['o_totalprice'],);$p_time = $info['o_addtime'];$p_key = ADMIN_KEY;$p_md5 = md5($p_arr.$p_time.$p_key);if( $p_md5 != $pay_md5 ){$mssage = "请勿非法操作!";showinfo($mssage,'' ,3);exit;}
}//申请还款
if($result_order['flag']=='repayment'){//检测是否有订单号$where = " and l_orderid = '".$out_trade_no."' and l_returnnum='".$total_amount."' and l_status=3 ";$info = get_info($GLOBALS["conn"],"game_loan_order",array(),$where);if( empty($info) ){$mssage = "没有此订单!";showinfo($mssage,'' ,3);exit;}
//验证数据$p_arr = array( 'uid'=>$info['l_playerid'], 'uorder'=>$info['l_orderid'], 'uprice'=>$info['l_returnnum']);$p_time = $info['l_addtime'];$p_key = ADMIN_KEY;$p_md5 = md5($p_arr.$p_time.$p_key);if( $p_md5 != $pay_md5 ){$mssage = "请勿非法操作!";showinfo($mssage,'' ,3);exit;}
}//记录要提交的订单信息到日志
$log_msg = "订单内容:" . json_encode($result_order);
sys_log_write_content( $log_msg.__FILE__.__LINE__ ,"pay_log","jsapi");//发送支付指令
$payRequestBuilder = new AlipayTradeWapPayContentBuilder();
$payRequestBuilder->setBody($body);
$payRequestBuilder->setSubject($subject);
$payRequestBuilder->setOutTradeNo($out_trade_no);
$payRequestBuilder->setTotalAmount($total_amount);
$payRequestBuilder->setTimeExpress($timeout_express);$payResponse = new AlipayTradeService($config);
$result=$payResponse->wapPay($payRequestBuilder,$config['return_url'],$config['notify_url']);return ;
?>
个人在测试中发现DEMO中有坑,需对AlipayTradeService.php做以下修改:
<?php
/* ** 功能:支付宝手机网站支付接口(alipay.trade.wap.pay)接口调试入口页面* 版本:2.0* 修改日期:2016-11-01* 说明:* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。请确保项目文件有可写权限,不然打印不了日志。*/header("Content-type: text/html; charset=utf-8");include_once("../../../include/config.inc.php");
require_once dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'service/AlipayTradeService.php';
require_once dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'buildermodel/AlipayTradeWapPayContentBuilder.php';
require dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'./../config.php';//接收支付数据
$order_data = trim(get_param("orderDa")); //订单数据
if($order_data == "" ){$mssage = "数据不能为空";showinfo($mssage,'' ,3);exit;
}
$result_order = json_decode(uc_authcode(base64_decode($order_data), 'DECODE', ADMIN_KEY),true);//商户订单号,商户网站订单系统中唯一订单号,必填
$out_trade_no = $result_order['WIDout_trade_no'];//订单名称,必填
$subject = $result_order['WIDsubject'];//付款金额,必填
$total_amount = $result_order['WIDtotal_amount'];//商品描述,可空
$body = $result_order['WIDbody'];//超时时间
$timeout_express="1m";//验证数据
$pay_md5 = $result_order['infoPy']; //订单验证if($out_trade_no==''){$mssage = "订单号不能为空";showinfo($mssage,'' ,3);exit;
}
if($total_amount=='' || $total_amount==0){$mssage = "订单金额不能为空";showinfo($mssage,'' ,3);exit;
}//购买商品
if($result_order['flag']=='paycard'){//检测是否有订单号$where = " and o_orderid = '".$out_trade_no."' and o_totalprice='".$total_amount."' and o_status=4 ";$info = get_info($GLOBALS["conn"],"game_order",array(),$where);if( empty($info) ){$mssage = "没有此订单!";showinfo($mssage,'' ,3);exit;}
//验证数据$p_arr = array( 'uid'=>$info['o_playerid'], 'uorder'=>$info['o_orderid'], 'uprice'=>$info['o_totalprice'],);$p_time = $info['o_addtime'];$p_key = ADMIN_KEY;$p_md5 = md5($p_arr.$p_time.$p_key);if( $p_md5 != $pay_md5 ){$mssage = "请勿非法操作!";showinfo($mssage,'' ,3);exit;}
}//申请还款
if($result_order['flag']=='repayment'){//检测是否有订单号$where = " and l_orderid = '".$out_trade_no."' and l_returnnum='".$total_amount."' and l_status=3 ";$info = get_info($GLOBALS["conn"],"game_loan_order",array(),$where);if( empty($info) ){$mssage = "没有此订单!";showinfo($mssage,'' ,3);exit;}
//验证数据$p_arr = array( 'uid'=>$info['l_playerid'], 'uorder'=>$info['l_orderid'], 'uprice'=>$info['l_returnnum']);$p_time = $info['l_addtime'];$p_key = ADMIN_KEY;$p_md5 = md5($p_arr.$p_time.$p_key);if( $p_md5 != $pay_md5 ){$mssage = "请勿非法操作!";showinfo($mssage,'' ,3);exit;}
}//记录要提交的订单信息到日志
$log_msg = "订单内容:" . json_encode($result_order);
sys_log_write_content( $log_msg.__FILE__.__LINE__ ,"pay_log","jsapi");//发送支付指令
$payRequestBuilder = new AlipayTradeWapPayContentBuilder();
$payRequestBuilder->setBody($body);
$payRequestBuilder->setSubject($subject);
$payRequestBuilder->setOutTradeNo($out_trade_no);
$payRequestBuilder->setTotalAmount($total_amount);
$payRequestBuilder->setTimeExpress($timeout_express);$payResponse = new AlipayTradeService($config);
$result=$payResponse->wapPay($payRequestBuilder,$config['return_url'],$config['notify_url']);return ;
?>
在此之前要根据注释在config.php中填入自己的参数
后台通知中根据DEMO中注释修改即可,本人实际测试发现无需验证sell_id
notify_url.php
<?php
/* ** 功能:支付宝服务器异步通知页面* 版本:2.0* 修改日期:2016-11-01* 说明:* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。*************************页面功能说明************************** 创建该页面文件时,请留心该页面文件中无任何HTML代码及空格。* 该页面不能在本机电脑测试,请到服务器上做测试。请确保外部可以访问该页面。* 如果没有收到该页面返回的 success 信息,支付宝会在24小时内按一定的时间策略重发通知*/
include_once("../../include/config.inc.php");
require_once("config.php");
require_once 'wappay/service/AlipayTradeService.php';$arr=$_POST;
$alipaySevice = new AlipayTradeService($config);
$alipaySevice->writeLog(var_export($_POST,true));
$result = $alipaySevice->check($arr);/* 实际验证过程建议商户添加以下校验。
1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
4、验证app_id是否为该商户本身。
*/
if($result) {//验证成功///请在这里加上商户的业务逻辑程序代//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——//获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表//商户订单号$out_trade_no = $_POST['out_trade_no'];//支付宝交易号$trade_no = $_POST['trade_no'];//交易状态$trade_status = $_POST['trade_status'];//订单金额$total_amount = $_POST['total_amount'];//sell_id//$sell_id = $_POST['seller_id'];//app_id$app_id = $_POST['app_id'];//判断支付类型(提现还是借贷)$type = substr($out_trade_no,0,2);//获取对应订单信息if($type=='tx'){$order_info = get_order_info($out_trade_no);//验证订单数据if(empty($order_info)){echo 'fail';exit;}if($total_amount != $order_info['o_totalprice']){echo 'fali';exit;}}if($type=='jd'){$order_info = get_loan_order_info($out_trade_no);//验证订单数据if(empty($order_info)){echo 'fail';exit;}if($total_amount != $order_info['l_returnnum']){echo 'fali';exit;}}/*if($sell_id!=$config['sell_id']){echo 'fali';exit;}*/if($app_id!=$config['app_id']){echo 'fali';exit;}if($_POST['trade_status'] == 'TRADE_FINISHED') {//判断该笔订单是否在商户网站中已经做过处理//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序//请务必判断请求时的total_amount与通知时获取的total_fee为一致的//如果有做过处理,不执行商户的业务程序//注意://退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知if($type=='tx'){if($order_info['o_status']==4){//执行业务处理//取出礼包码$sql = "select sysid,gc_code from ".get_table("game_gift_code")." where gc_status=1 limit 1";$query = $GLOBALS["conn"]->Query($sql);$value = $GLOBALS['conn']->FetchArray($query);$up_arr = array('o_status' => 1,'o_trade_no' => $trade_no,'o_giftcode' => $value['gc_code']);$up_where = " and o_orderid='".$out_trade_no."'";$row = update_record($GLOBALS["conn"],'game_order',$up_arr,array(),$up_where);//更新订单数据if($row>0){$msg = "订单 ".$out_trade_no." 已支付";$log_msg = "call back:" . $msg;sys_log_write_content( $log_msg.__FILE__.__LINE__ ,"pay_log","notify_order_success");//更新礼包码状态$up_gift = array('gc_status'=>2,'gc_time' => THIS_DATETIME,'gc_orderid' => $out_trade_no);$gift_where = " and sysid=".$value['sysid'];update_record($GLOBALS["conn"],'game_gift_code',$up_gift,array(),$gift_where);//更新商品出售数量/*$where = " and og_sysid='".$out_trade_no."'";$garr = get_info($GLOBALS['conn'],"game_order_goods",array('og_goodsid'),$where,'',true);foreach($garr as $k=>$v){$up_num = array('g_sellnum' => 'g_sellnum'+1);$num_where = " and g_id='".$v."'";update_record($GLOBALS['conn'],"game_goods",$up_num,array(),$num_where);//更新商品出售}*///新增用户消息$title = '付款成功,请试用后尽快退款';//标题$content = '您的订单['.$out_trade_no.']已经付款成功,<br>道具试用后可申请退款退回绑定借记卡,适合现金紧缺的玩家!系统赠送您的游戏兑换码:'.$value['gc_code'].',可以在您的游戏中进行使用,感谢您的支持!<br>如需帮助,请点击左上角【帮助】找到您的问题或者联系客服进行人工服务,QQ:2013609564';add_player_msg($order_info['o_playerid'],$title,$content);}}}if($type=='jd'){if($order_info['l_status']==3){//执行业务处理$up_arr = array('l_status' => 4,'l_trade_no' => $trade_no,'l_returntime' => THIS_DATETIME);$up_where = " and l_orderid='".$out_trade_no."'";$row = update_record($GLOBALS["conn"],'game_loan_order',$up_arr,array(),$up_where);//更新订单数据if($row>0){$msg = "订单 ".$out_trade_no." 已支付";$log_msg = "call back:" . $msg;sys_log_write_content( $log_msg.__FILE__.__LINE__ ,"pay_log","notify_order_success");}}}}else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {//判断该笔订单是否在商户网站中已经做过处理//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序//请务必判断请求时的total_amount与通知时获取的total_fee为一致的//如果有做过处理,不执行商户的业务程序 //注意://付款完成后,支付宝系统发送该交易状态通知if($type=='tx'){if($order_info['o_status']==4){//执行业务处理//取出礼包码$sql = "select sysid,gc_code from ".get_table("game_gift_code")." where gc_status=1 limit 1";$query = $GLOBALS["conn"]->Query($sql);$value = $GLOBALS['conn']->FetchArray($query);$up_arr = array('o_status' => 1,'o_trade_no' => $trade_no,'o_giftcode' => $value['gc_code']);$up_where = " and o_orderid='".$out_trade_no."'";$row = update_record($GLOBALS["conn"],'game_order',$up_arr,array(),$up_where);//更新订单数据if($row>0){$msg = "订单 ".$out_trade_no." 已支付";$log_msg = "call back:" . $msg;sys_log_write_content( $log_msg.__FILE__.__LINE__ ,"pay_log","notify_order_success");//更新礼包码状态$up_gift = array('gc_status'=>2,'gc_time' => THIS_DATETIME,'gc_orderid' => $out_trade_no);$gift_where = " and sysid=".$value['sysid'];update_record($GLOBALS["conn"],'game_gift_code',$up_gift,array(),$gift_where);//更新商品出售数量/*$where = " and og_sysid='".$out_trade_no."'";$garr = get_info($GLOBALS['conn'],"game_order_goods",array('og_goodsid'),$where,'',true);foreach($garr as $k=>$v){$up_num = array('g_sellnum' => 'g_sellnum'+1);$num_where = " and g_id='".$v."'";update_record($GLOBALS['conn'],"game_goods",$up_num,array(),$num_where);//更新商品出售}*///新增用户消息$title = '付款成功,请试用后尽快退款';//标题$content = '您的订单['.$out_trade_no.']已经付款成功,<br>道具试用后可申请退款退回绑定借记卡,适合现金紧缺的玩家!系统赠送您的游戏兑换码:'.$value['gc_code'].',可以在您的游戏中进行使用,感谢您的支持!<br>如需帮助,请点击左上角【帮助】找到您的问题或者联系客服进行人工服务,QQ:2013609564';add_player_msg($order_info['o_playerid'],$title,$content);}}}if($type=='jd'){if($order_info['l_status']==3){//执行业务处理$up_arr = array('l_status' => 4,'l_trade_no' => $trade_no,'l_returntime' => THIS_DATETIME);$up_where = " and l_orderid='".$out_trade_no."'";$row = update_record($GLOBALS["conn"],'game_loan_order',$up_arr,array(),$up_where);//更新订单数据if($row>0){$msg = "订单 ".$out_trade_no." 已支付";$log_msg = "call back:" . $msg;sys_log_write_content( $log_msg.__FILE__.__LINE__ ,"pay_log","notify_order_success");}}}}//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——echo "success"; //请不要修改或删除}else {//验证失败echo "fail"; //请不要修改或删除}?>
前台通知return_url.php同后台类似,只是加上成功后的跳转页面即可