-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpasskit.php
128 lines (120 loc) · 4.64 KB
/
passkit.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<?php
class passKit{
protected $certPath;// 签名证书路径
protected $wwdrPath;// WWDR证书路径
protected $certPassword = "";// 签名证书密码
protected $passDir;// 卡包模板路径
protected $tempPath;// 可读可写的临时文件目录
protected $extendFiles;// 额外添加到压缩包的文件二进制数组
public $passkit = [];
/*
* 传入卡包预制模板的路径,需包含pass.json文件
*/
public function __construct(String $dir){
try{
$this->passDir = realpath($dir) . "/";
$passfile = file_get_contents($this->passDir . "pass.json");
$this->passkit = json_decode($passfile,true);
$this->extendFiles = [];
}catch(Exception $e){
return $e->getMessage();
}
}
public function setCert($path){ // 设置签名证书路径
$this->certPath = $path;
return true;
}
public function setWWDR($path){ // 设置WWDR证书路径
$this->wwdrPath = $path;
return true;
}
public function setPassword($password){ // 设置证书密码
$this->certPassword = $password;
return true;
}
/*
* 向用户生成好的pkpass文件
*/
public function outputPass(){
if(is_array($this->passkit))
$this->exportPass();
header('Content-Type: application/vnd.apple.pkpass');
header('Content-Disposition: attachment; filename="pass.pkpass"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
echo $this->passkit;
}
/*
* 返回生成的pkpass文件
*/
public function exportPass(){
$mainfest = [];
$this->setTempDir();
$zip = new \ZipArchive;
$zip->open($this->tempPath."pass.pkpass", \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
$this->passkit = json_encode($this->passkit,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
foreach(scandir($this->passDir) as $file)
if(is_file($this->passDir.$file) && $file != "pass.json")
$mainfest[$file] = sha1_file($this->passDir.$file);
if(count($this->extendFiles))// 如果有更改额外文件,则依次添加
foreach($this->extendFiles as $name => $data){
$zip->addFromString($name,$data);
$mainfest[$name] = sha1($data);
}
$mainfest["pass.json"] = sha1($this->passkit);
$this->signPass($mainfest);
foreach(scandir($this->passDir) as $file)
if(is_file($this->passDir.$file) && $file != "pass.json")
$zip->addFile($this->passDir.$file,$file);
$zip->addFile($this->tempPath."manifest.json","manifest.json");
$zip->addFile($this->tempPath."signature","signature");
$zip->addFromString("pass.json",$this->passkit);
$zip->close();
$this->passkit = file_get_contents($this->tempPath."pass.pkpass");
return $this->passkit;
}
/*
* 对mainfest进行签名
*/
private function signPass(Array $mainfest){
$certs = [];
file_put_contents($this->tempPath."manifest.json",json_encode($mainfest,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES));
try{
openssl_pkcs12_read(file_get_contents($this->certPath), $certs, $this->certPassword);
$openssl_args = [
$this->tempPath."manifest.json",
$this->tempPath."signature",
openssl_x509_read($certs['cert']),
openssl_pkey_get_private($certs['pkey'], $this->certPassword),
[],
PKCS7_BINARY | PKCS7_DETACHED,
$this->wwdrPath
];
call_user_func_array('openssl_pkcs7_sign', $openssl_args);
}catch(Exception $e){
return $e->getMessage();
}
if(!is_file($this->tempPath."signature"))
return false;
$signature = file_get_contents($this->tempPath."signature");
$begin = 'filename="smime.p7s"';
$end = '------';
$signature = substr($signature, strpos($signature, $begin) + strlen($begin));
$signature = substr($signature, 0, strpos($signature, $end));
$signature = trim($signature);
$signature = base64_decode($signature);
file_put_contents($this->tempPath."signature", $signature);
return true;
}
/*
* 提供一个可用的临时目录
*/
private function setTempDir(){
$dir = sys_get_temp_dir() . '/passkit-'.time() . '/';
if(!is_dir($dir))
mkdir($dir,0777);
$this->tempPath = $dir;
return true;
}
}