ThinkPHP 2.x 開啟 URL_MODEL=2(PATHINFO 模式)隱藏 index.php 後,第三方回調(如支付寶)帶有 ? 參數的 URL 會被框架錯誤重寫,導致 404。本文提供在入口檔案層面動態切換 URL 模式的解決方案。
支付寶回調原始 URL:
https://www.xxx.com/index.php/alipay/callback/?is_success=T&sign_type=MD5¬ify_id=RqPnCoPT3K9...
框架重寫後(錯誤):
https://www.xxx.com/alipay/callback/is_success/T/sign_type/MD5/notify_id/RqPnCoPT3K9...
重寫後的 URL 無法正確路由到控制器/方法,導致回調失敗。
<?php
// index.php - 專案入口檔案
// 定義框架路徑
define('THINK_PATH', '你的ThinkPHP框架目錄/');
// 定義專案名稱與路徑
define('APP_NAME', 'home');
define('APP_PATH', 'home');
// 【關鍵】在框架啟動前,根據請求 URI 動態調整配置
// 1. 若為支付寶回調,刪除配置快取並建立標記檔
if (strstr($_SERVER['REQUEST_URI'], 'alipay/callback/') ||
strstr($_SERVER['REQUEST_URI'], 'order.return_pay')) {
// 刪除編譯快取(~app.php 包含 URL_MODEL 配置)
$runtimePath = './home/Runtime/~app.php';
if (file_exists($runtimePath)) unlink($runtimePath);
// 建立標記檔,供配置檔讀取
$flagFile = './home/Runtime/re_url_model.php';
$fp = fopen($flagFile, 'wb');
fclose($fp);
} elseif (file_exists('./home/Runtime/re_url_model.php')) {
// 非支付寶請求,但存在標記檔 → 清理標記與快取,恢復預設模式
unlink('./home/Runtime/re_url_model.php');
unlink('./home/Runtime/~app.php');
}
// 載入框架入口
require(THINK_PATH . "ThinkPHP.php");
// 實例化應用
App::run();
?>
<?php
// home/Conf/config.php
// 兼容支付寶回調的 ? 參數請求
if (file_exists('./home/Runtime/re_url_model.php')) {
return array(
'URL_MODEL' => 1, // 普通模式:index.php/模組/控制器/方法?參數
);
}
return array(
'URL_MODEL' => 2, // PATHINFO 模式:/模組/控制器/方法/參數
// 其他配置...
);
| 階段 | 動作 | 關鍵點 |
|---|---|---|
| 請求進入 | index.php 最先執行 | 框架尚未啟動,可安全操作快取檔 |
| 識別回調 | 判斷 REQUEST_URI 特徵 | 支付寶回調路徑固定,易於匹配 |
| 清除快取 | 刪除 ~app.php | 強制框架重新讀取配置檔 |
| 建立標記 | 建立 re_url_model.php | 配置檔讀取此檔判斷模式 |
| 框架啟動 | App::run() | 讀取最新配置,URL_MODEL=1 |
| 後續請求 | 標記檔存在 → 正常模式 | 非回調請求自動清理標記恢復 PATHINFO |
<?php
// 擴展支援多種回調
$callbackPatterns = [
'alipay/callback/',
'wechat/notify/',
'unionpay/return/',
'order.return_pay',
];
$isCallback = false;
foreach ($callbackPatterns as $pattern) {
if (strstr($_SERVER['REQUEST_URI'], $pattern)) {
$isCallback = true;
break;
}
}
if ($isCallback) {
// 清除快切 + 建立標記
// ...
}
C('URL_MODEL', 1),但需在 App::run() 前config('url_route_on', false) 或路由配置排除回調路徑route.php 中定義回調路由,完全避開 PATHINFO 解析callback.php 獨立入口檔,不載入完整框架,僅處理驗證與業務邏輯'url_convert' => false 或正則排除此方案在不修改框架核心、不影響正常 URL 美化的前提下,精準解決第三方帶參回調的相容問題,是 ThinkPHP 2.x 專案的經典最佳實踐。