edamov / pushok

PHP client for Apple Push Notification Service (APNs) - Send push notifications to iOS using the new APNs HTTP/2 protocol with token-based (JWT with p8 private key)
MIT License
368 stars 119 forks source link

Http code status 0 #134

Closed halie412 closed 1 year ago

halie412 commented 3 years ago

Hi i´m trying to use this library but i get http status code zero int(0) and no success on sending notifications, i try using certificate.pem and also with Authkey.p8 but get same error

I´m using: Centos: 8 (clean only for send notifications) PHP: 7.2.24 CURL: 7.61.1 CURL with http2: yes Apache: 2.4.37 OpenSSL: 1.1.1c

My App are on production, and already can send push notifications using binary protocol so i know than the Device Token are fine and also App are fine

This are the response:

Pushok\Response Object ( [apnsId:Pushok\Response:private] => [deviceToken:Pushok\Response:private] => used_token_here [statusCode:Pushok\Response:private] => 0 [errorReason:Pushok\Response:private] => [error410Timestamp:Pushok\Response:private] => )

This is my script:

$team_id = 'TEAM_BY_APPLE'; $key_id = 'KEY_BY_APPLE'; $device_token = "64_char_tested_working_code"; $apns_topic = 'com.myapp'; $p8file = "/var/www/html/AuthKey.p8";

// code require '/var/www/html/vendor/autoload.php'; use Pushok\AuthProvider; use Pushok\Client; use Pushok\Notification; use Pushok\Payload; use Pushok\Payload\Alert;

// tipo key $options = [ 'key_id' => $key_id, // The Key ID obtained from Apple developer account 'team_id' => $team_id, // The Team ID obtained from Apple developer account 'app_bundle_id' => $apns_topic, // The bundle ID for app obtained from Apple developer account 'private_key_path' => $p8file, // Path to private key 'private_key_secret' => null // Private key secret ];

// Be aware of thing that Token will stale after one hour, so you should generate it again. // Can be useful when trying to send pushes during long-running tasks $authProvider = AuthProvider\Token::create($options);

$alert = Alert::create()->setTitle('Hello!'); $alert = $alert->setBody('First push notification');

$payload = Payload::create()->setAlert($alert);

//set notification sound to default $payload->setSound('default');

//add custom value to your notification, needs to be customized //$payload->setCustomValue('key', 'value');

$deviceTokens = [$device_token];

$notifications = []; foreach ($deviceTokens as $deviceToken) { $notifications[] = new Notification($payload,$deviceToken); }

// If you have issues with ssl-verification, you can temporarily disable it. Please see attached note. // Disable ssl verification //$client = new Client($authProvider, $production = false, [CURLOPT_SSL_VERIFYPEER=>false] ); $client = new Client($authProvider, $production = false); $client->addNotifications($notifications);

$responses = $client->push(); // returns an array of ApnsResponseInterface (one Response per Notification)

var_dump($responses);

foreach ($responses as $response) {

// The device token
$response->getDeviceToken();
// A canonical UUID that is the unique ID for the notification. E.g. 123e4567-e89b-12d3-a456-4266554400a0
$response->getApnsId();
// Status code. E.g. 200 (Success), 410 (The device token is no longer active for the topic.)
$response->getStatusCode();
// E.g. The device token is no longer active for the topic.
$response->getReasonPhrase();
// E.g. Unregistered
$response->getErrorReason();
// E.g. The device token is inactive for the specified topic.
$response->getErrorDescription();
$response->get410Timestamp();

}

jusefjames commented 3 years ago

Could you try a curl --http2 -v https://api.push.apple.com from the command line? Do you get a error NSS: client certificate not found (nickname not specified)?

If yes you probably have the same issue as I have. Curl is built with NSS instead of OpenSSL: curl -V curl 7.76.0 (x86_64-redhat-linux-gnu) libcurl/7.76.0 NSS/3.53.1 zlib/1.2.7 libpsl/0.7.0 (+libicu/50.1.2) libssh2/1.9.0 nghttp2/1.33.0

I tried curl built with OpenSSL and connection to https://api.push.apple.com is working without any problems.

IgorErmakov commented 3 years ago

Got the same issue recently. I use Certificate instead of JWT, but getting 0 status and no error message :( $this->_authProvider = AuthProvider\Certificate::create($options);

Could it be related to this update? https://developer.apple.com/news/?id=c88acm2b

jusefjames commented 3 years ago

Yes, I think it's related to that change. There is no difference if you use Certificate or JWT because the problem is one step before: The connection to the apple server is not working. If you are able to use the command line on your server you could try this and see the result: curl --http2 -v https://api.push.apple.com

jusefjames commented 3 years ago

Not sure if you tried the curl command from shell but on my side the issue was related to curl release 7.76.0. See this comment for details: https://github.com/edamov/pushok/issues/136#issuecomment-820589905

Beardev118 commented 3 years ago

I have already encountered this issue and solved it. This is not this repository's issue. Only this is depended on the curl and OpenSSL, HTTP2 setting of the server.

If you are able to use the command line on your server, you can try this

curl -V

Then you have to see as follows:

curl 7.67.0 (x86_64-pc-linux-gnu) libcurl/7.67.0 OpenSSL/1.1.1g zlib/1.2.7 nghttp2/1.24.0 Release-Date: 2019-11-06 Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp Features: AsynchDNS HTTP2 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets

The main point is OpenSSL and HTTP2 setting. If you can't find the OpenSSL and HTTP2 items or you can see the NSS instead of OpenSSL, then you have to recompile the curl with SSL and nghttp2.

I hope this can help you.

yosus commented 2 years ago

Just to share my experience. I am using cert-based.

I do get the catch from statusCode == 0 when I am sending >50k of notifications to different apns-topic at the same time. Error says it timeout. To solve this (my notifications are time critical), I used a different server to send the notification for different apns-topic. If it wasn't time critical, I would have just stagger it to be sent later.

$statusCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if ($statusCode === 0) {
    throw new \Exception(curl_error($handle));
}