TP5.1接入支付寶實現網頁/APP支付完整請求回調流程(沙箱環境)

目前互聯網項目如果涉及到第三方支付模塊,那麼支付寶/微信無非是最好的選擇,此文先以支付寶爲例講解,想了解微信支付的可以看我之後的文章,當然支付也分很多種形式,比如掃碼付、當面付、聲波付、調用APP付,網頁直接付等等。但最常用的形式還是服務端+APP+調用支付寶APP服務端+網頁掃碼/調用支付寶APP/直接支付,所以接下來我就以ThinkPHP5.1作爲服務端從接入SDK到實現支付請求以及回調業務流程完整的操作講解一下,雖然我用的是TP5.1但是TP5和TP5.1在此使用過程中沒有太大的區別,無非TP5.1使用了一些TP5沒有的靜態方法而已,所以使用TP5的也可以通過本文無障礙的接入使用。至於使用沙箱的原因是考慮到有些沒有接觸具體項目而且自己也沒有申請商戶資格的用戶,使用沙箱環境便不用考慮這些,直接使用支付寶提供的沙箱號接入測試即可,當然如果你是將上線的項目只需將APPID等信息改爲項目需求的即可正常使用,接下來進入正文。



一、接入支付寶SDK

1.下載SDK放入框架

首先第一步當然是下載支付寶提供的SDK,這裏我們選擇支付寶的服務端PHP SDK下載即可(點我進入下載頁)
在這裏插入圖片描述
下載得到的是一個壓縮包,接下來我們打開TP5.1框架,在extend文件夾下新建一個Alipay(文件夾命名隨意,但要和之後命名空間對應,本文全程以Alipay爲例)的文件夾,然後將壓縮包內容全部解壓進Alipay中,效果如下:
在這裏插入圖片描述

2.爲SDK所需類添加命名空間

先整理一下之後所需要的SDK類

生成供APP使用的支付串碼:AlipayTradeAppPayRequest.php、AopClient.php
網頁支付:AlipayTradePagePayRequest、AopClient.php
異步通知回調驗籤:AopClient.php
綜上我們需要使用SDK中這三個類,首先找到這三個類,手動爲其添加命名空間
AopClient.php位置:extend/Alipay/aop/AopClient.php
AlipayTradeAppPayRequest.php位置:extend/Alipay/aop/request/AlipayTradeAppPayRequest.php
AlipayTradePagePayRequest.php位置:extend/Alipay/aop/request/AlipayTradePagePayRequest

分別爲其添加命名空間如下
AopClient.php需添加此命名空間namespace Alipay\aop;
AlipayTradeAppPayRequest.php和AlipayTradePagePayRequest需添加命名空間namespace Alipay\aop\request;

3.控制器中引用

爲所需類庫文件添加好命名空間後就可以在控制器引用了,只需要簡單的使用use即可,如下:
在這裏插入圖片描述

二、沙箱環境

1.獲取商家/用戶沙箱賬號

首先使用你的支付寶賬號登錄支付寶開放平臺然後點擊進入我的開放平臺,頂部導航欄開發中心中選擇研發服務,即可跳轉到沙箱頁面。
在這裏插入圖片描述
在沙箱頁面我們可以看到支付寶爲我們生成的相應信息和賬號,之後我們使用SDK時要使用這些相應信息:
在這裏插入圖片描述
記得下載沙箱版支付寶,可以用於之後測試支付,餘額可以自己充值。
在這裏插入圖片描述

2.配置公鑰,私鑰

SDK中主要需要的是四個參數,分別是APPID、支付寶網關、應用私鑰,支付寶公鑰。
想要得到支付寶公鑰需要先生成一個私鑰然後將對應的公鑰提交纔會獲取支付寶公鑰,生成私鑰需要我們下載支付寶的支付寶開放平臺開發助手。打開後生成即可,記得選擇非JAVA適用
在這裏插入圖片描述
將公鑰複製到沙箱頁面提交即可獲取支付寶公鑰,至此我們就得到了之後所需的私鑰和支付寶公鑰。

三、APP支付(服務端提供串碼供APP調用支付寶APP)

具體環境和參數得到後使用起來就很簡單了,只需要將需要的參數寫入然後調用SDK提供的api即可生成可供APP端調起支付寶所需的串碼。

public function appAlipay()
    {
        $aop = new AopClient;
        $aop->gatewayUrl = "https://openapi.alipaydev.com/gateway.do";     //網關地址要使用沙箱網關alipaydev
        $aop->appId = "填寫你自己的APPID";
        $aop->rsaPrivateKey = '填寫你自己的應用私鑰';
        $aop->format = "json";
        $aop->postCharset = "UTF-8";
        $aop->signType = "RSA2";
        $aop->alipayrsaPublicKey = '填寫沙箱頁面給你的支付寶公鑰';
        //實例化具體API對應的request類,類名稱和接口名稱對應,當前調用接口名稱:alipay.trade.app.pay
        $request = new AlipayTradeAppPayRequest();
        //SDK已經封裝掉了公共參數,這裏只需要傳入業務參數,沙箱環境的product_code只能是FAST_INSTANT_TRADE_PAY
        $info = json_encode(['body'=>'商品簡述','subject'=>'商品名','out_trade_no'=>md5(time()),
            'timeout_express'=>'30m','total_amount'=>'5000','product_code'=>'FAST_INSTANT_TRADE_PAY'],JSON_UNESCAPED_UNICODE);
        $request->setNotifyUrl("請填寫你的異步回調通知地址,需要無任何驗證即可訪問");
        $request->setBizContent($info);
        //這裏和普通的接口調用不同,使用的是sdkExecute
        $response = $aop->sdkExecute($request);
        //htmlspecialchars是爲了輸出到頁面時防止被瀏覽器將關鍵參數html轉義,實際打印到日誌以及http傳輸不會有這個問題
        echo htmlspecialchars($response);//就是orderString 可以直接給客戶端請求,無需再做處理。
    }

