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

DedeCMS 整合財付通支付接口完整實現代碼

     編輯:PHP 綜合知識

背景

DedeCMS (織夢) 旅遊網站需接入騰訊財付通 (Tenpay) 支付。官方無現成模組,自行封裝 tenpay 類放入 include/payment/ 目錄,配合會員中心訂單流程。

核心類結構

<?php
if (!defined('DEDEINC')) exit('Request Error!');

class tenpay {
    var $dsql;
    var $mid;
    var $return_url = '/plus/carbuyaction.php?dopost=return'; // 回調入口

    function __construct() {
        global $dsql;
        $this->dsql = $dsql;
    }

    // 設定回調地址(可選)
    function SetReturnUrl($url) {
        if ($url) $this->return_url = $url;
    }

    // 生成支付按鈕/表單
    function GetCode($order, $payment) {
        global $cfg_basehost, $cfg_cmspath;
        if ($cfg_cmspath) $cfg_basehost .= '/' . $cfg_cmspath;

        $partner = $payment['tenpay_account'];
        $outTradeNo = $order['out_trade_no'];
        $totalFee = floatval($order['price']) * 100; // 分
        $body = $order['out_trade_no'];
        $bankType = 'DEFAULT';
        $transType = 1; // 1 實物 2 虛擬
        $tradeMode = $payment['tenpay_pay_method'] ?? '1';

        $params = [
            'partner' => $partner,
            'out_trade_no' => $outTradeNo,
            'total_fee' => $totalFee,
            'notify_url' => $cfg_basehost . $this->return_url . "&code={$payment['code']}",
            'return_url' => $cfg_basehost . $this->return_url . "&code={$payment['code']}",
            'body' => $body,
            'bank_type' => $bankType,
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
            'fee_type' => '1',
            'subject' => $body,
            'sign_type' => 'MD5',
            'service_version' => '1.0',
            'input_charset' => 'UTF-8',
            'sign_key_index' => '1',
            'attach' => '',
            'product_fee' => '',
            'transport_fee' => '0',
            'time_start' => date('YmdHis'),
            'time_expire' => '',
            'buyer_id' => '',
            'goods_tag' => '',
            'trade_mode' => $tradeMode,
            'transport_desc' => '',
            'trans_type' => $transType,
            'agentid' => '',
            'agent_type' => '',
            'seller_id' => '',
        ];

        ksort($params);
        $signStr = '';
        $urlParams = '';
        foreach ($params as $k => $v) {
            $urlParams .= "$k=" . urlencode($v) . "&";
            if ($v !== '' && $k !== 'sign') $signStr .= "$k=$v&";
        }
        $signStr .= "key={$payment['tenpay_key']}";
        $sign = strtolower(md5($signStr));
        $urlParams = rtrim($urlParams, '&');

        $btn = '<div style="text-align:center"><a href="https://gw.tenpay.com/gateway/pay.htm?' . $urlParams . '&sign=' . $sign . '"><button>立即使用財付通支付</button></a></div>';

        // 清空購物車(Dede 內建類)
        require_once DEDEINC . '/shopcar.class.php';
        $cart = new MemberShops();
        $cart->clearItem();
        $cart->MakeOrders();

        return $btn;
    }

    // 回調處理
    function respond() {
        $code = preg_replace('#[^0-9a-z-]#i', '', $_GET['code'] ?? '');
        require_once DEDEDATA . "/payment/$code.php"; // 載入該支付方式配置(含 tenpay_key)

        $attach = $_GET['attach'] ?? '';
        $tradeState = $_GET['trade_state'] ?? '';
        $totalFee = $_GET['total_fee'] ?? 0;
        $outTradeNo = trim($_GET['out_trade_no'] ?? '');

        // 驗證訂單號格式(示例:S-P123RN4)
        if (!preg_match('/S-P\d+RN\d+/', $outTradeNo)) return '訂單號格式錯誤';

        // 核對金額
        $row = $this->dsql->GetOne("SELECT * FROM `#@__shops_orders` WHERE oid = '$outTradeNo'");
        if (!$row || $row['priceCount'] != $totalFee) return '支付金額不符';

        $this->mid = $row['userid'];

        // 驗證簽名
        ksort($_GET);
        $signStr = '';
        foreach ($_GET as $k => $v) {
            if ($v !== '' && $k !== 'sign' && $k !== 'code') $signStr .= "$k=$v&";
        }
        $signStr .= "key={$payment['tenpay_key']}";
        $calcSign = strtolower(md5($signStr));

        if ($calcSign !== strtolower($_GET['sign'] ?? '')) return '簽名驗證失敗';

        if ($tradeState == '0') { // 成功
            if ($this->success_db($outTradeNo)) {
                return "支付成功!<br><a href='/'>返回首頁</a> <a href='/member'>會員中心</a>";
            } else {
                return "支付失敗!<br><a href='/'>返回首頁</a>";
            }
        }
        return '交易狀態異常';
    }

    // 更新訂單狀態
    function success_db($orderSn) {
        $sql = "UPDATE `#@__shops_orders` SET `state`=1 WHERE `oid`='$orderSn' AND `userid`='{$this->mid}'";
        if ($this->dsql->ExecuteNoneQuery($sql)) {
            $this->log_result("verify_success,訂單號:$orderSn");
            return true;
        }
        $this->log_result("verify_failed,訂單號:$orderSn");
        return false;
    }

    function log_result($msg) {
        $fp = fopen(dirname(__FILE__) . "/../../data/payment/log.txt", 'a');
        flock($fp, LOCK_EX);
        fwrite($fp, "$msg,執行時間:" . date('Y-m-d H:i:s') . "\r\n");
        flock($fp, LOCK_UN);
        fclose($fp);
    }
}

配置步驟

  1. 將上述代碼存為 include/payment/tenpay.php。
  2. 後台 → 模組 → 支付方式 → 新增 → 選擇「財付通」,填入商戶號、密鑰、支付模式 (1 即時到帳 / 2 擔保)。
  3. 確保 data/payment/ 目錄可寫入日誌。
  4. 測試:前台下單選擇財付通 → 跳轉騰訊網關 → 支付成功 → 回調 carbuyaction.php?dopost=return&code=tenpay → 更新訂單狀態。

安全加固建議

  • 回調驗證 務必 核對 sign、total_fee、out_trade_no 三要素。
  • 使用 notify_url (服務器間通知) 作為最終以準,return_url 僅作頁面跳轉提示。
  • 日誌記錄完整請求參數,便於對帳排查。
  • 財付通已升級為「微信支付商業版」,新項目建議直接接入 微信支付 V3 API,本代碼僅供維舊專案參考。

總結

DedeCMS 整合財付通核心在於:GetCode() 組裝簽名跳轉網關,respond() 驗證回調簽名並更新訂單。代碼遵循 Dede 支付模組規範,可直接放入 include/payment/ 使用。新專案請改用微信支付/支付寶官方 SDK。

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