apns

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Apr 23, 2022 License: MIT Imports: 19 Imported by: 0

README

APNs Provider

HTTP/2 Apple Push Notification service (APNs) provider for Go with token-based connection

Example:

key, err := apns.AuthKeyFromFile("AuthKey_XXXXXXXXXX.p8")
if err != nil {
	log.Fatal(err)
}

token := apns.NewToken(key, "XXXXXXXXXX", "YYYYYYYYYY")
client := apns.NewClient(token, nil)

n := &apns.Notification{
	DeviceToken: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
	Host:        apns.HostDevelopment,
	Topic:       "com.example.app",
	Payload: apns.BuildPayload(&apns.APS{
		Alert: "Hi",
	}, nil),
}

fmt.Println(client.Push(n))

Documentation

Overview

APNS package for sending remote notifications for iOS by token-based connection.

Example
key, err := apns.AuthKeyFromFile("testdata/AuthKey_5MDQ4KLTY7.p8")
if err != nil {
	log.Fatal(err)
}

token := apns.NewToken(key, "5MDQ4KLTY7", "SUPERTEEM1")
client := apns.NewClient(token, nil)

n := &apns.Notification{
	DeviceToken: "7c968c83f6fd6de5843c309150ed1a706bc64fcdc42310f66054c0271e67219e",
	Topic:       "com.example.app",
	ID:          "EC1BF194-B3B2-424A-89A9-5A918A6E6B5D",
	Host:        apns.HostDevelopment,
	PushType:    apns.PushTypeAlert,
	Priority:    apns.PriorityHigh,

	Payload: apns.BuildPayload(&apns.APS{
		Alert: apns.Alert{
			Title: "Hello",
		},
		Sound: apns.SoundDefault,
	}, map[string]interface{}{
		"push-id": "EC1BF194-B3B2-424A-89A9-5A918A6E6B5D",
		"type":    "hello",
	}),
}

res, err := client.Push(n)
if err != nil {
	log.Fatal(err)
}
if res.Status == apns.Status200 {
	fmt.Println("Successfully sent!")
} else {
	fmt.Println("Sent failed by reason:", res.Reason)
}
Output:

Index

Examples

Constants

View Source
const (
	// Development server.
	HostDevelopment = "https://api.sandbox.push.apple.com"

	// Development server with 2197 port.
	HostDevelopmentPort2197 = "https://api.sandbox.push.apple.com:2197"

	// Production server.
	HostProduction = "https://api.push.apple.com"

	// Production server with 2197 port.
	HostProductionPort2197 = "https://api.push.apple.com:2197"
)

Use HTTP/2 and TLS 1.2 or later to establish a connection between your provider server and one of the following servers:

View Source
const (
	// Use the alert push type for notifications that trigger
	// a user interaction—for example, an alert, badge, or sound.
	// If you set this push type, the apns-topic header field
	// must use your app’s bundle ID as the topic.
	//
	// If the notification requires immediate action from the user,
	// set notification priority to 10; otherwise use 5.
	//
	// The alert push type is required on watchOS 6 and later.
	// It is recommended on macOS, iOS, tvOS, and iPadOS.
	PushTypeAlert = "alert"

	// Use the background push type for notifications that deliver content in the background,
	// and don’t trigger any user interactions.
	// If you set this push type, the apns-topic header field must use
	// your app’s bundle ID as the topic. Always use priority 5.
	// Using priority 10 is an error. For more information,
	// see https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app.
	//
	// The background push type is required on watchOS 6 and later.
	// It is recommended on macOS, iOS, tvOS, and iPadOS.
	PushTypeBackground = "background"

	// Use the voip push type for notifications that provide information about
	// an incoming Voice-over-IP (VoIP) call. For more information,
	// see https://developer.apple.com/documentation/pushkit/responding_to_voip_notifications_from_pushkit.
	//
	// If you set this push type, the apns-topic header field must use your app’s bundle ID
	// with .voip appended to the end. If you’re using certificate-based authentication,
	// you must also register the certificate for VoIP services.
	// The topic is then part of the 1.2.840.113635.100.6.3.4 or 1.2.840.113635.100.6.3.6 extension.
	//
	// The voip push type is not available on watchOS.
	// It is recommended on macOS, iOS, tvOS, and iPadOS.
	PushTypeVoIP = "voip"

	// Use the complication push type for notifications
	// that contain update information for a watchOS app’s complications.
	// For more information,
	// see https://developer.apple.com/documentation/clockkit/keeping_your_complications_up_to_date.
	//
	// If you set this push type, the apns-topic header field
	// must use your app’s bundle ID with .complication appended to the end.
	// If you’re using certificate-based authentication,
	// you must also register the certificate for WatchKit services.
	// The topic is then part of the 1.2.840.113635.100.6.3.6 extension.
	//
	// The complication push type is recommended for watchOS and iOS.
	// It is not available on macOS, tvOS, and iPadOS.
	PushTypeComplication = "complication"

	// Use the fileprovider push type to signal changes to a File Provider extension.
	// If you set this push type, the apns-topic header field
	// must use your app’s bundle ID with .pushkit.fileprovider appended to the end.
	// For more information,
	// see https://developer.apple.com/documentation/fileprovider/content_and_change_tracking/tracking_your_file_provider_s_changes/using_push_notifications_to_signal_changes.
	//
	// The fileprovider push type is not available on watchOS.
	// It is recommended on macOS, iOS, tvOS, and iPadOS.
	PushTypeFileprovider = "fileprovider"

	// Use the mdm push type for notifications
	// that tell managed devices to contact the MDM server.
	// If you set this push type, you must use the topic
	// from the UID attribute in the subject
	// of your MDM push certificate.
	// For more information,
	// see https://developer.apple.com/documentation/devicemanagement.
	//
	// The mdm push type is not available on watchOS.
	// It is recommended on macOS, iOS, tvOS, and iPadOS.
	PushTypeMDM = "mdm"
)

Values for Notification.PushType field.

View Source
const (
	// Specify 10 to send the notification immediately.
	PriorityHigh = 10

	// Specify 5 to send the notification based on power considerations on the user’s device.
	PriorityLow = 5
)

Values for Notification.Priority field.

View Source
const (
	// The system presents the notification immediately,
	// lights up the screen, and can play a sound.
	InterruptionLevelActive = "active"

	// The system presents the notification immediately,
	// lights up the screen, and bypasses the mute switch to play a sound.
	InterruptionLevelCritical = "critical"

	// The system adds the notification to the notification list
	// without lighting up the screen or playing a sound.
	InterruptionLevelPassive = "passive"

	// The system presents the notification immediately, lights up the screen,
	// and can play a sound, but won’t break through system notification controls.
	InterruptionLevelTimeSensitive = "time-senstive"
)

Strings that indicates the importance and delivery timing of a notification

View Source
const (
	// Success.
	Status200 = 200

	// Bad request.
	Status400 = 400

	// There was an error with the certificate or with the provider’s authentication token.
	Status403 = 403

	// The request contained an invalid :path value.
	Status404 = 404

	// The request used an invalid :method value. Only POST requests are supported.
	Status405 = 405

	// The device token is no longer active for the topic.
	Status410 = 410

	// The notification payload was too large.
	Status413 = 413

	// The server received too many requests for the same device token.
	Status429 = 429

	// Internal server error.
	Status500 = 500

	// The server is shutting down and unavailable.
	Status503 = 503
)

The possible values in the :status header of the response.

View Source
const (
	// Status 400. The collapse identifier exceeds the maximum allowed size.
	// The same as ReasonInvalidCollapseId but APNs returns InvalidCollapseId instead of BadCollapseId.
	ReasonBadCollapseId = "BadCollapseId"

	// Status 400. The collapse identifier exceeds the maximum allowed size.
	// The same as ReasonBadCollapseId but APNs returns InvalidCollapseId instead of BadCollapseId.
	ReasonInvalidCollapseId = "InvalidCollapseId"

	// Status 400. The specified device token is invalid.
	// Verify that the request contains a valid token and that the token matches the environment.
	ReasonBadDeviceToken = "BadDeviceToken"

	// Status 400. The apns-expiration value is invalid.
	ReasonBadExpirationDate = "BadExpirationDate"

	// Status 400. The apns-id value is invalid.
	ReasonBadMessageId = "BadMessageId"

	// Status 400. The apns-priority value is invalid.
	ReasonBadPriority = "BadPriority"

	// Status 400. The apns-topic value is invalid.
	ReasonBadTopic = "BadTopic"

	// Status 400. The device token doesn’t match the specified topic.
	ReasonDeviceTokenNotForTopic = "DeviceTokenNotForTopic"

	// Status 400. One or more headers are repeated.
	ReasonDuplicateHeaders = "DuplicateHeaders"

	// Status 400. Idle timeout.
	ReasonIdleTimeout = "IdleTimeout"

	// Status 400. The apns-push-type value is invalid.
	ReasonInvalidPushType = "InvalidPushType"

	// Status 400. The device token isn’t specified in the request :path.
	// Verify that the :path header contains the device token.
	ReasonMissingDeviceToken = "MissingDeviceToken"

	// Status 400. The apns-topic header of the request isn’t specified and is required.
	// The apns-topic header is mandatory when the client is connected
	// using a certificate that supports multiple topics.
	ReasonMissingTopic = "MissingTopic"

	// Status 400. The message payload is empty.
	ReasonPayloadEmpty = "PayloadEmpty"

	// Status 400. Pushing to this topic is not allowed.
	ReasonTopicDisallowed = "TopicDisallowed"

	// Status 403. The certificate is invalid.
	ReasonBadCertificate = "BadCertificate"

	// Status 403. The client certificate is for the wrong environment.
	ReasonBadCertificateEnvironment = "BadCertificateEnvironment"

	// Status 403. The provider token is stale and a new token should be generated.
	ReasonExpiredProviderToken = "ExpiredProviderToken"

	// Status 403. The specified action is not allowed.
	ReasonForbidden = "Forbidden"

	// Status 403. The provider token is not valid, or the token signature can't be verified.
	ReasonInvalidProviderToken = "InvalidProviderToken"

	// Status 403. No provider certificate was used to connect to APNs,
	// and the authorization header is missing or no provider token is specified.
	ReasonMissingProviderToken = "MissingProviderToken"

	// Status 404. The request contained an invalid :path value.
	ReasonBadPath = "BadPath"

	// Status 405. The specified :method value isn’t POST.
	ReasonMethodNotAllowed = "MethodNotAllowed"

	// Status 410. The device token is inactive for the specified topic.
	// There is no need to send further pushes to the same device token,
	// unless your application retrieves the same device token,
	// see https://developer.apple.com/documentation/usernotifications/registering_your_app_with_apns.
	ReasonUnregistered = "Unregistered"

	// Status 413. The message payload is too large.
	// For information about the allowed payload size,
	// see https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns#2947607.
	ReasonPayloadTooLarge = "PayloadTooLarge"

	// Status 429. The provider’s authentication token is being updated too often.
	// Update the authentication token no more than once every 20 minutes.
	ReasonTooManyProviderTokenUpdates = "TooManyProviderTokenUpdates"

	// Status 429. Too many requests were made consecutively to the same device token.
	ReasonTooManyRequests = "TooManyRequests"

	// Status 500. An internal server error occurred.
	ReasonInternalServerError = "InternalServerError"

	// Status 503. The service is unavailable.
	ReasonServiceUnavailable = "ServiceUnavailable"

	// Status 503. The APNs server is shutting down.
	ReasonShutdown = "Shutdown"
)

The possible error codes included in the reason key of a response’s JSON payload.

View Source
const SoundDefault = "default"

Default system sound.

View Source
const TokenRefreshInterval = 2400 // 40 minutes

For security, APNs requires you to refresh your token regularly. Refresh your token no more than once every 20 minutes and no less than once every 60 minutes. APNs rejects any request whose token contains a timestamp that is more than one hour old. Similarly, APNs reports an error if you recreate your tokens more than once every 20 minutes.

Variables

View Source
var (
	// .p8 file is not PEM encoded or invalid PEM file.
	ErrAuthKeyBadPEM = errors.New("authkey: invalid PEM")

	// PEM block does not contain private key in PKCS #8, ASN.1 DER form.
	ErrAuthKeyBadPKCS8 = errors.New("authkey: invalid PKCS#8")

	// Authentication token signing key is not ECDSA private key with P-256 curve.
	ErrAuthKeyNotECDSAP256 = errors.New("authkey: not ECDSA P-256")
)
View Source
var (
	ErrClientNotificationNil = errors.New("client: notification is nil")
	ErrClientTokenNil        = errors.New("client: token is nil")
)
View Source
var (
	// Private key is not ECDSA key with P-256 curve.
	ErrJWTKeyNotECDSAP256 = errors.New("jwt: not ECDSA P-256 key")
)
View Source
var ErrTokenKeyNil = errors.New("token: key is nil")

Functions

func AuthKeyFromBytes

func AuthKeyFromBytes(bytes []byte) (*ecdsa.PrivateKey, error)

AuthKeyFromBytes loads an authentication token signing key from the in memory bytes and returns an *ecdsa.PrivateKey.

func AuthKeyFromFile

func AuthKeyFromFile(name string) (*ecdsa.PrivateKey, error)

AuthKeyFromFile loads an authentication token signing key from the named text file with a .p8 file extension and returns an *ecdsa.PrivateKey.

func BuildPayload

func BuildPayload(aps *APS, custom map[string]interface{}) map[string]interface{}

BuildPayload builds a remote notification payload from Apple-defined keys aps and custom keys custom. Returns merged payload from aps keys and custom keys. Aps will be choosen as result if it was presented in custom also.

Example
enc := json.NewEncoder(os.Stdout)

payload := apns.BuildPayload(&apns.APS{
	Alert: "Hello",
}, nil)
err := enc.Encode(payload)
if err != nil {
	log.Fatal(err)
}

payload = apns.BuildPayload(&apns.APS{
	Alert: "Hello",
}, map[string]interface{}{
	"type": "hello",
})
err = enc.Encode(payload)
if err != nil {
	log.Fatal(err)
}

payload = apns.BuildPayload(nil, map[string]interface{}{
	"aps": map[string]interface{}{
		"alert": "Hello",
	},
	"type": "hello",
})
err = enc.Encode(payload)
if err != nil {
	log.Fatal(err)
}
Output:

{"aps":{"alert":"Hello"}}
{"aps":{"alert":"Hello"},"type":"hello"}
{"aps":{"alert":"Hello"},"type":"hello"}

func GenerateBearer

func GenerateBearer(key *ecdsa.PrivateKey, keyID, teamID string, issuedAt int64) (string, error)

GenerateBearer creates JSON token with keyID, teamID and issuedAt and encrypts by an authentication token signing key with the ES256 algorithm. Returns encrypted token that used in the authorization header of a notification request as bearer <token data>.

Example
key, err := apns.AuthKeyFromFile("testdata/AuthKey_5MDQ4KLTY7.p8")
if err != nil {
	log.Fatal(err)
}

token, err := apns.GenerateBearer(key, "5MDQ4KLTY7", "SUPERTEEM1", time.Now().Unix())
if err != nil {
	log.Fatal(err)
}

n := &apns.Notification{
	// Notification parameters and payload
}

req, err := n.BuildRequest()
if err != nil {
	log.Fatal(err)
}

apns.SetBearer(req.Header, token)
// res, err := http.DefaultClient.Do(req)
Output:

func SetBearer added in v0.3.0

func SetBearer(h http.Header, b string)

Types

type APS

type APS struct {
	// String or Alert struct.
	// The information for displaying an alert.
	// A dictionary (Alert) is recommended. If you specify a string,
	// the alert displays your string as the body text.
	Alert interface{} `json:"alert,omitempty"`

	// Int or nil.
	// The number to display in a badge on your app’s icon.
	// Specify 0 to remove the current badge, if any.
	Badge interface{} `json:"badge,omitempty"`

	// String or Sound struct.
	// The name of a sound file in your app’s main bundle
	// or in the Library/Sounds folder of your app’s container directory.
	// Specify the string "default" (SoundDefault) to play the system sound.
	// Use this key for regular notifications.
	// For critical alerts, use the sound dictionary (Sound) instead.
	// For information about how to prepare sounds,
	// see https://developer.apple.com/documentation/usernotifications/unnotificationsound.
	Sound interface{} `json:"sound,omitempty"`

	// An app-specific identifier for grouping related notifications.
	// This value corresponds to the threadIdentifier property in the UNNotificationContent object.
	// See https://developer.apple.com/documentation/usernotifications/unmutablenotificationcontent/1649872-threadidentifier,
	ThreadID string `json:"thread-id,omitempty"`

	// The notification’s type.
	// This string must correspond to the identifier of one of the UNNotificationCategory objects you register at launch time.
	// See https://developer.apple.com/documentation/usernotifications/declaring_your_actionable_notification_types.
	Category string `json:"category,omitempty"`

	// The background notification flag.
	// To perform a silent background update,
	// specify the value 1 and don't include the alert, badge, or sound keys in your payload.
	// See https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app.
	ContentAvailable int `json:"content-available,omitempty"`

	// The notification service app extension flag.
	// If the value is 1, the system passes the notification
	// to your notification service app extension before delivery.
	// Use your extension to modify the notification’s content.
	// https://developer.apple.com/documentation/usernotifications/modifying_content_in_newly_delivered_notificationss.
	MutableContent int `json:"mutable-content,omitempty"`

	// The identifier of the window brought forward.
	// The value of this key will be populated on the UNNotificationContent object created from the push payload.
	// Access the value using the UNNotificationContent object's targetContentIdentifier property.
	TargetContentID string `json:"target-content-id,omitempty"`

	// A string that indicates the importance and delivery timing of a notification.
	// The string values “passive”, “active”, “time-senstive”, or “critical”
	// correspond to the UNNotificationInterruptionLevel enumeration cases.
	InterruptionLevel string `json:"interruption-level,omitempty"`

	// Float64 or nil.
	// The relevance score, a number between 0 and 1,
	// that the system uses to sort the notifications from your app.
	// The highest score gets featured in the notification summary.
	// See https://developer.apple.com/documentation/usernotifications/unnotificationcontent/3821031-relevancescore.
	RelevanceScore interface{} `json:"relevance-score,omitempty"`

	URLArgs []string `json:"url-args,omitempty"`
}

APS represents Apple-defined remote notification payload keys and their custom values.

type Alert

type Alert struct {
	// The title of the notification.
	// Apple Watch displays this string in the short look notification interface.
	// Specify a string that is quickly understood by the user.
	Title string `json:"title,omitempty"`

	// Additional information that explains the purpose of the notification.
	Subtitle string `json:"subtitle,omitempty"`

	// The content of the alert message.
	Body string `json:"body,omitempty"`

	// The name of the launch image file to display.
	// If the user chooses to launch your app,
	// the contents of the specified image
	// or storyboard file are displayed instead of your app's normal launch image.
	LaunchImage string `json:"launch-image,omitempty"`

	// The key for a localized title string.
	// Specify this key instead of the title key to retrieve
	// the title from your app’s Localizable.strings files.
	// The value must contain the name of a key in your strings file.
	TitleLocKey string `json:"title-loc-key,omitempty"`

	// An array of strings containing replacement values for variables in your title string.
	// Each %@ character in the string specified by the title-loc-key is replaced by a value from this array.
	// The first item in the array replaces the first instance of the %@ character in the string,
	// the second item replaces the second instance, and so on.
	TitleLocArgs []string `json:"title-loc-args,omitempty"`

	// The key for a localized subtitle string.
	// Use this key, instead of the subtitle key,
	// to retrieve the subtitle from your app's Localizable.strings file.
	// The value must contain the name of a key in your strings file.
	SubtitleLocKey string `json:"subtitle-loc-key,omitempty"`

	// An array of strings containing replacement values for variables in your title string.
	// Each %@ character in the string specified by subtitle-loc-key is replaced by a value from this array.
	// The first item in the array replaces the first instance of the %@ character in the string,
	// the second item replaces the second instance, and so on.
	SubtitleLocArgs []string `json:"subtitle-loc-args,omitempty"`

	// The key for a localized message string.
	// Use this key, instead of the body key,
	// to retrieve the message text from your app's Localizable.strings file.
	// The value must contain the name of a key in your strings file.
	LocKey string `json:"loc-key,omitempty"`

	// An array of strings containing replacement values for variables in your message text.
	// Each %@ character in the string specified by loc-key is replaced by a value from this array.
	// The first item in the array replaces the first instance of the %@ character in the string,
	// the second item replaces the second instance, and so on.
	LocArgs []string `json:"loc-args,omitempty"`

	// The string the notification adds to the category’s summary format string.
	// Deprecated since iOS 15.
	SummaryArg string `json:"summary-arg,omitempty"`

	// The number of items the notification adds to the category’s summary format string.
	// Deprecated since iOS 15.
	SummaryArgCount int `json:"summary-arg-count,omitempty"`

	Action       string `json:"action,omitempty"`
	ActionLocKey string `json:"action-loc-key,omitempty"`
}

The information for displaying an alert.

type Client

type Client struct {
	Token      *Token
	HTTPClient *http.Client
}

Token-based client for sending remote notifications.

func NewClient

func NewClient(token *Token, httpClient *http.Client) *Client

NewClient creates client with token and http.Client client, pass nil for client to use http.DefaultClient.

func (*Client) Push

func (c *Client) Push(n *Notification) (*Response, error)

Push sends remote notification.

func (*Client) PushWithContext

func (c *Client) PushWithContext(ctx context.Context, n *Notification) (*Response, error)

Push sends remote notification with context.

type Notification

type Notification struct {
	// The device token is the hexadecimal bytes that identify the user’s device.
	// Your app receives the bytes for this device token w
	// hen registering for remote notifications;
	// see https://developer.apple.com/documentation/usernotifications/registering_your_app_with_apns.
	DeviceToken string

	Host string

	// A canonical UUID that is the unique ID for the notification.
	// If an error occurs when sending the notification,
	// APNs includes this value when reporting the error to your server.
	// If you omit this header,
	// APNs creates a UUID for you and returns it in its response.
	ID string // header: apns-id

	// The topic for the notification.
	// In general, the topic is your app’s bundle ID/app ID.
	// It can have a suffix based on the type of push notification.
	// If you are using a certificate that supports Pushkit VoIP
	// or watchOS complication notifications,
	// you must include this header with bundle ID of you app
	// and if applicable, the proper suffix.
	// If you are using token-based authentication with APNs,
	// you must include this header with the correct bundle ID
	// and suffix combination.
	Topic string // header: apns-topic

	// The value of this header must accurately reflect the contents
	// of your notification’s payload. If there is a mismatch,
	// or if the header is missing on required systems,
	// APNs may return an error, delay the delivery of the notification,
	// or drop it altogether.
	// Required for watchOS 6 and later; recommended for macOS, iOS, tvOS, and iPadOS.
	PushType string // header: apns-push-type

	// The date at which the notification is no longer valid.
	// This value is a UNIX epoch expressed in seconds (UTC).
	// If the value is nonzero, APNs stores the notification
	// and tries to deliver it at least once,
	// repeating the attempt as needed until the specified date.
	// If the value is 0, APNs attempts to deliver
	// the notification only once and doesn’t store it.
	Expiration string // header: apns-expiration

	// The priority of the notification.
	// If you omit this header, APNs sets the notification priority to 10.
	// Specify 10 to send the notification immediately.
	// Specify 5 to send the notification based on power considerations on the user’s device.
	Priority int // header: apns-priority

	// An identifier you use to coalesce multiple notifications
	// into a single notification for the user.
	// Typically, each notification request causes
	// a new notification to be displayed on the user’s device.
	// When sending the same notification more than once,
	// use the same value in this header to coalesce the requests.
	// The value of this key must not exceed 64 bytes.
	CollapseID string // header: apns-collapse-id

	// The JSON payload with the notification’s content.
	// The JSON payload must not be compressed
	// and is limited to a maximum size of 4 KB (4096 bytes).
	// For a Voice over Internet Protocol (VoIP) notification,
	// the maximum size is 5 KB (5120 bytes).
	Payload interface{}
}
Example
key, err := apns.AuthKeyFromFile("testdata/AuthKey_5MDQ4KLTY7.p8")
if err != nil {
	log.Fatal(err)
}
token := apns.NewToken(key, "5MDQ4KLTY7", "SUPERTEEM1")

n := &apns.Notification{
	DeviceToken: "7c968c83f6fd6de5843c309150ed1a706bc64fcdc42310f66054c0271e67219e",
	Topic:       "com.example.app",
	ID:          "EC1BF194-B3B2-424A-89A9-5A918A6E6B5D",
	Host:        apns.HostDevelopment,

	Payload: apns.BuildPayload(&apns.APS{
		Alert: apns.Alert{
			Title: "Hello",
		},
		Sound: apns.SoundDefault,
	}, nil),
}

req, err := n.BuildRequest()
if err != nil {
	log.Fatal(err)
}

token.SetAuthorization(req.Header)
// res, err := http.DefaultClient.Do(req)
Output:

Example (Payload)
enc := json.NewEncoder(os.Stdout)

n := &apns.Notification{
	Payload: `{"aps":{"alert":"Hello"}}`,
}
err := enc.Encode(n)
if err != nil {
	log.Fatal(err)
}

n = &apns.Notification{
	Payload: []byte(`{"aps":{"alert":"Hello"}}`),
}
err = enc.Encode(n)
if err != nil {
	log.Fatal(err)
}

n = &apns.Notification{
	Payload: apns.BuildPayload(&apns.APS{
		Alert: "Hello",
	}, nil),
}
err = enc.Encode(n)
if err != nil {
	log.Fatal(err)
}
Output:

{"aps":{"alert":"Hello"}}
{"aps":{"alert":"Hello"}}
{"aps":{"alert":"Hello"}}

func (*Notification) BuildRequest

func (n *Notification) BuildRequest() (*http.Request, error)

BuildRequest builds remote notification request for notification.

func (*Notification) BuildRequestWithContext

func (n *Notification) BuildRequestWithContext(ctx context.Context) (*http.Request, error)

BuildRequestWithContext builds request with context.

func (*Notification) MarshalJSON

func (n *Notification) MarshalJSON() ([]byte, error)

MarshalJSON marshals the notification payload to JSON.

func (*Notification) Path

func (n *Notification) Path() string

The path to the device token. The value of this header is /3/device/<device_token>.

func (*Notification) SetHeaders

func (n *Notification) SetHeaders(h http.Header)

SetHeaders sets headers of notification for remote notification request.

func (*Notification) URL

func (n *Notification) URL() string

URL builds full URL of remote notification request. If Host field omitted HostProduction will be used.

type Response

type Response struct {
	// The same value found in the apns-id field of the request’s header.
	// Use this value to identify the notification.
	// If you don’t specify an apns-id field in your request,
	// APNs creates a new UUID and returns it in this header.
	ID string // header: apns-id

	// The HTTP status code.
	Status int // header: :status

	// The error code (specified as a string) indicating the reason for the failure.
	Reason string `json:"reason,omitempty"`

	// The time, represented in milliseconds since Epoch,
	// at which APNs confirmed the token was no longer valid for the topic.
	// This key is included only when the error in the :status field is 410.
	Timestamp int64 `json:"timestamp,omitempty"`
}

Response for APNs request. Each response contains a header with fields indicating the status of the response. If the request was successful, the body of the response is empty. If an error occurred, the body contains a JSON dictionary with additional information about the error.

func ParseResponse

func ParseResponse(r *http.Response) (*Response, error)

ParseResponse parses HTTP response r from APNs request. Parses request header and JSON body.

type Sound

type Sound struct {
	// The critical alert flag. Set to 1 to enable the critical alert.
	Critical int `json:"critical,omitempty"`

	// The name of a sound file in your app’s main bundle
	// or in the Library/Sounds folder of your app’s container directory.
	// Specify the string "default" to play the system sound.
	// For information about how to prepare sounds,
	// see https://developer.apple.com/documentation/usernotifications/unnotificationsound.
	Name string `json:"name,omitempty"`

	// The volume for the critical alert’s sound.
	// Set this to a value between 0 (silent) and 1 (full volume).
	Volume float32 `json:"volume,omitempty"`
}

A dictionary that contains sound information for critical alerts. For regular notifications, use the sound string instead.

type Token

type Token struct {
	sync.Mutex

	// Authentication token signing key extracted from a text file (with a .p8 file extension).
	// Use AuthKeyFromFile or AuthKeyFromBytes.
	Key *ecdsa.PrivateKey

	// The 10-character Key ID you obtained from your developer account
	// with an authentication token signing key.
	KeyID string

	// The value is the 10-character Team ID you use for developing your company’s apps.
	// Obtain this value from your developer account.
	TeamID string

	// Time window in from IssuedAt to IssuedAt + RefreshInterval
	// when Bearer is not expired.
	RefreshInterval int64 // in seconds

	// Time at Bearer was generated.
	IssuedAt int64 // Epoch time in seconds

	// Generated JWT Token for APNs request authorization at IssuedAt time.
	Bearer string
}

Token represents JSON Token used for token-based connection to APNs.

func NewToken

func NewToken(key *ecdsa.PrivateKey, keyID, teamID string) *Token

NewToken returns Token with key, keyID, teamID with default TokenRefreshInterval. How obtain credentials, see https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns#2943371

func (*Token) Expired

func (t *Token) Expired() bool

func (*Token) Generate

func (t *Token) Generate() (string, error)

func (*Token) GenerateIfExpired

func (t *Token) GenerateIfExpired() (string, error)

func (*Token) SetAuthorization

func (t *Token) SetAuthorization(h http.Header) error

Jump to

Keyboard shortcuts

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