While trying to switch to the new APNs Provider API using Certificate based authentication, I am trying to get a script to deliver a push notification to my testing device.
<?php
HEADERS
- END_STREAM
+ END_HEADERS
:method = POST
:scheme = https
:path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
host = api.sandbox.push.apple.com
apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
apns-push-type = alert
apns-expiration = 0
apns-priority = 10
DATA
+ END_STREAM
{ "aps" : { "alert" : "Hello" } }
// Put your device token here (without spaces):
$deviceToken = 'bed76ed5078e6b1302f680bfec69aa73ead7045e67c9cb6dac31466b90513c7e';
// Put your private key's passphrase here:
$passphrase = 'pushchat';
// Put your alert message here:
$message = 'Hello!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://api.sandbox.push.apple.com:443', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
According to Sending Notification Requests to APNs
the method and path header request fields are now required.
When I try to run the script, the terminal output is:
PHP Parse error: syntax error, unexpected token ":" in /Users/Desktop/simple push folder/simplepush.php on line 6
When I delete lines 3 - 17, the terminal output is
`Connected to APNS
Message successfully delivered`
Though no message is received.
Do any of you know how to correctly add the request header fields to this script?
Post
Replies
Boosts
Views
Activity
This instance of imagePickerController takes a photo and sets it to a UIImageView IBOutlet.
.h
@property (retain, strong) UIImage* Image;
.m
#pragma mark - Image picker delegate methods
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
// Resize the image from the camera
UIImage *scaledImage = [image resizedImageWithContentMode:UIViewContentModeScaleAspectFill bounds:CGSizeMake(photo.frame.size.width, photo.frame.size.height) interpolationQuality:kCGInterpolationHigh];
// Crop the image to a square (yikes, fancy!)
UIImage *croppedImage = [scaledImage croppedImage:CGRectMake((scaledImage.size.width -photo.frame.size.width)/2, (scaledImage.size.height -photo.frame.size.height)/2, photo.frame.size.width, photo.frame.size.height)];
// Show the photo on the screen
photo.image = croppedImage;
[picker dismissModalViewControllerAnimated:NO];
}
After the photo is taken, it is over rotated 90 degrees? How can it be rotated back in place?
Solved
photo.transform=CGAffineTransformMakeRotation(M_PI*0.5);
Before the migration to the new APNs provider API requirement, this PHP script sent test notifications to a testing device.
Now when the script is run on a local server, the terminal output is
Connected to APNS Message successfully delivered
Though no push notification arrives on the test device.
<?php
// Put your device token here (without spaces):
$deviceToken = '09a0c8ff92b3621c5f5032c1fa031f2851d01dd99beaf1446c281c5458fe2ffd';
// Put your private key's passphrase here:
$passphrase = 'pushchat';
// Put your alert message here:
$message = 'Hello!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
After sending a TSI to Apple asking how to correctly migrate to the new APNs provider API, the response included, "To clarify, HTTP/2 is the connection protocol, and defines the endpoint, port, commands you use, and how you package your push request.”
Sending Notification Requests to APNs states:
Use HTTP/2 and TLS 1.2 or later to establish a connection between your provider server and one of the following servers..."
Development server: api.sandbox.push.apple.com:443
Production server: api.push.apple.com:443
"In addition to the preceding data, add the header fields in Table 1 to your request. Some header fields are required for delivering the notification. Other headers are optional or may depend on whether you’re using token-based or certificate-based authentication."
After trying to update the script with the correct servers as well as trying to implement how Sending Notification Requests to APNs documented the use of the new required header fields. The script was changed:
<?php
HEADERS
- END_STREAM
+ END_HEADERS
:method = POST
:scheme = https
:path = /3/device/bed76ed5078e6b1302f680bfec69aa73ead7045e67c9cb6dac31466b90513c7e
host = api.sandbox.push.apple.com
apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
apns-push-type = alert
apns-expiration = 0
apns-priority = 10
DATA
+ END_STREAM
// Put your device token here (without spaces):
$deviceToken = 'bed76ed5078e6b1302f680bfec69aa73ead7045e67c9cb6dac31466b90513c7e';
// Put your private key's passphrase here:
$passphrase = 'pushchat';
// Put your alert message here:
$message = 'Hello!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://api.sandbox.push.apple.com:443', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
When trying to run this script, the terminal output is:
Parse error: syntax error, unexpected ':' in /Users/MacBookAir/Desktop/simple push folder/simplepush.php on line 5
How should this script be written correctly in order to successfully be compatible with the new APNs provider API?
I've been using the following code to register for remote notifications using Objective C.
Recently, after building and running the app on a testing device, an iPad mini running iOS 9.3.5, the Debugger Window no longer prints the device token. registerForRemoteNotificationTypes: is not supported in iOS 8.0 and later.
I am trying to use the device token to send a test notification using Sending Push Notifications Using Command-Line Tools
//REGISTER FOR THE NOTIFICATIONS TYPES
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
//-- Set Notification
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
// iOS 8 Notifications
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[application registerForRemoteNotifications];
}
else
{
// iOS < 8 Notifications
_storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
_storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];
if (launchOptions != nil)
{
NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil)
{
NSLog(@"Launched from push notification: %@", dictionary);
/*[self addMessageFromRemoteNotification:dictionary updateUI:NO];*/
}
}
return YES;
}
I have also tried the following:
if (@available(iOS , *)) {
// iOS 8 Notifications: Registering for notifications and types
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[application registerForRemoteNotifications];
} else {
// iOS < 8 Notifications
_storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
And Xcode gives a parse error that says Expected a version of the form 'major[.minor[.subminor]]'
What is the correct way to register for push notifications on iOS 9 and above using Objective C?
I am trying to migrate to the new APNs Provider API.
Here is how I've been registering for push notifications:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
//-- Set Notification
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
// iOS 8 Notifications: Registering for notifications and types
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[application registerForRemoteNotifications];
}
else
{
// iOS < 8 Notifications
_storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
_storyBoard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];
if (launchOptions != nil)
{
NSDictionary* dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil)
{
NSLog(@"Launched from push notification: %@", dictionary);
/*[self addMessageFromRemoteNotification:dictionary updateUI:NO];*/
}
}
return YES;
}
Within the last week, I have been using the following terminal command from Sending Push Notifications Using Command-Line Tools to successfully send a test push notification to a testing device.
curl -v --header 'apns-topic: com.domain.appname' --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"Test"}}' --http2 https://api.sandbox.push.apple.com/3/device/258ecf658e25256c8f06ddb1138d5d536ba0e760a96ebd12d3b1dbe112857c58
Recently after creating provisioning profile and adding it to Xcode, the app no longer prints the device token in the debug window.
After removing the provisioning profile from my Apple Developer account under profiles, I tried using a backed up version of the app which still prints a device token to the debugger window.
When I copy the device token and enter it into the terminal command to send another test push notification, the terminal output is a 400 status code : {"reason":"BadDeviceToken"}* Closing connection 1
curl -v --header 'apns-topic: com.domain.appname' --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"Hello From Faunna"}}' --http2 https://api.sandbox.push.apple.com/3/device/a146d82d4acea02c9ef6de5838174292d0e2cd18a40be17fb79334c5003a0058
* Could not resolve host: alert
* Closing connection 0
curl: (6) Could not resolve host: alert
* Trying 17.188.138.73...
* TCP_NODELAY set
* Connected to api.sandbox.push.apple.com (17.188.138.73) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
Enter PEM pass phrase:
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=api.development.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US
* start date: Feb 8 21:41:22 2021 GMT
* expire date: Mar 10 21:41:22 2022 GMT
* subjectAltName: host "api.sandbox.push.apple.com" matched cert's "api.sandbox.push.apple.com"
* issuer: CN=Apple Public Server RSA CA 12 - G1; O=Apple Inc.; ST=California; C=US
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fbd4700aa00)
> POST /3/device/a146d82d4acea02c9ef6de5838174292d0e2cd18a40be17fb79334c5003a0058 HTTP/2
> Host: api.sandbox.push.apple.com
> User-Agent: curl/7.64.1
> Accept: */*
> apns-topic: com.faunna.PushChat
> Content-Length: 37
> Content-Type: application/x-www-form-urlencoded
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!
* We are completely uploaded and fine
< HTTP/2 400
< apns-id: 8DE6AA75-8E41-E95E-1FAF-51D93A8B3200
<
* Connection #1 to host api.sandbox.push.apple.com left intact
{"reason":"BadDeviceToken"}* Closing connection 1
What is causing the bad device token output in this set up? And how should I be registering for remote notifications from this point forward?
I have been trying to migrate to the new APNs Provider API.
I have successfully generated a new CSR, registered a new App ID, obtained a provider certificate from Apple, installed the certificate and private key on my provider server, and tested using my certificate to make a connection to APNs using this command:
openssl s_client -connect "${APNS_HOST_NAME}":443 -cert "${CERTIFICATE_FILE_NAME}" -certform DER -key "${CERTIFICATE_KEY_FILE_NAME}" -keyformat PEM
Then I Used The Following Command To Send A Push Notification:
% curl -v --header "apns-topic: ${TOPIC}" --header "apns-push-type: alert" --cert "${CERTIFICATE_FILE_NAME}" --cert-type DER --key "${CERTIFICATE_KEY_FILE_NAME}" --key-type PEM --data '{"aps":{"alert":"test"}}' --http2 https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}
The HTTP status: 200 (request succeeded), and delivery of a notification with the text “test”on my destination device.
Now I would like to use an existing API that uses APNs to send messages on iOS. I am ready to add the request header fields that seem to be required now.
Are provisioning profiles still required for APNs development for iOS? I did not see it mentioned in Apple's Documentation.
User Notifications
Setting Up a Remote Notification Server
Generating a Remote Notification
Sending Notification Requests to APNs
Sending Push Notifications Using Command-Line Tools
Based on Sending Push Notifications Using Command-Line Tools, these shell variables were set after making a new CSR, App ID, and obtaining a new provider certificate from Apple:
CERTIFICATE_FILE_NAME=/Users/developer/desktop/aps.cer
CERTIFICATE_KEY_FILE_NAME=/Users/developer/desktop/PushChatKey.p12
TOPIC=com.domainname.appname
DEVICE_TOKEN=af59ba83a511f21f343df63ebd1bcd32225878e7d9401a4e933a3caf0cf55a63
APNS_HOST_NAME=api.sandbox.push.apple.com
The following terminal command was entered to send a test push notification:
curl -v --header apns-topic: com.domainname.appname --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"test"}}' --http2 https://api.sandbox.push.apple.com/3/device/45822f2c09e0dbdfa6659b08f0b35ab8bda910d29f4abb107dfbf88f323e34f1
This was the resulting terminal output:
curl -v --header apns-topic: com.domainname.appname --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"test"}}' --http2 https://api.sandbox.push.apple.com/3/device/45822f2c09e0dbdfa6659b08f0b35ab8bda910d29f4abb107dfbf88f323e34f1
* Could not resolve host: com.domainname.appname
* Closing connection 0
curl: (6) Could not resolve host: com.domainname.appname
* Could not resolve host: alert
* Closing connection 1
curl: (6) Could not resolve host: alert
* Trying 17.188.138.71...
* TCP_NODELAY set
* Connected to api.sandbox.push.apple.com (17.188.138.71) port 443 (#2)
* ALPN, offering h2
* ALPN, offering http/1.1
Enter PEM pass phrase:
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=api.development.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US
* start date: Feb 8 21:41:22 2021 GMT
* expire date: Mar 10 21:41:22 2022 GMT
* subjectAltName: host "api.sandbox.push.apple.com" matched cert's "api.sandbox.push.apple.com"
* issuer: CN=Apple Public Server RSA CA 12 - G1; O=Apple Inc.; ST=California; C=US
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fe70780d600)
> POST /3/device/45822f2c09e0dbdfa6659b08f0b35ab8bda910d29f4abb107dfbf88f323e34f1 HTTP/2
> Host: api.sandbox.push.apple.com
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 24
> Content-Type: application/x-www-form-urlencoded
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 1000)!
* We are completely uploaded and fine
< HTTP/2 400
< apns-id: E9EC6D23-7E07-BA0A-B574-F478271AE803
<
* Connection #2 to host api.sandbox.push.apple.com left intact
{"reason":"MissingTopic"}* Closing connection 2
How can this be fixed?
the only difference between the new apns api and the old one seems to be the lack of pem file creation in the root directory.
Hello. Hope all is well.
The app I am working on stopped receiving push notifications yesterday. Both UI updates, and to the device.
I noticed an Apple Developer email that was sent out saying, "On March 29, 2021, token and certificate-based HTTP/2 connections to the Apple Push Notification service must incorporate the new root certificate (AAACertificateServices 5/12/2020) which replaces the old GeoTrust Global CA root certificate".
Can you please point me in the direction of learning the new technology to incorporate?
I'd also like to discuss the validity of the old way of creating SSL certificates and provisioning profiles?
Please help me affirm the previously taken steps to incorporate push via APNS as I learn about the new certificates.
I am:
generating a code signing request from the keychain application on mac
Exporting the private key as a p12 file
Creating a new app ID
Generating and downloading the SSL certificate
Generating the pem file
Making a new provisioning profile
Please help me verify whether these steps are still valid for the APNS enabled app functionality and If I am correct in assuming to drag the downloaded certs included in the Apple Developer email into the folder where the app I am working on connects to APNS.
Aaron N.
After configuring an app to use push notifications with a development provisioning profile and ssl certificate, it is time to switch to production mode so the app can be submitted to the app store.
Can the registered devices associated with a developer program membership receive push notifications if signed with a production provisioning profile and ssl certificate before being on the app store?
This project target breaks when an umbrella header is added.
Now there is an error of "No type or protocol named 'ComposeDelegate'" on of the target's existing <ComposeDelegate> protocols. This code had no errors before an umbrella header etc.
Any suggestions?
ComposeViewController.h
@class ComposeViewController;
@class DataModel;
@class Message;
// The delegate protocol for the Compose screen
@protocol ComposeDelegate <NSObject>
(void)didSaveMessage:(Message*)message atIndex:(int)index;
@end
@interface ComposeViewController : UIViewController /*<UITextViewDelegate>*/@property (nonatomic, assign) id<ComposeDelegate> delegate;
@property (nonatomic, strong) DataModel* dataModel;
@property (nonatomic, strong) AFHTTPClient *client;
@end