1

I created a pass successfully and it opens properly on my MacBook safari browser however, when I try to open it on my physical iPhone or the Simulator it looks like safari doesn't recognize the pass file.

On Mac Safari it shows this: Snapshot of how the pass looks when I download it on Mac Safari

On iPhone or Simulator Safari it shows this: Sanpshot of how it look on iPhone or Simulator Safari

I've checked that all image assets are included in the bundle as well as using the right mime type(application/vnd.apple.pkpass) which I even added to my server mime.types conf file.

Any other thing to check in order to fix this strange issue.

Request and response headers:

URL: http://hayak.localhost/api/request/pass?locale=en-us&uuid=eb5b16db-2a33-4bc8-b3e6-b5dcc5240dfd
Request GET /api/request/pass HTTP/1.1 
Accept: */* 
Accept-Encoding: gzip, deflate
Accept-Language: en-us 
Host: hayak.localhost 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15 Connection: keep-alive Referer: http://hayak.localhost/request/vw
Response HTTP/1.1 200 OK 
Content-Type: application/vnd.apple.pkpass
Keep-Alive: timeout=5, max=100 
Pragma: no-cache 
Content-Disposition: attachment; filename=CP_3_731585792.pkpass
Last-Modified: Tue, 02 Feb 2021 16:00:53 GMT
Cache-Control: public 
Date: Wed, 03 Feb 2021 15:18:46 GMT 
Content-Length: 302319 
Connection: Keep-Alive 
Accept-Ranges: bytes
Vary: Authorization 
X-Powered-By: PHP/7.4.12 Server: Apache/2.4.46 (Unix) OpenSSL/1.0.2u PHP/7.4.12 mod_wsgi/3.5 Python/2.7.13 mod_fastcgi/mod_fastcgi-SNAP-0910052141 mod_perl/2.0.11 Perl/v5.30.1 Content-Transfer-Encoding: binary X-RateLimit-Limit: 60 X-RateLimit-Remaining: 52 Content-Description: File Transfer

JS (Vue) Code:

methods: 
    {
        forceFileDownload(response){
          const url = window.URL.createObjectURL(new Blob([response.data]))
          const link = document.createElement('a')
          link.href = url
          link.setAttribute('download', 'pass.pkpass') //or any other extension
          document.body.appendChild(link)
          link.click()
        },
        downloadWithAxios(){
        axios({
          method: 'get',
          url: '/request/pass',
          params: {locale: this.$i18n.locale, uuid: this.$store.state.app.request.uuid},
          responseType: 'arraybuffer'
        })
        .then(response => {
          
          this.forceFileDownload(response)
          
        })
        .catch(() => console.log('error occured'))
      }  
    }

PHP code:

$path = storage_path().'/passgenerator/'.$pass_identifier.'.pkpass';
        
        return response()->download($path, $pass_identifier.'.pkpass', 
        [
          'Content-Transfer-Encoding' => 'binary',
          'Content-Description' => 'File Transfer',
          'Content-Disposition' => 'attachment; filename=pass.pkpass',
          'Content-length' => strlen($pkpass),
          'Content-Type' => PassGenerator::getPassMimeType(),
          'Pragma' => 'no-cache',
        ]);
  • Does it download on a device? Can you post a link to the pass so that we can replicate? Could you post `curl -I https://{pass url.pkpass}` – PassKit Feb 03 '21 at 02:53
  • Yes it downloads fine with same expected size (similar to the file size on Mac). – salim alzahrani Feb 03 '21 at 03:49
  • Unfortunately, I can’t put a link yet because I’m still doing this locally. – salim alzahrani Feb 03 '21 at 03:51
  • Can you paste the headers using curl? – PassKit Feb 03 '21 at 03:51
  • didn't know how to get the header from curl but I tried to copy it from safari console. sorry for the late response as I was far from my computer all day. See below. – salim alzahrani Feb 03 '21 at 15:26
  • Try changing your endpoint to add a `.pkpass` extension. E.g. ` http://hayak.localhost/api/request/pass.pkpass?locale=en-us&uuid=eb5b16db-2a33-4bc8-b3e6-b5dcc5240dfd . If you are accessing via Javascript, you will need to make sure you have the proper Access-Control headers set. You should change your Cache-Control header, to `Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0`. And consider adding `Content-Transfer-Encoding: binary`. – PassKit Feb 04 '21 at 09:43
  • can you please clarify what do you mean by "changing your endpoint". – salim alzahrani Feb 04 '21 at 14:16
  • Change `/pass?` to `/pass.pkpass?` – PassKit Feb 04 '21 at 14:18
  • See the question post above, I added front and back end codes. – salim alzahrani Feb 04 '21 at 14:32
  • I tried changing the endpoint to 'pass.pkpass' but that didn't have any impact. still having the same response on iPhone/Simulator Safari. – salim alzahrani Feb 04 '21 at 14:46
  • See the last answer to this question for PHP headers https://stackoverflow.com/questions/15383552/how-to-set-mime-type-of-application-vnd-apple-pkpass-in-order-to-share-pass-by-l. And remove 'Content-Description: File Transfer'. – PassKit Feb 04 '21 at 14:52
  • Tried changing the header as advised but still I'm getting the same response on iPhone Safari. – salim alzahrani Feb 05 '21 at 20:43

1 Answers1

0

Since you do not get the file directly from server URL, but through axios then construct the file again, therefore setting these things in PHP will not help:

'Content-Transfer-Encoding' => 'binary',
'Content-Description' => 'File Transfer',
'Content-Disposition' => 'attachment; filename=pass.pkpass',
'Content-length' => strlen($pkpass),
'Content-Type' => PassGenerator::getPassMimeType(),

You could remove them if you want, because we only need the buffer data.

The problem is when you construct the file again in frontend, you must provide MINE type application/vnd.apple.pkpass for it, it will help Safari recognize the pkpass file and open it automatically.

So, replace this line:

const url = window.URL.createObjectURL(new Blob([response.data]))

with this may help:

const url = window.URL.createObjectURL(
  new Blob([response.data], {
    type: "application/vnd.apple.pkpass",
  })
);