1. 程式人生 > >PHP中整合PayPal標準支付(非form提交方式)

PHP中整合PayPal標準支付(非form提交方式)

需求

老闆:咱們公司想打歐美市場,線上支付這一塊再用支付寶和微信就不合適了,你找一個比較適合國外人的支付方式,把他們的錢裝進咱們公司的口袋裡; 經過深思熟慮和多出調研;paypal是最適合國際市場的一種支付方式

在這裡插入圖片描述

概述

paypal官網:https://www.paypal.com/ PayPal是eBay旗下的一家公司,致力於讓個人或企業通過電子郵件,安全、簡單、便捷地實現線上付款和收款。PayPal賬戶是PayPal公司推出的最安全的網路電子賬戶,使用它可有效降低網路欺詐的發生。PayPal賬戶所整合的高階管理功能,使您能輕鬆掌控每一筆交易詳情。截止2017年,在跨國交易中超過90%的賣家和超過85%的買家認可並正在使用PayPal電子支付業務。全球使用者廣 ,PayPal在全球190國家和地區;實時交易,即時到賬;支援美元、歐元、英鎊等20多種貨幣付款;安全保障高,使用成本低。

實現方式

本文以語言PHP,框架laravel為例 srmklive/paypal外掛

1.使用composer命令安裝:

composer require srmklive/paypal

2. 將服務提供程式新增到檔案中的$providers陣列,config/app.php下

Srmklive \ PayPal \ Providers \ PayPalServiceProvider :: class

將別名新增到檔案中的$aliases陣列,config/app.php:

' PayPal '  =>  Srmklive \ PayPal \ Facades \ PayPal :: class

3. 執行php artisan命令生成config配置檔案:

php artisan vendor:publish --provider "Srmklive\PayPal\Providers\PayPalServiceProvider"

config/paypal.php 檔案內容

return [
    'mode'    => 'live',//只能是'sandbox'或'live'。如果為空或無效,將使用“live”。
    'sandbox' => [
        'username'    => env('PAYPAL_SANDBOX_API_USERNAME', ''), 
        'password'    => env('PAYPAL_SANDBOX_API_PASSWORD', ''),
        'secret'      => env('PAYPAL_SANDBOX_API_SECRET', ''),
        'certificate' => env('PAYPAL_SANDBOX_API_CERTIFICATE', ''),
        'app_id'      => 'APP-80W284485P519543T',//用於測試沙盒模式下的自適應支付API 
    ],
    'live' => [
        'username'    => env('PAYPAL_LIVE_API_USERNAME', ''),
        'password'    => env('PAYPAL_LIVE_API_PASSWORD', ''),
        'secret'      => env('PAYPAL_LIVE_API_SECRET', ''),
        'certificate' => env('PAYPAL_LIVE_API_CERTIFICATE', ''),
        'app_id'      => '',//用於自適應付款API
    ],
    'payment_action' => 'Sale', // 只能為 'Sale', 'Authorization' ,'Order'
    'currency'       => 'TWD',   //預設幣種 臺灣幣
    'billing_type'   => '',      //如果僅僅使用及時支付,這裡為空
    'notify_url'     => '', // Change this accordingly for your application.
    'locale'         => '', //強制閘道器語言即it_IT,es_ES,en_US ...(僅限快速結賬)
    'validate_ssl'   => true,//建立api客戶端時驗證SSL
];

將此新增到.env.example和.env

#沙盒環境
PAYPAL_SANDBOX_API_USERNAME=
PAYPAL_SANDBOX_API_PASSWORD=
PAYPAL_SANDBOX_API_SECRET=
PAYPAL_SANDBOX_API_CERTIFICATE=
#真實環境
PAYPAL_LIVE_API_USERNAME=
PAYPAL_LIVE_API_PASSWORD=
PAYPAL_LIVE_API_SECRET=
PAYPAL_LIVE_API_CERTIFICATE=