這裏要注意的是如果你的PHP版本>7的話AopClient中一行代碼會報錯,這是因爲語法被廢棄需要我們手動修改,打開AopClient.php定位到420行(因人而異)

/**
     * 建立請求,以表單HTML形式構造(默認)
     * @param $para_temp 請求參數數組
     * @return 提交表單HTML文本
     */
	protected function buildRequestForm($para_temp) {
		
		$sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='".$this->gatewayUrl."?charset=".trim($this->postCharset)."' method='POST'>";
        foreach ($para_temp as $key => $val) {   //修改的是這一行,將被PHP7廢棄的each語法改爲foreach即可
			if (false === $this->checkEmpty($val)) {
				//$val = $this->characet($val, $this->postCharset);
				$val = str_replace("'","&apos;",$val);
				//$val = str_replace("\"","&quot;",$val);
				$sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";
			}
        }

然後我們只需要將這個方法作爲API提供給APP端即可讓APP端開發人員使用此串碼調用起支付寶進行支付,至於支付後的異步回調通知驗籤處理業務邏輯等放入網頁支付中說明。

四、網頁支付(服務端調用API生成付款頁並添加回調方法完成業務流程)

1.生成訂單調用API生成付款頁

 public function webAlipay()
    {
        $aop = new AopClient;
        $aop->gatewayUrl = "https://openapi.alipaydev.com/gateway.do";    //網關地址要使用沙箱網關alipaydev
        $aop->appId = "填寫你的APPID";
        $aop->rsaPrivateKey = '填寫你自己的應用私鑰';
        $aop->format = "json";
        $aop->apiVersion = '1.0';
        $aop->postCharset='UTF-8';
        $aop->signType = "RSA2";
        $aop->alipayrsaPublicKey = '填寫沙箱頁面給你的支付寶公鑰';
        //實例化具體API對應的request類,類名稱和接口名稱對應,當前調用接口名稱:alipay.trade.app.pay
        $request = new AlipayTradePagePayRequest();
        //SDK已經封裝掉了公共參數,這裏只需要傳入業務參數
        $info = json_encode(['body'=>'商品簡述','subject'=>'商品名','out_trade_no'=>md5(time()),
            'timeout_express'=>'30m','total_amount'=>'5000.00','product_code'=>'FAST_INSTANT_TRADE_PAY'],JSON_UNESCAPED_UNICODE);
        $request->setBizContent($info);
        $request->setReturnUrl("請填寫你的付款後頁面返回地址");
        $request->setNotifyUrl("請填寫你的異步回調通知地址,需要無任何驗證即可訪問");
        $result = $aop->pageExecute($request);
        return $result;
    }

這裏要注意的是如果你的PHP版本>7的話AopClient中一行代碼會報錯,這是因爲語法被廢棄需要我們手動修改。請參考APP支付中,我已說明過如何修改。

2.通過回調方法驗籤並處理業務邏輯

這裏的returnback和notify分別是之前填的返回地址和回調地址所調用的方法:
$request->setReturnUrl(“請填寫你的付款後頁面返回地址”);
$request->setNotifyUrl(“請填寫你的異步回調通知地址,需要無任何驗證即可訪問”);

//異步通知回調
public function notify()
    {
        try{
            $info = Request::param();
            $aop = new AopClient;
            $aop->alipayrsaPublicKey = '填寫你的支付寶公鑰';
            $flag = $aop->rsaCheckV1($info,NULL,"RSA2");     //驗籤
            if(!$flag)
            {
                Log::write('驗籤失敗','ALIPAY_THORW');
            }
            else if($info['trade_status']=='TRADE_SUCCESS')     //支付狀態
            {
                if(!Db::table('order')->where('ordernum','=',$info['out_trade_no'])->find())
                {
                    $insertData = ['create_time'=>time(),'update_time'=>time(),'goodname'=>$info['subject'],'ordernum'=>$info['out_trade_no'],
                        'alipaynum'=>$info['trade_no'],'total_money'=>$info['total_amount'],'status'=>1];
                    Db::table('order')->insert($insertData);}
                }
            }
        }
        catch (Exception $e)
        {
            Log::write($e->getMessage(),'ALIPAY_THORW');
        }
    }

	//網頁付款成功後返回頁面
    public function returnback()
    {
        echo "<h1>支付成功<h1>";
        halt(Request::param());
    }

在異步通知回調中首先要驗籤,通過後再根據trade_status的狀態來處理相應的業務邏輯,這裏注意支付寶會在支付成功後24小時內分時通知,不一定只發一次,所以要在此方法中做相應判斷避免重複處理同一訂單。

如果接入SDK使用過程中有什麼問題可以評論提出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章