diff --git a/src/AuthProvider/Certificate.php b/src/AuthProvider/Certificate.php index cf44c88..69d4cbe 100644 --- a/src/AuthProvider/Certificate.php +++ b/src/AuthProvider/Certificate.php @@ -84,7 +84,30 @@ public function authenticateClient(Request $request) ] ); $request->addHeaders([ - "apns-topic" => $this->appBundleId + 'apns-topic' => $this->generateApnsTopic($request->getHeaders()['apns-push-type']), ]); } + + /** + * Generate a correct apns-topic string + * + * @param string $pushType + * @return string + */ + public function generateApnsTopic(string $pushType) + { + switch ($pushType) { + case 'voip': + return $this->appBundleId . '.voip'; + + case 'complication': + return $this->appBundleId . '.complication'; + + case 'fileprovider': + return $this->appBundleId . '.pushkit.fileprovider'; + + default: + return $this->appBundleId; + } + } } diff --git a/src/AuthProvider/Token.php b/src/AuthProvider/Token.php index bc9c03d..295746c 100644 --- a/src/AuthProvider/Token.php +++ b/src/AuthProvider/Token.php @@ -136,11 +136,34 @@ public static function useExisting(string $tokenString, array $options): Token public function authenticateClient(Request $request) { $request->addHeaders([ - "apns-topic" => $this->appBundleId, - 'Authorization' => 'bearer ' . $this->token + 'apns-topic' => $this->generateApnsTopic($request->getHeaders()['apns-push-type']), + 'Authorization' => 'bearer ' . $this->token, ]); } + /** + * Generate a correct apns-topic string + * + * @param string $pushType + * @return string + */ + public function generateApnsTopic(string $pushType) + { + switch ($pushType) { + case 'voip': + return $this->appBundleId . '.voip'; + + case 'complication': + return $this->appBundleId . '.complication'; + + case 'fileprovider': + return $this->appBundleId . '.pushkit.fileprovider'; + + default: + return $this->appBundleId; + } + } + /** * Get last generated token. * diff --git a/tests/AuthProvider/CertificateTest.php b/tests/AuthProvider/CertificateTest.php index 9868d71..908611a 100644 --- a/tests/AuthProvider/CertificateTest.php +++ b/tests/AuthProvider/CertificateTest.php @@ -21,20 +21,15 @@ class CertificateTest extends TestCase { public function testCreatingCertificateAuthProvider() { - $options = []; - $options['certificate_path'] = __DIR__ . '/../files/certificate.pem'; - $options['certificate_secret'] = 'secret'; + $options = $this->getOptions(); $authProvider = Certificate::create($options); $this->assertInstanceOf(AuthProviderInterface::class, $authProvider); } - public function testCreatingCertificateAuthProviderWithAppBundleId() + public function testAuthenticatingClient() { - $options = []; - $options['certificate_path'] = __DIR__ . '/../files/certificate.pem'; - $options['certificate_secret'] = 'secret'; - $options['app_bundle_id'] = 'com.apple.test'; + $options = $this->getOptions(); $authProvider = Certificate::create($options); $request = $this->createRequest(); @@ -42,14 +37,53 @@ public function testCreatingCertificateAuthProviderWithAppBundleId() $this->assertSame($request->getOptions()[CURLOPT_SSLCERT], $options['certificate_path']); $this->assertSame($request->getOptions()[CURLOPT_SSLCERTPASSWD], $options['certificate_secret']); - $this->assertSame($request->getOptions()[CURLOPT_SSLCERTPASSWD], $options['certificate_secret']); + } + + public function testVoipApnsTopic() + { + $options = $this->getOptions(); + $authProvider = Certificate::create($options); + + $request = $this->createRequest('voip'); + $authProvider->authenticateClient($request); + + $this->assertSame($request->getHeaders()['apns-topic'], $options['app_bundle_id'] . '.voip'); + } + + public function testComplicationApnsTopic() + { + $options = $this->getOptions(); + $authProvider = Certificate::create($options); - $this->assertSame($request->getHeaders()["apns-topic"], $options['app_bundle_id']); + $request = $this->createRequest('complication'); + $authProvider->authenticateClient($request); + + $this->assertSame($request->getHeaders()['apns-topic'], $options['app_bundle_id'] . '.complication'); + } + + public function testFileproviderApnsTopic() + { + $options = $this->getOptions(); + $authProvider = Certificate::create($options); + + $request = $this->createRequest('fileprovider'); + $authProvider->authenticateClient($request); + + $this->assertSame($request->getHeaders()['apns-topic'], $options['app_bundle_id'] . '.pushkit.fileprovider'); + } + + private function getOptions() + { + return [ + 'certificate_path' => __DIR__ . '/../files/certificate.pem', + 'certificate_secret' => 'secret', + 'app_bundle_id' => 'com.apple.test', + ]; } - private function createRequest(): Request + private function createRequest(string $pushType = 'alert'): Request { - $notification = new Notification(Payload::create(), '123'); + $notification = new Notification(Payload::create()->setPushType($pushType), '123'); $request = new Request($notification, $production = false); return $request; diff --git a/tests/AuthProvider/TokenTest.php b/tests/AuthProvider/TokenTest.php index 9cd7c39..76c511ac 100644 --- a/tests/AuthProvider/TokenTest.php +++ b/tests/AuthProvider/TokenTest.php @@ -12,39 +12,30 @@ namespace Pushok\AuthProvider; use PHPUnit\Framework\TestCase; -use Pushok\AuthProvider; use Pushok\AuthProviderInterface; +use Pushok\Notification; +use Pushok\Payload; +use Pushok\Request; class TokenTest extends TestCase { - public function testCreatingTokenAuthProvider() + public function testCreatingTokenAuthProviderWithKeyPath() { $options = $this->getOptions(); $options['private_key_path'] = __DIR__ . '/../files/private_key.p8'; - $authProvider = AuthProvider\Token::create($options); + $authProvider = Token::create($options); $this->assertInstanceOf(AuthProviderInterface::class, $authProvider); $this->assertTrue(is_string($authProvider->get())); } - private function getOptions() - { - return [ - 'key_id' => '1234567890', - 'team_id' => '1234567890', - 'app_bundle_id' => 'com.app.Test', - ]; - } - public function testCreatingTokenAuthProviderWithKeyContent() { $options = $this->getOptions(); - $options['private_key_content'] = file_get_contents( implode(DIRECTORY_SEPARATOR, [__DIR__, '..', 'files', 'private_key.p8']) ); - - $authProvider = AuthProvider\Token::create($options); + $authProvider = Token::create($options); $this->assertInstanceOf(AuthProviderInterface::class, $authProvider); $this->assertTrue(is_string($authProvider->get())); @@ -55,7 +46,7 @@ public function testCreatingTokenAuthProviderWithoutKey() $this->expectException(\InvalidArgumentException::class); $options = $this->getOptions(); - AuthProvider\Token::create($options); + Token::create($options); } public function testUseExistingToken() @@ -64,9 +55,62 @@ public function testUseExistingToken() 'YxR8Hw--Hp8YH8RF2QDiwOjmGhTC_7g2DpbnzKQZ8Sj20-q12LrLrAMafcuxf97CTHl9hCVere0vYrzcLmGV-A'; $options = $this->getOptions(); - $authProvider = AuthProvider\Token::useExisting($token, $options); + $authProvider = Token::useExisting($token, $options); $this->assertInstanceOf(AuthProviderInterface::class, $authProvider); $this->assertEquals($token, $authProvider->get()); } + + public function testVoipApnsTopic() + { + $options = $this->getOptions(); + $options['private_key_path'] = __DIR__ . '/../files/private_key.p8'; + $authProvider = Token::create($options); + + $request = $this->createRequest('voip'); + $authProvider->authenticateClient($request); + + $this->assertSame($request->getHeaders()['apns-topic'], $options['app_bundle_id'] . '.voip'); + } + + public function testComplicationApnsTopic() + { + $options = $this->getOptions(); + $options['private_key_path'] = __DIR__ . '/../files/private_key.p8'; + $authProvider = Token::create($options); + + $request = $this->createRequest('complication'); + $authProvider->authenticateClient($request); + + $this->assertSame($request->getHeaders()['apns-topic'], $options['app_bundle_id'] . '.complication'); + } + + public function testFileproviderApnsTopic() + { + $options = $this->getOptions(); + $options['private_key_path'] = __DIR__ . '/../files/private_key.p8'; + $authProvider = Token::create($options); + + $request = $this->createRequest('fileprovider'); + $authProvider->authenticateClient($request); + + $this->assertSame($request->getHeaders()['apns-topic'], $options['app_bundle_id'] . '.pushkit.fileprovider'); + } + + private function getOptions() + { + return [ + 'key_id' => '1234567890', + 'team_id' => '1234567890', + 'app_bundle_id' => 'com.app.Test', + ]; + } + + private function createRequest(string $pushType = 'alert'): Request + { + $notification = new Notification(Payload::create()->setPushType($pushType), '123'); + $request = new Request($notification, $production = false); + + return $request; + } }