php手搓APNs苹果消息推送
做App总少不了消息推送,公司的App为了开发敏捷方便都直接上的三方推送诸如某盟、某推、某光,安卓和苹果都一套代码,高效好维护,只要按时给推送vip付费就好了。最近心血来潮想手搓下苹果的消息推送,踩踩以前没踩过的坑。
看了下苹果官方文档感觉并不困难,文档详情戳这里
<a href="https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns">Sending Notification Requests to APNs | Apple Developer Documentation</a>
恰逢chatGPT大火赶下时髦,直接问了ai代码怎么写
<img src="https://product.liyiru.top/uploads/8f74afa622d57d35b88702c669bf7551.png" />
ai回答得有模有样,我里面换上证书和相关参数尝试,然后发现死活不行,苹果那边没反应。
一查文档发现其实苹果这边服务器推送大致分了两种模式:
一种是基于ssl证书模式推送,另一种是根据p8证书生产jwt token授权来推送。
显然代码给的是第一种,然后看了苹果的官方文档2021年就已经废弃了第一种模式并且强行要求使用http2请求,看来chatGPT3.5的投喂数据截止于2021年所言非虚。
<img src="https://product.liyiru.top/uploads/a88729a543a7e7df73cb8f0ab9793923.png" />
这里我踩了两个大坑:
第一个是苹果证书ssl模式下要pem证书,我拿到的是p12证书,只能先用OpenSSL转成pem公钥和私钥,后来发现要公钥和私钥放在一起合成一个pem第一张图的代码才能用。然后转为jwt授权模式后要的是p8证书,之前的pem证书生成的token死活过不了。
第二个是我这边的服务器环境curl并不支持http2,一直报错Unexpected HTTP/1.x request: POST /3/device/XXXX。后来我只好重新编译curl和php相关的扩展直接升级到了curl 8.1.0。参考连接
怎么让php curl发http2请求
怎么让curl支持http2
下面是推送和jwt生成demo
<code>
//jwt token模式下的苹果推送
$device_token = 'your_device_token'; //苹果给的设备推送token
$message = 'Hello, world!'; //要推送的消息
// Create the notification payload
$payload = array(
'aps' => array(
'alert' => $message,
'sound' => 'default'
)
);
$payload_json = json_encode($payload);
//正式环境推送地址
$url = 'https://api.push.apple.com:443/3/device/' . $device_token;
//沙盒推送地址
//$url = "https://api.sandbox.push.apple.com:443/3/device/".$device_token;
$headers = array(
'Authorization: Bearer 你生成的jwt_token',
'Content-Type: application/json'
);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload_json);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); //这里很关键,以http2发送请求,如果你的curl不支持http2则需要看前面的步骤
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Check the response
if ($http_code == 200) {
echo 'Notification sent successfully.';
} else {
echo 'Notification failed with error code: ' . $http_code;
}
</code>
<code>
//jwt token生成代码
$key_id = 'your_key_id';
$team_id = 'your_team_id';
$pkey_file = 'AuthKey_your_key_id.p8'; //p8证书文件,我在这里填的绝对地址
// token过期时间
$expires = time() + 3600;
// Generate the JWT header
$header = array(
'alg' => 'ES256',
'kid' => $key_id
);
$jwt_header = base64_encode(json_encode($header));
//JWT payload
$payload = array(
'iss' => $team_id,
'iat' => time(),
'exp' => $expires,
'aud' => 'https://appleid.apple.com',
'sub' => 'your_bundle_id' //这里填你的App包名
);
$jwt_payload = base64_encode(json_encode($payload));
//载入证书文件
$pkey_contents = file_get_contents($pkey_file);
$pkey = openssl_get_privatekey($pkey_contents);
//JWT 签名
$signature = '';
openssl_sign($jwt_header . '.' . $jwt_payload, $signature, $pkey, 'sha256');
$jwt_signature = base64_encode($signature);
// 生成JWT
$jwt = $jwt_header . '.' . $jwt_payload . '.' . $jwt_signature;
echo $jwt;
</code>
更多>>