apns

package module
v0.0.0-...-e9c9bf0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2016 License: MIT Imports: 22 Imported by: 0

README

Apple Push Notification Service Provider (HTTP/2)

GoDoc Build Status Coverage Status

Apple Push Notification service includes the APNs Provider API that allows you to send remote notifications to your app on iOS, tvOS, and OS X devices, and to Apple Watch via iOS. This API is based on the HTTP/2 network protocol. Each interaction starts with a POST request, containing a JSON payload, that you send from your provider server to APNs. APNs then forwards the notification to your app on a specific user device.

With certificate authorization

Your APNs certificate, which you obtain as explained in Creating a Universal Push Notification Client SSL Certificate in App Distribution Guide, enables connection to both the APNs Production and Development environments.

You can use your APNs certificate to send notifications to your primary app, as identified by its bundle ID, as well as to any Apple Watch complications or backgrounded VoIP services associated with that app.

package main

import (
	"log"
	"math/rand"
	"time"

	"github.com/mdigger/apns"
)

func main() {
	cert, err := apns.LoadCertificate("cert.p12", "xopen123")
	if err != nil {
		log.Fatalln("Error loading certificate:", err)
	}
	client := apns.New(*cert)
	id, err := client.Push(apns.Notification{
		Token: `883982D57CDC4138D71E16B5ACBCB5DEBE3E625AFCEEE809A0F32895D2EA9D51`,
		Payload: map[string]interface{}{
			"aps": map[string]interface{}{
				"alert": "Hello!",
				"badge": rand.Int31n(99),
			},
			"time": time.Now().Format(time.RFC3339Nano),
		},
	})
	if err != nil {
		log.Fatalln("Error push:", err)
	}
	log.Println("Sent:", id)
}
With JWT authorization

You can use token-based authentication as an alternative to using provider certificates to connect to APNs. The provider API supports JSON Web Token (or JWT), an open standard, to pass authentication claims to APNs along with the push message.

package main

import (
	"log"
	"math/rand"
	"time"

	"github.com/mdigger/apns"
)
func main() {
	providerToken, err := apns.NewProviderToken("W23G28NPJW", "67XV3VSJ95")
	if err != nil {
		log.Fatal(err)
	}
	err = providerToken.LoadPrivateKey("APNSAuthKey_67XV3VSJ95.p8")
	if err != nil {
		log.Fatal(err)
	}
	client := apns.NewWithToken(providerToken)
	id, err := client.Push(apns.Notification{
		Token: `883982D57CDC4138D71E16B5ACBCB5DEBE3E625AFCEEE809A0F32895D2EA9D51`,
		Topic: "com.xyzrd.trackintouch",
		Payload: map[string]interface{}{
			"aps": map[string]interface{}{
				"alert": "Hello, JWT!",
				"badge": rand.Int31n(99),
			},
			"time": time.Now().Format(time.RFC3339Nano),
		},
	})
	if err != nil {
		log.Fatalln("Error push:", err)
	}
	log.Println("Sent:", id)
}

Documentation

Overview

Package apns provide a Apple Push Notification service provider.

Apple Push Notification service (APNs) is the centerpiece of the remote notifications feature. It is a robust and highly efficient service for propagating information to iOS (and, indirectly, watchOS), tvOS, and macOS devices. On initial activation, a device establishes an accredited and encrypted IP connection with APNs and receives notifications over this persistent connection. If a notification for an app arrives when that app is not running, the device alerts the user that the app has data waiting for it.

You provide your own server to generate remote notifications for the users of your app. This server, known as the provider, has three main responsibilities. It:

  • Gathers data for the users of your app
  • Decides when push notifications need to be sent and determines to which devices they should be sent
  • Sends notifications, which APNs conveys on your behalf to users

For each notification, the provider:

  1. Generates a notification payload
  2. Attaches the payload and a device identifier — the device token — to an HTTP/2 request
  3. Sends the request to APNs over a persistent and secure channel that uses the HTTP/2 network protocol

On receiving the HTTP/2 request, APNs delivers the notification payload to your app on the user's device.

Quality of Service

Apple Push Notification service includes a default Quality of Service (QoS) component that performs a store-and-forward function. If APNs attempts to deliver a notification but the destination device is offline, APNs stores the notification for a limited period of time and delivers it to the device when the device becomes available.

This mechanism stores only one recent notification per device, per app: if you send multiple notifications while a device is offline, a new notification causes the previous notification to be discarded.

If a device remains offline for a long time, all notifications that were being stored for it are discarded; when the device goes back online, none of the notifications are displayed.

When a device is online, all the notifications you send are delivered and available to the user. However, you can avoid showing duplicate notifications by employing a collapse identifier across multiple, identical notifications. The APNs request header key for the collapse identifier is "apns-collapse-id".

For example, a news service that sends the same headline twice in a row could employ the same collapse identifier for both push notification requests. APNs would then take care of coalescing these requests into a single notification for delivery to a device.

Security Architecture

To ensure secure communication, APNs servers employ connection certificates, certification authority (CA) certificates, and cryptographic keys (private and public) to validate connections to, and identities of, providers and devices. APNs regulates the entry points between providers and devices using two levels of trust: connection trust and device token trust.

Connection trust establishes certainty that APNs is connected to an authorized provider, owned by a company that Apple has agreed to deliver notifications for. You must take steps to ensure connection trust exists between your provider servers and APNs. APNs also uses connection trust with each device to ensure the legitimacy of the device. Connection trust with the device is handled automatically by APNs.

Device token trust ensures that notifications are routed only between legitimate start and end points. A device token is an opaque, unique identifier assigned to a specific app on a specific device. Each app instance receives its unique token when it registers with APNs. The app must share this token with its provider, to allow the provider to employ the token when communicating with APNs. Each notification that your provider sends to APNs must include the device token, which ensures that the notification is delivered only to the app-device combination for which it is intended.

Important: To protect user privacy, do not attempt to use a device token to identify a device.

Device tokens can change after updating the operating system, and always change when a device's data and settings are erased. Whenever the system delivers a device token to an instance of your app, the app must forward it to your provider servers to allow further push notifications to the device.

Provider-to-APNs Connection Trust

A provider using the HTTP/2-based APNs Provider API can use JSON web tokens (JWT) to validate the provider's connection with APNs. In this scheme, the provider does not require a certificate-plus-private key to establish connection. Instead, you provision a public key to be retained by Apple, and a private key which you retain and protect. Your providers then use your private key to generate and sign JWT authentication tokens. Each of your push requests must include an authentication token.

Important: To establish TLS sessions with APNs, you must ensure that a GeoTrust Global CA root certificate is installed on each of your providers. You can download this certificate from the GeoTrust Root Certificates website: https://www.geotrust.com/resources/root-certificates/.

The HTTP/2-based provider connection is valid for delivery to one specific app, identified by the topic (the app bundle ID) specified in the certificate. Depending on how you configure and provision your APNs Transport Layer Security (TLS) certificate, the trusted connection can also be valid for delivery of remote notifications to other items associated with your app, including Apple Watch complications and voice-over-Internet Protocol (VoIP) services. APNs delivers these notifications even when those items are running in the background.

APNs maintains a certificate revocation list; if a provider's certificate is on the revocation list, APNs can revoke provider trust (that is, APNs can refuse the TLS initiation connection).

Example
package main

import (
	"log"
	"math/rand"
	"time"

	"github.com/mdigger/apns"
)

func main() {
	cert, err := apns.LoadCertificate("cert.p12", "xopen123")
	if err != nil {
		log.Fatalln("Error loading certificate:", err)
	}
	client := apns.New(*cert)
	id, err := client.Push(apns.Notification{
		Token: `883982D57CDC4138D71E16B5ACBCB5DEBE3E625AFCEEE809A0F32895D2EA9D51`,
		Payload: map[string]interface{}{
			"aps": map[string]interface{}{
				"alert": "Hello!",
				"badge": rand.Int31n(99),
			},
			"time": time.Now().Format(time.RFC3339Nano),
		},
	})
	if err != nil {
		log.Fatalln("Error push:", err)
	}
	log.Println("Sent:", id)
}
Output:

Example (Jwt)
package main

import (
	"log"
	"math/rand"
	"time"

	"github.com/mdigger/apns"
)

func main() {
	provederToken, err := apns.NewProviderToken("W23G28NPJW", "67XV3VSJ95")
	if err != nil {
		log.Fatal(err)
	}
	err = provederToken.LoadPrivateKey("APNSAuthKey_67XV3VSJ95.p8")
	if err != nil {
		log.Fatal(err)
	}
	client := apns.NewWithToken(provederToken)
	id, err := client.Push(apns.Notification{
		Token: `883982D57CDC4138D71E16B5ACBCB5DEBE3E625AFCEEE809A0F32895D2EA9D51`,
		Topic: "com.xyzrd.trackintouch",
		Payload: map[string]interface{}{
			"aps": map[string]interface{}{
				"alert": "Hello, JWT!",
				"badge": rand.Int31n(99),
			},
			"time": time.Now().Format(time.RFC3339Nano),
		},
	})
	if err != nil {
		log.Fatalln("Error push:", err)
	}
	log.Println("Sent:", id)
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrPTBad           = errors.New("bad provider token")
	ErrPTBadKeyID      = errors.New("bad provider token key id")
	ErrPTBadTeamID     = errors.New("bad provider token team ID")
	ErrPTBadPrivateKey = errors.New("bad provider token private key")
)

Error parsing token provider.

View Source
var JWTLifeTime = time.Minute * 55

JWTLifeTime contains the lifetime of the authorization token provider, through which it needs to be automatically updated.

APNs will reject push messages with an Expired Provider Token error if the token issue timestamp is not within the last hour.

View Source
var Timeout = 15 * time.Second

Timeout contains the maximum waiting time connection to the APNS server.

Functions

func LoadCertificate

func LoadCertificate(filename, password string) (*tls.Certificate, error)

LoadCertificate return parsed TLS certificate from .p12 file.

Types

type CertificateInfo

type CertificateInfo struct {
	CName       string    // certificate full name
	OrgName     string    // organization name
	OrgUnit     string    // organization identifier
	Country     string    // country
	BundleID    string    // bundle ID
	Topics      []string  // supported topics
	Development bool      // sandbox support flag
	Production  bool      // production support flag
	IsApple     bool      // certificate signed by Apple flag
	Expire      time.Time // expire date and time
}

CertificateInfo describes information about the certificate.

func GetCertificateInfo

func GetCertificateInfo(certificate *tls.Certificate) *CertificateInfo

GetCertificateInfo parses and returns information about the certificate.

func (CertificateInfo) String

func (i CertificateInfo) String() string

String return certificate CName.

func (CertificateInfo) Support

func (i CertificateInfo) Support(topic string) bool

Support returns true, if the certificate support the specified topic.

type Client

type Client struct {
	Host string // http URL
	// contains filtered or unexported fields
}

Client supports APNs Provider API.

The APNs provider API lets you send remote notifications to your app on iOS, tvOS, and macOS devices, and to Apple Watch via iOS. The API is based on the HTTP/2 network protocol. Each interaction starts with a POST request, containing a JSON payload, that you send from your provider server to APNs. APNs then forwards the notification to your app on a specific user device.

The first step in sending a remote notification is to establish a connection with the appropriate APNs server Host:

Development server: api.development.push.apple.com:443
Production server:  api.push.apple.com:443

Note: You can alternatively use port 2197 when communicating with APNs. You might do this, for example, to allow APNs traffic through your firewall but to block other HTTPS traffic.

The APNs server allows multiple concurrent streams for each connection. The exact number of streams is based on the authentication method used (i.e. provider certificate or token) and the server load, so do not assume a specific number of streams. When you connect to APNs without a provider certificate, only one stream is allowed on the connection until you send a push message with valid token.

It is recommended to close all existing connections to APNs and open new connections when existing certificate or the key used to sign provider tokens is revoked.

func New

func New(certificate tls.Certificate) *Client

func NewWithToken

func NewWithToken(pt *ProviderToken) *Client

NewWithToken returns an initialized Client with JSON Web Token (JWT) authentication support.

func (*Client) Pool

func (c *Client) Pool(workers uint, responses chan<- Response) *ClientsPool

Pool wraps a client with a queue for sending notifications asynchronously.

You can establish multiple connections to APNs servers to improve performance. When you send a large number of remote notifications, distribute them across connections to several server endpoints. This improves performance, compared to using a single connection, by letting you send remote notifications faster and by letting APNs deliver them faster.

func (*Client) Push

func (c *Client) Push(notification Notification) (id string, err error)

Push send push notification to APNS API.

