1. 程式人生 > >PHP實現支付寶手機WAP支付接入說明

PHP實現支付寶手機WAP支付接入說明

因為專案原因,最近剛在專案中接入了支付寶的支付,故將支付過程記錄下來以備檢視。

專案背景:該專案為手機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做以下修改:


在此之前要根據註釋在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同後臺類似,只是加上成功後的跳轉頁面即可