Search code examples
iosbarcodevcf-vcardpasskitapple-wallet

Encoding a vCard as QR/Barcode for Apple Wallet


I am trying to use a vCard as the content of a QR or barcode in Apple Wallet. I've been able to encode the content, but the QR code is not readable - and I believe thats because I've not been able to prep/format the data ahead of time properly.

While I am using PHP, this isn't a language-specific question.

Here is a sample vCard that I've been using:

BEGIN:VCARD
VERSION:3.0
REV:2023-11-08T00:00:00Z
N:Murphy;Jill;;;
ORG:Company
TITLE:Developer
EMAIL;INTERNET;WORK:[email protected]
URL:https://example.com
END:VCARD

In Apple's Wallet format, the barcode data is specified in JSON format:

"barcode": {
    "format": "PKBarcodeFormatQR",
    "message": "VCARD_DATA_HERE",
    "messageEncoding": "iso-8859-1"
},

I've tried the following in various combinations:

  1. Passing in the vCard text directly
  2. Concatenate the vCard data into one line with "\n" delimiters
  3. Using urlencode (PHP)
  4. All of the above with Apple's various supported barcode formats

Those formats are: PKBarcodeFormatQR, PKBarcodeFormatPDF417, PKBarcodeFormatAztec, and PKBarcodeFormatCode128

I know I can host a vCard and just have the barcode be of a URL but I am intentionally going for a self-contained version.

Can anyone provide guidance on how to format the vCard text before I put it into pass.json so it allows for a readable barcode?


Solution

  • After further trial and error I stumbled upon the answer. It was in how the data is prepared. I had been concatenating each line of the vCard with the wrong delimiters.

    I should have been using "\n\r", and in my case, once escaped would be "\\r\\n".

    function getVCard($pass_name) {
        $vcard = '';
        $vcfFilePath = "./passes/$pass_name/vcard.vcf";
        if (file_exists($vcfFilePath)) {
            $vcard = '';
            $file = fopen($vcfFilePath, 'r');
            $vcard = '';
            while (!feof($file)) {
                $line = fgets($file);
                $vcard .= trim($line) . "\\r\\n";
            }
            fclose($file);
        }
        return $vcard;
    }
    

    In my pass.json for Apple Wallet, the relevant JSON snippet looks like this:

    "barcode": {
        "format": "PKBarcodeFormatQR",
        "message": "BEGIN:VCARD\r\nVERSION:3.0\r\nREV:2023-11-08T00:00:00Z\r\nN:Murphy;Jill;;;\r\nORG:Company\r\nTITLE:Developer\r\nEMAIL;INTERNET;WORK:[email protected]\r\nURL:https://example.com\r\nEND:VCARD\r\n\r\n",
        "messageEncoding": "iso-8859-1"
    },