BennyKJohnson / OpenCloudKit

Open Source CloudKit Framework
MIT License
96 stars 17 forks source link

registerForNotifications #1

Open malhal opened 7 years ago

malhal commented 7 years ago

Do you have plans to implement the registerForNotifications feature?

BennyKJohnson commented 7 years ago

Hi mahal, unfortunately I was unable to figure out how it worked and didn't end up implementing it. I seem to receive a 405 'Method not found' when creating a new token. For example the following should create an APN token based on the documentation here

curl -X "POST" "https://api.apple-cloudkit.com/database/1/[CONTAINER ID]/development/tokens/create" \ -H "Content-Type: application/json; charset=utf-8" \ -d $'{ "apnsEnvironment": "development" }' If you are able to figure out how to construct the correct requests. I would be happy to implement it.

Thanks, Benjamin

malhal commented 7 years ago

So in Safari on the CloudKit catalogue on notifications page if you look at the network requests you see the URL:

https://api.apple-cloudkit.com/device/1/iCloud.com.malhal.CKEvents/development/tokens/create?ckjsBuildVersion=16HProjectDev83&ckjsVersion=2.0.3&clientId=bf282b1b-c608-493a-b7db-d14e21afab68&ckWebAuthToken=XXX&ckAPIToken=XXX

Notice device and not database, which is different from the doc page on this. And the request body is:

{"apnsEnvironment":"development","clientId":"bf282b1b-c608-493a-b7db-d14e21afab68"}

The response is:

{
    "apnsToken": "XXX",
    "apnsEnvironment": "development",
    "webcourierURL": "https://webcourier.sandbox.push.apple.com:443/aps?tok=XXX&ttl=86400"
}

That webcourierURL is for long polling, and when a notification arrives it looks like this:

{"ck":{"ce":2,"nid":"10818dbb-de04-4fec-9fd5-47815e69ee16","qry":{"zid":"_defaultZone","dbs":2,"fo":1,"zoid":"_defaultOwner","rid":"8DB9E4F5-C74B-4545-8A18-6A690594E621","sid":"_edc508d67427c94657cf29ad07f1dae4"},"cid":"iCloud.com.malhal.CKEvents"}}

The ttl param is the number of seconds to wait, after that expires it sends: <html><head><title>204 No Content</title></head><body bgcolor="white"><h1>204 No Content</h1><hr><center></center></body></html>

Note that I've been trying to call registerForNotifications from CloudKit.js using a Node console app and it errors with: Error: no auth method found. I think that method doesn't work with the server-to-server auth, and it requires the ckWebAuthToken (ckSession), do you know how to get one of those?

BennyKJohnson commented 7 years ago

Thanks for the detailed information. I'm working on implementing a notifications, expect to have it finished in a day or two.

malhal commented 7 years ago

That would be excellent thanks. In return I can implement finishOnCallbackQueueWithError because I know how all that works.

BennyKJohnson commented 7 years ago

I've implemented notification support in acf651f2b4802b70408a6c0675209bf2bf728310 however this implementation is not totally complete. As you mentioned above the long polling urls expire after the ttl. So currently it will still require some class to handle the reregistration of tokens once they expire or are used. I need to do a little more research on this. But in the meantime use the steps below in order to receive notifications in your project.

Steps to receive notifications:

  1. Set a delegate that implements OpenCloudKitDelegate protocol on the main singleton via CloudKit.shared.delegate in order to receive call backs on notifications
  2. Call CloudKit.shared.registerForRemoteNotifications(). This will automatically create and register a token. And begin listening on its respective polling url.

Also I'm not sure whether notifications are supported for Server-to-Server, so you may have to use a CloudKit account web auth token and set it via CloudKit.shared.defaultAccount.iCloudAuthToken = [auth token]. Do this before you call registerForRemoteNotifications().