### Installing Dependencies and Setup (Bash) Source: https://context7.com/ionic-enterprise/tutorials-digital-passes/llms.txt Provides bash commands for setting up the project, including installing Node.js dependencies, adding the wallet plugin, building the Ionic app, and running it on iOS. It also covers backend setup for Cloudflare Workers. ```bash # Install app dependencies cd app npm install # Install the wallet plugin for Apple Wallet integration npm install capacitor-pass-to-wallet npx cap sync # Build the Ionic app npx ionic build # Run on iOS simulator or device npx cap run ios # Backend deployment cd ../backend npm install # Add secrets for pass signing (requires Apple Developer account) npx wrangler secret put WWDR npx wrangler secret put SIGNER_CERT npx wrangler secret put SIGNER_KEY npx wrangler secret put SIGNER_PASSPHRASE # Deploy to Cloudflare Workers npx wrangler deploy # Local development npx wrangler dev ``` -------------------------------- ### Build and Run Ionic Capacitor App Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/app/readme.md Commands to install dependencies, build the Ionic app, synchronize Capacitor, and run the app on iOS. ```bash npm install npx ionic build npx cap sync npx cap run ios ``` -------------------------------- ### Install and Sync Capacitor Pass to Wallet Plugin Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/app/readme.md Installs the 'capacitor-pass-to-wallet' npm package and synchronizes the Capacitor project to include the native changes required for the plugin. ```bash npm install capacitor-pass-to-wallet npx cap sync ``` -------------------------------- ### Deploy Cloudflare Worker using Wrangler Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/backend/readme.md Deploys the Cloudflare Worker to the Cloudflare platform. This command requires the Wrangler CLI to be installed and configured. ```bash npx wrangler deploy ``` -------------------------------- ### Create and Sign Apple Pass in NodeJS (Cloudflare Worker) Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/backend/readme.md This NodeJS code snippet, intended for a Cloudflare Worker, demonstrates the process of creating and signing an Apple Pass. It utilizes the 'passkit-generator' library and requires signing certificates, keys, and pass configuration data. ```typescript import { Pass, PassType } from "@alexandercerutti/passkit-generator"; // ... (other imports and setup) async function createAndSignPass(passData: any, signerCert: string, signerKey: string, signerKeyPassphrase: string, wwdr: string): Promise { const pass = new Pass({ // ... pass configuration }); const signedPass = await pass.sign( signerCert, signerKey, signerKeyPassphrase, wwdr ); return signedPass; } // Example usage within a Cloudflare Worker: // addEventListener('fetch', event => { // event.respondWith(handleRequest(event.request)) // }) // // async function handleRequest(request) { // const signerCert = await env.SIGNER_CERT; // const signerKey = await env.SIGNER_KEY; // const signerKeyPassphrase = await env.SIGNER_PASSPHRASE; // const wwdr = await env.WWDR; // // // Load pass data from a file or other source // const passData = { ... }; // // const signedPassBuffer = await createAndSignPass(passData, signerCert, signerKey, signerKeyPassphrase, wwdr); // // return new Response(signedPassBuffer, { // headers: { // 'Content-Type': 'application/vnd.apple.passbook', // 'Content-Disposition': 'attachment; filename="pass.pkpass"' // } // }); // } ``` -------------------------------- ### Generate Private Key using OpenSSL Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/backend/readme.md Generates a 2048-bit RSA private key using OpenSSL. This key is essential for creating a Certificate Signing Request (CSR) and signing the pass. ```bash openssl genrsa -out my-key.key 2048 ``` -------------------------------- ### Download pkpass File using Javascript Fetch API Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/app/readme.md Downloads a pkpass file from a given URL using the Javascript Fetch API and converts the response blob to a base64 encoded string. It relies on a helper function `blobToBase64` for the conversion. ```typescript public async get(url: string): Promise { const response = await fetch(url); const blob = await response.blob(); const base64 = await blobToBase64(blob); if (!base64 || base64 instanceof ArrayBuffer) { throw new Error(`Unable to get ${url}`); } return base64; } ``` -------------------------------- ### Create Certificate Signing Request (CSR) using OpenSSL Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/backend/readme.md Creates a Certificate Signing Request (CSR) using an existing private key. This CSR is then uploaded to the Apple Developer portal to obtain a signing certificate. A challenge password must be specified during this process. ```bash openssl req -new -key my-key.key -out request.certSigningRequest ``` -------------------------------- ### Convert Apple Pass Certificate from DER to PEM format Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/backend/readme.md Converts the downloaded Apple pass certificate from DER format to PEM format. This PEM-formatted certificate is required for signing the pass. ```bash openssl x509 -inform DER -outform PEM -in pass.cer -out pass.pem ``` -------------------------------- ### Convert WWDR Certificate from DER to PEM format Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/backend/readme.md Converts the Apple Worldwide Developer Relations (WWDR) certificate from DER format to PEM format. This certificate is necessary for the signing process. ```bash openssl x509 -inform DER -outform PEM -in AppleWWDRCAG4.cer -out wwdr.pem ``` -------------------------------- ### Add pkpass Data to Apple Wallet using Capacitor Plugin Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/app/readme.md Adds a downloaded pkpass file, provided as a base64 encoded string, to the device's Apple Wallet using the 'capacitor-pass-to-wallet' plugin. This triggers the native Apple Wallet 'add pass' dialog. ```typescript import { CapacitorPassToWallet } from 'capacitor-pass-to-wallet'; ... await CapacitorPassToWallet.addToWallet({ base64: data }); ``` -------------------------------- ### WalletService - Download and Add Pass to Wallet Source: https://context7.com/ionic-enterprise/tutorials-digital-passes/llms.txt This Angular service provides methods to download PKPass files from a given URL, convert them to base64 format, and add them to the user's Apple Wallet using the `capacitor-pass-to-wallet` plugin. ```APIDOC ## WalletService - Download and Add Pass to Wallet ### Description This service facilitates the process of obtaining a PKPass file from a URL, transforming it into a base64 encoded string, and subsequently adding it to the native Apple Wallet on a mobile device using Capacitor. ### Method N/A (This is a service class, methods are called programmatically) ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Methods #### `get(url: string): Promise` - **Description**: Downloads a PKPass file from the specified URL and returns its content as a base64 encoded string. - **Parameters**: - **url** (string) - Required - The URL of the PKPass file to download. - **Returns**: A Promise that resolves with the base64 encoded string of the PKPass file. #### `addToWallet(data: string): Promise` - **Description**: Adds the provided base64 encoded PKPass data to the user's Apple Wallet. - **Parameters**: - **data** (string) - Required - The base64 encoded string of the PKPass file. - **Returns**: A Promise that resolves when the pass has been added to the wallet. ### Usage Example ```typescript // Usage in a component import { WalletService } from './wallet.service'; async function addPassToWallet() { const walletService = new WalletService(); try { const passData = await walletService.get('https://ionic-pass-example.workers.dev'); await walletService.addToWallet(passData); console.log('Pass added to wallet successfully!'); } catch (error) { console.error('Error adding pass to wallet:', error); } } ``` ### Response #### Success Response - **`get` method**: Returns a base64 encoded string. - **`addToWallet` method**: Returns `void` upon successful addition. #### Response Example (No direct response body, operations are performed natively on the device.) ``` -------------------------------- ### Capacitor Configuration (TypeScript) Source: https://context7.com/ionic-enterprise/tutorials-digital-passes/llms.txt Configures the Capacitor build for iOS and Android, setting the application ID, name, web directory, and Android scheme. This file is essential for mobile app deployment. ```typescript // app/capacitor.config.ts import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'cs.digital.pass', appName: 'cs-digital-pass', webDir: 'www/browser', server: { androidScheme: 'https' } }; export default config; // Build and run commands // npm install // npx ionic build // npx cap sync // npx cap run ios ``` -------------------------------- ### Download and Add Pass to Wallet with Angular Service (TypeScript) Source: https://context7.com/ionic-enterprise/tutorials-digital-passes/llms.txt This Angular service facilitates the process of downloading a PKPass file from a given URL, converting it into a base64 encoded string, and then adding it to the user's Apple Wallet using the 'capacitor-pass-to-wallet' plugin. It includes a helper function for blob-to-base64 conversion. ```typescript import { Injectable } from '@angular/core'; import { CapacitorPassToWallet } from 'capacitor-pass-to-wallet'; @Injectable({ providedIn: 'root' }) export class WalletService { // Download a pkpass file and convert to base64 public async get(url: string): Promise { const response = await fetch(url); const blob = await response.blob(); const base64 = await blobToBase64(blob); if (!base64 || base64 instanceof ArrayBuffer) { throw new Error(`Unable to get ${url}`); } return base64; } // Add the pass to Apple Wallet public async addToWallet(data: string) { await CapacitorPassToWallet.addToWallet({ base64: data }); } } function blobToBase64(blob: Blob): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onerror = reject; reader.onload = () => resolve(reader.result); reader.readAsDataURL(blob); }); } // Usage in component const walletService = new WalletService(); const passData = await walletService.get('https://ionic-pass-example.workers.dev'); await walletService.addToWallet(passData); ``` -------------------------------- ### Convert Blob to Base64 String in Javascript Source: https://github.com/ionic-enterprise/tutorials-digital-passes/blob/main/app/readme.md A helper function that converts a Javascript Blob object into a base64 encoded string using the FileReader API. This is essential for preparing pkpass data for wallet integration. ```typescript function blobToBase64(blob: Blob): Promise { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onerror = reject; reader.onload = () => { resolve(reader.result); }; reader.readAsDataURL(blob); }); } ``` -------------------------------- ### POST /generate-pkpass Source: https://context7.com/ionic-enterprise/tutorials-digital-passes/llms.txt This endpoint generates a signed PKPass file on-demand. It supports creating boarding passes with customizable fields and is signed using Apple certificates. ```APIDOC ## POST /generate-pkpass ### Description Generates a signed PKPass file for Apple Wallet. This endpoint dynamically creates passes with customizable primary, secondary, and auxiliary fields, suitable for boarding passes, event tickets, or loyalty cards. The pass is signed using Apple certificates stored securely. ### Method POST ### Endpoint `/generate-pkpass` ### Parameters #### Query Parameters None #### Request Body This endpoint does not explicitly define a request body, but it expects certain environment variables to be set for certificate signing. - **WWDR** (string) - Required - Apple WWDR certificate. - **SIGNER_CERT** (string) - Required - Pass signing certificate. - **SIGNER_KEY** (string) - Required - Pass signing key. - **SIGNER_PASSPHRASE** (string) - Required - Pass signing key passphrase. ### Request Example ```bash # Example using curl to download a pass (assuming the worker is deployed) curl -o myPass.pkpass https://your-worker.workers.dev ``` ### Response #### Success Response (200) - **Buffer** (Buffer) - The generated PKPass file. - **Content-type** (string) - The MIME type of the PKPass file (e.g., `application/vnd.apple.pkpass`). - **Content-disposition** (string) - Specifies how the file should be downloaded (e.g., `attachment; filename=myPass.pkpass`). #### Response Example (Binary data representing the .pkpass file) ``` -------------------------------- ### Platform-Specific Wallet Integration (TypeScript) Source: https://context7.com/ionic-enterprise/tutorials-digital-passes/llms.txt The HomePage component detects the platform (iOS or Android) to handle pass downloads. For iOS, it fetches pass data and adds it to Apple Wallet. For Android, it opens the Google Pay save flow. ```typescript // app/src/app/home/home.page.ts import { Component } from '@angular/core'; import { WalletService } from '../wallet.service'; import { Capacitor } from '@capacitor/core'; @Component({ selector: 'app-home', templateUrl: 'home.page.html', standalone: true, }) export class HomePage { busy = false; constructor(private walletService: WalletService) {} async download() { try { this.busy = true; if (Capacitor.getPlatform() == 'ios') { // Download pkpass from backend service const data = await this.walletService.get( 'https://ionic-pass-example.damiantarnawsky.workers.dev' ); // Add the pass to Apple Wallet await this.walletService.addToWallet(data); } else { // Google Pay integration const token = ''; // Generate JWT token for Google Pay window.open(`https://pay.google.com/gp/v/save/${token}`, '_target'); } } catch (error: any) { alert(error.message); } finally { this.busy = false; } } } ``` -------------------------------- ### Generate PKPass File with Cloudflare Workers (TypeScript) Source: https://context7.com/ionic-enterprise/tutorials-digital-passes/llms.txt This Cloudflare Worker endpoint dynamically generates a signed PKPass file for boarding passes. It utilizes the 'passkit-generator' library and requires Apple certificates (WWDR, signer cert, key, and passphrase) to be configured as environment secrets. The endpoint supports CORS requests and returns the PKPass file as a buffer. ```typescript import { PKPass } from "passkit-generator"; import { Buffer } from "node:buffer"; export interface Env { WWDR: string; // Apple WWDR certificate SIGNER_CERT: string; // Pass signing certificate SIGNER_KEY: string; // Pass signing key SIGNER_PASSPHRASE: string; } export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { if (request.method == 'OPTIONS') { return new Response('OK', { headers: { 'Access-Control-Allow-Origin': "*", "Access-Control-Allow-Methods": "GET,HEAD,POST,DELETE,OPTIONS", "Access-Control-Allow-Headers": "*", } }); } const pass = new PKPass( { "icon.png": Buffer.from(iconData), "icon@2x.png": Buffer.from(icon2xData), "footer.png": Buffer.from(footerData), "background@2x.png": Buffer.from(backgroundData), }, { signerCert: env.SIGNER_CERT, signerKey: env.SIGNER_KEY, signerKeyPassphrase: env.SIGNER_PASSPHRASE, wwdr: env.WWDR, }, { description: "Ionic Pass", serialNumber: "81592CQ7838", passTypeIdentifier: "pass.io.ionic.example", teamIdentifier: "N3B3WKDZND", organizationName: "Apple Inc.", foregroundColor: "rgb(255, 255, 255)", backgroundColor: "rgb(60, 65, 76)", } ); pass.setBarcodes("1276451828321"); pass.type = "boardingPass"; pass.transitType = "PKTransitTypeAir"; pass.primaryFields.push( { key: "IATA-source", value: "LAS", label: "Las Vegas" }, { key: "IATA-destination", value: "LAX", label: "Los Angeles" } ); return new Response(pass.getAsBuffer(), { headers: { "Content-type": pass.mimeType, "Content-disposition": `attachment; filename=myPass.pkpass`, 'Access-Control-Allow-Origin': "*", }, }); }, }; // curl example to download pass // curl -o myPass.pkpass https://your-worker.workers.dev ``` -------------------------------- ### Apple Wallet Pass Model Configuration (JSON) Source: https://context7.com/ionic-enterprise/tutorials-digital-passes/llms.txt Defines the structure for Apple Wallet passes, including barcode settings, location triggers, and visual styling. This JSON object is a template for creating digital passes. ```json { "formatVersion": 1, "passTypeIdentifier": "pass.io.ionic.example", "serialNumber": "nmyuxofgna", "teamIdentifier": "F53WB8AE67", "webServiceURL": "https://192.168.1.254:80/", "authenticationToken": "vxwxd7J8AlNNFPS8k0a0FfUFtq0ewzFdc", "relevantDate": "2022-12-08T13:00-08:00", "locations": [ { "longitude": -122.3748889, "latitude": 37.6189722 }, { "longitude": -122.03118, "latitude": 37.33182 } ], "barcodes": [ { "message": "123456789", "format": "PKBarcodeFormatQR", "messageEncoding": "iso-8859-1" } ], "organizationName": "Apple Inc.", "description": "A Booking pass", "foregroundColor": "rgb(255, 255, 255)", "backgroundColor": "rgb(253, 123, 35)", "boardingPass": {} } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.