PHP cURL Error: Peer reports incompatible or unsupported protocol version.

PHP cURL 遇到的錯誤:cURL Error: Peer reports incompatible or unsupported protocol version.,探討解決方案。

範例程式碼

以下是我使用的範例程式碼,用於向 API Server 傳送資料:

curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_DEFAULT);
// 執行 cURL 請求
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURL Error: ' . curl_error($ch) . "\n";
} else {
echo "Response:\n";
echo $response;
}

此程式碼導致錯誤,因為主機與 API Server 支援的 SSL/TLS 協議不匹配。

系統環境

發生原因

檢查 OpenSSL 版本後發現,OpenSSL 1.0.2k-fips 只支持到 TLS 1.2,但目標 API Server 僅允許 TLS 1.3。這就導致了協議不匹配,從而引發了錯誤。

OpenSSL 1.0.2k-fips 支援的 SSL/TLS 協議:

因為 OpenSSL 1.0.2 不支持 TLS 1.3,而 API Server 僅允許 TLS 1.3,導致 SSL/TLS 協議不兼容。

解決方案

1. 升級主機的 SSL/TLS 支援

若 API Server 僅支援 TLS 1.3,主機必須升級至支援 TLS 1.3 的 OpenSSL 版本(至少為 OpenSSL 1.1.1)。這樣可以確保 PHP 主機與 API Server 之間的 SSL/TLS 協議匹配。

2. 讓 API Server 向下兼容 TLS 1.2

如果 API Server 能夠向下兼容 TLS 1.2,則可以暫時允許 TLS 1.2 通訊,以解決當前的不兼容問題。儘管 TLS 1.3 更加安全,但在過渡期間允許使用 TLS 1.2,可以確保現有系統正常運行。

實作過程

在我的情況下,由於主機當前無法即時升級至支援 TLS 1.3 的 OpenSSL,我選擇了讓 API Server 向下兼容 TLS 1.2 的方案。這樣系統可以恢復運作,並且在未來 OpenSSL 升級至支援 TLS 1.3 時,再切換至僅支持 TLS 1.3 的模式。

在 Plesk 中,可以使用以下命令來啟用 TLS 1.2 和 TLS 1.3:

# plesk bin server_pref -u -ssl-protocols 'TLSv1.2 TLSv1.3'

執行此命令後,請重啟相關服務(如 Apache、Nginx、PHP-FPM)以應用更改。
這樣可以臨時解決協議不兼容的問題。

檢測工具

SSL Labs

當不確定目標主機支援哪些 TLS 協議版本時,可以使用 SSL Labs 工具來檢查目標主機的 TLS 支援情況。該工具可以幫助你確定目標主機的協議支援,從而避免不兼容問題的發生。

參考資料

https://www.plesk.com/kb/support/how-to-enable-disable-tls-protocol-versions-in-plesk-for-linux/
https://talk.plesk.com/threads/best-practice-for-upgrading-openssl-on-centos-7-9-obsidian-v18-0-54.371042/
https://www.isres.com/jingyan2/79.html
https://blog.csdn.net/weixin_46858088/article/details/135718447

[……]

閱讀更多

WordPress wp_remote_post curl: (35) Peer reports incompatible or unsupported protocol version

分享如何處理使用 WordPress 的 wp_remote_post() 函數時遇到的錯誤:curl: (35) Peer reports incompatible or unsupported protocol version,探討解決方案。

範例程式碼

以下是我使用的範例程式碼,用於向 API Server 傳送資料:

$crm_api_url = 'https://crm.example.com/api/hello';
$response = wp_remote_post( $crm_api_url, [
'body' => $post_body,
]);
wp_die( print_r( $response, true ) );

此程式碼導致錯誤,因為主機與 API Server 支援的 SSL/TLS 協議不匹配。

系統環境

發生原因

檢查 OpenSSL 版本後發現,OpenSSL 1.0.2k-fips 只支持到 TLS 1.2,但目標 API Server 僅允許 TLS 1.3。這就導致了協議不匹配,從而引發了錯誤。

