Apple Push Notification Service (APNs) 要求使用 PEM 格式證書建立 TLS 連線。本文詳細記錄從 Apple Developer 後台申請到生成 apns-dev.pem / apns-prod.pem 的完整流程,適用於 PHP 服務端推送開發。
com.example.app)CertificateSigningRequest.certSigningRequest.certSigningRequest 文件aps_development.cer 或 aps_production.cer.cer 文件自動導入鑰匙串apns-dev-cert.p12(開發)或 apns-prod-cert.p12(生產),設置導出密碼(記住)apns-dev-key.p12 / apns-prod-key.p12打開終端機執行:
# 憑證 .p12 → .pem (無需密鑰)
openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
# 私鑰 .p12 → .pem (需輸入導出密碼,再設置 PEM 密語)
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
# 移除私鑰密語(PHP stream_context 需無密語私鑰)
openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem
# 合併憑證與無密語私鑰為最終 PEM
cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem
# 開發環境沙箱
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert apns-dev-cert.pem -key apns-dev-key-noenc.pem
# 生產環境
openssl s_client -connect gateway.push.apple.com:2195 -cert apns-prod-cert.pem -key apns-prod-key-noenc.pem
若顯示 CONNECTED 並返回憑證鏈資訊,證書配置正確。
$ctx = stream_context_create([
'ssl' => [
'local_cert' => '/path/to/apns-dev.pem',
'passphrase' => '', // 已移除密語留空
'verify_peer' => false,
]
]);
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195',
$err, $errstr, 60, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, $ctx
);
if (!$fp) {
throw new Exception("APNs 連線失敗: $errstr ($err)");
}
// 發送二進制載荷...
fwrite($fp, $payload);
fclose($fp);
gateway.sandbox.push.apple.com,生產用 gateway.push.apple.com,證書不可混用。verify_peer_name 提升安全性。