PHP-Laravel支付寶支付和微信支付

zmxyzmxy1234發表於2022-07-26

支付寶

註冊

首先要註冊兩個平臺賬號,一個是支付寶商戶平臺,一個是支付寶開放平臺,需要企業賬號實名認證,免費。
沒有條件的可以是用支付寶模擬沙箱進行測試。

開發前置
  1. 支付寶開放平臺註冊後,申請一個應用,獲得APPID,例如我要開發一個網站的支付,我就申請一個 網頁/移動應用 的應用。
  2. 支付寶商戶平臺註冊後,獲得商戶ID,然後將前面的APPID與商戶ID繫結。
  3. 支付寶開放平臺設定獲取
    • 金鑰(即:應用私鑰、應用公鑰、支付寶公鑰) ,有兩種,一種是公鑰模式,一種是證照模式,公鑰模式可不上傳證照。
      • 應用閘道器(用來接收支付寶非同步通知資訊)
      • 回撥地址(支付後的回撥,可以設定只驗證域名)。
下載SDK

前往官網下載SDK,支付寶SDK有兩種,一種是通用版,一種是easy版,簡單來說通用版適用於非框架,easy版適用於框架。

  1. 通用版:
    這裡以Laravel為例,放入/app/alipay目錄下(可以隨自己喜歡換別的位置),然後composer.json裡的autoload下classmap里加入一行”app/alipay”來載入SDK:
"classmap": [
      "app/alipay"
]

之後在CMD裡執行composer dump-autoload命令,就可以使用SDK了

composer dump-autoload
  1. easy版:
    執行composer命令
    composer require alipaysdk/easysdk:^2.0
    配置資訊
    在config目錄裡新建一個alipay.php,在裡面配置資訊(在前面的支付寶開放平臺都可以獲取)
<?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",

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

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

        //介面加密key(沒有設定可不用)
        'screct_key' => '',

        //支付寶閘道器
        'gatewayUrl' => "https://openapi.alipay.com/gateway.do",

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

        //日誌路徑
        'log_path' => "",
];

ps:沙箱環境和正式環境閘道器不一樣的

//支付寶正式環境閘道器
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
//支付寶沙箱環境閘道器
'gatewayUrl' => "https://openapi.alipaydev.com/gateway.do",
支付寶支付程式碼

