Apple Pass push notifications

Dear lazyweb, how do I send Apple Pass push notifications?

Yesterday I added Apple Wallet passes to the DNA Lounge ticketing system: now when you buy a ticket, the confirmation email comes with an attachment that will dump the ticket into your phone such that it will automatically pop up on your lock screen when you are in physical proximity of the club on the day of the event. It's kinda neat.

What I haven't figured out is how to send push notifications.

When someone adds the pass to their phone, their phone registers with my server, sending it the device ID, the serial number of the pass, and a "pushToken". I should be able to take this info and tell Apple, "tell the device to re-download the pass from my server".

The Binary Provider API document explains how to pack up a request to ship off to Apple. The "device ID" is a 32-digit hex number, meaning a 16-byte value; and the "pushToken" is a 64-digit hex number, meaning a 32-byte value, so I assume that when that doc says "32 byte device token" it means the "pushToken" and not the "device ID".

So I'm packing it up like this, and getting neither an error message back, nor a return connection from the phone. What am I missing?

    $note_id = time();
    $expires = time() + (60 * 60 * 24);
    $payload = "{}";

    // Decode the 64-digit hex string to a 32-byte number.
    $push_token = pack ('H*', $push_token);

    $items = (chr(1) .        // ID 1 = device token
              pack('n', strlen($push_token)) .
              $push_token .

              chr(2) .        // ID 2 = payload
              pack('n', strlen($payload)) .
              $payload .

              chr(3) .        // ID 3 = notification ID
              pack('n', 4) .
              pack('N', $note_id) .

              chr(4) .        // ID 4 = expiration date
              pack('n', 4) .
              pack('N', $expires) .

              chr(5) .        // ID 5 = priority
              pack('n', 1) .
              chr(10));

    $cmd = (chr(2) .          // Command = 2
            pack ('N', strlen($items)) .
            $items);
    ...
    stream_context_set_option ($ctx, 'ssl', 'local_cert', $CERT_FILE);
    $fp = stream_socket_client ('ssl://gateway.push.apple.com:2195', ...

Please do not answer with "pay some third-party web service to do this for you" or "install this multi-gigabyte black-box framework".

Update: Got it working, woo...

Tags: , , ,

14 Responses:

  1. Owen Jacobson says:

    I tried to read the docs and went crosseyed from the lack of wire-level examples anywhere in the documentation.

    At the risk of looking like an utter tool, does it work any better with the HTTP/2 API than it does with the binary API?

  2. Brett Thomas says:

    My office-mate spent quite some time beating his head against an ApplePay thing before he realized that the "send thing X" thing that he quite reasonably thought meant "thing A" actually meant "thing B". Have you tried the device ID? It might be the documentation being less precise than you are.

    • Brett Thomas says:

      And re-reading your description it sounds really similar to the issue he had, where he thought that the "x-byte thing" must've obviously meant the binary-byte, not the string-byte size. He's offline for the next few days or I'd ask him.

  3. Jesper says:

    Concatenating $note_id/$expires onto $items will concatenate the string decimal representation of the timestamp (ie "1453880568") instead of its int32 representation, won't it? Don't you need to pack('N', ..) them?

    • jwz says:

      Doh! Well spotted. That might have been the problem...

      You'd think that unparsably malformed data would result in an error message, but I've never seen this thing return an error message at all.

    • jwz says:

      Yup, that was it! Thanks!

  4. Nate says:

    I don't Perl, but the service you want to talk to is APNS. It looks like this is one library that does this:

    http://search.cpan.org/~haoyayoi/Net-APNS-0.0202/lib/Net/APNS.pm

    • jwz says:

      Except that this is PHP. But, actually, the two languages are syntactically identical in this code fragment, except for the comment characters!

  5. Johny come lately says:

    I'm now going to be turning up to the gig on Friday with that image on the screen of my device. Demanding to be let in. Well, I would if I was anywhere near the gig...