首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 接入支付寶即時到賬:從表單提交到異步通知驗證完整代碼

     編輯:PHP 綜合知識

支付寶即時到賬接入的最小可行代碼集:前端表單、配置文件、同步跳轉頁、異步通知驗證頁。基於官方 PHP SDK,精簡去冗餘,適合快速集成到現有項目。

1. 前端支付表單(自動提交)

2. 核心配置 alipay.config.php

$alipay_config = [
    'partner'       => '2088xxxxxxxxxxxx',  // PID
    'seller_id'     => '2088xxxxxxxxxxxx',  // 收款賬號
    'key'           => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // MD5密鑰
    'sign_type'     => 'MD5',
    'input_charset' => 'utf-8',
    'cacert'        => getcwd() . '/cacert.pem',
    'transport'     => 'https',             // 強制HTTPS
    'notify_url'    => 'https://your.com/pay/notify_url.php', // 異步通知(關鍵)
    'return_url'    => 'https://your.com/pay/return_url.php', // 同步跳轉
    'service'       => 'create_direct_pay_by_user',
    'payment_type'  => '1',
];

3. 異步通知驗證 notify_url.php(業務邏輯核心)

require_once "alipay.config.php";
require_once "lib/alipay_notify.class.php";

$alipayNotify = new AlipayNotify($alipay_config);
$verifyResult = $alipayNotify->verifyNotify(); // 簽名驗證 + 遠程驗證 notify_id

if ($verifyResult) {
    $outTradeNo = $_POST['out_trade_no'];
    $tradeNo    = $_POST['trade_no'];
    $tradeStatus = $_POST['trade_status'];
    $totalFee   = $_POST['total_fee'];
    
    // 解析擴展參數
    $extra = $_POST['extra_common_param'] ?? '';
    [$uid, $code, $tags] = explode('.', $extra);
    
    if (in_array($tradeStatus, ['TRADE_FINISHED', 'TRADE_SUCCESS'])) {
        // 幂等性檢查
        $order = Order::where('order_sn', $outTradeNo)->first();
        if ($order && $order->status === 'pending') {
            DB::transaction(function() use ($order, $tradeNo, $totalFee, $uid, $code, $tags) {
                $order->update([
                    'status' => 'paid',
                    'trade_no' => $tradeNo,
                    'paid_at' => now(),
                    'pay_amount' => $totalFee,
                ]);
                // 觸發業務事件
                event(new OrderPaid($order, $uid, $code, $tags));
            });
        }
    }
    echo 'success'; // 必須輸出 success 結束通知
} else {
    Log::error('Alipay verify failed', $_POST);
    echo 'fail';
}

4. 同步跳轉 return_url.php(僅展示)

require_once "alipay.config.php";
require_once "lib/alipay_notify.class.php";

$alipayNotify = new AlipayNotify($alipay_config);
$verifyResult = $alipayNotify->verifyReturn(); // 僅驗證簽名

if ($verifyResult && in_array($_GET['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
    $outTradeNo = $_GET['out_trade_no'];
    $totalFee   = $_GET['total_fee'];
    $extra = $_GET['extra_common_param'] ?? '';
    [$uid, $code, $tags] = explode('.', $extra);
    
    // 跳轉到業務訂單詳情頁
    header("Location: /user/order/$outTradeNo?pay_success=1&uid=$uid&code=$code&tags=$tags&amount=$totalFee");
    exit;
} else {
    header("Location: /pay/failed?msg=" . urlencode('支付驗證失敗'));
    exit;
}

5. alipayapi.php 入口(構造請求並跳轉)

require_once "alipay.config.php";
require_once "lib/alipay_submit.class.php";

$parameter = [
    'service'           => $alipay_config['service'],
    'partner'           => $alipay_config['partner'],
    'seller_id'         => $alipay_config['seller_id'],
    'payment_type'      => $alipay_config['payment_type'],
    'notify_url'        => $alipay_config['notify_url'],
    'return_url'        => $alipay_config['return_url'],
    '_input_charset'    => $alipay_config['input_charset'],
    'out_trade_no'      => $_POST['WIDout_trade_no'],
    'subject'           => $_POST['WIDsubject'],
    'total_fee'         => $_POST['WIDtotal_fee'],
    'body'              => $_POST['WIDbody'],
    'show_url'          => 'https://your.com/order/' . $_POST['WIDout_trade_no'],
    'extra_common_param' => $_POST['uid'] . '.' . $_POST['codes'] . '.' . $_POST['tags'],
];

$alipaySubmit = new AlipaySubmit($alipay_config);
$html = $alipaySubmit->buildRequestForm($parameter, 'post', '正在跳轉...');
echo $html; // 輸出自動提交表單 HTML

關鍵避坑提醒

  1. notify_url/return_url 必須外網 HTTPS 可訪問,本地測試用 ngrok/frp 映射
  2. 異步通知才是訂單狀態最終依據,同步頁面只做展示跳轉
  3. 幂等性:訂單狀態機 pending → paid,僅 pending 可轉 paid
  4. 金額用分(int)存儲或 BCMath 比較,避免 float 精度問題
  5. Key 僅存環境變量,代碼不硬編碼,防洩露
  6. 完整記錄通知日誌(原始 POST + 驗證結果 + 處理結果),備查糾紛

升級 RSA2 簽名(推薦)

  • 生成應用公私鑰:openssl genrsa -out app_private_key.pem 2048 → openssl rsa -in app_private_key.pem -pubout -out app_public_key.pem
  • 支付寶開放平台上傳公鑰,獲取支付寶公鑰
  • 配置:'sign_type' => 'RSA2', 'private_key_path' => '...', 'alipay_public_key_path' => '...'
  • SDK 內部自動使用 openssl_sign/verify,業務代碼無需修改

這套代碼結構清晰、職責單一,可直接複製到項目 /pay 目錄,修改配置即可運行。建議將驗證/業務處理封裝為 AlipayService,控制器僅做調度。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved