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

PHP 對接交通銀行網銀支付:Socket 通信模式完整實現

     編輯:PHP 綜合知識

交通銀行 B2C 支付接口開發指南

交通銀行網銀支付與支付寶等聚合支付最大不同在於:核心加密/簽名邏輯由 Java 實現,PHP 需通過 Socket 與 Java 服務端通信。官方提供兩種模式:Socket 通信與 Java Bridge,本文採用前者。

環境部署

  1. 安裝 JDK:Oracle 官網下載,配置 JAVA_HOME 與 PATH
  2. 導入測試證書:
    keytool -import -keystore "C:\Program Files\Java\jre1.5\lib\security\cacerts" \
    -storepass changeit -alias test_bocommca -file "C:\socket\cert\test_root.cer"
  3. 修改配置:in/B2CMerchantSocket.xml,測試商號可不改
  4. 啟動 Socket 服務:
    • Windows:雙擊 start.bat
    • Linux:nohup sh start.sh & 後台運行

MVC 架構整合

1. 配置文件

$config['interfaceVersion'] = "1.0.0.0";
$config['tranType'] = 0; // B2C
$config['curType'] = 'CNY';
$config['notifyType'] = 1; // 主動通知
$config['merURL'] = "/pay/notify";
$config['goodsURL'] = '/goods/1.html';
$config['jumpSeconds'] = 3;
$config['socketUrl'] = "tcp://127.0.0.1:8891";
$config['merID'] = '301310063009501';

2. Model 層:支付與通知驗證

class Bocom extends CI_Model {
    private $arrReturn = [];
    private $socket;

    public function __construct() {
        parent::__construct();
        $this->config->load('bocom');
        $this->socket = $this->config->item('socketUrl');
    }

    // 發起支付
    public function pay($arr_data) {
        // 組裝報文數據...
        $source = implode('|', array_slice($this->arrReturn, 0, -1));
        
        $fp = stream_socket_client($this->socket, $errno, $errstr, 30);
        if (!$fp) return false;

        $in = "";
        $in .= "cb2200_sign";
        $in .= "$source";
        
        fwrite($fp, $in);
        $retMsg = '';
        while (!feof($fp)) $retMsg .= fgets($fp, 1024);
        fclose($fp);

        return $this->xmlParse($retMsg);
    }

    // 異步通知驗證
    public function notify() {
        if (!isset($_REQUEST['notifyMsg'])) return false;
        $notifyMsg = $_REQUEST["notifyMsg"];
        
        // 分離簽名與原文
        $lastIndex = strripos($notifyMsg, "|");
        $signMsg = substr($notifyMsg, $lastIndex + 1);
        $srcMsg = substr($notifyMsg, 0, $lastIndex + 1);

        // 發送驗證請求至 Java 端
        $fp = stream_socket_client($this->socket, $errno, $errstr, 30);
        $in = "";
        $in .= "cb2200_verify";
        $in .= "{$this->config->item('merID')}";
        $in .= "$notifyMsg";
        
        fwrite($fp, $in);
        $retMsg = '';
        while (!feof($fp)) $retMsg .= fgets($fp, 1024);
        fclose($fp);

        // 解析驗證結果
        $dom = new DOMDocument;
        $dom->loadXML($retMsg);
        $retCode = $dom->getElementsByTagName('retCode')->item(0)->nodeValue;
        
        if ($retCode != '0') return false;
        
        $arr = preg_split("/\|/", $srcMsg);
        return $arr[9] == "1" ? $this->updateBill($arr[1]) : false;
    }

    private function xmlParse($retMsg) { /* 解析 XML 返回陣列 */ }
    private function updateBill($billNo) { /* 更新訂單狀態 */ }
}

3. Controller 層調用

$this->load->model("Bocom");
// 支付
$this->arrData = $this->Bocom->pay($this->data);
// 通知
$this->arrData = $this->Bocom->notify();

關鍵技術點

  • 編碼轉換:銀行接口要求 GB2312,PHP 內部 UTF-8 需 iconv 轉換
  • 報文格式:管道符 | 分隔字段,末尾附加簽名
  • Socket 通信:使用 stream_socket_client 長連接,需處理超時與異常
  • 證書管理:Java 端依賴 cacerts 存儲根證書,過期需更新

常見問題排查

  1. 連接失敗:檢查 Java 服務是否啟動、端口是否被佔用、防火牆規則
  2. 簽名驗證失敗:確認證書導入正確、編碼一致、報文字段順序無誤
  3. 中文亂碼:全鏈路統一 GB2312,避免雙向轉換丟失字符
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved