Apple Wallet Pass更新文档存疑及后端实现问题咨询
Apple Wallet Pass 更新实现疑问与代码求助
我正在遵循Apple官方PassKit文档实现Apple Wallet Pass的更新功能,目前已获取注册端点并记录deviceID与push_token,但仍有以下疑问:
- 问题1:Pass Type Identifier和push token在APNs推送中如何使用?文档提到Pass Type Identifier在证书中,是否需要加入JWT?若需要,是放在claims还是headers中?push token文档提及用于与APNs通信,是否确实放在payload中?
- 问题2:APNs推送的
apns-push-type、apns-topic、apns-priority字段需配置什么值?我猜测类型为background,主题为Pass Type Identifier,无需设置优先级,但代码未生效。 - 问题3:是否可在推送通知中添加Pass序列号,跳过「设备请求变更序列号」步骤?我的API丢失上下文后难以确定需更新的Pass,且用户不应持有同标识的多个Pass。
- 问题4:最后一步「设备请求最新Pass版本」中,设备期望的Pass数据格式是什么?我猜测是包含
pass-data字节数组(代表同序列号的签名pkpass文件)的JSON,但未找到确认依据。
当前我已完成Pass创建与注册,记录push token,并用Go语言实现APNs推送代码如下:
authorization, err := getAppleBearerAuth() endpoint := fmt.Sprintf("https://api.sandbox.push.apple.com/3/device/%s", device_id) //APNs dev endpoint //token in payload payload := map[string]interface{}{"push_token": push_token} payloadJSON, err := json.Marshal(payload) if err != nil { fmt.Println("Failed to marshal payload:", err) return err } expiration := time.Now().Add(24 * time.Hour).Unix() // Set the headers for the request headers := map[string]string{ "Authorization": *authorization, "Content-Type": "application/json", "apns-push-type": "background", "apns-topic": os.Getenv("APPLE_PASS_TYPE_IDENTIFIER"), "apns-expiration": fmt.Sprintf("%d", expiration), } httpClient := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, // Set to false in production }, }, } request, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(payloadJSON)) if err != nil { fmt.Println("Failed to create request:", err) return err } for key, value := range headers { request.Header.Set(key, value) } response, err := httpClient.Do(request) if err != nil { fmt.Println("Failed to send request:", err) return err } defer response.Body.Close() if response.StatusCode == http.StatusOK { fmt.Println("Push notification sent successfully.") } else { fmt.Println("Failed to send the push notification. Status code:", response.StatusCode) } return nil } func getAppleBearerAuth() (*string, error) { kid := os.Getenv("APPLE_PUSH_KEY") iss := os.Getenv("APPLE_TEAM_ID") // Create a new JWT token token := jwt.New(jwt.SigningMethodES256) // Add claims claims := token.Claims.(jwt.MapClaims) claims["iss"] = iss claims["iat"] = time.Now().Unix() // Add kid to the header token.Header["kid"] = kid // Load your ES256 key key, err := loadPrivateKey() if err != nil { return nil, err } // Sign and get the complete encoded token as a string tokenString, err := token.SignedString(key) if err != nil { return nil, err } // Add "Bearer " to the token string to make it a bearer token bearer := "Bearer " + tokenString return &bearer, nil } func loadPrivateKey() (interface{}, error) { // Here you should implement loading your private key // Usually it involves reading from a PEM file and parsing the key // Path to the .p12 file certPath := os.Getenv("APPLE_CERT") // Password for the .p12 file certPassword := os.Getenv("PASSKEYPASS") p12Bytes, err := ioutil.ReadFile(certPath) if err != nil { return nil, err } blocks, err := pkcs12.ToPEM(p12Bytes, certPassword) if err != nil { return nil, err } pemData := pem.EncodeToMemory(&pem.Block{ Type: "RSA PRIVATE KEY", Bytes: blocks[0].Bytes, }) key, err := jwt.ParseRSAPrivateKeyFromPEM(pemData) if err != nil { return nil, err } return key, nil }
推送使用创建Pass时的同一证书签名,我怀疑Pass Type Identifier的配置位置有误导致功能失效,但不确定正确位置。求有Apple Pass后端更新实现经验的开发者解答。
内容的提问来源于stack exchange,提问作者Ryan McCaffrey
相关产品推荐
相关产品推荐