The APNs Provider API consists of a request and a response that you configure and send using an HTTP/2 POST command. You use the request to send a push notification to the APNs server and use the response to determine the results of that request.

Response from APNs:

  • The apns-id value from the request. If no value was included in the request, the server creates a new UUID and returns it in this header.
  • :status - the HTTP status code.
  • reason - the error indicating the reason for the failure. The error code is specified as a string.
  • timestamp - if the value in the :status header is 410, the value of this key is the last time at which APNs confirmed that the device token was no longer valid for the topic. Stop pushing notifications until the device registers a token with a later timestamp with your provider.

type ClientsPool

type ClientsPool struct {
	// contains filtered or unexported fields
}

ClientsPool manages a pool of Clients.

The APNs server allows multiple concurrent streams for each connection. The exact number of streams is based on the authentication method used (i.e. provider certificate or token) and the server load, so do not assume a specific number of streams. When you connect to APNs without a provider certificate, only one stream is allowed on the connection until you send a push message with valid token.

func (*ClientsPool) Close

func (p *ClientsPool) Close()

Close the channels for notifications and Responses and shutdown workers. You should only call this after all responses have been received.

func (*ClientsPool) Push

func (p *ClientsPool) Push(n Notification, tokens ...string)

Push queues a notification to the APN service.

type Error

type Error struct {
	// List of the possible status codes for a request (these values are
	// included in the :status header of the response):
	// 	400 Bad request
	// 	403 There was an error with the certificate.
	// 	405 The request used a bad :method value. Only POST requests are
	// 	    supported.
	// 	410 The device token is no longer active for the topic.
	// 	413 The notification payload was too large.
	// 	429 The server received too many requests for the same device token.
	// 	500 Internal server error
	// 	503 The server is shutting down and unavailable.
	Status int

	// The error indicating the reason for the failure.
	//
	// List of the possible error codes included in the reason key of a
	// response's JSON payload:
	// 	400 BadCollapseId - the collapse identifier exceeds the maximum allowed
	// 	    size.
	// 	400 BadDeviceToken - the specified device token was bad. Verify that the
	// 	    request contains a valid token and that the token matches the
	// 	    environment.
	// 	400 BadExpirationDate - the apns-expiration value is bad.
	// 	400 BadMessageId - the apns-id value is bad.
	// 	400 BadPriority - the apns-priority value is bad.
	// 	400 BadTopic - the apns-topic was invalid.
	// 	400 DeviceTokenNotForTopic - the device token does not match the
	// 	    specified topic.
	// 	400 DuplicateHeaders - one or more headers were repeated.
	// 	400 IdleTimeout - idle time out.
	// 	400 MissingDeviceToken - the device token is not specified in the
	// 	    request :path. Verify that the :path header contains the device
	// 	    token.
	// 	400 MissingTopic - the apns-topic header of the request was not
	// 	    specified and was required. The apns-topic header is mandatory when
	// 	    the client is connected using a certificate that supports multiple
	// 	    topics.
	// 	400 PayloadEmpty - the message payload was empty. Expected HTTP/2
	// 	    :status code is 400.
	// 	400 TopicDisallowed - pushing to this topic is not allowed.
	// 	403 BadCertificate - the certificate was bad.
	// 	403 BadCertificateEnvironment - the client certificate was for the wrong
	// 	    environment.
	// 	403 ExpiredProviderToken - the provider token is stale and a new token
	// 	    should be generated.
	// 	403 Forbidden - the specified action is not allowed.
	// 	403 InvalidProviderToken - the provider token is not valid or the token
	// 	    signature could not be verified
	// 	403 MissingProviderToken - no provider certificate was used to connect
	// 	    to APNs and Authorization header was missing or no provider token
	// 	    was specified
	// 	404 BadPath - the request contained a bad :path value.
	// 	405 MethodNotAllowed - the specified :method was not POST.
	// 	410 Unregistered - the device token is inactive for the specified topic.
	// 	    Expected HTTP/2 status code is 410; see Table 6-4.
	// 	413 PayloadTooLarge - the message payload was too large. See The Remote
	// 	    Notification Payload for details on maximum payload size.
	// 	429 TooManyProviderTokenUpdates - the provider token is being updated
	// 	    too often.
	// 	429 TooManyRequests - too many requests were made consecutively to the
	// 	    same device token.
	// 	500 InternalServerError - an internal server error occurred.
	// 	503 ServiceUnavailable - the service is unavailable.
	// 	503 Shutdown - the server is shutting down.
	Reason string `json:"reason"`

	// If the value in the :status header is 410, the value of this key is the
	// last time at which APNs confirmed that the device token was no longer
	// valid for the topic. Stop pushing notifications until the device
	// registers a token with a later timestamp with your provider.
	Timestamp int64 `json:"timestamp"`
}

