ios — только из PHP: невозможно подключить APNS gateway.push.apple.com:2195

Это поздно ночью. Я только что провел 10 часов в поиске и экспериментах google / stackoverflow. И, кажется, я ненавижу Apple Push-уведомления. Я полностью расстроен и буду признателен за любую помощь.

Спасибо.

Эта проблема:

PHP-код для отправки Apple Push-уведомлений, который успешно работал две недели назад, перестал работать и выдает следующие ошибки:

PHP Warning:  stream_socket_client(): Failed to enable crypto in /home/...
PHP Warning:  stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error) in /home/...

Он перестал работать на двух отдельных серверах, которые используют отдельные сценарии для отправки APN.

Среда:

Серверы: CentOS 6.5 с PHP 5.4.32 и Ubuntu 14.04.3 с PHP 5.5.9

APN: в производственном режиме

Сертификаты: протестировано с 700+ push-уведомлениями.

Один из серверов использует https://github.com/immobiliare/ApnsPHP, Другой — https://github.com/antongorodezkiy/wp-apn, на локальном хосте я тестировал простой файл без использования стороннего кода.

Изучение:

Для всех описанных ниже случаев я использовал один и тот же токен активного устройства и один и тот же производственный сертификат PEM.

PHP

Тем не менее, даже этот простой код не работает на обоих серверах и на локальном хосте и возвращают ту же ошибку, что и выше:

$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', '/absolute/path/to/apn_prod.pem');

// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

Я также пытался играть с stream_context_set_option() варианты, включают entrust_2048_ca.cerи т.д., и даже некоторые варианты из Эта статья. Хотя предоставленный код работал без каких-либо изменений до августа 2015 года.

OpenSSL

Соединение сработало с openssl (ссылка на сайт):

openssl s_client -connect gateway.push.apple.com:2195 -cert /absolute/path/to/apn_prod.pem -debug -showcerts -CAfile /absolute/path/to/server-ca-cert.pem

И получил с CONNECTED(00000003) а также Verify return code: 0 ( ok ),

телнет

Соединение сработало с телнетом:

-sh-4.1$ telnet gateway.push.apple.com 2195
Trying 17.172.233.150...
Connected to gateway.push.apple.com.

pecl apn

Не отправлено push-уведомление. Я просто пытался использовать адаптацию образец кода, но получил ошибку Invalid token, Токен активен и тот же токен, который я использовал везде, а также для Хьюстона и Руби.

Хьюстон

Это сработало с Хьюстоном

apn push "0346a53f...231d9d6abe11" -c /absolute/path/to/apn_prod.pem -m "Hello from the command line!" -e "production"

Рубин

Я не программист на Ruby (пока, по крайней мере), но после успеха в Хьюстоне я нашел и адаптировал код Ruby без зависимости от Хьюстона.

А также это сработало:

#!/usr/bin/env ruby

require 'openssl'
require 'socket'
require 'json'

token = "0346a53f...231d9d6abe11"cert = File.read("/absolute/path/to/apn_prod.pem")
ctx = OpenSSL::SSL::SSLContext.new
ctx.key = OpenSSL::PKey::RSA.new(cert, '') #set passphrase here, if any
ctx.cert = OpenSSL::X509::Certificate.new(cert)

sock = TCPSocket.new('gateway.push.apple.com', 2195) #development gateway
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.connect

payload = {"aps" => {"alert" => "Oh hai!", "badge" => 1, "sound" => 'default'}}
json = payload.to_json()
token =  [token.delete(' ')].pack('H*') #something like 2c0cad 01d1465 346786a9 3a07613f2 b03f0b94b6 8dde3993 d9017224 ad068d36
apnsMessage = "\0\0 #{token}\0#{json.length.chr}#{json}"ssl.write(apnsMessage)

ssl.close
sock.close

puts "End"
  1. Что не так с PHP? Есть ли какая-то ошибка, связанная с этой проблемой? (Я не нашел сообщение об ошибке, хотя)
  2. Есть идеи, как решить эту проблему?
  3. Любые идеи, в чем может быть разница в случаях PHP и Ruby (я предполагаю, что Python или Perl тоже могут работать нормально)? Я даже пытался читать исходники PHP, но безуспешно, чтобы понять, как stream_socket_client() реализованы.

Пожалуйста помоги.

6

Решение

Я нашел проблему и исправил ее.

проблема был в .pem сертификате. Каким-то образом в одном файле было два сертификата для файлов производства и разработки .pem. Один и тот же файл .pem с двумя сертификатами долгое время находился в репо, но APN перестали работать только несколько месяцев назад. Может быть, что-то было обновлено / изменено на стороне Apple.

Я предполагаю, что код Ruby каким-то образом удаляет дублирование сертификатов или, возможно, он потребовал только первый сертификат, поэтому он работал в Ruby.

Тем не менее решение должен был удалить второй сертификат из файла .pem. После этого APN начали работать, и теперь они работают (некоторые я получил только вчера).

5

Другие решения

Если вы просто повторно используете старый запрос на подпись сертификата (CSR), обязательно удалите устаревший / старый сертификат APNs из цепочки для ключей, прежде чем экспортировать новый и его закрытый ключ в виде файла p12. Если вы этого не сделаете, файл PEM, сгенерированный вами из экспортированного p12, все равно будет содержать устаревший / старый сертификат, который не подходит для Apple Push-провайдера. Таким образом, в результате чего unable to connect to ssl...,

0

По вопросам рекламы [email protected]