How to create an Apple Wallet membership card using Node.js

How to create an Apple Wallet membership card using Node.js

How to Create a Membership Card for Apple Wallet Using Node.js

Apple Wallet (formerly Passbook) allows users to store and manage various passes, such as boarding passes, tickets, and membership cards. Creating a membership card for Apple Wallet can enhance user engagement and provide a seamless experience. In this guide, we'll walk you through the process of generating Apple Wallet Passes (Passbook Passes) using Node.js.

Table of Contents

  1. Prerequisites
  2. Step 1: Generate Certificates
  3. Step 2: Set Up Your Project
  4. Step 3: Create the Node.js Server
  5. Step 4: Create the Pass Model
  6. Step 5: Test Your Pass Generation
  7. Additional Notes
  8. Conclusion

Prerequisites

Before you begin, ensure you have the following:

  • Apple Developer Account: Required to create Pass Type IDs and access necessary certificates.
  • Node.js and npm Installed: Ensure you have Node.js (v12 or later) and npm installed on your machine.
  • Basic Knowledge of Node.js and Express: Familiarity with setting up a basic Node.js server.

Step 1: Generate Certificates

Apple Wallet passes require specific certificates to ensure security and authenticity. Follow these steps to generate the necessary certificates:

  1. Create a Pass Type ID:

    • Log in to your Apple Developer Account.
    • Navigate to Certificates, Identifiers & Profiles.
    • Under Identifiers, select Pass Type IDs.
    • Click the "+" button to create a new Pass Type ID.
    • Enter a description and identifier (e.g., pass.com.yourcompany.membership).
    • Complete the creation process and download the Pass Type ID certificate.
  2. Download the WWDR Certificate:

  3. Convert the .cer to .pem (if necessary):

    openssl x509 -in AppleWWDRCA.cer -inform DER -out AppleWWDRCA.pem -outform PEM
    
    
  4. Export Your Pass Type ID Certificate as .p12:

    • Open Keychain Access on your Mac.
    • Locate your Pass Type ID certificate.
    • Right-click and select Export.
    • Choose the .p12 format and set a secure passphrase.

Step 2: Set Up Your Project

Initialize your Node.js project and install the necessary dependencies.

# Create and navigate to your project directory
mkdir apple-wallet-pass
cd apple-wallet-pass

# Initialize a new Node.js project
npm init -y

# Install required packages
npm install express @walletpass/pass-js dotenv

Note: We've added the dotenv package to manage environment variables securely.


Step 3: Create the Node.js Server

Create a server that generates and serves the Apple Wallet pass.

  1. Project Structure:

    apple-wallet-pass/
    ├── certificates/
    │   ├── pass.p12
    │   └── AppleWWDRCA.pem
    ├── pass-model/
    │   ├── pass.json
    │   ├── icon.png
    │   └── logo.png
    ├── .env
    ├── server.js
    └── package.json
    
    
  2. Configure Environment Variables:

    Create a .env file to store sensitive information.

    PASS_CERT_PATH=./certificates/pass.p12
    WWDR_CERT_PATH=./certificates/AppleWWDRCA.pem
    PASS_CERT_PASSPHRASE=your-passphrase
    PORT=3000
    
    
  3. Create server.js:

    // server.js
    require('dotenv').config();
    const express = require('express');
    const { Pass } = require('@walletpass/pass-js');
    const fs = require('fs');
    const path = require('path');
    
    const app = express();
    
    // Load certificates
    const passCert = fs.readFileSync(
    	path.resolve(__dirname, process.env.PASS_CERT_PATH),
    );
    const wwdrCert = fs.readFileSync(
    	path.resolve(__dirname, process.env.WWDR_CERT_PATH),
    );
    
    // Route to generate the pass
    app.get('/membership-pass', async (req, res) => {
    	try {
    		const pass = new Pass({
    			model: path.join(__dirname, 'pass-model'), // Path to pass-model directory
    			certificates: {
    				wwdr: wwdrCert, // Apple WWDR Certificate
    				signerCert: passCert, // Pass Type ID Certificate
    				signerKey: passCert, // Same as passCert for .p12 files
    				signerKeyPassphrase: process.env.PASS_CERT_PASSPHRASE, // Passphrase for the .p12 file
    			},
    		});
    
    		// Set pass fields
    		pass.setType('generic'); // Use 'generic' for membership cards
    		pass.setPassFields({
    			primaryFields: [
    				{ key: 'name', label: 'MEMBER', value: 'Alex Hobday' },
    			],
    			secondaryFields: [
    				{ key: 'membership', label: 'Membership ID', value: 'MEM123456' },
    				{ key: 'balance', label: 'Balance', value: '$50.00' },
    			],
    		});
    
    		// Optional: Set barcode
    		pass.setBarcodes([
    			{
    				format: 'PKBarcodeFormatQR',
    				message: 'MEM123456',
    				messageEncoding: 'iso-8859-1',
    			},
    		]);
    
    		// Customize appearance
    		pass.setBackgroundColor('rgb(0, 0, 0)');
    		pass.setForegroundColor('rgb(255, 255, 255)');
    		pass.setLabelColor('rgb(255, 255, 255)');
    		pass.setLogoText('Membership Card');
    
    		// Generate the pass
    		const passStream = await pass.generate();
    
    		// Send the pass as a downloadable file
    		res.type('application/vnd.apple.pkpass');
    		res.setHeader(
    			'Content-Disposition',
    			'attachment; filename=membership.pkpass',
    		);
    		passStream.pipe(res);
    	} catch (error) {
    		console.error('Error generating pass:', error);
    		res.status(500).json({ error: 'Failed to generate pass' });
    	}
    });
    
    // Start the server
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => {
    	console.log(`Server is running on port ${PORT}`);
    });
    

    Security Tip: Always handle errors gracefully and avoid exposing sensitive error details to users.


