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

Getting Int(0)/String(0) back when trying to send any push notification #121

Closed schofs closed 1 year ago

schofs commented 3 years ago

Have been setting up a new server, which I believe meets the spec. I've got a live app at the moment using the old APNS setup, so I know the apple side of things is set up correctly, and I'm using a device token ID that I know is valid because it's the one I successfully use to send push notifications to using the old system.

Ubuntu 20.10 Apache 2.4.46

HTTP2

~$ curl -sI https://myserverhere.com -o/dev/null -w '%{http_version}\n'
2

lib-curl > 7.46

~$ curl --version
curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1i zlib/1.2.11 brotli/1.0.9 libidn2/2.3.0 libpsl/0.21.0 (+libidn2/2.3.0) libssh/0.9.3/openssl/zlib nghttp2/1.41.0 librtmp/2.3
Release-Date: 2020-01-08
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets

PHP >7.2

~$ php -v
PHP 7.4.9 (cli) (built: Oct 26 2020 15:17:14) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.9, Copyright (c), by Zend Technologies

Open SSL >1.0.2e

~$ openssl version -a
OpenSSL 1.1.1i  8 Dec 2020
built on: Wed Dec 23 09:12:36 2020 UTC
platform: debian-amd64
options:  bn(64,64) rc4(8x,int) des(int) blowfish(ptr) 
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -fdebug-prefix-map=/build/openssl-tM5R0Z/openssl-1.1.1i=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
OPENSSLDIR: "/usr/lib/ssl"
ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1"
Seeding source: os-specific

Execution file I run to send the push (using https:// url)

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

define ("_SHARED_ROOT_","/var/www/html");

require __DIR__ . '/vendor/autoload.php';

use Pushok\AuthProvider;
use Pushok\Client;
use Pushok\Notification;
use Pushok\Payload;
use Pushok\Payload\Alert;

$options = [
    'key_id' => 'MY-VALID-KEY', // The Key ID obtained from Apple developer account
    'team_id' => 'MY-VALID-TEAM-ID', // The Team ID obtained from Apple developer account
    'app_bundle_id' => 'com.MY-VALID-BUNDLE-ID', // The bundle ID for app obtained from Apple developer account
    'private_key_path' => _SHARED_ROOT_ . '/AuthKey.p8', // Valid path to private key
    'private_key_secret' => null // Private key secret
];

$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 = ['****my-valid-device-token-here****'];
$notifications = [];
foreach ($deviceTokens as $deviceToken) {
    $notifications[] = new Notification($payload,$deviceToken);
}

$client = new Client($authProvider, $production = true);
$client->addNotifications($notifications);

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

foreach ($responses as $response) {
    $response->getApnsId();
    $response->getStatusCode();
    $response->getReasonPhrase();
    $response->getErrorReason();
    $response->getErrorDescription();
}

var_dump($responses);

?>

This is the output I get:

array(1) {
  [0]=>
  object(Pushok\Response)#5 (5) {
    ["apnsId":"Pushok\Response":private]=>
    string(0) ""
    ["deviceToken":"Pushok\Response":private]=>
    string(64) "****my-valid-device-token-here****"
    ["statusCode":"Pushok\Response":private]=>
    int(0)
    ["errorReason":"Pushok\Response":private]=>
    string(0) ""
    ["error410Timestamp":"Pushok\Response":private]=>
    string(0) ""
  }
}

What am I missing? It's the empty responses that make me think something in the system setup is wrong and no valid data is coming back.

edamov commented 3 years ago

@schofs Could you please check that your php is compiled against Curl 7.46+ ? You can have correct version of curl in your system but it can be wrong version in php

schofs commented 3 years ago

When running phpinfo() from the server, this is what I get back Screenshot 2021-01-19 at 17 11 23

edamov commented 3 years ago

PHP-CLI and PHP-FPM can have different compiled versions of curl. Did you check this also?

schofs commented 3 years ago

When running the following from the command line:

php -r "phpinfo();"

I get:

phpinfo()
PHP Version => 7.4.9

System => Linux ... 5.8.0-33-generic #36-Ubuntu SMP Wed Dec 9 09:14:40 UTC 2020 x86_64
Build Date => Oct 26 2020 15:17:14
Server API => Command Line Interface

....
....

curl

cURL support => enabled
cURL Information => 7.68.0
Age => 5
Features
AsynchDNS => Yes
CharConv => No
Debug => No
GSS-Negotiate => No
IDN => Yes
IPv6 => Yes
krb4 => No
Largefile => Yes
libz => Yes
NTLM => Yes
NTLMWB => Yes
SPNEGO => Yes
SSL => Yes
SSPI => No
TLS-SRP => Yes
HTTP2 => Yes
GSSAPI => Yes
KERBEROS5 => Yes
UNIX_SOCKETS => Yes
PSL => Yes
HTTPS_PROXY => Yes
MULTI_SSL => No
BROTLI => Yes
Protocols => dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3, pop3s, rtmp, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp
Host => x86_64-pc-linux-gnu
SSL Version => OpenSSL/1.1.1i
ZLib Version => 1.2.11
libSSH Version => libssh/0.9.3/openssl/zlib

Directive => Local Value => Master Value
curl.cainfo => no value => no value

Is the curl.cainfo => no value => no value likely to be an issue? (same for FPM too)

edamov commented 3 years ago

Now I have no idea what can be wrong

schofs commented 3 years ago

If there's no errors coming back, does that suggest the curl is failing? I've tested that curl itself is working, so it's not that curl itself can't be called, but I'm wondering why there are no actual errors coming back.

schofs commented 3 years ago

OK - I've worked out the issue. Having gone through the code and looked at where the failure is, it's that the Curl requests to https sites are failing. So I added the following to prepareHandle(Notification $notification) in Client.php:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

And it's working now!

edamov commented 3 years ago

Seems it is the same problem which was fixed in PR #110 yesterday You can add curl options for Client in version 0.12.1

dinhdanh commented 3 years ago

@schofs I'm facing the same issue as you, but due to security reasons, we could not disable CURLOPT_SSL_VERIFYPEER by adding the above option. Any suggestion @edamov? I also have tried to download cacert.pem file from https://curl.se/docs/caextract.html and then add the option as: curl_setopt($ch, CURLOPT_CAINFO, "cacert.pem"); but it still not work

marcorocca commented 3 years ago

@dinhdanh you can use this approach we have discussed today.

dwightwatson commented 3 years ago

I think @andrew-bibby has uncovered the actual bug in Linux that's caused this, their comment on the related issue on a Laravel implementation of this library includes more information and a solution for the time being.