Takahiro Octopress Blog

-1から始める情弱プログラミング

Node-passbookではまったこと

PassbookのPassを動的生成するためにnode-passbookを使ってみました

皆様、あけましておめでとうございます。2014年1回目のブログ更新です。
今回はnode-passbookではまったことについて紹介したいと思います。通常、はまらないことかもしれないのですが、筆者は2日半くらい悩みました。

node-passbookはGithub上で公開されています。

node-passbookの設定

今回は、nodeのWebフレームワークであるExpressを使います。Expressの始め方についてはgihyo.jsさんのページを参考にしてください。Expressの準備が整っている前提で説明を始めたいと思います。

まずはnode-passbookモジュールをインストールしましょう。

1
npm install passbook

次に、app.jsを編集しましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
// passbook発行処理を書いたpass.jsをrequire
var pass = require('./routes/pass');

<省略>

app.get('/', routes.index);
app.get('/users', user.list);
// passbookのpassをダウンロードするときのget
app.get('/download', pass.download);
// passbookのpassを作成するときのget
app.get('/create', pass.create);

<省略>

では、passbook発行処理を書いたpass.jsをroutes配下に作成します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
var fs = require('fs');
var path = require('path');
var createTemplate = require("passbook");

exports.create = function(req, res) {
  // Passbook作成
  var template = createTemplate('eventTicket', {
      'passTypeIdentifier': 'pass.****.****.****',
      'teamIdentifier': '***********',
      'organizationName': 'Passbookテスト'
  });
  template.keys('./public/keys', 'test12345');
  var passbook = template.createPass({
      serialNumber: 'abcdefc',
      description: 'Passbookテスト用のチケットです。',
      logoText: '参加チケット',
      foregroundColor: 'rgb(255, 255, 255)',
      backgroundColor: 'rgb(60, 65, 76)'
  });
  passbook.fields.webServiceURL = "https://example.com/passes";
  passbook.fields.authenticationToken = "vxwxd7J8AlNNFPS8k0a0FfUFtq0ewzFdc";
  passbook.fields.relevantDate = "2014-01-25T17:00+09:00";
  passbook.fields.barcode = {
      message: "http://google.com",
      format: "PKBarcodeFormatQR",
      messageEncoding: "iso-8859-1",
      altText: "ユーザID"
  };
  passbook.primaryFields.add([
      {
          "key" : "event",
          "label" : "イベント",
          "value" : "Passbookテスト"
      }
  ]);
  passbook.secondaryFields.add([
      {
          "key" : "loc",
          "label" : "場所",
          "value" : "東京近辺"
      }
  ]);
  passbook.backFields.add([
      {
          "key" : "message",
          "label" : "メッセージ",
          "value" : "Passbook盛り上げていきましょう!"
      }
  ]);
  passbook.loadImagesFrom("./public/images");

  var pkpassFile = fs.createWriteStream("mypass.pkpass");
  passbook.on("error", function(error) {
      console.error(error);
      process.exit(1);
  });
  passbook.pipe(pkpassFile);
          
  res.end();
};

exports.download = function(req, res){

  var file = './mypass.pkpass',
      filestream = fs.createReadStream(file),
      filename = path.basename(file),
      mimetype = 'application/vnd.apple.pkpass';
  res.setHeader('Content-disposition', 'attachment; filename=' + filename);
  res.setHeader('Content-type', mimetype); 
  filestream.on('data', function(chunk) {
      res.write(chunk);
  });
  filestream.on('end', function() {
      res.end();
  });
};

さて、これでソースの準備は完了です。
次の章では、筆者がはまった点について具体的に説明します。

証明書ではまりました

筆者は上記のソースを書き終わった時点で完了だと思ったのですが、iPhoneから落としてもうまくいきませんでした。
うまくいかなかったときの現象は下記です。
iOS6 ⇒ Pass自体は表示されるものの、追加ボタンを押しても追加されない
iOS7 ⇒ Pass自体表示されない

また、XcodeのOrganizerのコンソールでログを見たところ、Signature is missingと表示されてしまいました。
悩んだ果てにnode-inspectorでデバッグして1つ1つ処理を確認したところ、node_modules/passbook/lib/pass.jsの342〜350行目を見て気づきました。

1
2
3
4
5
6
7
8
9
10
11
12
 function signManifest(template, manifest, callback) {
   var identifier = template.passTypeIdentifier().replace(/^pass./, "");
   
   var args = [
      "smime",
      "-sign", "-binary",
      "-signer",    Path.resolve(template.keysPath, identifier + ".pem"),
      "-certfile",  Path.resolve(template.keysPath, "wwdr.pem"),
      "-passin",    "pass:" + template.password
  ];

  <省略>

そう、pemファイルの名前が間違っていたのです。pemファイルの名前はpassTypeIdentifierに設定する文字列からpass.を削除したものにしなくてはなりませんでした。

やっぱりデバッグは大切ですね。

参考ページ:
node.jsでPassbookサーバをつくってみる
Node.jsでPassbookを発行してみる

Comments