golang通过HTTP/2协议发送Apple推送通知插件库APNs2的使用

Golang通过HTTP/2协议发送Apple推送通知插件库APNs2的使用

概述

APNS/2是一个Go语言包,设计用于通过新的HTTP/2推送提供者API在iOS、OSX和Safari上发送简单、灵活且快速的Apple推送通知。

特性

  • 使用新的Apple APNs HTTP/2连接
  • 快速
  • 支持Go 1.7及更高版本
  • 支持新的Apple基于令牌的认证(JWT)
  • 支持iOS 10新特性如折叠ID、副标题和可变通知
  • 支持iOS 15新特性interruptionLevel和relevanceScore
  • 支持与APNs的持久连接
  • 支持VoIP/PushKit通知(iOS 8及更高版本)
  • 模块化且易于使用
  • 已在APNs生产环境中测试并运行

安装

  1. 确保已安装Go并设置了GOPATH
  2. 安装apns2:
go get -u github.com/sideshow/apns2

如果运行测试套件,还需要安装testify:

go get -u github.com/stretchr/testify

示例代码

基本使用示例

package main

import (
  "log"
  "fmt"

  "github.com/sideshow/apns2"
  "github.com/sideshow/apns2/certificate"
)

func main() {
  // 加载证书文件
  cert, err := certificate.FromP12File("../cert.p12", "")
  if err != nil {
    log.Fatal("Cert Error:", err)
  }

  // 创建通知
  notification := &apns2.Notification{}
  notification.DeviceToken = "11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"
  notification.Topic = "com.sideshow.Apns2"
  notification.Payload = []byte(`{"aps":{"alert":"Hello!"}}`) // 参见下面的Payload部分

  // 如果要测试直接从XCode运行的构建的推送通知(开发环境),使用:
  // client := apns2.NewClient(cert).Development()
  // 对于发布到App Store或作为ad-hoc分发的应用,使用Production()

  client := apns2.NewClient(cert).Production()
  res, err := client.Push(notification)

  if err != nil {
    log.Fatal("Error:", err)
  }

  fmt.Printf("%v %v %v\n", res.StatusCode, res.ApnsID, res.Reason)
}

JWT令牌认证示例

authKey, err := token.AuthKeyFromFile("../AuthKey_XXX.p8")
if err != nil {
  log.Fatal("token error:", err)
}

token := &token.Token{
  AuthKey: authKey,
  // 来自开发者账户的KeyID(证书、标识符和配置文件 -> 密钥)
  KeyID:   "ABC123DEFG",
  // 来自开发者账户的TeamID(查看账户 -> 会员资格)
  TeamID:  "DEF123GHIJ",
}
...

client := apns2.NewTokenClient(token)
res, err := client.Push(notification)

通知结构

通知至少需要DeviceToken、Topic和Payload:

notification := &apns2.Notification{
  DeviceToken: "11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7",
  Topic: "com.sideshow.Apns2",
  Payload: []byte(`{"aps":{"alert":"Hello!"}}`),
}

还可以设置可选的ApnsID、Expiration或Priority:

notification.ApnsID =  "40636A2C-C093-493E-936A-2A4333C06DEA"
notification.Expiration = time.Now()
notification.Priority = apns2.PriorityLow

Payload构建

可以使用原始字节作为notification.Payload,也可以使用payload构建器包,它使构建APNs payload变得容易:

// {"aps":{"alert":"hello","badge":1},"key":"val"}

payload := payload.NewPayload().Alert("hello").Badge(1).Custom("key", "val")

notification.Payload = payload
client.Push(notification)

响应和错误处理

APNS/2区分来自Apple的有效响应(指示通知是否发送成功)和不可恢复或意外的错误:

  • 如果发生不可恢复的错误(如底层http.Client连接或证书有问题、payload未发送或未收到有效响应),将返回Error
  • 如果payload成功发送到Apple并收到文档化的响应,将返回Response

检查通知是否成功发送:

res, err := client.Push(notification)
if err != nil {
  log.Println("There was an error", err)
  return
}

if res.Sent() {
  log.Println("Sent:", res.ApnsID)
} else {
  fmt.Printf("Not Sent: %v %v %v\n", res.StatusCode, res.ApnsID, res.Reason)
}

上下文和超时

为了更好地控制请求取消和超时,APNS/2支持上下文:

ctx, cancel = context.WithTimeout(context.Background(), 10 * time.Second)
res, err := client.PushWithContext(ctx, notification)
defer cancel()

速度和性能

为了获得最佳性能,应该保留一个apns2.Client实例,而不是每次推送都重新创建它。底层TLS连接本身可能需要几秒钟来连接和协商,因此如果每次推送都设置和拆除apns2.Client,这将极大地影响性能。(Apple建议始终保持连接打开)

还应该限制apns2.Client实例的数量。底层传输本身有一个http连接池,因此单个客户端实例对大多数用户来说就足够了(一个实例每秒可以处理4000+推送)。如果需要更多,那么每个CPU核心一个实例是一个很好的起点。

命令行工具

APNS/2有一个命令行工具,可以通过go get github.com/sideshow/apns2/apns2安装。用法:

apns2 --help
usage: apns2 --certificate-path=CERTIFICATE-PATH --topic=TOPIC [<flags>]

Listens to STDIN to send notifications and writes APNS response code and reason to STDOUT.

The expected format is: <DeviceToken> <APNS Payload>
Example: aff0c63d9eaa63ad161bafee732d5bc2c31f66d552054718ff19ce314371e5d0 {"aps": {"alert": "hi"}}
Flags:
      --help               Show context-sensitive help (also try --help-long and --help-man).
  -c, --certificate-path=CERTIFICATE-PATH
                           Path to certificate file.
  -t, --topic=TOPIC        The topic of the remote notification, which is typically the bundle ID for your app
  -m, --mode="production"  APNS server to send notifications to. `production` or `development`. Defaults to `production`
      --version            Show application version.

许可证

MIT许可证


更多关于golang通过HTTP/2协议发送Apple推送通知插件库APNs2的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang通过HTTP/2协议发送Apple推送通知插件库APNs2的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用APNs2库通过HTTP/2协议发送Apple推送通知

APNs2是一个流行的Go语言库,用于通过Apple的HTTP/2推送通知服务(APNs)发送iOS、macOS和Safari推送通知。下面我将详细介绍如何使用这个库。

安装APNs2

首先,你需要安装APNs2库:

go get github.com/sideshow/apns2

基本使用示例

1. 准备必要的证书和密钥

你需要从Apple开发者账户获取以下文件之一:

  • 证书文件(.p12)和密码
  • 或者认证密钥文件(.p8)

2. 使用证书认证的示例代码

package main

import (
	"crypto/tls"
	"log"

	"github.com/sideshow/apns2"
	"github.com/sideshow/apns2/certificate"
	"github.com/sideshow/apns2/payload"
)

func main() {
	// 1. 加载证书
	cert, err := certificate.FromP12File("path/to/cert.p12", "password")
	if err != nil {
		log.Fatal("证书错误:", err)
	}

	// 2. 创建客户端
	client := apns2.NewClient(cert).Production() // 或者使用 .Development() 测试环境

	// 3. 创建通知
	notification := &apns2.Notification{
		DeviceToken: "设备token字符串",
		Topic:       "你的应用bundle ID", // 如 com.example.app
		Payload:     payload.NewPayload().Alert("Hello, APNs2!").Badge(1),
	}

	// 4. 发送通知
	res, err := client.Push(notification)
	if err != nil {
		log.Fatal("发送错误:", err)
	}

	log.Printf("状态: %v, 原因: %v", res.StatusCode, res.Reason)
}

3. 使用认证密钥(JWT)的示例代码

package main

import (
	"log"

	"github.com/sideshow/apns2"
	"github.com/sideshow/apns2/token"
	"github.com/sideshow/apns2/payload"
)

func main() {
	// 1. 创建认证令牌
	authKey, err := token.AuthKeyFromFile("path/to/AuthKey_XXX.p8")
	if err != nil {
		log.Fatal("令牌错误:", err)
	}

	token := &token.Token{
		AuthKey: authKey,
		KeyID:   "你的密钥ID",  // 从Apple开发者账户获取
		TeamID:  "你的团队ID", // 从Apple开发者账户获取
	}

	// 2. 创建客户端
	client := apns2.NewTokenClient(token).Production() // 或者使用 .Development() 测试环境

	// 3. 创建通知
	notification := &apns2.Notification{
		DeviceToken: "设备token字符串",
		Topic:      "你的应用bundle ID",
		Payload:    payload.NewPayload().Alert("Hello from JWT!").Sound("default"),
	}

	// 4. 发送通知
	res, err := client.Push(notification)
	if err != nil {
		log.Fatal("发送错误:", err)
	}

	log.Printf("状态: %v, 原因: %v", res.StatusCode, res.Reason)
}

高级功能

自定义HTTP/2客户端

cert, err := certificate.FromP12File("path/to/cert.p12", "password")
if err != nil {
	log.Fatal("证书错误:", err)
}

// 自定义TLS配置
tlsConfig := &tls.Config{
	Certificates: []tls.Certificate{cert},
	MinVersion:   tls.VersionTLS12, // HTTP/2需要TLS 1.2或更高
}

// 创建自定义HTTP客户端
httpClient := &http.Client{
	Transport: &http.Transport{
		TLSClientConfig: tlsConfig,
	},
}

// 使用自定义HTTP客户端
client := apns2.NewClientWithHTTPClient(httpClient).Production()

发送静默通知

notification := &apns2.Notification{
	DeviceToken: "设备token",
	Topic:      "com.example.app",
	Payload:    payload.NewPayload().ContentAvailable(),
}

发送自定义数据

notification := &apns2.Notification{
	DeviceToken: "设备token",
	Topic:      "com.example.app",
	Payload: payload.NewPayload().
		Alert("新消息").
		Custom("custom_key", "custom_value").
		Custom("another_key", map[string]interface{}{"nested": "value"}),
}

错误处理

APNs2会返回详细的错误信息:

res, err := client.Push(notification)
if err != nil {
	if res != nil {
		log.Printf("APNs错误: %v, 原因: %v", res.StatusCode, res.Reason)
	} else {
		log.Printf("网络错误: %v", err)
	}
	return
}

性能优化

对于高吞吐量场景,可以复用客户端:

// 初始化时创建客户端
var client *apns2.Client

func init() {
	cert, _ := certificate.FromP12File("cert.p12", "password")
	client = apns2.NewClient(cert).Production()
}

// 然后可以多次调用
func sendNotification(token string, message string) {
	notification := &apns2.Notification{
		DeviceToken: token,
		Topic:      "com.example.app",
		Payload:    payload.NewPayload().Alert(message),
	}
	client.Push(notification)
}

总结

APNs2库提供了简单而强大的接口来通过HTTP/2协议与Apple推送通知服务交互。它支持两种认证方式(证书和JWT),提供了丰富的通知定制选项,并且可以轻松处理错误和性能优化。

回到顶部