tinovyatkin / pass-js Goto Github PK
View Code? Open in Web Editor NEWApple Wallet Passes generating library for Node.JS
License: MIT License
Apple Wallet Passes generating library for Node.JS
License: MIT License
Thanks for the super useful package! I had quite a hard time setting it up for various reasons so I wrote a rather detailed step by step tutorial on how to get the right keys and certificates: https://github.com/adipasquale/passe-passe
I also wrote a super small Node Express API that uses this lib and can be quickly deployed to Heroku.
Would you be interested in listing it as a useful resource on the pass-js
README? I'd be happy to backport a few of the instructions updates directly into the project's README as well if you're open for PRs.
Hi, I'm trying to add a longer text on the backside of the wallet card, using the "backFields" property.
I'm supposed to be able to use \n or \r \n for linebreaks, but nothing seems to be working.
Does the library somehow cut linebreaks from texts, or does anybody have linebreaks working?
Thanks
When im running pass_test.js im getting this error please help me out what im doing wrong?
` mocha pass_test.js
Pass
from template
√ should copy template fields
√ should start with no images
√ should create a structure based on style
without serial number
√ should not be valid
without organization name
√ should not be valid
without description
√ should not be valid
without icon.png
√ should not be valid
without logo.png
undefined
√ should not be valid
generated
1) "before all" hook
8 passing (49ms)
1 failing
The end
event is not fired, although the README says so:
const file = fs.createWriteStream("mypass.pkpass");
pass.on("end", () => {
console.log('end');
})
pass.pipe(file);
First of all, thank you for maintaining this useful library.
The README says that in order to load some images:
pass.images.icon = iconFilename;
pass.icon(iconFilename);
await pass.images.loadFromDirectory('./images');
I understand that each of these lines can be used alone (and you don't have to call the first or second line followed by the third one), but when I use template.images.loadFromDirectory(directoryname)
followed by pass.images.icon = filename
, I get the following error:
error: Unhandled Rejection at: Promise {
<rejected> { Error: EISDIR: illegal operation on a directory, read errno: -21, code: 'EISDIR', syscall: 'read' } } reason: Error: EISDIR: illegal operation on a directory, read
What am I doing wrong?
We can use it then at Pass.validate
and for providing autocomplete in VSCode pass.json
editing
IssueHunt has been backed by the following sponsors. Become a sponsor
node-passbook mentions you can load images from URL.
I noticed you had removed this from your documentation so I assume that you don't directly support it.
What would be the best approach for loading the images from a URL?
Im currently loading the images using request and buffer, but it feels a bit heavy.
pass.images.setImage('icon', '1x', function(err, callback) {
request({
url: ENDPOINTS.IMAGE + offer.agency.image + '?w=29&h=29&bgcolor=ffffff',
encoding: null,
method: 'GET',
proxy: null
}, function(error, response, body) {
callback(body);
})
}
);
Does the library support barcode? I saw an issue related with this it was solved but I am doing the same thing and I can't see the barcode
This is the original issue: #40
I am doing this:
pass.barcodes([{
message: "1234567890",
format: 'PKBarcodeFormatQR',
messageEncoding: 'iso-8859-1'
}]);
@tinovyatkin @nickasd Is this a limitation of the library or I am doing something wrong?
Library version: "@destinationstransfers/passkit": "^6.5.2"
Thanks
I'm trying to figure out why some of the ios devices failing to open generated pass.
I'm testing the same pass on different devices and some works some don't
So far i think it has something to do with IOS becouse after updating ios on iPhone 6 Plus from 12.1.4 to 12.3 it started to work.
Works:
On 5se devices with 12.2 it works
On older 5s with 12.2 it works
On iphone x with 12.3 it works
On iphone 7 plus with 12.2 it works
On iPhone 6 Plus 12.3 works after update from 12.1.4
does not works
On iphone 5 with 10.3.3 it does not work
On iphone 7 with 12.1.4 it does not work - did not yet updated to new 12.3
On iphone 7 with 12.0 it does not work
On iPhone 6 Plus 12.1.4 does not work before update to 12.3
But on thease ^ devies if i import other passes generated from different online services it works.
On android it work.
I tried to open the pass on the mac mini with the newes macos - and it opened it fine with no errors.
This was the reason my i updated from 4.3.1 to 6.4.0 in the first place... but it the newest version did not help.
I don't know that is the reason why it doesn't open on some of the devices.
Then i say it doesn't opens it - i mean
i click to on the link to download pkpass file (all the needed headers are present)
The iphone download it (because if i put break point on server - it waits after resume the error shows) - and shows error safari can not download file (error is in russian Safari не удается загрузить файл.
)
if i do the same from chrome i get a much better error it sais that can not enter data to passbook.
Не удалось внести данные в Passbook.
I also tried to send the file over telegram app, but file is not clickable in it - i guess the ios blocks it.
I don't know what else to try, any ideas ?
With the newest version, as soon as I include require('@destinationstransfers/passkit')
I get the error
node_modules/@destinationstransfers/passkit/dist/lib/images.js:13
exports.IMAGE_FILENAME_REGEX = new RegExp(`^(?<imageType>${Object.keys(constants_1.IMAGES).join('|')}+)(@(?<density>[23]x))?.png$`);
^
SyntaxError: Invalid regular expression: /^(?<imageType>icon|logo|background|footer|strip|thumbnail+)(@(?<density>[23]x))?.png$/: Invalid group
at new RegExp (<anonymous>)
at Object.<anonymous> (node_modules/@destinationstransfers/passkit/dist/lib/images.js:13:32)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (node_modules/@destinationstransfers/passkit/dist/lib/base-pass.js:5:18)
I'm using NodeJS 8.3.0 and I get the following error:
/Users/sja/.nvm/versions/node/v8.3.0/bin/node /Users/sja/dev/mypass/index.js
/Users/sja/dev/mypass/index.js:12
await template.images.loadFromDirectory("./images");
^^^^^^^^
SyntaxError: Unexpected identifier
at createScript (vm.js:74:10)
at Object.runInThisContext (vm.js:116:10)
at Module._compile (module.js:537:28)
at Object.Module._extensions..js (module.js:584:10)
at Module.load (module.js:507:32)
at tryModuleLoad (module.js:470:12)
at Function.Module._load (module.js:462:3)
at Function.Module.runMain (module.js:609:10)
at startup (bootstrap_node.js:158:16)
at bootstrap_node.js:578:3
Process finished with exit code 1
top-level:
barcodes: [],
calendarEvent: {
"title": "Party",
"location": "Discovery Meadow",
"startDate": w3cdate
"endDate": w3cdate
}
Source: https://developer.apple.com/videos/play/wwdc2018-720/?time=1705
We pack to pass strip-image of three sizes: 1125x369, 750x246 and 375x123. But on devices it is clipped on right and left.
What is a correct size? Or maybe where is no "correct" size, and width of strip depends on device.
Thanks for help.
Hello, I faced a fix when a "createPass" attempt shows this message:
"INFO ReferenceError: Set private key in pass template before producing pass buffers
at Pass.asBuffer (/var/task/node_modules/@walletpass/pass-js/dist/pass.js:53:19)
at createTemplate (/var/task/customers/customerAddWallet.js:67:28)"
How do I fix it?
Please any insight.
They don't seem to work ?
Hi,
while am using pass.icon/ pass.loadimages it always returning as not a function error, can you please let me know if there is a work around to overcome this, please find my whole source code below
var express = require('express');
var app = express();
var fs = require('fs');
app.set('port', process.env.PORT || 3000 );
const { Template } = require("@destinationstransfers/passkit");
const { Pass } = require("@destinationstransfers/passkit");
const template = new Template("coupon", {
passTypeIdentifier: "pass.org.example.walletpoc",
teamIdentifier: "2343234",
backgroundColor: "rgb(255,255,255)",
organizationName: "poc"
});
const pass = template.createPass({
serialNumber: "123456",
description: "20% off"
});
pass.images.icon = "logo.png";
pass.icon("logo.png");
pass.loadImagesFrom("./images");
const file = fs.createWriteStream("mypass.pkpass");
pass.on("error", error => {
console.error(error);
process.exit(1);
})
pass.pipe(file);
app.get("/mypass", (request, response) => {
file();
pass.render(response, error => {
if (error)
console.error(error);
});
});
var server = app.listen(app.get('port'), function() {
console.log('Listening on port ' + app.get('port'));
});
or any reference to working example is much help full, thanks in advance
Hello, we have created a pass using your library, but we cannot add it to Apple Wallet.
We have tried to send it via email, download it from our server but iOS doesn't open Wallet.
Instead, it prompts us to select which application to use to open the pkpass file (Wallet is not in the list).
What could be the issue here??
I tried using this module with Google Firebase and got stuck when deploying the project. There are at least two parsing errors:
First one in /node_modules/@destinationstransfers/passkit/dist/lib/images.js:49
for await (const entry of entries) {
^^^^^
SyntaxError: Unexpected reserved word
Second one in /node_modules/@destinationstransfers/passkit/dist/lib/images.js:14:32
SyntaxError: Invalid regular expression: /(^|/)((?<lang>[-A-Z_a-z]+).lproj/)?(?<imageType>icon|logo|background|footer|strip|thumbnail+)(@(?<density>[23]x))?.png$/: Invalid group
Can we safely remove await
in the first error?
For the second one, my guess is the slashes have to be escaped /
should be \/
Hi,
We try to use PassKit directly in our react native project. Is it somehow possible to use it that way and generate pass on device? Because now we are getting 'there is no module http2', etc. errors.
And by the way, thanks for the library)
How do I get the pass out of this,
I ma using a lambda with POST api to create the pass and return it, but how do I use the
pass.asBuffer() to return the data to the iOS app via rest api ?
This library strips out any meta information you add to a field using the add
method.
This biggest downfall with this is you can't replicate the key value pairs found in the apple specification for;
pass.auxiliaryFields.add({
key: "claim_expiryDate",
label: "Expires",
value: moment(offer.claim.expiryDate),
dateStyle: 'PKDateStyleMedium'
});
In process of render pass trailing slash added even if I specify webServiceUrl without it.
How I can control it? I need it because Wallet Union adds one more slash and requests //v1/...
causes 404 error.
Given my code below, the Template.pushUpdates()
method never reaches the APNs:
(async () => {
res = await template.pushUpdates(push_token);
console.log(res); // res is 'undefined' here
process.exit();
})();
i am using node 11 and did a fresh installation on a new project.
I am getting Error: Cannot find module '@destinationstransfers/passkit' when i start the server.
I dont get this error if i try with 4.3.2
I have tried deleting node modules package and package-lock json several times and doing fresh install but I keep getting same error on below line
const { Template } = require("@destinationstransfers/passkit");
The NFCField
type does not match the datatype specified in the Apple documentation for the pass.json file.
According to Apple's documentation, the nfc
top level attribute should be a single dictionary, with the required nfc fields (message
and an optional public key
). See: https://developer.apple.com/library/archive/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/TopLevel.html#//apple_ref/doc/uid/TP40012026-CH2-DontLinkElementID_3
However, the NFCField
type extends from Array<{message: string; publicKey?: string;}>
(see: src/lib/nfc-fields.ts) which means that nfc properties are serialised as an array in pass.json
, and that the generated pass file fails to be verified and added to a Wallet.
I keep getting this error when trying to generate the pass:
Error: Invalid certificate, no key found at decodePrivateKey (/...something.../passkit/node_modules/@destinationstransfers/passkit/src/lib/decodePrivateKey.js:14:11) at signManifest (/...something.../passkit/node_modules/@destinationstransfers/passkit/src/lib/signManifest-forge.js:31:15)
I have a pem file in the correct place, and the pem was generated by passkit-keys from a .p12 file exported from Keychain. I tried exporting a .p12 with the cert+private key, only the key or only the cert...to no avail, I always get the same problem.
Any hint?
Thanks!
AWS lambda is stuck
on an older version.
How strict are you about the 8.X requirement?
Would you accept a pull request to get it working on AWS lambda?
https://developer.apple.com/documentation/passkit/pkaddpassbutton
Implement a class that will return PNG/SVG image in given locale for Add Pass button
As per #48 runtime support under node 10.1 was dropped. Node 8.x is still widely used as a runtime, especially in servers. I suggest that it should be supported a bit longer.
Also note that the fs Promises API is still experimental in node 10.
These changes would be needed for node 8 support:
fs.promises
was unavailable prior to node 10.
Util.promisify
like before.require('url').URL
references the same object in earlier versions.[General] Invalid data error reading pass pass.co.uk.xxxxx/1234567890. The passTypeIdentifier or teamIdentifier provided may not match your certificate, or the certificate trust chain could not be verified.
I have create the .pem using your passkit-key and selected both cert and key
The passTypeIdentifier and teamIdentifier are correct in my cert I'm exporting as a .p12
Proxy
are part of Node 8, so, we can perfectly use them to separate validation logic and sake of beauty
It appears as though the relevantText key of the locations object is never actually being set when the pass is generated.
addLocation(
point:
| number[]
| { lat: number; lng: number; alt?: number }
| { longitude: number; latitude: number; altitude?: number },
relevantText?: string,
): this {
const { longitude, latitude, altitude } = getGeoPoint(point);
const location: import('../interfaces').Location = {
longitude,
latitude,
};
if (altitude) location.altitude = altitude;
if (typeof relevantText === 'string') location.relevantText = relevantText;
if (!Array.isArray(this.fields.locations))
this.fields.locations = [location];
else this.fields.locations.push(location);
return this;
}
get locations(): ApplePass['locations'] {
return this.fields.locations;
}
set locations(v: ApplePass['locations']) {
delete this.fields.locations;
if (!v) return;
if (!Array.isArray(v)) throw new TypeError(`locations must be an array`);
else for (const location of v) this.addLocation(location);
}
this.addLocation is called without passing the relevantText parameter.
I'm running on Lambda with Node 8.10. When calling pipe
into a write stream, the end
event is never emitted (nor is the error
event, for that matter). Although the file's finish
method is emitted, the .pkpass file seems to be corrupt. Here's my code:
const file = fs.createWriteStream("/tmp/mypass.pkpass");
pass.on("error", error => {
console.error(error);
process.exit(1);
})
pass.on("end", function() {
console.log("ended");
})
pass.pipe(file);
Taking the file returned to the client and attempting to install it, the system gives me the following error:
Failed to add pass: 'file:///Users/bryanbartow/Downloads/mypass.pkpass' Error Domain=PKPassKitErrorDomain Code=1 "The pass cannot be read because it isn’t valid." UserInfo={NSLocalizedDescription=The pass cannot be read because it isn’t valid., NSUnderlyingError=0x61000005bba0 {Error Domain=PKPassKitErrorDomain Code=1 "(null)"}}.
Encoding the file as a base64 string, I can decode the string and end up with the contents of the zip(.pkpass) file. The proper files are all present. I just think this is an issue where the last few bytes aren't getting written to the zip file. Has anyone else run into this?
Additionally, "downgrading" to busbud/node-passbook
the end
event fires on pipe
and the resultant .pkpass file is recognized by the system.
Sometimes, not always, this string:
https://github.com/destinationstransfers/passkit/blob/8189323aa39c936d9b697001ef31f3587bade2ce/src/lib/images.ts#L140
causes error: Error: EBADF, Bad file descriptor
.
Maybe it will better to read file as a buffer in case when pathOrBuffer
passed as a string?
async add(
imageType: ImageType,
pathOrBuffer: string | Buffer,
density?: ImageDensity,
lang?: string,
): Promise<void> {
if (!IMAGES_TYPES.has(imageType))
throw new TypeError(`Unknown image type ${imageSize} for ${imageType}`);
if (density && !DENSITIES.has(density))
throw new TypeError(`Invalid density ${density} for ${imageType}`);
if (typeof pathOrBuffer !== 'string' && !Buffer.isBuffer(pathOrBuffer))
throw new TypeError( `Image data for ${imageType} must be either file path or buffer`);
pathOrBuffer = (typeof pathOrBuffer === 'string') ? readFileAsBuffer(pathOrBuffer) : pathOrBuffer;
const { Parser } = imagesize;
const parser = Parser();
const res = parser.parse(pathOrBuffer);
if (res !== Parser.DONE)
throw new TypeError(`Supplied buffer doesn't contain valid PNG image for ${imageType}`);
sizeRes = parser.getResult() as ImageSizeResult;
this.checkImage(imageType, sizeRes, density);
super.set(this.getImageFilename(imageType, density, lang), pathOrBuffer);
}
readFileAsBuffer(path: string): Promise<Buffer> {
return new Promise((resolve, reject) => {
fs.readFile(path, (error, data) => {
if (!!error) {
reject(error);
} else {
resolve(data);
}
});
});
}
The apple developer website best practices (and enterpise best practices) requries us to sign the passes on a separate system that handles private keys and signs files.
Below reference from wallet developer guide
Best Practices
As you implement your web service, keep the following best practices in mind:
Always make a backup of your private key and certificate, and keep them in a secure place.
Avoid storing your private keys on your web server, because web servers typically have a larger attack surface. A more secure approach is to have a different server handle creating and signing passes, and push the finished passes to your web server.
https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/PassKit_PG/Updating.html#//apple_ref/doc/uid/TP40012195-CH5-SW1
The template load function only allows to load certificates from a given location of keys,certs with password. Is it possible to externalize the signing like apple suggests?
https://developer.apple.com/documentation/passkit/wallet/supporting_semantic_tags_in_wallet_passes
Hi
After updating from 4.3.1 to 6.4.0 the cyrillic text in pass.json became broken.
I have looked in to this issue and figured out that code in pass.ts
zip.push({ path: 'pass.json', data: JSON.stringify(this) });
should be
zip.push({ path: 'pass.json', data: Buffer.from(JSON.stringify(this)) });
So this way do-not-zip module will make correct files, otherwise it will make non english text to gibberish
I will make a pull request in a few.
I was following Apple's examples and the sign_pass utility successfully outputs the barcode object, but when using your passkit no barcode is on the pass
In my pass.json I have:
"barcode" : {
"message" : "123456",
"format" : "PKBarcodeFormatQR",
"messageEncoding" : "iso-8859-1"
},
But no barcode is present in the generated pass.
Hi
In some passes in pass.json I see sharingProhibited: true
. This button hides "Share" button.
Why it absent in your package?
There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.
Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.
Original module implementation seems to not support string values at structure level (the only entry of this type currently is transitType
for boardingPass
). Such values also a good candidate to be included in templates, however, it's not clear how to fix that from API point of view, as it doesn't support any second level properties now.
Breaking changes?
Hi!
I'm not sure, thats because I don't create a PR, but require("@destinationstransfers/passkit").createTemplate
is not a function. I did the following:
const {Template, Pass} = require("@destinationstransfers/passkit");
const template = new Template("eventTicket", {...
That seems to work, but it stops on loading the images. I did a template.images.loadFromDirectory("images");
and the relative path contains e.g. a icon.png
and a thumbnail.png
but I get the following error:
pass.loadImagesFrom("images");
^
TypeError: pass.loadImagesFrom is not a function
at Object.<anonymous> (/Users/sja/dev/testpass/index.js:20:6)
at Module._compile (module.js:569:30)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:503:32)
at tryModuleLoad (module.js:466:12)
at Function.Module._load (module.js:458:3)
at Function.Module.runMain (module.js:605:10)
at startup (bootstrap_node.js:158:16)
at bootstrap_node.js:575:3
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.