訂單支付邏輯程式碼

獲取訂單資料

訂單單個商品金額*商品個數+其他商品金額一定要等於總金額

   public function getCart()
   {
       $data = [];
       $data['items'] = [
           [
               'name' => 'Product 1',//商品名稱
               'price' => 9.99,      //商品價格
               'qty' => 1            //商品個數
           ],
           [
               'name' => 'Product 2',//商品名稱
               'price' => 4.99,      //商品價格
               'qty' => 2            //商品個數
           ]
       ];
       $data['invoice_id'] = 1; //訂單id
       $data['invoice_description'] = "Order #{$data['invoice_id']} Invoice";//訂單描述
       $data['return_url'] = url('/expressCheckoutSuccess');//統一下單成功,跳轉地址
       $data['cancel_url'] = url('/paypal_send?order_id='.$data['invoice_id'].);//下單失敗,跳轉地址

        $total = 0;
        foreach($data['items'] as $item) {
        $total += $item['price']*$item['qty'];
        }
        $data['total'] = $total;//訂單總額
       return $data;
   }

paypal下單

如果在下單時,如果在setExpressCheckout方法前設定支付幣種,一定要在doExpressCheckoutPayment方法之前也設定幣種,不然執行do方法會走預設幣種,幣種不統一,報錯

$data = $this->getCart();
$this->provider->setCurrency('USD')->setExpressCheckout($data); //設定paypal支付幣種(可以使用config中的預設)
$response = $provider->setExpressCheckout($data);//設定引數,獲取paypal連結(及時支付)
//$response = $provider->setExpressCheckout($data, true); //在建立定期付款配置檔案(訂閱)時使用以下行
return redirect($response['paypal_link']);//使用者重定向到PayPal的url地址 

訂單成功頁

   public function expressCheckoutSuccess(Request $request)
   {
        $token = $request->get('token');
        $PayerID = $request->get('PayerID');//支付者paypalid
        $response = $this->provider->getExpressCheckoutDetails($token);//解析回撥資料
        if (!in_array(strtoupper($response['ACK']), ['SUCCESS', 'SUCCESSWITHWARNING'])) {
            $invoice_id = explode('_', $response['INVNUM'])[1];
            try{
                 $order=\App\order::where('order_id',$invoice_id)->update(['order_type'=>'12']);
                }catch(Exception $e){
                }
            return redirect('/endfail')->with(['type' =>'0']);
        }
       $invoice_id = explode('_', $response['INVNUM'])[1];//獲取資料庫訂單表中訂單號
       $cart = $this->getCart();//獲取發起請求時組裝的引數
       $this->provider->setCurrency('USD')->setExpressCheckout($cart);//設定幣種
        //二次驗證回撥資料
        $payment_status = $this->provider->doExpressCheckoutPayment($cart, $token, $PayerID);
        if (!in_array(strtoupper($payment_status['ACK']), ['SUCCESS', 'SUCCESSWITHWARNING'])) {
            $invoice_id = explode('_', $response['INVNUM'])[1];
            try{
                 $order=\App\order::where('order_id',$invoice_id)->update(['order_type'=>'12']);
                }catch(Exception $e){
                }
            return redirect('/endfail?type=0');//訂單失敗
        }
        //處理訂單資料,儲存下單資訊
        ........
      return redirect("/endsuccess?type=1&goods_id={$goods_id}&order_id={$order_id}");//訂單成功   
   }

訂單失敗

   public function paypal_send()
   {
       $order_id = $_GET['order_id'];
       $msg=\App\order::where('order_id',$order_id)->first()['order_type'];
       $order = order::where('order_id', $order_id)->delete();
       return redirect('/pay');
   }

好了,今天的paypal分享就到這裡了,已經基本實現paypal的及時線上支付功能,程式碼中getCart()方法為假資料,如果真實情況開發需要訂單表提供真實資料,希望能幫到來參觀的道友,加油