Error describes the error response from the server.

func (*Error) Error

func (e *Error) Error() string

Error return full error description string.

func (*Error) IsToken

func (e *Error) IsToken() bool

IsToken returns true if the error associated with the device token.

func (*Error) Time

func (e *Error) Time() time.Time

Time return parsed time and date, returned from server with response. If the value in the Status is 410, the returned value is the last time at which APNs confirmed that the device token was no longer valid for the topic.

type Notification

type Notification struct {
	// Unique device token for the app.
	//
	// Every notification that your provider sends to APNs must be accompanied
	// by the device token associated of the device for which the notification
	// is intended.
	Token string

	// A canonical UUID that identifies the notification.  If there is an error
	// sending the notification, APNs uses this value to identify the
	// notification to your server.
	//
	// The canonical form is 32 lowercase hexadecimal digits, displayed in five
	// groups separated by hyphens in the form 8-4-4-4-12. An example UUID is
	// as follows: 123e4567-e89b-12d3-a456-42665544000
	//
	// If you omit this header, a new UUID is created by APNs and returned in
	// the response.
	ID string

	// This identifies the date when the notification is no longer valid and
	// can be discarded.
	//
	// If this value is in future time, APNs stores the notification and tries
	// to deliver it at least once, repeating the attempt as needed if it is
	// unable to deliver the notification the first time. If the value is
	// before now, APNs treats the notification as if it expires immediately
	// and does not store the notification or attempt to redeliver it.
	Expiration time.Time

	// Specify the hexadecimal bytes (hex-string) of the device token for the
	// target device.
	//
	// Flag for send the push message at a time that takes into account power
	// considerations for the device. Notifications with this priority might be
	// grouped and delivered in bursts. They are throttled, and in some cases
	// are not delivered.
	LowPriority bool

	// The topic of the remote notification, which is typically the bundle ID
	// for your app. The certificate you create in Member Center must include
	// the capability for this topic.
	//
	// If your certificate includes multiple topics, you can specify a value
	// for this. If you omit this or your APNs certificate does not specify
	// multiple topics, the APNs server uses the certificate's Subject as the
	// default topic.
	//
	// If you are using a provider token instead of a certificate, you must
	// specify a value for this request header. The topic you provide should be
	// provisioned for the your team named in your developer account.
	Topic string

	// Multiple notifications with same collapse identifier are displayed to the
	// user as a single notification. The value should not exceed 64 bytes.
	CollapseID string

	// The body content of your message is the JSON dictionary object containing
	// the notification data. The body data must not be compressed and its
	// maximum size is 4KB (4096 bytes). For a Voice over Internet Protocol
	// (VoIP) notification, the body data maximum size is 5KB (5120 bytes).
	Payload interface{}
}

Notification describes the Remote Notification for sending to Apple Push.

Each Apple Push Notification service (APNs) remote notification includes a payload. The payload contains the custom data you want to provide, along with information about how the system should alert the user.

The maximum payload size for a notification: for Regular push notification is 4KB (4096 bytes), for Voice over Internet Protocol (VoIP) notification — 5KB (5120 bytes).

APNs refuses notifications that exceed the maximum size.

For each notification, compose a JSON dictionary object (as defined by RFC 4627). This dictionary must contain another dictionary identified by the aps key. The aps dictionary can contain one or more properties that specify the following user notification types: an alert message to display to the user, a number to badge the app icon with and a sound to play.

If the target app isn't running when the notification arrives, the alert message, sound, or badge value is played or shown. If the app is running, the system delivers the notification to the app.

Providers can specify custom payload values outside the Apple-reserved aps dictionary. Custom values must use the JSON structured and primitive types: dictionary (object), array, string, number, and Boolean. You should not include customer information (or any sensitive data) as custom payload data. Instead, use it for such purposes as setting context (for the user interface) or internal metrics. For example, a custom payload value might be a conversation identifier for use by an instant-message client app or a timestamp identifying when the provider sent the notification. Any action associated with an alert message should not be destructive—for example, it should not delete data on the device.

