tschoffelen / php-pkpass

💳 PHP class for creating passes for Wallet on iOS.
https://includable.com
MIT License
908 stars 187 forks source link

PKPass opens as html on iphone/safari #72

Closed ammahieu closed 6 years ago

ammahieu commented 6 years ago

On Windows and its browsers, the .pkpass file is shown as expected. Though on an iphone the file is automatically changed into a .html file and the code is simply shown on a page.

tschoffelen commented 6 years ago

This sounds like your web server is not configured to handle the pkpass mime type correctly. Have a look at Apple's documentation or this Stack Overflow question: https://stackoverflow.com/questions/15383552/how-to-set-mime-type-of-application-vnd-apple-pkpass-in-order-to-share-pass-by-l

ammahieu commented 6 years ago

Okay thanks, I will try to do that. It says you can also add header('Content-Type: application/vnd.apple.pkpass'); into the code, but I can already see that in PKPass.php Do I need to add it anywhere else, or do I really have to add the mime type to apache?

ammahieu commented 6 years ago

I have added the mime type, though it still outputs as an html page

tschoffelen commented 6 years ago

Can you send a screenshot? I might not be understanding you correctly

ammahieu commented 6 years ago

screenshot_1

This is what I get on Safari on an iphone. If I run it on firefox or chrome I do get a .pkpass output.

tschoffelen commented 6 years ago

This does make it seem like there is a web server misconfiguration, as it seems like the script outputs the correct stuff. Don't really know why that's happening though, sorry! Perhaps connect your iPhone to Xcode, and look at the console output. Might be that your pass is not valid (due to certificate or JSON content), causing Safari to not know what to do with it.

Also, make sure your script doesn't output any content before or after the pass content, as that will make the file unreadable.

icetee commented 6 years ago

You use create method and use true output option? $pass->create(true);

Cafnio commented 6 years ago

Any solution to this? This is also happening to me on IOS phones (not on computers or android ones though).

It used to work on May, but tested it today and has stopped working. Not sure if related with IOS 11

tschoffelen commented 6 years ago

Please try attaching the iOS device to a Mac running Xcode, and have a look at the device logs. There is probably something wrong with the pass (either with the JSON values or with the certificate you use to create the pass signature). The Mac pass preview isn't as strict on those things as the iOS version. This result often happens when the pass is invalid, and the PKPass rendering process crashes as a result of it.

Cafnio commented 6 years ago

@tschoffelen any possibility to test it out without without having a mac device?

tschoffelen commented 6 years ago

I don't think it is...

icetee commented 6 years ago

@Cafnio Use PHP framework?

Cafnio commented 6 years ago

Yes, I'm using Cakephp.

It's really strange, it was working perfectly on our platform. It works well (downloading the .pkpass) on windows computer, android phone. So far, it's failing only on iOS.

I'm dropping the file it generates in here, to see if you can find any error

https://1drv.ms/u/s!AqhKvZhc6O_UjqAO4kVHpheDnTrvDw

icetee commented 6 years ago

Works on macOS preview and the file is correct. Headers correct? No use prehook, etc on router?

Cafnio commented 6 years ago

I guess that everything is okay.. If it wasn't, it wouldn't work on every browser, right?

tschoffelen commented 6 years ago

Okay, very strange. I couldn't directly install it on my iPhone from the OneDrive link, but when I re-uploaded it to my own Dropbox, and opened the Dropbox share link, it added it to my Wallet without problems.

So my previous theory was wrong, I think it must have something to do with headers. Assuming you have curl installed, and the pass creation happens at an address with no authentication, could you try getting the response headers using the following command and paste them here:

curl -I <URL of pass>
tschoffelen commented 6 years ago

Here’s the pass in my wallet app (iPhone X, iOS 11.1) for reference.

1324558e-0281-4b37-8d63-770a23b9cc7b

Cafnio commented 6 years ago

Yep, the information is correct.

I'm not using curl, i'm using a cakephp framework that downloads the file when a Url is called. I've narrowed down the problem a little bit more:

If i have the following code: $this->response->header('Content-Type','application/vnd.apple.pkpass'); $this->response->body($file); return $this->response;

The pkpass is generated properly (as i'm able to check on winrar), but on iOS it doesn't get downloaded

If I change into this:

$this->response->type(['pkpass' => 'application/vnd.apple.pkpass']); $this->response->file($file, array( 'download' => true, 'name' => "teste" ));

The download on iOS works good, yet, the pkpass is corrupted

I understand that the $file variable returned from $pass->create(true); is not a file.. The question is how can i use file_put_contents to save it on a place, so I can force the download?

Thanks

tschoffelen commented 6 years ago

That shouldn't be neccessary though. The first parameter of the create() function is $output. Currently, you have set it to true, which means that it will output the pass itself, along with the appropriate headers.

If you just want the contents of the pass, set $output to false:

$pass_contents = $pass->create(false);
lock[bot] commented 6 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.