使用 iOS 中的标记对 Azure App Service 推送通知注册进行故障排除

Troubleshooting Azure App Service Push Notfication registration with tags in iOS

我这个月开始使用 Azure 应用服务,在应用服务之前我使用的是 Azure 移动服务,带有标签的注册设备令牌非常简单,但在应用服务中我意识到它由于安全问题而被删除所以我有使用自定义 API.

来做到这一点

我在我的数据库中使用自定义身份验证(不是 Azure 身份验证服务(因为我的客户不想要它)),所以我需要将用户 ID 设置为标记以将通知发送到特定 user.However 我面临的问题是即使设备令牌注册正常(我可以向没有标签的所有人发送推送)标签不起作用,我正在关注这些博客文章

https://blogs.msdn.microsoft.com/writingdata_services/2016/04/14/adding-push-notification-tags-from-a-node-js-backend/

https://blogs.msdn.microsoft.com/writingdata_services/2016/01/22/adding-push-notification-tags-from-an-azure-mobile-apps-client/

我的自定义 API (updateNotification.js)

var api = {

    get: (request,response,next) => {
            var push = request.azureMobile.push;
            var installationId = request.query.id;

            push.getInstallation(installationId, function(error, installation, res){
                if (error){                 
                    console.log('An error occurred when retrieving installation : ' + error);
                    response.status(error.statusCode).send(error.detail);                   
                }
                else{
                    // Return an array of current tags.
                    response.json(installation.tags);   
                }               
            }); 
    },

    post: (request, response, next) => {
        var push = request.azureMobile.push;
        var installationId = request.query.id;
        var tags = request.query.userID;

        var updateOperation = [{
            "op": "add",
            "path": "/tags",
            "value": tags.toString()
        }];     

        push.patchInstallation(installationId, updateOperation, function(error, res){
            if(error){
                console.log(error)
                response.status(error.statusCode).send(error.detail);
            }
            else{
                console.log("Success");
                console.log("Tags : " + tags);
                response.status(200).send(tags);
            }
        });
    }
};

module.exports = api;

在我的 AppDelegate.swift class 中,我正在这样做

func application(application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        let keychain = KeychainSwift()
        let id : NSString = keychain.get("userID")! as String
        let client = MSClient(applicationURLString: "https://XXXX.XXXX.XXX")
        var deviceTokenString = "\(deviceToken)"
        deviceTokenString = deviceTokenString.stringByReplacingOccurrencesOfString("<", withString: "")
        deviceTokenString = deviceTokenString.stringByReplacingOccurrencesOfString(">", withString: "")
        deviceTokenString = deviceTokenString.stringByReplacingOccurrencesOfString(" ", withString: "-")        

        client.push?.registerDeviceToken(deviceToken, completion: { (error) in
            if let err = error {
                print("ERROR ", err)
            }else{
                client.invokeAPI("updateNotification", body: nil, HTTPMethod: "Post", parameters: ["id" : deviceTokenString , "userID" : id], headers: nil) { (result, response, error) in
                    if response?.statusCode != 200 {
                        NSLog("ERROR %@", error!)
                    } else {
                        print("Tags Successfully Implemented")
                    }
                }
            }
        })

    }

现在一切似乎都很好,在我的控制台中我可以看到我的用户 ID,我的设备令牌和用户 ID 是这样的(我把 X 放在中间 :D 很抱歉)

deviceToken = 22afedf6-a08f1ce9-XXXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXX-db431577-2dfbbee1 用户 ID = 88d06c97-XXXX-XXXX-XXXX-042215c46575

然而,当我尝试使用此 GET 方法查看设备 ID 的标签时,

    client.invokeAPI("updateNotification", body: nil, HTTPMethod: "GET", parameters: ["id" : deviceTokenString], headers: nil) { (result, response, error) in
             if response?.statusCode != 200 {
                   NSLog("ERROR %@", error!)
             } else {
                  print(result)
             }
   }

我收到这个错误:

Error Domain=com.Microsoft.MicrosoftAzureMobile.ErrorDomain Code=-1302 "Installation not found.TrackingId:57239dd3-XXXX-XXXX-XXXX-0bd9579c660e_G1,TimeStamp:7/18/2016 8:22:05 PM"

如何解决此错误消息?

好的,长时间工作后这里是解决方案

1.Step

如果可以 debug the Notification Hub(我建议从 Visual studio 2015 Express 等进行调试。),您可以看到 PNS 标识符(这是我们的设备令牌) 都是大写字母,没有破折号,所以首先我们需要更改 AppDelegate.swift 中的设备令牌代码,它会像这样

deviceTokenString = deviceTokenString.stringByReplacingOccurrencesOfString("<", withString: "")
deviceTokenString = deviceTokenString.stringByReplacingOccurrencesOfString(">", withString: "")       
deviceTokenString = deviceTokenString.stringByReplacingOccurrencesOfString(" ",withString: "-")
deviceTokenString = deviceTokenString.uppercaseString

//In case of any spaces just guarantee with trim
let trimmedDeviceToken = deviceTokenString.stringByTrimmingCharactersInSet(
    NSCharacterSet.whitespaceAndNewLineCharacterSet()
)

2.Step

InstallationId 和设备令牌是完全不同的东西。您将标签推送到 installationId 而不是设备令牌,因此您需要在客户端代码中获取 installationId。

问题出在 IOS 的 Azure 移动 SDK 中,您无法使用 client.installationId 调用安装 ID(至少我找不到从 MSClient 对象获取的方法)

我所做的是,进入框架并找到 MSClient.m。我意识到安装 ID 实际上存储在 NSUserDefaults 中,键为 "WindowsAzureMobileServicesInstallationId".所以我可以用这个

从 NSUser Defaults 到达它
let defaults = NSUserDefaults.standartUserDefaults()
let installationID = defaults.stringForKey("WindowsAzureMobileServicesInstallationId")

完成这些步骤后,您实际上可以将标签注册到安装 ID。这是结果和应用程序 didRegisterForRemoteNotificationsWithDeviceToken 方法的完整代码

    func application(application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        let keychain = KeychainSwift()
        let id : NSString = keychain.get("userID")! as String
        let client = MSClient(applicationURLString: "https://XXXX.XXXX.XXX")
        var deviceTokenString = "\(deviceToken)"
        deviceTokenString = deviceTokenString.stringByReplacingOccurrencesOfString("<", withString: "")
        deviceTokenString = deviceTokenString.stringByReplacingOccurrencesOfString(">", withString: "")
        deviceTokenString = deviceTokenString.stringByReplacingOccurrencesOfString(" ", withString: "")
        deviceTokenString = deviceTokenString.uppercaseString

        //In case of any spaces just guarantee with trim
        let trimmedDeviceToken = deviceTokenString.stringByTrimmingCharactersInSet(
            NSCharacterSet.whitespaceAndNewLineCharacterSet()
        )

        let defaults = NSUserDefaults.standartUserDefaults()
        let installationID = defaults.stringForKey("WindowsAzureMobileServicesInstallationId")

        client.push?.registerDeviceToken(deviceToken, completion: { (error) in
            if let err = error {
                print("ERROR ", err)
            }else{
                client.invokeAPI("updateNotification", body: nil, HTTPMethod: "Post", parameters: ["id" : installationID! , "userID" : id], headers: nil) { (result, response, error) in
                    if response?.statusCode != 200 {
                        NSLog("ERROR %@", error!)
                    } else {
                        print("Tags Successfully Implemented")
                    }
                }
            }
        })

    }

在此之后,您还可以通过调用 updateNotification 的 GET 方法并发送我们从 NSUserDefaults 获得的 installationId 来检查标签