Apple Wallet — Safari Delivery Tests

Testing different delivery methods. Same pass bytes each time — only the HTTP delivery path differs.

Test A/B — Direct download to test locally on Mac

Generates pass and downloads as demo.pkpass to Downloads folder.

Test C — Uploaded public storage URL (ends in .pkpass)

Generates pass → uploads to Base44 public storage → direct file URL. Storage likely serves application/octet-stream not application/vnd.apple.pkpass — expected to fail.

Test D — Cloudflare Worker proxy at wallet.playoneweknow.co.uk/pass/demo.pkpass

This is the most reliable Safari delivery method. The Worker re-serves the pass bytes from a clean .pkpass path with forced Content-Type: application/vnd.apple.pkpass.

✅ This is the fix for Safari. Deploy the Cloudflare Worker below, then tap on iPhone Safari.

+ Add to Wallet (D) — Recommended ✓

Cloudflare Worker code for Test D

1. Go to Cloudflare Dashboard → Workers & Pages → Create Worker
2. Paste the code below
3. Add a custom domain route: wallet.playoneweknow.co.uk/*
4. Deploy — then tap Test D on iPhone Safari

// Cloudflare Worker — deploy at wallet.playoneweknow.co.uk // Routes: GET /pass/*.pkpass → fetches from Base44 generateApplePass and re-serves // with forced Content-Type: application/vnd.apple.pkpass const PASS_FUNCTION_URL = "https://playoneweknow.co.uk/functions/generateApplePass"; const DEMO_QR = "https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://app.yuubee.com/pay/demo"; export default { async fetch(request) { const url = new URL(request.url); if (!url.pathname.endsWith(".pkpass")) { return new Response("Not found", { status: 404 }); } // Forward query params if present, or use demo defaults const params = new URLSearchParams({ qrCodeUrl: url.searchParams.get("qrCodeUrl") || DEMO_QR, displayName: url.searchParams.get("displayName") || "POWK User", userId: url.searchParams.get("userId") || "user", }); const upstream = await fetch(`${PASS_FUNCTION_URL}?${params}`); if (!upstream.ok) { return new Response("Upstream error: " + upstream.status, { status: 502 }); } const body = await upstream.arrayBuffer(); return new Response(body, { status: 200, headers: { "Content-Type": "application/vnd.apple.pkpass", "Content-Disposition": 'inline; filename="pass.pkpass"', "Content-Length": body.byteLength.toString(), "Cache-Control": "no-store", }, }); }, };
Diagnosis so far: A & B (function URL, wrong path) failed. C (storage URL, likely wrong MIME) expected to fail. D (Cloudflare Worker, correct path + forced MIME) is the most likely fix. The pass itself is valid — confirmed by email attachment test.

We use cookies to understand how you use POWK and improve your experience. By continuing to browse, you agree to our use of cookies.