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

PHP 串接支付寶支付介面完整實作指南

     編輯:PHP 相關知識

前言:電商支付整合的關鍵步驟

隨著網購普及,支付寶成為台灣/大陸電商不可或缺的支付方式。本文提供從申請商戶、簽名驗證、訂單建立、回調處理到退款流程的完整 PHP 實作指南(基於支付寶開放平台標準介面)。

前置準備

  1. 註冊支付寶開放平台開發者帳號,完成實名認證
  2. 創建應用,獲得 AppID、應用私鑰、支付寶公鑰
  3. 配置簽名方式:RSA2 (SHA256)(推薦,安全性最高)
  4. 設定同步回調 return_url、非同步通知 notify_url

核心 SDK 封裝(簡易版)

<?php
namespace App\Payment;

class Alipay {
    private $config;

    public function __construct(array $config) {
        $this->config = array_merge([
            'gateway' => 'https://openapi.alipay.com/gateway.do',
            'charset' => 'UTF-8',
            'sign_type' => 'RSA2',
            'format' => 'JSON',
        ], $config);
    }

    // 產生待簽名字串
    private function getSignContent(array $params): string {
        ksort($params);
        $str = '';
        foreach ($params as $k => $v) {
            if ($v !== '' && $k !== 'sign') {
                $str .= "$k=$v&";
            }
        }
        return rtrim($str, '&');
    }

    // RSA2 簽名
    private function sign(string $data): string {
        $privateKey = "-----BEGIN PRIVATE KEY-----\n" .
                      wordwrap($this->config['private_key'], 64, "\n", true) .
                      "\n-----END PRIVATE KEY-----";
        $res = openssl_get_privatekey($privateKey);
        openssl_sign($data, $signature, $res, OPENSSL_ALGO_SHA256);
        openssl_free_key($res);
        return base64_encode($signature);
    }

    // 驗證支付寶回調簽名
    public function verify(array $params): bool {
        $sign = $params['sign'] ?? '';
        unset($params['sign'], $params['sign_type']);
        $content = $this->getSignContent($params);
        $publicKey = "-----BEGIN PUBLIC KEY-----\n" .
                     wordwrap($this->config['alipay_public_key'], 64, "\n", true) .
                     "\n-----END PUBLIC KEY-----";
        $res = openssl_get_publickey($publicKey);
        $ok = openssl_verify($content, base64_decode($sign), $res, OPENSSL_ALGO_SHA256);
        openssl_free_key($res);
        return $ok === 1;
    }

    // 建立表單自動提交(頁面支付)
    public function buildForm(string $method, array $bizContent): string {
        $params = [
            'app_id'     => $this->config['app_id'],
            'method'     => $method,
            'charset'    => $this->config['charset'],
            'sign_type'  => $this->config['sign_type'],
            'timestamp'  => date('Y-m-d H:i:s'),
            'version'    => '1.0',
            'biz_content'=> json_encode($bizContent, JSON_UNESCAPED_UNICODE),
            'notify_url' => $this->config['notify_url'],
            'return_url' => $this->config['return_url'],
        ];
        $params['sign'] = $this->sign($this->getSignContent($params));

        $html = '<form id="alipay_form" action="' . $this->config['gateway'] . '" method="POST">';
        foreach ($params as $k => $v) {
            $html .= '<input type="hidden" name="' . $k . '" value="' . htmlspecialchars($v) . '">';
        }
        $html .= '</form><script>document.getElementById("alipay_form").submit();</script>';
        return $html;
    }
}

實作:電腦網站支付

<?php
require 'Alipay.php';

$config = [
    'app_id'           => '202100xxxxxx',
    'private_key'      => 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD...',
    'alipay_public_key'=> 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...',
    'notify_url'       => 'https://yourdomain.com/alipay/notify',
    'return_url'       => 'https://yourdomain.com/alipay/return',
];

$alipay = new Alipay($config);

$bizContent = [
    'out_trade_no' => 'ORDER_' . date('YmdHis') . rand(1000,9999),
    'total_amount' => '99.00',
    'subject'      => '測試商品 - PHP 整合支付寶',
    'product_code' => 'FAST_INSTANT_TRADE_PAY',
];

echo $alipay->buildForm('alipay.trade.page.pay', $bizContent);

非同步通知處理

<?php
// notify.php
require 'Alipay.php';
$alipay = new Alipay($config);

if ($alipay->verify($_POST)) {
    $tradeStatus = $_POST['trade_status'] ?? '';
    $outTradeNo  = $_POST['out_trade_no'] ?? '';

    if (in_array($tradeStatus, ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
        // 1. 驗證金額、商戶單號是否符合預期
        // 2. 更新訂單狀態為「已付款」
        // 3. 發送確認通知、發貨邏輯
        // 4. 記錄日誌
        file_put_contents('alipay_notify.log', date('c') . " SUCCESS: $outTradeNo\n", FILE_APPEND);
    }
    echo 'success'; // 必須輸出 success,否則支付寶會重試通知
} else {
    file_put_contents('alipay_notify.log', date('c') . " VERIFY FAIL\n", FILE_APPEND);
    echo 'fail';
}

同步回調處理

<?php
// return.php
require 'Alipay.php';
$alipay = new Alipay($config);

if ($alipay->verify($_GET)) {
    echo "支付成功!訂單號: " . htmlspecialchars($_GET['out_trade_no']);
    // 此處僅做頁面提示,實際訂單狀態以非同步通知為準
} else {
    echo "簽名驗證失敗,請聯繫客服";
}

退款介面範例

$refundResult = $alipay->execute('alipay.trade.refund', [
    'out_trade_no' => 'ORDER_202401151200001234',
    'refund_amount' => '50.00',
    'refund_reason' => '客戶申請部分退款',
]);
// 解析 $refundResult 判斷退款是否成功

安全與最佳實踐清單

  • ✅ 私鑰絕不提交至版本控制,使用環境變數或密鑰管理系統
  • ✅ 簽名驗證必須在伺服器端進行,前端不可信
  • ✅ 非同步通知需冪等處理(防重複通知導致多次發貨)
  • ✅ 金額驗證:通知中的 total_amount 必須與訂單金額一致
  • ✅ 使用 HTTPS 確保傳輸加密
  • ✅ 定期輪換金鑰,關注支付寶公告更新

結語

支付寶介面整合核心在於「簽名驗證」與「非同步通知冪等處理」。建議生產環境直接使用官方 alipay-sdk-php,減少造輪子風險。本文提供的簡易封裝適合學習原理或輕量專案參考。

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