大佬教程收集整理的这篇文章主要介绍了golang 实现 iOS http2 推送 Apns通知,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
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 main import ( "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 appropriately const ( 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) } }
// Package push sends notifications over http/2 to // Apple's Push Notification service. package push import ( "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://code.js-code.com/article/p-ejnmigde-bnx.html。然后需要将你服务器的curl升级到支持http2的版本,好的这些是准备工作。
从头开始,如果校验你的服务器能不能发送push呢?通过curl测试是否发送成功是最简单的方式。
最常见的错误是两个,一个是 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,这个的话,你要确保你的证书是通用版证书,这个可以@L_673_53@查下或者问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语言的push找的是GitHub上开源的,下载地址如下:https://github.com/RobotsAndPencils/buford
1.需要修改的地方是src/github.com/RobotsAndPencils/buford/push/service.go
这个路径下的service.go文件需要修改。
在设置header的地方增加一行,不然会因为topic没有报错的
2.然后可以将以.p12结尾的通用版证书放在这个目录下面src/github.com/RobotsAndPencils/buford/example/push
。然后在这个目录下,编译打码,用go build main.go,会生成@L_385_33@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通知所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。