如何使用附加数据将 apns 令牌发送到服务器

Posted

技术标签:

【中文标题】如何使用附加数据将 apns 令牌发送到服务器【英文标题】:How to send apns token to server with additional data 【发布时间】:2021-01-23 14:34:24 【问题描述】:

我正在尝试在调用 didRegisterForRemoteNotificationsWithDeviceToken 时向我的服务器发送一个 apns 令牌。我可以成功地将令牌打印到控制台,所以我知道该部分正在工作。

我还在我的网络服务上实现了这样一个端点,它也可以与我的应用程序的其余部分一起正常工作。

在Apple Developer documentation 中,在名为 Forward Tokens to Your Provider Server 的最后一节下,它说

收到设备令牌后,打开从您的应用到您的提供商服务器的网络连接。将设备令牌和识别特定用户所需的任何其他信息安全地转发到您的服务器。例如,您可以包含用户的登录名或将他们连接到您的服务的其他内容。

实际上,我如何包含这样的信息?我似乎无法将其他参数传递给 didRegisterForRemoteNotificationsWithDeviceToken,例如用户的访问令牌、用户 ID 等。

由于我使用的是 SwiftUI,所有用户的信息,包括他们的访问令牌,都在我的视图结构中的 @EnvironmentObject 中。我需要切换到单例吗?

【问题讨论】:

【参考方案1】:

您可以将包含所有用户元数据(包括令牌)的结构编码为 JSON JSONEncoder 和 send it 以向服务器发出请求。

【讨论】:

【参考方案2】:

事实证明,单例可能是更好的实现。一旦你进入了 didRegisterForRemoteNotificationsWithDeviceToken,你就不能从视图中访问任何东西,所以@EnvironmentObject 是没用的。

在我可以将登录的用户数据完全重组为单例之前(涉及删除/更改一堆代码),我只需在请求权限之前设置一个 ApiAccessToken 单例(用户登录那一点),然后访问 didRegisterForRemoteNotificationsWithDeviceToken 中的单例。

ApiTokenSingleton.swift

import Foundation

class ApiTokenSingleton

    static let shared = ApiTokenSingleton()
    
    private var token = ""
    
    func getToken() -> String 
        return token
    
    
    func setToken(newToken: String) 
        token = newToken
    

MyView.swift,onAppear,当我请求访问时。 authenticatedUser 是 EnvironmentObject

.onAppear() 
    ApiTokenSingleton.shared.setToken(newToken: authenticatedUser.accessToken ?? "")
    appDelegate.registerForPushNotifications()

AppDelegate.swift

    func application(
        _ application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
    ) 
        let tokenParts = deviceToken.map  data in String(format: "%02.2hhx", data) 
        let token = tokenParts.joined()
        print("Device Token: \(token)")
        
        // send token to backend here
        let deviceService = DeviceService()
        deviceService.add(accessToken: ApiTokenSingleton.shared.getToken(), deviceToken: token)  createDeviceResponse in
            print(createDeviceResponse)
        
        
    

【讨论】:

【参考方案3】:

您可以先将 apnToken 保存在某个地方 - 它可以是应用程序首选项数据库,或应用程序首选项状态(在应用程序启动时初始化),您可以从 API 层访问。

例子:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) 
    let encryptedToken = [UInt8](deviceToken).mapString(format: "%02x", $0).joined()
    
    // persist encrypted token to application settings DB

从我的 API 层中的数据库中获取 apnToken 并将其发送到 API 以及其他数据

private static func subscribeToNotification() 
    guard let apnToken = // get apnToken from app preferences DB

    // ... code for getting other params for API request from different other places

    let result = apiFetcher.request(
        type: ApiRequestType.post,
        path: // url,
        headers: // headers,
        queryParams: [
           "Token": apnToken,
           "Param1": param1,
           "Param2": param2
        ],
        withAuth: true
    )
 

【讨论】:

以上是关于如何使用附加数据将 apns 令牌发送到服务器的主要内容,如果未能解决你的问题,请参考以下文章

如果应用断开互联网,如何再次获取设备令牌(APNS)?

服务器 apns 上丢失的设备令牌

如何更改 jwt 访问令牌的附加信息

获取 APNS 服务的设备令牌列表

iOS APN 推送通知 - 设备令牌

从 Apple APNS 接收设备令牌所需的时间