Step 4: Create the Pass Model

The pass model defines the structure and appearance of your Apple Wallet pass.

  1. Create pass-model/pass.json:

    {
    	"formatVersion": 1,
    	"passTypeIdentifier": "pass.com.yourcompany.membership",
    	"serialNumber": "123456789",
    	"teamIdentifier": "YOUR_TEAM_ID",
    	"organizationName": "Your Company",
    	"description": "Membership Card",
    	"backgroundColor": "rgb(0,0,0)",
    	"logoText": "Membership",
    	"foregroundColor": "rgb(255,255,255)",
    	"barcode": {
    		"format": "PKBarcodeFormatQR",
    		"message": "MEM123456",
    		"messageEncoding": "iso-8859-1"
    	},
    	"generic": {
    		"primaryFields": [
    			{
    				"key": "name",
    				"label": "MEMBER",
    				"value": "Alex Hobday"
    			}
    		],
    		"secondaryFields": [
    			{
    				"key": "membership",
    				"label": "Membership ID",
    				"value": "MEM123456"
    			},
    			{
    				"key": "balance",
    				"label": "Balance",
    				"value": "$50.00"
    			}
    		]
    	}
    }
    

    Important: Replace "pass.com.yourcompany.membership" with your actual Pass Type ID and "YOUR_TEAM_ID" with your Apple Developer Team ID.

  2. Add Required Images:

    Place the following images in the pass-model directory. Ensure they meet Apple's PassKit image requirements.

    • icon.png: 29x29 pixels (mandatory)

    • logo.png: 160x50 pixels (mandatory)

    Image Formats: Use PNG format without transparency for the images.


Step 5: Test Your Pass Generation

Now that everything is set up, you can test the generation of your Apple Wallet membership pass.

  1. Start the Server:

    
    node server.js
    
    
  2. Access the Pass Generation Endpoint:

    Open your browser or use a tool like Postman to navigate to:

    http://localhost:3000/membership-pass
    
    

    This should prompt a download of the membership.pkpass file.

  3. Add the Pass to Apple Wallet:

    • Transfer the .pkpass file to your iOS device (e.g., via email or AirDrop).
    • Open the file on your device, and it should prompt you to add the pass to Apple Wallet.

Additional Notes

Pass Customization

  • Dynamic Data: Integrate a database to dynamically populate pass fields based on user data.
  • Localization: Support multiple languages by adding localization files.
  • Images: Enhance your pass with additional images like thumbnail, strip, and background images.

Security Considerations

  • Protect Certificates: Ensure your certificates are stored securely and not exposed publicly.
  • HTTPS: Serve your application over HTTPS to secure data transmission.
  • Validation: Implement validation to ensure only authorized users can generate passes.

Error Handling

  • Implement comprehensive error handling to catch and respond to potential issues during pass generation.
  • Log errors securely for debugging purposes without exposing sensitive information to users.

Deployment

  • Environment Variables: Use environment variables to manage configurations securely in different environments (development, staging, production).
  • Scalability: Consider deploying your application on scalable platforms like AWS, Heroku, or Vercel to handle increased traffic.

Conclusion

Creating a membership card for Apple Wallet using Node.js involves generating secure Passbook passes, setting up a server to handle pass generation, and customizing the pass model to fit your brand and requirements. By following this guide, you can integrate Apple Wallet into your application, providing users with a convenient and modern way to access their membership information.

For more advanced features, consider exploring Apple's PassKit Framework and integrating additional functionalities like push updates and location-based notifications.

Happy coding!

Vivek Thumar

Software Engineer

Vivek is a software engineer with a passion for building innovative solutions. He enjoys working on challenging problems and creating software that makes a positive impact.