OpenSSL 1.0.2k-fips 支援的 SSL/TLS 協議:

因為 OpenSSL 1.0.2 不支持 TLS 1.3,而 API Server 僅允許 TLS 1.3,導致 SSL/TLS 協議不兼容。

解決方案

1. 升級主機的 SSL/TLS 支援

若 API Server 僅支援 TLS 1.3,主機必須升級至支援 TLS 1.3 的 OpenSSL 版本(至少為 OpenSSL 1.1.1)。這樣可以確保 WordPress 主機與 API Server 之間的 SSL/TLS 協議匹配。

2. 讓 API Server 向下兼容 TLS 1.2

如果 API Server 能夠向下兼容 TLS 1.2,則可以暫時允許 TLS 1.2 通訊,以解決當前的不兼容問題。儘管 TLS 1.3 更加安全,但在過渡期間允許使用 TLS 1.2,可以確保現有系統正常運行。

實作過程

在我的情況下,由於主機當前無法即時升級至支援 TLS 1.3 的 OpenSSL,我選擇了讓 API Server 向下兼容 TLS 1.2 的方案。這樣系統可以恢復運作,並且在未來 OpenSSL 升級至支援 TLS 1.3 時,再切換至僅支持 TLS 1.3 的模式。

在 Plesk 中,可以使用以下命令來啟用 TLS 1.2 和 TLS 1.3:

# plesk bin server_pref -u -ssl-protocols 'TLSv1.2 TLSv1.3'

執行此命令後,請重啟相關服務(如 Apache、Nginx、PHP-FPM)以應用更改。
這樣可以臨時解決協議不兼容的問題。

檢測工具

SSL Labs

當不確定目標主機支援哪些 TLS 協議版本時,可以使用 SSL Labs 工具來檢查目標主機的 TLS 支援情況。該工具可以幫助你確定目標主機的協議支援,從而避免不兼容問題的發生。

參考資料

https://www.plesk.com/kb/support/how-to-enable-disable-tls-protocol-versions-in-plesk-for-linux/
https://talk.plesk.com/threads/best-practice-for-upgrading-openssl-on-centos-7-9-obsidian-v18-0-54.371042/
https://www.isres.com/jingyan2/79.html
https://blog.csdn.net/weixin_46858088/article/details/135718447

[……]

閱讀更多

PHP 錯誤處理(new Exception、new Error、trigger_error、error_log )

不記起來會忘記,雖然記起來會混亂,寫個筆記紀錄一下

本文將介紹如何觸發錯誤、錯誤級別介紹、處理錯誤、錯誤日誌的寫法。

觸發錯誤

使用 Exception 類別

這種方式用於例外處理,當你想捕捉並處理某些條件下的錯誤時,可以拋出一個例外。這通常用於邏輯錯誤或應用程式級別的錯誤。

使用 Error 類別

Error 類別是從 PHP 7 開始引入的,用於處理更底層的錯誤,例如語法錯誤或類型錯誤。這些錯誤通常表示程式碼中的嚴重問題,應該被捕捉並記錄。

使用 trigger_error 函數

trigger_error 函數允許你生成一個用戶定義的錯誤。這對於在開發過程中發出警告或錯誤訊息非常有用。你可以指定錯誤等級,例如 E_USER_WARNING 或 E_USER_ERROR。

範例對比

以下是一個綜合範例,展示了這三種錯誤發出的方式及其處理方法:

這個範例中,Exception 和 Error 被捕捉並處理,而 trigger_error 生成的錯誤則由自訂錯誤處理函數處理。程式不會中止,並且會輸出所有錯誤訊息。

錯誤級別表

系統級別錯誤

錯誤級別中止程式引發者情境描述E_ERROR是系統致命的運行錯誤,例如無效的函數調用E_WARNING否系統運行時警告,例如包含不存在的文件E_PARSE是系統解析錯誤,例如語法錯誤E_NOTICE否系統運行時通知,例如使用未定義的變數E_CORE_ERROR是系統PHP 啟動時的致命錯誤E_CORE_WARNING否系統PHP 啟動時的警告E_COMPILE_ERROR是系統編譯時的致命錯誤E_COMPILE_WARNING否系統編譯時的警告E_STRICT否系統建議的代碼改進措施E_RECOVERABLE_ERROR否系統可捕捉的致命錯誤,例如類型錯誤E_DEPRECATED否系統運行時通知,不建議使用的代碼

用戶級別錯誤

錯誤級別中止程式引發者情境描述E_USER_ERROR是用戶 trigger_error()用戶生成的致命錯誤,例如自訂的致命錯誤E_USER_WARNING否用戶 trigger_error()用戶生成的警告,例如自訂的警告訊息E_USER_NOTICE否用戶 trigger_error()用戶生成的通知,例如自訂的通知訊息E_USER_DEPRECATED否用戶 trigger_error()用戶生成的過時警告,例如自訂的不建議使用的代碼警告

處理錯誤

以下介紹錯誤處裡的方法:
set_error_handler
set_exception_handler
register_shutdown_function

使用 set_error_handler 處理的錯誤

錯誤級別會中止程式引發者簡單描述情境E_WARNING否系統運行時警告,例如包含不存在的文件E_NOTICE否系統運行時通知,例如使用未定義的變數E_USER_WARNING否用戶 (trigger_error())用戶生成的警告E_USER_NOTICE否用戶 (trigger_error())用戶生成的通知E_USER_ERROR是用戶 (trigger_error())用戶生成的致命錯誤E_USER_DEPRECATED否用戶 (trigger_error())用戶生成的過時警告E_DEPRECATED否系統運行時通知,不建議使用的代碼E_RECOVERABLE_ERROR否系統可捕捉的致命錯誤,例如類型錯誤

使用 set_exception_handler 處理的例外

錯誤類型會中止程式引發者簡單描述情境Exception是用戶例如 throw new ExceptionError是用戶例如 throw new Error

使用 register_shutdown_function 處理的錯誤

錯誤級別會中止程式引發者簡單描述情境E_ERROR是系統致命的運行錯誤,例如無效的函數調用E_CORE_ERROR是系統PHP 啟動時的致命錯誤E_COMPILE_ERROR是系統編譯時的致命錯誤E_PARSE是系統解析錯誤,例如語法錯誤

這些表格展示了不同的錯誤處理方法以及它們可以處理的錯誤類型,確保你可以有效地處理所有可能發生的錯誤和例外。

錯誤處裡範例

set_error_handler()

系統只會有一個有作用的 set_error_handler(),後面設置的 handler 會覆蓋前面設置 handler,無法刪除,如有套件設置了,可以用覆蓋的或 set_error_handler(null) 使 handler 失去作用

try-catch

捕獲到 Error or Exception 可統一進行錯誤處裡,當然也可以捕獲後步處理,或存於 error_log

輸出:

錯誤日誌

錯誤日誌就像飛機的黑盒子,記錄著所有錯誤發生的詳細信息,讓我們能夠在錯誤發生後進行分析和診斷,從而提高應用程式的穩定性和可靠性。

以下是錯誤日誌寫法:

綜合錯誤處裡

錯誤日誌的記錄不僅有助於在開發過程中及早發現和修復問題,還能在生產環境中提供寶貴的錯誤追蹤信息。透過詳細的錯誤日誌記錄,我們可以了解錯誤發生的時間、錯誤類型、錯誤訊息以及錯誤發生的文件和行號,這些資訊讓我們快速修正非常重要。

[……]

閱讀更多

PHP json_encode sting in HTML input field

json_encode 輸出於 HTML input 發生異常

把PHP中的Array透過json_encode()轉換成Json格式輸出到HTML input value中如下:

輸出於 HTML 發生異常,只剩下左側「中括號」

主要原因是Json中的雙引號與HTML的雙引號打架

可以使用 htmlspecialchars() 簡單解決這問題

在執行 json_encode() 後再執行 htmlspecialchars() 如下方代碼

如此就正常輸出囉

https://stackoverflow.com/a/21887262

[……]

閱讀更多

Social Network Service (SNS) Share Link

Facebook

  • http://www.facebook.com/share.php?u=[URL]&t=[TITLE]&pic=[IMAGE]

Twitter

  • http://twitter.com/intent/tweet?text=[TITLE]&url=[URL]&pic=[IMAGE]

Google Plus

  • https://plus.google.com/share?url=[URL]&t=[TITLE]

Pinterest

  • https://www.pinterest.com/pin/create/button/?url=[URL]&description=[TITLE]&media=[IMAGE]

Linkedin

  • https://www.linkedin.com/sharing/share-offsite/?url=[URL]&title=[TITLE]

Delicious

  • http://del.icio.us/post?url=[URL]&title=[TITLE]

Tumblr

  • http://www.tumblr.com/share?v=3&u=[URL]&t=[TITLE]

Digg

  • http://digg.com/submit?phase=2&url=[URL]&title=[TITLE]

StumbleUpon

  • http://www.stumbleupon.com/submit?url=[URL]&title=[TITLE]

Reddit

  • http://reddit.com/submit?phase=2&url=[URL]&title=[TITLE]

新浪微博

  • http://v.t.sina.com.cn/share/share.php?title=[TITLE]+[URL]&pic=[IMAGE]

QQ 空间

  • http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=[URL]

人人网

  • http://share.renren.com/share/buttonshare.do?link=[URL]&title=[TITLE]

腾讯微博

  • http://v.t.qq.com/share/share.php?url=[URL]&title=[TITLE]

https://github.com/bradvin/social-share-urls
https://chon.io/notes/social-media-sharing-link-url/

[……]

閱讀更多

PHP function alias 方法別名

開發PHP專案的時候,有時會有更改 function 名稱的需求,也許當時是趕時間草率命名,也許是拼錯字,但隨時間推移,更改 function 的名字就變得很可怕,可能一改造成一連串的錯誤,但不改又很礙眼,感覺很痛苦,為避免錯誤連換爆的這個狀況,思考是否可以用「別名」的概念,讓新的 function 跟舊的 function 都可以做一樣的事情,在不發生錯誤的情況下慢慢汰除舊名字,隨著版本的演進直至所有舊名都被移除,最後再將「別名」移除

最簡單的做法

stackoverflow Jon 提供了一個最簡單的做法

https://stackoverflow.com/a/23426311

不過此做法存在缺陷,在 class 中呼叫會找不到 function

以下是目前最好解法

由 stackoverflow Nathan Crause 提出

https://stackoverflow.com/a/2877219/6784662

做了一點小修改

龜毛了一點,我習慣別名再右方,為維持這習慣我把上面方法做了一點小修改,更好理解

[……]

閱讀更多

三竹簡訊串接 – API 網址

三竹簡訊官方API文件,API Call 的網址如下:,

https://{三竹網域名稱}/b2c/mtk/SmSend

還以為真的是直接用他官網的網域,太天真了,弄半天結果不是,最後透過客服得知三竹簡訊目前帳號分為,個人帳號 (二站)、企業帳號 (三站),Call 的網址不同,call 的網址分別為下面兩個網址:

API 網址

企業帳號 (三站)
https://smsapi.mitake.com.tw/api/mtk/SmSend?

個人帳號 (二站)
http://smsb2c.mitake.com.tw/b2c/mtk/SmSend?

簡單測試API

[……]

閱讀更多

WAMP Server change default Browser to Chrome

開啟 WAMP Sever 居然是用 IE 11 開啟,到底對不對阿,這都什麼時期的產物了,雖然直接用瀏覽器輸入網址瀏覽本地端網頁也是可行,但心裡就是有個疙瘩,來哥教你改成用你愛的瀏覽器開

修改設定檔

如果安裝路徑沒有修改的話,開啟下面這個檔案,如果安裝路徑有修改的話,自己去找這個檔案。

用你愛用的文字編輯器打開,照到該死的這一行

替換成瀏覽器執行檔位置

關閉 WAMP Server 重新開啟,SEE Chrome 出現了,開勳

[……]

閱讀更多