反馈请联系hertz@hertzwang.com,谢谢
准备
操作步骤
- 下载推送证书,加入到 钥匙串,并将文件改名为
aps_development.cer
放入本文件夹; - 从 钥匙串 将证书导出为 p12 格式,更名为
aps_development.p12
放入本文件夹; - 修改
push.php
文件中的配置; - 终端执行
init.py
初始化证书; - 终端执行
php push.php
发送(默认为开发环境)。
注: 执行完 python
脚本终端会输出以下内容,若没有则表示操作有误,请重新操作
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
常见问题及解决
证书相关查看上面的
参考
不能导出
p12
说明该证书不是这台机器颁发的,解决方案是找到那台机器拿到 p12 文件,或者重新生成证书(慎用)。
SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
/Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages: error:14094410:SSL routines:SSL3_READ_BYTES
下载 entrust_2048_ca.cer 证书 放至本文件夹
文件说明
aps_development.cer
推送证书,分
Development
和Production
两种,从 开发官方下载aps_development.p12
私钥,官方下载的推送证书(
aps_development.cer
)加入钥匙串
后导出aps_cert.pem
推送证书(
aps_development.cer
)的pem
格式aps_key.pem
私钥(
aps_development.p12
)的pem
格式aps.pem
合成文件,推送证书(
pem
格式)和私钥(pem
格式)的合成文件
有兴可查看下面的 init.py
entrust_2048_ca.cer
这个不太确认…是个CA证书,有了解的可以联系hertz@hertzwang.com
附
测试推送
init.py
# -*- coding: utf-8 -*-
import os
def main():
# 将 aps_development.cer 转成 pem 格式
os.system('openssl x509 -in aps_development.cer -inform DER -out aps_cert.pem -outform PEM')
# 将 aps_development.p12 格式的私钥转换成 aps_key.pem
print('请输入导出时的密码,无密码按回车继续,然后设置 PEM pass phrase\nPlease enter the password of the export, no password to press enter to continue, setting PEM pass phrase.\n')
os.system('openssl pkcs12 -nocerts -out aps_key.pem -in aps_development.p12')
# 合成
os.system('cat aps_cert.pem aps_key.pem > aps.pem')
print('证书初始化结束/The certificate initialization done.')
main()
push.php
<?php
// token:设备注册成功后 application:didRegisterForRemoteNotificationsWithDeviceToken: 中查看,去除空格
$deviceToken = '1ff8a0af52b48748c7628609a812f15d1c961df4bb04e618def369996a7e72ae';
// passphrase:私钥密码
$passphrase = 'qwe123';
// 数值:显示在 icon 上
$badge = 0;
// 环境 TRUE-开发,FALSE-正式
$devPlatform = TRUE;
// 推送信息设置
$message = '推送消息'; // 推送消息
////////////////////////////////////////////////////////////////////////////////
// 设置上下文
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'aps.pem'); // 设置证书
stream_context_set_option($ctx, 'ssl', 'cafile', 'entrust_2048_ca.cer'); // 设置CA证书
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase); // 设置私钥密码
// 打开一个 APNs 的连接,开发环境 gateway.sandbox.push.apple.com:2195 正式环境 gateway.push.apple.com:2195
$sslPath = 'ssl://gateway.sandbox.push.apple.com:2195';
if ($devPlatform == FALSE) {
$sslPath = 'ssl://gateway.push.apple.com:2195';
}
$fp = stream_socket_client(
$sslPath, $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// 封装推送信息
$body['aps'] = array(
'alert' => $message,
'sound' => 'default',
'badge' => $badge,
);
// 转为 JSON 格式
$payload = json_encode($body);
// 转为二进制
$msg = chr(0).pack('n', 32).pack('H*', $deviceToken).pack('n', strlen($payload)).$payload;
// 发送至 Apple 服务器
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// 关闭连接
fclose($fp);
?>