Solo desde PHP: no se puede conectar APNS gateway.push.apple.com:2195

Es una tarde en la noche. Acabo de pasar 10 horas en google / stackoverflow, búsqueda y experimentos. Y parece que odio las notifications Apple Push. Estoy totalmente frustrado y agradeceré cualquier ayuda.

Gracias.

El problema:

El código PHP para enviar notifications Apple Push, que funcionó con éxito hace dos semanas, se detuvo para funcionar ahora y arroja los siguientes errores:

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/... 

Se detuvo para trabajar en dos serveres separados, que utilizan scripts separados para el envío de APN.

Ambiente:

Servidores: CentOS 6.5 con PHP 5.4.32 y Ubuntu 14.04.3 con PHP 5.5.9

APN: en modo de producción

Certificados: probado con más de 700 notifications push.

Uno de los serveres está utilizando https://github.com/immobiliare/ApnsPHP , otro – https://github.com/antongorodezkiy/wp-apn , en localhost probé el file simple sin usar ningún código de terceros.

Investigación:

Para todos los casos a continuación, utilicé el mismo token de dispositivo activo y el mismo certificate PEM de producción.

php

Sin embargo, incluso este código simple no funciona en ambos serveres y localhost y devuelve el mismo error que el anterior:

 $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); 

También intenté jugar con las opciones de stream_context_set_option() , include entrust_2048_ca.cer , etc., e incluso algunas opciones de este artículo . Aunque el código proporcionado funcionó sin modificaciones antes de agosto de 2015.

openssl

La connection funcionó con openssl ( enlace ):

 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 

Y conseguí CONNECTED(00000003) y Verify return code: 0 ( ok ) .

telnet

La connection funcionó con telnet:

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

pecn apn

No envió notifications push . Acabo de intentar usar la adaptación del código de muestra , pero tengo el error Invalid token . El token está activo y el mismo token que usé en todas partes y también para Houston y Ruby.

houston

Funcionó con Houston

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

Ruby

No soy progtwigdor de Ruby (aunque al less), pero después del éxito con Houston, encontré y adapté el código de Ruby sin la dependencia de Houston.

Y funcionó :

 #!/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" 

Preguntas:

  1. ¿Qué sucede con PHP? ¿Hay algún error relacionado con este problema? (No encontré el informe de errores, sin embargo)
  2. ¿Alguna idea de cómo resolver este problema?
  3. ¿Alguna idea de cuál podría ser la diferencia en los casos de PHP y Ruby (supongo que Python o Perl también podrían funcionar bien)? Incluso intenté leer fonts PHP, pero sin éxito para comprender cómo se implementó stream_socket_client() .

Por favor ayuda.

Encontré el problema y lo solucioné.

El problema estaba en el certificate .pem. De alguna manera, había dos certificates en un file para producción y desarrollo de files .pem. El mismo file .pem con dos certificates estuvo en el repository por mucho time, pero los APN se detuvieron para funcionar hace unos meses. Tal vez algo fue actualizado / cambiado por el lado de Apple.

Supongo que el código de Ruby de alguna manera elimina la duplicación de certificates o tal vez solo tomó el primer certificate, por lo que funcionó en Ruby.

Sin embargo, la solución fue eliminar el segundo certificate del file .pem. Después de que los APN comenzaron a funcionar y ahora funcionan (recibí algunos ayer).

Si solo está reutilizando una Solicitud de firma de certificate (CSR) anterior, asegúrese de eliminar el certificate de APN caducado / antiguo de su Llavero antes de exportar el nuevo y su key privada como file p12. Si no lo hace, el file PEM que generó de la p12 exportada todavía contendrá el certificate caducado / antiguo que no funciona bien con el proveedor Push de Apple. Por lo tanto, resulta unable to connect to ssl...