這裡以網站支付為例,可參考SDK文件

  1. 通用版

     $config = config("alipay");
     //商戶訂單號,商戶網站訂單系統中唯一訂單號,必填
     $out_trade_no = time() . mt_rand(1111, 9999);
     //訂單名稱,必填
     $subject = trim("Q幣訂單支付");
    
     //付款金額,必填
     $total_amount = 499;
    
     //商品描述,可空
     $body = "EDG皮膚大禮包";
    
     //構造引數
     $payRequestBuilder = new AlipayTradePagePayContentBuilder();
     $payRequestBuilder->setBody($body);
     $payRequestBuilder->setSubject($subject);
     $payRequestBuilder->setTotalAmount($total_amount);
     $payRequestBuilder->setOutTradeNo($out_trade_no);
    
     $aop = new AlipayTradeService($config);
    
     /**
     * pagePay 電腦網站支付請求
     * @param $builder 業務引數,使用buildmodel中的物件生成。
     * @param $return_url 同步跳轉地址,公網可以訪問
     * @param $notify_url 非同步通知地址,公網可以訪問
     * [[@return](https://learnku.com/users/31554)](https://learnku.com/users/31554) $response 支付寶返回的資訊
     */
     return $aop->pagePay($payRequestBuilder,$config['return_url'],$config['notify_url']);
  2. easy版

    //1. 設定引數(全域性只需設定一次)
             $config = config('alipay');
             $options = new Config();
             $options->protocol = 'https';
             $options->gatewayHost = 'openapi.alipay.com';
             $options->signType = 'RSA2';
    
             $options->appId = $config['app_id'];
    
             // 為避免私鑰隨原始碼洩露,推薦從檔案中讀取私鑰字串而不是寫入原始碼中
             $options->merchantPrivateKey = $config['merchant_private_key'];
             $options->gatewayHost = "openapi.alipaydev.com";
    
             $options->alipayPublicKey = $config['alipay_public_key'];
             //可設定非同步通知接收服務地址(可選)
             $options->notifyUrl = $config['notify_url'];
    
             //可設定AES金鑰,呼叫AES加解密相關介面時需要(可選)
             // $options->encryptKey = $config['screct_key'];
             Factory::setOptions($options);
             try {
                 //2. 發起API呼叫(以支付能力下的統一收單交易建立介面為例)
                 $result = Factory::payment()->page()->pay("iPhone6 16G", "2020423435526001", "88.88", $config['return_url']);
                 return $result->body;
             } catch (Exception $e) {
                 echo "呼叫失敗,". $e->getMessage(). PHP_EOL;;
             }

    其他呼叫方法可以在alipaysdk裡找到API文件進行呼叫,例如手機網站H5支付:

    $result = Factory::payment()->wap()->pay("Q幣充值標題", "訂單號", 88.88, "支付失敗跳轉URL", "支付成功同步跳轉URL");
    return $result->body;
    支付

    支付成功後會跳轉到之前配置的同步GET跳轉URL,然後支付寶會傳送一個POST請求到非同步通知URL。

    $params = $request->all();
    echo '購買成功!';
    支付回撥

    非必需,防止資料洩露被惡意呼叫介面。支付寶驗籤要將所有引數拼接成字串驗籤,所以不要帶入多餘的引數。

  3. 通用版

    $params = $request->all();
    $config = config("alipay");
    $aop = new AlipayTradeService($config);
    $config = config("alipay");
    // 記得去除多餘引數params
    if($aop->check($params))
    {
     echo '驗籤成功';
    }
  4. easy版

    $config = config('alipay');
    $params = $request->all();
    $Signer = new Signer();
    // 記得去除多餘引數params
    $v = $Signer->verifyParams($params, $config['alipay_public_key']);
    if($v)
    {
     echo '驗籤成功';
    }

    微信

    註冊

    註冊微信開放平臺微信商戶平臺。微信商戶需要微信認證(支付300塊錢)。
    註冊完成後獲取資訊

下載SDK

這裡我們直接使用easywechat工具來進行開發,由於我們使用的是Laravel,可以下載easywechat的laravel版本

composer require "overtrue/laravel-wechat:~5.0"
配置檔案

執行命令

php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"

會在config目錄生成wechat.php
修改wechat.php

 /*
     * 微信支付
     */
    'payment' => [
        'default' => [
            'sandbox'            => env('WECHAT_PAYMENT_SANDBOX', false),
            'app_id'             => env('WECHAT_PAYMENT_APPID', '你的appid'),
            'mch_id'             => env('WECHAT_PAYMENT_MCH_ID', '你的商戶ID'),
            'key'                => env('WECHAT_PAYMENT_KEY', '你的key'),
            'cert_path'          => env('WECHAT_PAYMENT_CERT_PATH', '/cert/apiclient_cert.pem'),    // XXX: 絕對路徑!!!!
            'key_path'           => env('WECHAT_PAYMENT_KEY_PATH', '/cert/apiclient_key.pem'),      // XXX: 絕對路徑!!!!
            'notify_url'         => 'http://www.baidu.com',                           // 預設支付結果通知地址
        ],
        // ...
    ],
支付程式碼
型別

注意金額欄位total_fee的數是要*100的,比如1塊錢應該寫100,trade_type型別是支付方式,其他方式為:

JSAPI–JSAPI支付(或小程式支付)、NATIVE–Native支付、APP–app支付,MWEB–H5支付,不同trade_type決定了調起支付的方式,請根據支付產品正確上傳

掃碼支付
$config = config('wechat.payment.default');
        $app = Factory::payment($config);
        $result = $app->order->unify([
            'body' => 'Q幣微信支付',
            'out_trade_no' => 隨機生成的訂單號,
            'total_fee' => 1 * 100,
            'trade_type' => 'NATIVE', // 請對應換成你的支付方式對應的值型別
        ]);
        $result['total'] = $data['total'];

        return $result;

這裡我使用的是Native支付,會返回一個二維碼,SDK 並不內建二維碼生成庫,使用你熟悉的工具建立二維碼即可,比如 PHP 部分有以下工具可以選擇

H5支付
$config = config('wechat.payment.default');
        $app = Factory::payment($config);
        $result = $app->order->unify([
            'body' => 'Q幣微信支付',
            'out_trade_no' => 隨機生成的訂單號,
            'total_fee' => 1 * 100,
            'trade_type' => 'MWEB', // 請對應換成你的支付方式對應的值型別
        ]);
        $result['total'] = $data['total'];

        return redirect($result['mweb_url']);

這個是在非微信瀏覽器下進行的H5支付,如果要進行微信內部瀏覽器H5支付,需要使用JSSDK支付。

JSSDK支付
  1. 先申請公眾號,然後配置公眾號資訊
 /*
     * 公眾號
     */
    'official_account' => [
        'default' => [
            'app_id'  => env('WECHAT_OFFICIAL_ACCOUNT_APPID', '你的AppID'),         // AppID
            'secret'  => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', '你的secret'),    // AppSecret
            'token'   => env('WECHAT_OFFICIAL_ACCOUNT_TOKEN', '你的token'),           // Token
            'aes_key' => env('WECHAT_OFFICIAL_ACCOUNT_AES_KEY', '你的aes加密key')
            ]
    ]
  1. 用介面獲取openid。這裡使用easywechat封裝好的user()方法獲取openid,先透過authorize介面獲取code,然後透過code獲取openid,之後可以考慮將openid存在session裡,或者資料庫等其他地方。
if ($request->has('code'))
{
    $config = config('wechat.official_account.default');
    $c = \EasyWeChat\Factory::officialAccount($config);
    $rs = $c->oauth->user();
    return redirect("你的訂單頁面?openid=" . $rs['original']['openid']);
}
// 獲取code
$currentUrl = urlencode(url()->current());
$url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe96b27ac2a780cb1&redirect_uri={$currentUrl}&response_type=code&scope=snsapi_base&state=STATE&connect_redirect=1#wechat_redirect";
return redirect($url);
  1. 用前面獲取的openid去下單,然後這裡有三種js支付方式:WeixinJSBridge, JSSDK, 小程式
$config = config('wechat.payment.default');
$app = \EasyWeChat\Factory::payment($config);

$result = $app->order->unify([
    'body' => 'Q幣訂單微信支付',
    'out_trade_no' => 隨機生成的訂單號,
    'total_fee' => 1 * 100,
    'trade_type' => 'JSAPI', // 請對應換成你的支付方式對應的值型別
    'openid' => $openid,
]);
// 未完待續
  1. WeixinJSBridge
    PHP

     $json = $jssdk->bridgeConfig($prepayId); // 返回 json 字串,如果想返回陣列,傳第二個引數 false

    JavaScript

    
     WeixinJSBridge.invoke(
            'getBrandWCPayRequest', $json,
            function(res){
                if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                     // 使用以上方式判斷前端返回,微信團隊鄭重提示:
                     // res.err_msg將在使用者支付成功後返回
                     // ok,但並不保證它絕對可靠。
                }
            }
        );
  2. JSSDK
    PHP

    $config = $jssdk->sdkConfig($prepayId); // 返回陣列

    JavaScript

    wx.chooseWXPay({
        timestamp: <?= $config['timestamp'] ?>,
        nonceStr: '<?= $config['nonceStr'] ?>',
        package: '<?= $config['package'] ?>',
        signType: '<?= $config['signType'] ?>',
        paySign: '<?= $config['paySign'] ?>', // 支付簽名
        success: function (res) {
            // 支付成功後的回撥函式
        }
    });
  3. 小程式

    PHP

    $config = $jssdk->bridgeConfig($prepayId, false); // 返回陣列

    JavaScript

    wx.requestPayment({
        timeStamp: <?= $config['timeStamp'] ?>, //注意 timeStamp 的格式
        nonceStr: '<?= $config['nonceStr'] ?>',
        package: '<?= $config['package'] ?>',
        signType: '<?= $config['signType'] ?>',
        paySign: '<?= $config['paySign'] ?>', // 支付簽名
        success: function (res) {
            // 支付成功後的回撥函式
        }
    });
支付回撥

微信支付成功後會有一個支付回撥,這裡返回的是XML,需要解析才能使用

$xml = $request->getContent();
$param = (array)simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
echo 'Q幣充值成功';
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章