Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notifications not working when using "non-Mac-Steps" #33

Closed
figuerb opened this issue Jul 3, 2019 · 20 comments
Closed

Notifications not working when using "non-Mac-Steps" #33

figuerb opened this issue Jul 3, 2019 · 20 comments

Comments

@figuerb
Copy link

figuerb commented Jul 3, 2019

I am having an issue getting notifications when using the steps in this link...

non-macOS-steps

Passes should be able to receive notifications if a device id and push token were generated when they first downloaded their pass (this is logic we have in our application to handle on the server and storage/ db level)

I have confirmed that if I update a pass in our database and then do a pull to refresh on a pass, it updates the data so I know it is not my webhooks that are a problem. The webhooks were implemented using these docs...

PassKit Web Service Reference

I continue to receive notification from apple's notification server that they have received my request but the devices registered never receive a notification

I think I have an idea why. I have read that when creating the certificate for a pass, you can select it to allow notification. I think that the instructions in the "non Mac steps" no not seem to have a way to make the certificate receive notifications. Is this correct?

I think in order to receive notifications I would have to re-create the certificate using Apple's developer dashboard, after creating the pass type id and then creating a production certificate to download

Please let me know if this is something you know to be true or if the steps in the "non Mac steps" somehow create a certificate that allows for push notifications

Thanks

@alexandercerutti
Copy link
Owner

alexandercerutti commented Jul 3, 2019

@figuerb Hi
I must be sincere: I never setup a server nor webhooks to send updates from server. I just tried once to see what I was receiving as datas but nothing else. So I barely followed Apple reference to set up.

I don't know anything also about the certificates: have you tried with the "official steps" in the Readme? If not, can you try and let me know? It may be possible there is something I didn't knew while creating "non official steps" for Terminal.
And what happens if you try to create again the certificates through the "non official steps"?

Also, can you please provide me where you read this thing of notifications? Thank you very much! 😊

@figuerb
Copy link
Author

figuerb commented Jul 3, 2019

@alexandercerutti

Thanks for the quick reply. This link here shows a diagram for showing how push notifications work

Updating a pass

@alexandercerutti
Copy link
Owner

alexandercerutti commented Jul 3, 2019

I was looking at the same page before.
As I'm pretty new to this, I think we'll investigate and learn together 😂.

What I was reading in that page, is this sentence:

You use the same certificate and private key for sending push notifications as for signing passes. For more information about push notifications, see Local and Remote Notification Programming Guide.

Are you doing this?

So, we have these steps:

  • Devices Register for Updates
  • Your Server Sends a Push Notification When Something Changes
  • Devices Ask for Changed Serial Numbers
  • Devices Ask for Latest Version of Passes
  • Devices Display Change Messages

And you are blocking in between the last two steps, or, as I don't know how APNs work, after the second step. Are you perhaps receiving a request from the device, with the following info?

  • The device ID (in the URL)
  • The pass type ID from the push notification (in the URL)
  • The latest update tag that it’s seen from this pass type ID (as an optional query)

Or a one with these?

  • Pass type identifier (in the URL)
  • Serial number (in the URL)
  • Authentication token (in the header)

Another thing I can suggest you is to try to do this:
I saw at the end of Passkit Web Service Reference, a Logging endpoint that can be set up to receive messages about errors. Have you tried to set up an endpoint on your server for this?

Let me know!

@figuerb
Copy link
Author

figuerb commented Jul 5, 2019

Hi @alexandercerutti thanks for your prompt responses and sorry for the delayed response. Yesterday was a holiday as you know

Regarding the steps I know for sure the registration step is working, I have all the information I need. Push token, device id etc

The step where I seem to be stuck on is after I create a notification request. I send a request to Apple's notification server and Apple replies with no error and tells me the notification was received

I m going to show you some of the information I am hitting and what is coming from the logging URL too because I did implement that URL

  • Your Server Sends a Push Notification When Something Changes

I get the following response

{ sent:
   [ { device:
        'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' } ],
  failed: [] }