Important: Delivery of notifications is a “best effort”, not guaranteed. It is not intended to deliver data to your app, only to notify the user that there is new data available.

The aps dictionary can also contain the content-available property. The content-available property with a value of 1 lets the remote notification act as a silent notification. When a silent notification arrives, iOS wakes up your app in the background so that you can get new data from your server or do background information processing. Users aren't told about the new or changed information that results from a silent notification, but they can find out about it the next time they open your app.

For a silent notification, take care to ensure there is no alert, sound, or badge payload in the aps dictionary. If you don't follow this guidance, the incorrectly-configured notification might be throttled and not delivered to the app in the background, and instead of being silent is displayed to the user.

type ProviderToken

type ProviderToken struct {
	// contains filtered or unexported fields
}

ProviderToken is Provider Authentication Tokens.

If the provider token signing key is suspected to be compromised, you can revoke the key from your online developer account. You can issue a new key pair and generate new tokens with the new private key. For maximum security, it is recommended to close connections to APNs that were using the tokens signed with the revoked key and reconnect before using tokens signed with the new key.

func NewProviderToken

func NewProviderToken(teamID, keyID string) (*ProviderToken, error)

NewProviderToken returns a new ProviderToken with the established IDs team and key. Your Team ID and Key ID values can be obtained from your developer account.

func ProviderTokenFromPEM

func ProviderTokenFromPEM(data []byte) (*ProviderToken, error)

ProviderTokenFromPEM parses and returns the description of the ProviderToken from PEM format.

func (*ProviderToken) JWT

func (pt *ProviderToken) JWT() (string, error)

JWT returns a string with the signed authorization token in JWT format.

The provider token that authorizes APNs to send push notifications for the specified topics. The token is in Base64URL-encoded JWT format, specified as bearer <provider token>.

In order to ensure security, APNs requires new tokens to be generated periodically (confirm the validity). The new token will have an updated Issued At claim indicating the time when the token was generated. APNs will reject push messages with an Expired Provider Token error if the token issue timestamp is not within the last hour.

func (*ProviderToken) LoadPrivateKey

func (pt *ProviderToken) LoadPrivateKey(filename string) error

LoadPrivateKey loads a private key from a file in PKCS8 format.

func (*ProviderToken) MarshalJSON

func (pt *ProviderToken) MarshalJSON() ([]byte, error)

MarshalJSON returns the description of the ProviderToken using the JSON format.

func (*ProviderToken) SetPrivateKey

func (pt *ProviderToken) SetPrivateKey(privateKey []byte) error

SetPrivateKey adds to the ProviderToken private key in the format of ASN.1.

func (*ProviderToken) SetPrivateKeyPKCS8

func (pt *ProviderToken) SetPrivateKeyPKCS8(data []byte) error

SetPrivateKeyPKCS8 adds to the ProviderToken private key in the format of PKCS8.

func (*ProviderToken) String

func (pt *ProviderToken) String() string

String returns a string with the IDs team and key.

func (*ProviderToken) UnmarshalJSON

func (pt *ProviderToken) UnmarshalJSON(data []byte) error

UnmarshalJSON restores the ProviderToken from a JSON format.

func (*ProviderToken) WritePEM

func (pt *ProviderToken) WritePEM(out io.Writer) error

WritePEM stores the ProviderToken in PEM format.

type Response

type Response struct {
	Token string // Unique device token for the app.
	ID    string // A canonical UUID that identifies the notification
	Error error  // Error describes the error response from the server
}

Response from sending a notification.

Directories

Path Synopsis
Send Apple Push notification ./push [-params] <token> [<token2> [...]] -t use development service -b badge badge number -c certificate push certificate (default "cert.p12") -f file JSON file with push message -p password certificate password -a text message text (default "Hello!") Sample JSON file: { "payload": { "aps": { "alert": "message", "badge": 0 } } }
Send Apple Push notification ./push [-params] <token> [<token2> [...]] -t use development service -b badge badge number -c certificate push certificate (default "cert.p12") -f file JSON file with push message -p password certificate password -a text message text (default "Hello!") Sample JSON file: { "payload": { "aps": { "alert": "message", "badge": 0 } } }

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL