Help us shape the future of Go! Take the 2026 Go Developer Survey

apns

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

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

Go to latest
Published: Sep 18, 2016 License: MIT Imports: 15 Imported by: 3

README

#modify:

add ComboPEMClient use combo pem file (cert & key in one pem)

	pemfile := "your/combo/pem/file"

	payload := apns.NewPayload()
	payload.Alert = "Hello, world!"
	payload.Badge = 42
	payload.Sound = "bingbong.aiff"

	pn := apns.NewPushNotification()
	pn.DeviceToken = "your device token"
	pn.AddPayload(payload)

	client := apns.ComboPEMClient("gateway.sandbox.push.apple.com:2195", pemfile)

	resp := client.Send(pn)

	alert, _ := pn.PayloadString()
	fmt.Println("  Alert:", alert)
	fmt.Println("Success:", resp.Success)
	fmt.Println("  Error:", resp.Error)
	

apns

Utilities for Apple Push Notification and Feedback Services.

Installation

go get github.com/anachronistic/apns

Documentation

Usage

Creating pns and payloads manually
package main

import (
  "fmt"
  apns "github.com/anachronistic/apns"
)

func main() {
  payload := apns.NewPayload()
  payload.Alert = "Hello, world!"
  payload.Badge = 42
  payload.Sound = "bingbong.aiff"

  pn := apns.NewPushNotification()
  pn.AddPayload(payload)

  alert, _ := pn.PayloadString()
  fmt.Println(alert)
}
Returns
{
  "aps": {
    "alert": "Hello, world!",
    "badge": 42,
    "sound": "bingbong.aiff"
  }
}
Using an alert dictionary for complex payloads
package main

import (
  "fmt"
  apns "github.com/anachronistic/apns"
)

func main() {
  args := make([]string, 1)
  args[0] = "localized args"

  dict := apns.NewAlertDictionary()
  dict.Body = "Alice wants Bob to join in the fun!"
  dict.ActionLocKey = "Play a Game!"
  dict.LocKey = "localized key"
  dict.LocArgs = args
  dict.LaunchImage = "image.jpg"

  payload := apns.NewPayload()
  payload.Alert = dict
  payload.Badge = 42
  payload.Sound = "bingbong.aiff"

  pn := apns.NewPushNotification()
  pn.AddPayload(payload)

  alert, _ := pn.PayloadString()
  fmt.Println(alert)
}
Returns
{
  "aps": {
    "alert": {
      "body": "Alice wants Bob to join in the fun!",
      "action-loc-key": "Play a Game!",
      "loc-key": "localized key",
      "loc-args": [
        "localized args"
      ],
      "launch-image": "image.jpg"
    },
    "badge": 42,
    "sound": "bingbong.aiff"
  }
}
Setting custom properties
package main

import (
  "fmt"
  apns "github.com/anachronistic/apns"
)

func main() {
  payload := apns.NewPayload()
  payload.Alert = "Hello, world!"
  payload.Badge = 42
  payload.Sound = "bingbong.aiff"

  pn := apns.NewPushNotification()
  pn.AddPayload(payload)

  pn.Set("foo", "bar")
  pn.Set("doctor", "who?")
  pn.Set("the_ultimate_answer", 42)

  alert, _ := pn.PayloadString()
  fmt.Println(alert)
}
Returns
{
  "aps": {
    "alert": "Hello, world!",
    "badge": 42,
    "sound": "bingbong.aiff"
  },
  "doctor": "who?",
  "foo": "bar",
  "the_ultimate_answer": 42
}
Sending a notification
package main

import (
  "fmt"
  apns "github.com/anachronistic/apns"
)

func main() {
  payload := apns.NewPayload()
  payload.Alert = "Hello, world!"
  payload.Badge = 42
  payload.Sound = "bingbong.aiff"

  pn := apns.NewPushNotification()
  pn.DeviceToken = "YOUR_DEVICE_TOKEN_HERE"
  pn.AddPayload(payload)

  client := apns.NewClient("gateway.sandbox.push.apple.com:2195", "YOUR_CERT_PEM", "YOUR_KEY_NOENC_PEM")
  resp := client.Send(pn)

  alert, _ := pn.PayloadString()
  fmt.Println("  Alert:", alert)
  fmt.Println("Success:", resp.Success)
  fmt.Println("  Error:", resp.Error)
}
Returns
  Alert: {"aps":{"alert":"Hello, world!","badge":42,"sound":"bingbong.aiff"}}
Success: true
  Error: <nil>
Checking the feedback service
package main

import (
  "fmt"
  apns "github.com/anachronistic/apns"
  "os"
)

func main() {
  fmt.Println("- connecting to check for deactivated tokens (maximum read timeout =", apns.FEEDBACK_TIMEOUT_SECONDS, "seconds)")

  client := apns.NewClient("gateway.sandbox.push.apple.com:2195", "YOUR_CERT_PEM", "YOUR_KEY_NOENC_PEM")
  go client.ListenForFeedback()

  for {
    select {
    case resp := <-apns.FeedbackChannel:
      fmt.Println("- recv'd:", resp.DeviceToken)
    case <-apns.ShutdownChannel:
      fmt.Println("- nothing returned from the feedback service")
      os.Exit(1)
    }
  }
}
Returns
- connecting to check for deactivated tokens (maximum read timeout = 5 seconds)
- nothing returned from the feedback service
exit status 1

Your output will differ if the service returns device tokens.

- recv'd: DEVICE_TOKEN_HERE
...etc.

Documentation

Index

Constants

View Source
const FEEDBACK_TIMEOUT_SECONDS = 5

Wait at most this many seconds for feedback data from Apple.

View Source
const IDENTIFIER_UBOUND = 9999

Every push notification gets a pseudo-unique identifier; this establishes the upper boundary for it. Apple will return this identifier if there is an issue sending your notification.

View Source
const MAX_PAYLOAD_SIZE_BYTES = 256

Your total notification payload cannot exceed 256 bytes.

View Source
const PUSH_COMMAND_VALUE = 1

Push commands always start with command value 1.

View Source
const TIMEOUT_SECONDS = 5

The maximum number of seconds we're willing to wait for a response from the Apple Push Notification Service.

Variables

View Source
var APPLE_PUSH_RESPONSES = map[uint8]string{
	0:   "NO_ERRORS",
	1:   "PROCESSING_ERROR",
	2:   "MISSING_DEVICE_TOKEN",
	3:   "MISSING_TOPIC",
	4:   "MISSING_PAYLOAD",
	5:   "INVALID_TOKEN_SIZE",
	6:   "INVALID_TOPIC_SIZE",
	7:   "INVALID_PAYLOAD_SIZE",
	8:   "INVALID_TOKEN",
	10:  "SHUTDOWN",
	255: "UNKNOWN",
}

This enumerates the response codes that Apple defines for push notification attempts.

View Source
var FeedbackChannel = make(chan (*FeedbackResponse))

FeedbackChannel will receive individual responses from Apple.

View Source
var ShutdownChannel = make(chan bool)

If there's nothing to read, ShutdownChannel gets a true.

Functions

func StartMockFeedbackServer

func StartMockFeedbackServer()

This is a simple stand-in for the Apple feedback service that can be used for testing purposes. Doesn't handle many errors, etc. Just for the sake of having something "live" to hit.

Types

type AlertDictionary

type AlertDictionary struct {
	Body         string   `json:"body,omitempty"`
	ActionLocKey string   `json:"action-loc-key,omitempty"`
	LocKey       string   `json:"loc-key,omitempty"`
	LocArgs      []string `json:"loc-args,omitempty"`
	LaunchImage  string   `json:"launch-image,omitempty"`
}

From the APN docs: "Use the ... alert dictionary in general only if you absolutely need to." The AlertDictionary is suitable for specific localization needs.

func NewAlertDictionary

func NewAlertDictionary() *AlertDictionary

Constructor.

type Client

type Client struct {
	Gateway           string
	CertificateFile   string
	CertificateBase64 string
	KeyFile           string
	KeyBase64         string
}

You'll need to provide your own CertificateFile and KeyFile to send notifications. Ideally, you'll just set the CertificateFile and KeyFile fields to a location on drive where the certs can be loaded, but if you prefer you can use the CertificateBase64 and KeyBase64 fields to store the actual contents.

func BareClient

func BareClient(gateway, certificateBase64, keyBase64 string) (c *Client)

Constructor. Use this if you want to set cert and key blocks manually.

func ComboPEMClient

func ComboPEMClient(gateway, comboPEMFile string) (c *Client)

func NewClient

func NewClient(gateway, certificateFile, keyFile string) (c *Client)

Constructor. Use this if you want to load cert and key blocks from a file.

func (*Client) ConnectAndWrite

func (this *Client) ConnectAndWrite(resp *PushNotificationResponse, payload []byte) (err error)

In lieu of a timeout (which would be available in Go 1.1) we use a timeout channel pattern instead. We start two goroutines, one of which just sleeps for TIMEOUT_SECONDS seconds, while the other waits for a response from the Apple servers.

Whichever channel puts data on first is the "winner". As such, it's possible to get a false positive if Apple takes a long time to respond. It's probably not a deal-breaker, but something to be aware of.

func (*Client) ListenForFeedback

func (this *Client) ListenForFeedback() (err error)

Connect to the Apple Feedback Service and check for feedback. Feedback consists of device identifiers that should not be sent to in the future; Apple does monitor that you respect this so you should be checking it ;)

func (*Client) Send

func (this *Client) Send(pn *PushNotification) (resp *PushNotificationResponse)

Connects to the APN service and sends your push notification. Remember that if the submission is successful, Apple won't reply.

type FeedbackResponse

type FeedbackResponse struct {
	Timestamp   uint32
	DeviceToken string
}

func NewFeedbackResponse

func NewFeedbackResponse() (resp *FeedbackResponse)

Constructor.

type Payload

type Payload struct {
	Alert            interface{} `json:"alert,omitempty"`
	Badge            int         `json:"badge,omitempty"`
	Sound            string      `json:"sound,omitempty"`
	ContentAvailable int         `json:"content-available,omitempty"`
}

Alert is an interface here because it supports either a string or a dictionary, represented within by an AlertDictionary struct.

func NewPayload

func NewPayload() *Payload

Constructor.

type PushNotification

type PushNotification struct {
	Identifier  int32
	Expiry      uint32
	DeviceToken string
	// contains filtered or unexported fields
}

The PushNotification is the wrapper for the Payload. The length fields are computed in ToBytes() and aren't represented here.

func NewPushNotification

func NewPushNotification() (pn *PushNotification)

Constructor. Also initializes the pseudo-random identifier.

func (*PushNotification) AddData

func (this *PushNotification) AddData(value interface{})

func (*PushNotification) AddPayload

func (this *PushNotification) AddPayload(p *Payload)

func (*PushNotification) Get

func (this *PushNotification) Get(key string) interface{}

func (*PushNotification) PayloadJSON

func (this *PushNotification) PayloadJSON() ([]byte, error)

func (*PushNotification) PayloadString

func (this *PushNotification) PayloadString() (string, error)

func (*PushNotification) Set

func (this *PushNotification) Set(key string, value interface{})

func (*PushNotification) ToBytes

func (this *PushNotification) ToBytes() ([]byte, error)

Returns a byte array of the complete PushNotification struct. This array is what should be transmitted to the APN Service.

type PushNotificationResponse

type PushNotificationResponse struct {
	Success       bool
	AppleResponse string
	Error         error
}

func NewPushNotificationResponse

func NewPushNotificationResponse() (resp *PushNotificationResponse)

Constructor.

Jump to

Keyboard shortcuts

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