If it had failed we would get data in the failed array instead of sent. So I know Apple received the notification

  • Devices Ask for Changed Serial Numbers

Here I am outputting snippets in the code to make sure it hits this code and looking in the logs and I see this..

2019-07-05T17:41:17.372611+00:00 xxxxxx[router]: at=info method=GET path="/passkit/v1/devices/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/registrations/pass.org.xxxx.membership?passesUpdatedSince=1562348001375" host=card.xxxx.org request_id=8ef3e21b-9502-4fed-8435-f3c39b0a6cfb fwd="67.84.179.85" dyno=web.1 connect=1ms service=29ms status=200 bytes=348 protocol=https
2019-07-05T17:41:17.371473+00:00 app[web.1]: 
2019-07-05T17:41:17.371504+00:00 app[web.1]: 
2019-07-05T17:41:17.371534+00:00 app[web.1]: //==================================================================//
2019-07-05T17:41:17.371574+00:00 app[web.1]: 
2019-07-05T17:41:17.371606+00:00 app[web.1]: passesUpdatedSince 1562348001375
2019-07-05T17:41:17.371630+00:00 app[web.1]: 
2019-07-05T17:41:17.371714+00:00 app[web.1]: serialNumbers [ 'xxxxxxxxxxxxxxxxx' ]
2019-07-05T17:41:17.371751+00:00 app[web.1]: 
2019-07-05T17:41:17.371778+00:00 app[web.1]: //==================================================================//

You can see here we hit the URL for Getting the Serial Numbers for Passes Associated with a Device and I respond with the serial number for that device id that was passed in the url from Apple

  • Devices Ask for Latest Version of Passes

Here I am outputting the card that will be returned and I know this URL is working because as I mentioned, if I go to my card/ pass on my phone and click on info and pull down to refresh, it hits the URL and grabs the right data and updates the pass. The only thing not working here is the notification step :/

I have been checking things over and over and over and the fact that the "update pass" url works when I manually pull to refresh just confirms the problem is the notification step and since I receive a response that says Apple received it, I don't even know what else it could be

@alexandercerutti
Copy link
Owner

Hi @figuerb
I don't know where you come from, but for me yesterday (Italy) was not a holiday but a regular work day 😂 So no, I didn't know.

Mmm, about your information... wait, which kind of info are you updating? Because, for example, fields emit notifications only if they have an object field called changeMessage, which has a specific format.

So, are you compliant with Field Dictionary / changeMessage?

Furthermore, can I ask you again to retry to generate certificates through the steps in the main README? So through macOS' Keychain Access. Just to try to isolate the issue.
If you don't have access to a Mac, mine is available if you need that (I mean, you should give me in P.M. the needed info and files to generate them).

Another thing that came in my mind is this: if you have a Mac, you can try to debug through Console.app on your device through USB, because it might have sent you some information in there and you don't know. I don't know how to find them, because this time I don't think that filtering through key "passkit" will give you the correct info.

@figuerb
Copy link
Author

figuerb commented Jul 8, 2019

@alexandercerutti

Sorry I assumed you were in the United States. Last week was 4th of July so I was off from work Thursday and Friday

Regarding changeMessage, what makes you think this field is necessary? Our pass.json does not have a field for it. The documentation says it is Optional and that is probably why it was left out

Regarding the last part I will do some research on how to do this.

@alexandercerutti
Copy link
Owner

@figuerb Don't worry 😊
About changeMessage, in the Passkit Package Format Reference it is written that you need that field to be formatted like with @% if I remember correctly if you want to receive a notification for that field.
Optional is the fact that you don't need to set it, as you may not want to update the field.

Okay, let me know! 👍

@figuerb
Copy link
Author

figuerb commented Jul 8, 2019

@alexandercerutti

So if are you saying that if I want to receive a notification, I need to add the changeMessage field with the actual field I would like it to send a update notification for? i.e. for the name field I can do the following...

