golang 实现 iOS http2 推送 Apns通知

golang 实现 iOS http2 推送 Apns通知,第1张

概述由于要用到viop和远程推送通知 并使用go作为后台语言 就找到了开源的 https://github.com/RobotsAndPencils/buford   作为代码使用,但是 发现 这个开源代码在 生产环境下 无法推送消息 一直提示 :  the Topic header of the request was not specified and was required 这个错误 这个错误 由于要用到viop和远程推送通知 并使用go作为后台语言 就找到了开源的 https://github.com/RobotsAndPencils/buford 作为代码使用,但是 发现 这个开源代码在 生产环境下 无法推送消息 一直提示 :

the topic header of the request was not specifIEd and was required 这个错误

这个错误 在开发环境和viop的生产环境里面没问题,但是就在 release的生产环境里面报这个错误!

最终发现 问题 是由于代码中的 server类的Push 在使用时 要传入header头,但是在demo中确直接传nil 发现问题后示例代码改成 :

主要是 从证书中解析出来topic既BundleID然后再传递给Push函数即可。

ID,err := service.Push(devicetoken,&headers,b)//主要需要传入 头参数

package mainimport (	"enCoding/Json"	"fmt"    "os"    //"net/http"	"github.com/RobotsAndPencils/buford/certificate"	"github.com/RobotsAndPencils/buford/payload"	"github.com/RobotsAndPencils/buford/payload/badge"	"github.com/RobotsAndPencils/buford/push")// set these variables appropriatelyconst (	filename = "ck.p12"	password = "123456"	//host = push.Development    host = push.Production	devicetoken = "5cbf2c60e4907c2c3c168575d05c80a3f4cde2bbb2ff05bbbed8e3a4f25c615f")func main() {	// load a certificate and use it to connect to the APN service:	cert,err := certificate.Load(filename,password)	exitOnError(err)    topic := ""    if err == nil{        fmt.Printf("err is nil ****\n");        fmt.Printf("@@@@@@@@@@@@@@@@@@@????????????????????\n");        topic = certificate.topicFromCert(cert);        fmt.Printf("topic: %s\n",topic);    }	clIEnt,err := push.NewClIEnt(cert)	exitOnError(err)	service := push.NewService(clIEnt,host)	// construct a payload to send to the device:	p := payload.APS{		Alert: payload.Alert{Body: "Hello http/2"},Badge: badge.New(42),}	b,err := Json.Marshal(p)    fmt.Println("Json.Marshal")	exitOnError(err)	// push the notification:/*headers := headers{ID:          "uuID",CollapseID:  "game1.score.IDentifIEr",Expiration:  time.Unix(12622780800,0),LowPriority: true,topic:       "bundle-ID",}*//* headers := push.headers{};fmt.Printf("topic is %s\n",headers.topic)//push.ShowInfo();reqheader := http.header{}headers.showInfo()headers.set(reqheader);*/    var headers push.headers    fmt.Printf("topic: %s\n",topic);    if topic != "" {            headers = push.headers{                topic:       topic,}        fmt.Printf("the topic is *** %s\n",headers.topic)    }	ID,b)    //ID,nil,b)    fmt.Println("service.Push")	exitOnError(err)	fmt.Println("apns-ID:",ID)}func exitOnError(err error) {    if err != nil {        fmt.Println(err)        os.Exit(1)    }}



//service.go 代码不用修改即可

// Package push sends notifications over http/2 to// Apple's Push Notification Service.package pushimport (	"bytes"	"crypto/tls"	"enCoding/Json"	"fmt"	"io"	"net/http"	"net/url"	"strings"	"time"	"golang.org/x/net/http2")// Apple host locations for configuring Service.const (	Development     = "https://API.development.push.apple.com"	Development2197 = "https://API.development.push.apple.com:2197"	Production      = "https://API.push.apple.com"	Production2197  = "https://API.push.apple.com:2197")const maxPayload = 4096 // 4KB at most// Service is the Apple Push Notification Service that you send notifications to.type Service struct {	Host   string	ClIEnt *http.ClIEnt}// NewService creates a new service to connect to APN.func NewService(clIEnt *http.ClIEnt,host string) *Service {	return &Service{		ClIEnt: clIEnt,Host:   host,}}// NewClIEnt sets up an http/2 clIEnt for a certificate.func NewClIEnt(cert tls.Certificate) (*http.ClIEnt,error) {	config := &tls.Config{		Certificates: []tls.Certificate{cert},}	config.BuildnameToCertificate()	transport := &http.Transport{TLSClIEntConfig: config}	if err := http2.ConfigureTransport(transport); err != nil {		return nil,err	}	return &http.ClIEnt{Transport: transport},nil}// Push sends a notification and waits for a response.func (s *Service) Push(devicetoken string,headers *headers,payload []byte) (string,error) {	// check payload length before even hitting Apple.	if len(payload) > maxPayload {		return "",&Error{			Reason: ErrPayloadToolarge,Status: http.StatusRequestEntityToolarge,}	}	urlStr := fmt.Sprintf("%v/3/device/%v",s.Host,devicetoken)	fmt.Printf("the urlStr: %s\n",urlStr)    fmt.Printf("the payload: %s\n",payload)    fmt.Printf("the headers: %s\n",headers)	req,err := http.NewRequest("POST",urlStr,bytes.NewReader(payload))	if err != nil {		return "",err	}	req.header.Set("Content-Type","application/Json")    //req.header.Set("apns-topic","com.zzcs.mengliao")	headers.set(req.header)	resp,err := s.ClIEnt.Do(req)	if err != nil {		if e,ok := err.(*url.Error); ok {			if e,ok := e.Err.(http2.GoAwayError); ok {				// parse DeBUGData as JsON. no status code kNown (0)				return "",parseErrorResponse(strings.NewReader(e.DeBUGData),0)			}		}		return "",err	}	defer resp.Body.Close()	if resp.StatusCode == http.StatusOK {		return resp.header.Get("apns-ID"),nil	}	return "",parseErrorResponse(resp.Body,resp.StatusCode)}func parseErrorResponse(body io.Reader,statusCode int) error {	var response struct {		// Reason for failure		Reason string `Json:"reason"`		// Timestamp for 410 StatusGone (ErrUnregistered)		Timestamp int64 `Json:"timestamp"`	}	err := Json.NewDecoder(body).Decode(&response)	if err != nil {		return err	}	es := &Error{		Reason: mapErrorReason(response.Reason),Status: statusCode,}	if response.Timestamp != 0 {		// the response.Timestamp is Milliseconds,but time.Unix() requires seconds		es.Timestamp = time.Unix(response.Timestamp/1000,0).UTC()	}	return es}



另外参考了下面的文章:但是没有直接指出我所遇到的问题:

http://blog.csdn.net/rodgexue/article/details/54290676

在linux环境下执行上面的语句。需要改几个参数,
这个http2的ios push推送真的是要了我的老命啊,足足用了两个礼拜的时间,从零基础的go语言开始,一步步的学习和找对应的例子,终于掌握了其中的使用技巧。从此,多了一项生存之道啊。哈哈!!
好的,直接进入主题吧,首先第一步,需要安装一个go语言的环境,这个我之前的博客上写过了。来个跳转地址:http://www.jb51.cc/article/p-ejnmigde-bnx.html。然后需要将你服务器的curl升级到支持http2的版本,好的这些是准备工作。

一、使用最基本的curl命令来发送apns push。
从头开始,如果校验你的服务器能不能发送push呢?通过curl测试是否发送成功是最简单的方式。
      1  curl -i -d '{"aps":{"alert":"Hello http2.0","sound":"msg_high.m4abadgeNum":1}}'  --cert "push.pem":"" -H "apns-topic: 你的top,就是应用的bundle-ID" --http2  https://API.development.push.apple.com/3/device/你要发送的设备的device_token
一个是-d后面的内容,这个是需要根据你自己的应用,修改对应的结构。正常来说,上面的格式是能正常发送出来的,但是在使用voip的push的情况下,一般voip(voice over ip) 是要ios8.0以上能使用的。使用这类push的时候,ios工程师可能会对push内容进行屏蔽等。这也是可能导致你接口返回值为200,但是手机上没有收到push的问题的原因 一个是curl命令的 -i,表示展示返回展示curl返回的header头,因为push的返回结果是在header里面的,如果是下面这个200,表示是成功,的,如果错误可以去官网查看对应的编码,正常curl也会展示出来的。最常见的错误就是
    1    2  http/2 200 apns-ID: 65743B1B-BB3A-3CD6-BD27-D566660642D8

最常见的错误是两个,一个是 bad device token,一个是topic disallowed。这两个问题的时候,先是topic disallowed这个问题,这个是你的topic不被允许,你再和ios开发确认下应用的bundle ID,如果他确定的话,然后你可以在你的bundle ID的后面加上 .voip ,然后再去试一下,如bundle ID为com.a.a,然后试着将上面的curl的语句修改下,-H "apns-topic: com.a.a.voip然后再去试下

还有个最长见的错误是 bad device token,这个的话,你要确保你的证书是通用版证书,这个可以百度查下或者问ios开发。生成后,要放在你执行curl命令的地址下面,因为我--cert "push.pem":""这条命令后面是相对路径,然后名字也需要修改成你要的名字,然后要保证你的device_token是deBUG包还是生产包生成。如果是deBUG包生成的device token的话,就发送到https://API.development.push.apple.com/3/device/你要发送的设备的device_token这个苹果的沙盒地址,如果你的device token是生产包的话,需要发送到https://API.push.apple.com/3/device/你要发送的设备的device_token这个苹果的生产环境地址。

二、使用go语言的apns的开源程序来发送push

我的go语言的push找的是GitHub上开源的,下载地址如下:https://github.com/RobotsAndPencils/buford
1.需要修改的地方是src/github.com/RobotsAndPencils/buford/push/service.go这个路径下的service.go文件需要修改。
在设置header的地方增加一行,不然会因为topic没有报错的

    1    2  req.header.Set("apns-topic","com.a.a.voip")headers.set(req.header)

2.然后可以将以.p12结尾的通用版证书放在这个目录下面src/github.com/RobotsAndPencils/buford/example/push。然后在这个目录下,编译打码,用go build main.go,会生成一个main的可执行文件,然后输入命令./main -d 设备的device_token -c push.p12 -p 证书密码 -e development,这样就能给deBUG版本的发送push了。

3.src/github.com/RobotsAndPencils/buford/example/concurrent这个目录下下的main.go的话,是用go的并行的方式来发送push,增加push的效率。核心逻辑就是在主线程里面,用for循环不断的去redis去数据,然后取到数据后,放入chennel里面,然后在代码中,go func后面的代码表示子进程。读取这个chennel来发送push

总结

以上是内存溢出为你收集整理的golang 实现 iOS http2 推送 Apns通知全部内容,希望文章能够帮你解决golang 实现 iOS http2 推送 Apns通知所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/1278501.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存