laravel5.2引入支付寶支付sdk

業務功能

適用於商家在移動端網頁應用中集成支付寶支付功能。商家在網頁中調用支付寶提供的網頁支付接口調起支付寶客戶端內的支付模塊,商家網頁會跳轉到支付寶中完成支付,支付完後跳回到商家網頁內,最後展示支付結果。若無法喚起支付寶客戶端,則在一定的時間後會自動進入網頁支付流程。

 

一. 創建應用

鏈接:支付寶螞蟻金服開放平臺

注意:

  1. 需擁有實名認證的支付寶賬戶。
  2. 企業或個體工商戶可申請
  3. 需要有真實有效的營業執照,切網站必須通過ICP備案

進入螞蟻金服開放平臺->開發者中心->網頁&移動應用。按需求創建應用,在這裏我創建的是網頁/移動類應用

創建完成後提交審覈,大部分應用需要簽約後才能使用,簽約需要營業執照。

 

二. 配置應用環境

    

        

配置完成後,可提交審覈,開發者點擊提交審覈後,預計會有一個工作日的審覈時間。應用上線成功後,狀態變爲以上線,該狀態下的應用能夠調用生產環境的接口。

 

三. 接口調用配置

目前laravel中集成alipay SDK的支付接口很豐富。常用的有下面幾種:

OmniPay-laravel:github OmniPay-laravel鏈接

latrell/alipay:github latrell/alipay鏈接

...

因爲項目的需要,在這裏我採用的是alipay的原生SDK包。

首先下載PHP版本的Demo:支付寶手機網站支付PHP demo

從index.php中可以看出該demo支持以下功能

手機網站2.0支付(接口名:alipay.trade.wap.pay)
手機網站2.0訂單查詢 (接口名:alipay.trade.query)
手機網站2.0訂單退款  (接口名:alipay.trade.refund)
手機網站2.0訂單退款查詢(接口名:alipay.trade.fastpay.refund.query)
手機網站2.0賬單下載(接口名:alipay.data.dataservice.bill.downloadurl.query)

其中config.php是配置文件:

複製代碼

<?php
$config = array (    
        //應用ID,您的APPID。
        'app_id' => "",

        //商戶私鑰,您的原始格式RSA私鑰
        'merchant_private_key' => "",
        
        //異步通知地址
        'notify_url' => "",
        //http://工程公網訪問地址/alipay.trade.wap.pay-PHP-UTF-8/notify_url.php

        //同步跳轉
        'return_url' => "",
        //http://mitsein.com/alipay.trade.wap.pay-PHP-UTF-8/return_url.php
        // jk.mrwangqi.com

        //編碼格式
        'charset' => "UTF-8",

        //簽名方式
        'sign_type'=>"RSA2",

        //支付寶網關
        'gatewayUrl' => "https://openapi.alipay.com/gateway.do",

        //支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應APPID下的支付寶公鑰。
        'alipay_public_key' => "",
);

複製代碼

配置完成後,修改demo權限
sudo chmod -R 777 alipayDemo

 

訪問demo下的index.php

這樣子這個demo就可以運行了。

 

 

具體開發

現在下載SDK:支付寶手機網站支付PHP SDK

 

一.  引入SDK包

        在laravel中引入SDK包的步驟:

  1.     在app/新建libs文件夾,將SDK包放在該目錄下

       2.   找到根目錄下的composer.json文件,添加如下配置:

複製代碼

"autoload": {  
        "classmap": [  
            "database",  
            "app/libs/alipay" //這裏是自定義包的文件位置,我將我項目中的該SDK包命名爲alipay 
        ],  
        "psr-4": {  
            "App\\": "app/"  
        }  
    },  

複製代碼

 

        3.   執行以下命令

composer dump-autoload     //當在包中加入新的類,需要更新autoloader  

 

二.  移動/新建文件

在alipay目錄下新建wappay目錄,在wappay目錄下新建buildermodel和service兩個目錄。將上面demo目錄下的wappay/buildermodel/AlipayTradeWapPayContentBuilder.php和wappay/service/AlipayTradeService.php兩個文件分別複製到自己項目SDK包中新建的wappay中的相應目錄下。

AlipayTradeWapPayContentBuilder.php是alipay demo對支付寶手機網站支付接口業務參數的封裝。AlipayTradeService.php是alipay demo對支付寶手機網站支付接口業務功能的封裝。

在SDK目錄下新建log.txt。作爲支付寶支付日誌存放文件

 

三.  設置/引入命名空間

對AlipayTradeWapPayContentBuilder.php和AlipayTradeService.php設置命名空間,我設置的是

namespace App\libs\alipay\wappay\buildermodel;
namespace App\libs\alipay\wappay\buildermodel;

 

對alipay/aop/request/AlipayTradeWapPayRequest.php和alipay/aop/AopClient.php設置命名空間,我設置的是:

namespace App\libs\alipay\aop\request;
namespace App\libs\alipay\aop;

 

在AlipayTradeWapPayContentBuilder.php中引入上面兩個命名空間:

use App\libs\alipay\aop\request\AlipayTradeWapPayRequest;
use App\libs\alipay\aop\AopClient;

 

將AlipayTradeService.php中的下面代碼註釋:

// require_once dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'./../../AopSdk.php';
// require dirname ( __FILE__ ).DIRECTORY_SEPARATOR.'./../../config.php';

 

四.  配置config(alipay.php)

在上面中alipay的demo中是有一個config.php文件作爲配置文件的,這裏我們不需要這個文件,我們利用laravel的特性,在laravel項目目錄下的config目錄新建一個alipay.php:

複製代碼

return [

            //應用ID,您的APPID。
        'app_id' => "",

        //商戶私鑰,您的原始格式RSA私鑰
        'merchant_private_key' => "",
        
        //異步通知地址
        'notify_url' => "",
        //http://工程公網訪問地址/alipay.trade.wap.pay-PHP-UTF-8/notify_url.php

        //同步跳轉
        'return_url' => "",
        //http://mitsein.com/alipay.trade.wap.pay-PHP-UTF-8/return_url.php
        // jk.mrwangqi.com

        //編碼格式
        'charset' => "UTF-8",

        //簽名方式
        'sign_type'=>"RSA2",

        //支付寶網關
        'gatewayUrl' => "https://openapi.alipay.com/gateway.do",

        //支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應APPID下的支付寶公鑰。
        'alipay_public_key' => "",
];

複製代碼

 

五.  對應config修改函數

在alipay.php中進行配置支付接口所需參數。下面我們修改alipay/wappay/service/AlipayTradeService.php:

複製代碼

class AlipayTradeService {

    //支付寶網關地址
    public $gateway_url = "https://openapi.alipay.com/gateway.do";

    //支付寶公鑰
    public $alipay_public_key;

    //商戶私鑰
    public $private_key;

    //應用id
    public $appid;

    //編碼格式
    public $charset = "UTF-8";

    public $token = NULL;
    
    //返回數據格式
    public $format = "json";

    //簽名方式
    public $signtype = "RSA";

    function __construct(){
        $this->gateway_url = config('alipay.gatewayUrl'); //獲得config文件夾下的alipay.php中的gatewayUrl參數,下同。
        $this->appid = config('alipay.app_id');
        $this->private_key = config('alipay.merchant_private_key');
        $this->alipay_public_key = config('alipay.alipay_public_key');
        $this->charset = config('alipay.charset');
        $this->signtype= config('alipay.sign_type');

        if(empty($this->appid)||trim($this->appid)==""){
            throw new Exception("appid should not be NULL!");
        }
        if(empty($this->private_key)||trim($this->private_key)==""){
            throw new Exception("private_key should not be NULL!");
        }
        if(empty($this->alipay_public_key)||trim($this->alipay_public_key)==""){
            throw new Exception("alipay_public_key should not be NULL!");
        }
        if(empty($this->charset)||trim($this->charset)==""){
            throw new Exception("charset should not be NULL!");
        }
        if(empty($this->gateway_url)||trim($this->gateway_url)==""){
            throw new Exception("gateway_url should not be NULL!");
        }

    }
    function AlipayWapPayService($alipay_config) {
        $this->__construct($alipay_config);
    }

    /**
     * alipay.trade.wap.pay
     * @param $builder 業務參數,使用buildmodel中的對象生成。
     * @param $return_url 同步跳轉地址,公網可訪問
     * @param $notify_url 異步通知地址,公網可以訪問
     * @return $response 支付寶返回的信息
     */
    function wapPay($builder,$return_url,$notify_url) {
    
        $biz_content=$builder->getBizContent();
        //打印業務參數
        $this->writeLog($biz_content);
    
        $request = new AlipayTradeWapPayRequest();
    
        $request->setNotifyUrl($notify_url);
        $request->setReturnUrl($return_url);
        $request->setBizContent ( $biz_content );
    
        // 首先調用支付api
        $response = $this->aopclientRequestExecute ($request,true);
        // $response = $response->alipay_trade_wap_pay_response;
        return $response;
    }

     function aopclientRequestExecute($request,$ispage=false) {

        $aop = new AopClient ();
        $aop->gatewayUrl = $this->gateway_url;
        $aop->appId = $this->appid;
        $aop->rsaPrivateKey =  $this->private_key;
        $aop->alipayrsaPublicKey = $this->alipay_public_key;
        $aop->apiVersion ="1.0";
        $aop->postCharset = $this->charset;
        $aop->format= $this->format;
        $aop->signType=$this->signtype;
        // 開啓頁面信息輸出
        $aop->debugInfo=true;
        if($ispage)
        {
            $result = $aop->pageExecute($request,"post");
            echo $result;
        }
        else 
        {
            $result = $aop->Execute($request);
        }
        
        //打開後,將報文寫入log文件
        $this->writeLog("response: ".var_export($result,true));
        return $result;
    }
    //請確保項目文件有可寫權限,不然打印不了日誌。
    function writeLog($text) {
        // $text=iconv("GBK", "UTF-8//IGNORE", $text);
        //$text = characet ( $text );
        file_put_contents ( dirname ( __FILE__ ).DIRECTORY_SEPARATOR."./../../log.txt", date ( "Y-m-d H:i:s" ) . "  " . $text . "\r\n", FILE_APPEND );
    }
}

?>

複製代碼

其他接口暫時用不到,所以在這裏我將其隱去。

 

六.  新建控制器(AlipayController)

php artisan make:controller AlipayController

 

因爲需要實現手機網站支付,所以需要定義支付接口:

複製代碼

<?php

namespace App\Http\Controllers\User\Alipay;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

use App\libs\alipay\wappay\buildermodel\AlipayTradeWapPayContentBuilder;
use App\libs\alipay\wappay\service\AlipayTradeService;

class AlipayWapController extends Controller {

     /**
      *支付接口
     */
    public function alipayWapPay(Request $request) {
        $out_trade_no = getTradeNOString();          //公共方法生成唯一訂單號
        $subject = 'test';                           //數據僅供測試,下同
        $total_amount = 0.01;
        $body = 'test test!';
        $timeout_express="1m";

        $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();

        $result=$payResponse->wapPay($payRequestBuilder,config('alipay.return_url'),config('alipay.notify_url'));


    }

     /**
     *支付同步回調接口,在config/alipay.php的return_url參數進行配置

     */
    public function alipayReturn() {
        
    }

    /**
     *支付異步回調接口,在config/alipay.php的notify_url參數進行配置
     */
    public function alipayNotify() {

    }
}

複製代碼

 

七.  定義路由

定義支付路由及同步和異步回調路由

    Route::group(['prefix' => 'alipay'],function() {
        Route::get('wappay','AlipayWapController@alipayWapPay');
        Route::get('return','AlipayWapController@alipayReturn');
        Route::get('notify','AlipayWapController@alipayNotify');
    });

 

要注意的一點是同步路由是GET形式調用,而異步路由是POST形式調用,在調用支付接口的時候會出現CSRF錯誤,現在最簡單的方法是利用laravel的中間件避免CSRF,在app/Http/Middleware/VerifyCsrfToken.php中增加路由

複製代碼

    protected $except = [
        //
        'alipay/pay',
        'alipay/return',
        'alipay/notify'
    ];

複製代碼

 

八.  修改衝突

這時就可以通過定義路由進行調用支付接口,但是在調用時會報下面這個錯誤:

Cannot redeclare Encrypt() (previously declared in .../vendor/laravel/lumen-framework/src/helpers.php:126)
//或:
Cannot redeclare Decrypt() (previously declared in .../vendor/laravel/lumen-framework/src/helpers.php:126)

 

這是因爲Laravel 5使用Alipay SDK時,Laravel內帶的加密解密函數Encrypt()/Decrypt()函數和Alipay SDK中的加密解密函數Encrypt()/Decrypt()函數命名衝突

解決方法:只需修改Alipay SDK中定義的函數名稱,修改引用的函數名稱。

修改步驟:

    在Alipay SDK中,一共有需要修改三個文件的內容:

aop/AopEncrypt.php

aop/AopClient.php

lotusphp_runtime/Cookie/Cookie.php

 

    在文件中查找encrypt/decrypt替換爲alipayEncrypt/alipayDecrypt即可。

注:如果服務器是在Linux下,可能會報一個沒有權限的錯誤,這是因爲我們之前在SDK包中新建了一個log.txt,在alipay/wappay/service/AlipayTradeService.php中的writeLog()函數中向該文件寫入支付日誌時沒有寫入權限,給它個權限就好了。

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