{
  "formatVersion": 1,
  "passTypeIdentifier": "pass.xxx.xxxx.xxxxxxxxxx",
  "serialNumber": "xxxxxxxxxx",
  "teamIdentifier": "XXXXXXXXXX",
  "organizationName": "abc",
  "description": "xyz",
  "backgroundColor": "rgb(0, 175, 215)",
  "secondaryFields": [
    {
      "key": "name",
      "label": "Name",
      "changeMessage": "Your name was updated"
    }
  ],
  "storeCard": {}
}

And if that is the case, do I have to add each field that I want to get a "notification" for?

I am going to try to make this change now, I might have an answer before you reply but let me know please. Thanks

@alexandercerutti
Copy link
Owner

@figuerb Yes about. I've never tried this, but it should be like this: when you insert "changeMessage" in a field with the characters @% (which are mandatory for a notification), those two will be replaced with the key associated to the value that changed. In a field you can have a lot of field, like semantics (they are over 70 if I remember correctly).

Anyway, secondaryFields must be inserted under storeCard.

@figuerb
Copy link
Author

figuerb commented Jul 8, 2019

@alexandercerutti

So doing this in JavaScript using your tool this is what I have

  const pass = new Pass({
    overrides: this.overrides,
    ...defaults
  });

  ...
  
  pass.secondaryFields.push({
    key: 'name',
    label: 'Name',
    value: cardholderName,
    changeMessage: 'Your name has changed'
  });

Is this wrong? or does your code add those fields to the storeCard?

The ...defaults value you see being passed in, is basically the snippet json you saw up top which is the default pass.json file before we add fields to it and override it

@alexandercerutti
Copy link
Owner

alexandercerutti commented Jul 8, 2019

Apple says this:

Format string for the alert text that is displayed when the pass is updated. The format string must contain the escape %@, which is replaced with the field’s new value. For example, “Gate changed to %@.”
If you don’t specify a change message, the user isn’t notified when the field changes.

So I was wrong about the character sequence and the explanation.
Therefore you changeMessage should be like "Name changed to %@".

Of course, this is valid only if you want to receive a notification for an update to one of the fields. I'm saying this because all the fields, except authenticationToken and webServiceURL, can be updated according to Apple.

Anyway, pushing to secondaryFields is correct: it adds it into storeCards. I was asking because I saw that in you JSON snippet above.

Wait, no that is not correct: ...defaults shouldn't be a JSON! I mean, Pass's constructor accepts other key values, not pass.json contents. Please see the API Documentation 😊

@figuerb
Copy link
Author

figuerb commented Jul 9, 2019

@alexandercerutti

That was it. The problem was that we did not have changeMessage on the fields/ keys we wanted notifications for. The developer who originally wrote most of the logic did not add that when creating the storeCard fields. I just added it and it started to work.

I read through so many of these documents and searched all of the webpages for "notification" and missed "notified" right there in the changeMessage description 🤦🏽

Anyways, here is the notification

Screen Shot 2019-07-09 at 12 25 43 AM

I know this is in Apple's documentation but it would be great if you should add something like a notification section that says you must include changeMessage on all fields you want to be send a notification for

Regarding the pass.json. We have one with the basics and then when we create the Pass programmatically, we pass that in with the override option and dynamically add the fields etc your docs explain this...

For options.overrides you have...

Dictionary containing all the keys you can override in the pass.json file and does not have a method to get overridden.

Anyways, thanks a ton! I really appreciate your help

@alexandercerutti
Copy link
Owner

alexandercerutti commented Jul 9, 2019

Awesome!
Thank you for the suggestion. I have to think on this a bit more because I don't want to replace Apple's documentation (even probably they deserve it as Passkit Package Format Reference is an archived set of documents).

About the overrides, that is clear, but if you give ...defaults, you are not passing the properties to overrides but to the Pass class, which does not accept them 🤔.

You should do instead something like:

const pass = new Pass({
    ...
    overrides: { ...defaults, ...this.overrides }
  });

Anyway, this is not needed: in fact, you can insert your default pass.json in your model and it will be parsed and patched without changing the source file.

So, as we resolved this, can I ask you to leave a star ⭐️ to the project? It is really important to me 😊Thank you very much!

@figuerb
Copy link
Author

figuerb commented Jul 9, 2019

Thanks you for the help!

Regarding the pass being passed in, that was a mistake on my part. The defaults object we pass looks like this

const defaults = {
  model: './passes/membership',
  certificates: {
    wwdr: './config/security/iOS/certs/AppleWWDRCA.pem',
    signerCert: './config/security/iOS/certs/signerCert.pem',
    signerKey: {
      keyFile: './config/security/iOS/certs/passkey.pem',
      passphrase: passphrase
    }
  },
  shouldOverwrite: true
};

and this.overrides looks like this (TypeScript)

  private get overrides(): Schema.SupportedOptions {
    return {
      serialNumber: this.card.serialNumber,
      webServiceURL: this.webServiceURL,
      authenticationToken: authenticationToken
    };
  }

@alexandercerutti
Copy link
Owner

Awesome 😉I'm closing this!

Thank you for using this package ❤

@figuerb
Copy link
Author

figuerb commented Jul 9, 2019

Excellent work helping and excellent work on the package. I appreciate it. Have a good one

@engr-ahsan
Copy link

engr-ahsan commented Jul 13, 2019

Although I am pretty late at this, but I have been scratching my head for days wondering why am I not receiving any push notification for my Passes even though they are being updated. I forgot adding "changeMessage" in the backfields that I want to update (I am an idiot). Anyways, thanks alot @figuerb for raising this issue as it pointed out my mistake, and not least, @alexandercerutti for this awesome library :). Keep it up 🥇 💯

@alexandercerutti
Copy link
Owner

@DevFromPAK don't say you are an idiot, because developing Passes with Apple is always a battle 🤣

@engr-ahsan
Copy link

@alexandercerutti Yeah but changeMessage field was so obvious 😄. Anyway, I am just glad its resolved. Thanksalot 😃

@Dicondur
Copy link

Dicondur commented Jun 12, 2020

@figuerb @alexandercerutti Thanks for all the info.
I am facing a slightly different but relating to not getting notifications issue.

I have setup PK WebServices as per docs. Im able to update my pass Ie: Touch to pull on back of pass says "Updated just now" and shows the changes. But dont get notifications of changes.

In "Get Pass" api call I have this header
"Last-Modified": new Date().toUTCString() set.

On Get Serial function, I am returning in the body like below:

body: {
      serialNumbers: ["12312312", "123123"],
      lastUpdated : new Date().toUTCString()
}

Using Node APN for push
https://github.com/node-apn/node-apn

Created a token from Apple Dev portal. https://developer.apple.com/account/resources/authkeys/list

var apnProvider = new apn.Provider({
    token: {
      key: AuthKey_xxx.p8", // Path to the key p8 file
      keyId: "xxx", // The Key ID of the p8 file
      teamId: "nnn", // The Team ID of your Apple Developer Account
    },
    production: true,
  });

var notification = new apn.Notification();
notification.topic = passTypeIdentifier;
notification.payload = { };

I get this response:

{
    "sent": [
        {
            "device": "8cxxx4"
        }
    ],
    "failed": []
}

So Apple sent it successfully I dont get any notifications.
I have all fields with ChangeMessage set

{
    "key": "aux1",
    "label": "Aux1",
    "value": "Value",
    "row":0,
    "textAlignment": "PKTextAlignmentLeft",
    "changeMessage": "This changed to %@"
}

Now the logs call says there is an error in Get Serial function. Logs only show when there was an error, dont have any logs on success. Dont get any logs during device register, Pass Get or update.

Get serial #s task (for device xxx, pass type pass.com.xxx.xxx, last updated (null); with web service url https://xxx ) encountered error: Unexpected response code 502

"Get serial" call was getting / couldnt read "last updated (null)".
Am I missing some thing very obvious!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants