1
|
|
|
<?php |
2
|
|
|
namespace Wechat\Utils\Code; |
3
|
|
|
|
4
|
|
|
/** |
5
|
|
|
* 对公众平台发送给公众账号的消息加解密示例代码. |
6
|
|
|
* |
7
|
|
|
* @copyright Copyright (c) 1998-2014 Tencent Inc. |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
use Wechat\Utils\Code\Sha1; |
11
|
|
|
use Wechat\Utils\Code\Xmlparse; |
12
|
|
|
use Wechat\Utils\Code\Pkcs7Encoder; |
13
|
|
|
use Wechat\Utils\Code\ErrorCode; |
14
|
|
|
use Wechat\Utils\Code\Prpcrypt; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* 1.第三方回复加密消息给公众平台; |
18
|
|
|
* 2.第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。 |
19
|
|
|
*/ |
20
|
|
|
class WXBizMsgCrypt |
21
|
|
|
{ |
22
|
|
|
private $token; |
23
|
|
|
private $encodingAesKey; |
24
|
|
|
private $appId; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* 构造函数 |
28
|
|
|
* |
29
|
|
|
* @param $token string 公众平台上,开发者设置的token |
30
|
|
|
* @param $encodingAesKey string 公众平台上,开发者设置的EncodingAESKey |
31
|
|
|
* @param $appId string 公众平台的appId |
32
|
|
|
*/ |
33
|
|
|
public function __construct($token, $encodingAesKey, $appId) |
34
|
|
|
{ |
35
|
|
|
$this->token = $token; |
36
|
|
|
$this->encodingAesKey = $encodingAesKey; |
37
|
|
|
$this->appId = $appId; |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* 将公众平台回复用户的消息加密打包. |
42
|
|
|
* <ol> |
43
|
|
|
* <li>对要发送的消息进行AES-CBC加密</li> |
44
|
|
|
* <li>生成安全签名</li> |
45
|
|
|
* <li>将消息密文和安全签名打包成xml格式</li> |
46
|
|
|
* </ol> |
47
|
|
|
* |
48
|
|
|
* @param $replyMsg string 公众平台待回复用户的消息,xml格式的字符串 |
49
|
|
|
* @param $timeStamp string 时间戳,可以自己生成,也可以用URL参数的timestamp |
50
|
|
|
* @param $nonce string 随机串,可以自己生成,也可以用URL参数的nonce |
51
|
|
|
* @param &$encryptMsg string 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串, |
52
|
|
|
* 当return返回0时有效 |
53
|
|
|
* |
54
|
|
|
* @return int 成功0,失败返回对应的错误码 |
55
|
|
|
*/ |
56
|
|
|
public function encryptMsg($replyMsg, $timeStamp = null, $nonce, &$encryptMsg) |
57
|
|
|
{ |
58
|
|
|
$pc = new Prpcrypt($this->encodingAesKey); |
59
|
|
|
//加密 |
60
|
|
|
$array = $pc->encrypt($replyMsg, $this->appId); |
61
|
|
|
|
62
|
|
|
$ret = $array[0]; |
63
|
|
|
if ($ret != 0) { |
64
|
|
|
return $ret; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
if ($timeStamp == null) { |
68
|
|
|
$timeStamp = time(); |
69
|
|
|
} |
70
|
|
|
$encrypt = $array[1]; |
71
|
|
|
|
72
|
|
|
//生成安全签名 |
73
|
|
|
$sha1 = new SHA1; |
74
|
|
|
$array = $sha1->getSHA1($this->token, $timeStamp, $nonce, $encrypt); |
75
|
|
|
|
76
|
|
|
$ret = $array[0]; |
77
|
|
|
if ($ret != 0) { |
78
|
|
|
return $ret; |
79
|
|
|
} |
80
|
|
|
$signature = $array[1]; |
81
|
|
|
|
82
|
|
|
//生成发送的xml |
83
|
|
|
$xmlparse = new XMLParse; |
84
|
|
|
$encryptMsg = $xmlparse->generate($encrypt, $signature, $timeStamp, $nonce); |
85
|
|
|
|
86
|
|
|
return ErrorCode::$OK; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* 检验消息的真实性,并且获取解密后的明文. |
91
|
|
|
* <ol> |
92
|
|
|
* <li>利用收到的密文生成安全签名,进行签名验证</li> |
93
|
|
|
* <li>若验证通过,则提取xml中的加密消息</li> |
94
|
|
|
* <li>对消息进行解密</li> |
95
|
|
|
* </ol> |
96
|
|
|
* |
97
|
|
|
* @param $msgSignature string 签名串,对应URL参数的msg_signature |
98
|
|
|
* @param $timestamp string 时间戳 对应URL参数的timestamp |
99
|
|
|
* @param $nonce string 随机串,对应URL参数的nonce |
100
|
|
|
* @param $postData string 密文,对应POST请求的数据 |
101
|
|
|
* @param &$msg string 解密后的原文,当return返回0时有效 |
102
|
|
|
* |
103
|
|
|
* @return int 成功0,失败返回对应的错误码 |
104
|
|
|
*/ |
105
|
|
|
public function decryptMsg($msgSignature, $timestamp = null, $nonce, $postData, &$msg) |
106
|
|
|
{ |
107
|
|
|
if (strlen($this->encodingAesKey) != 43) { |
108
|
|
|
return ErrorCode::$IllegalAesKey; |
109
|
|
|
} |
110
|
|
|
$pc = new Prpcrypt($this->encodingAesKey); |
111
|
|
|
|
112
|
|
|
//提取密文 |
113
|
|
|
$xmlparse = new XMLParse; |
114
|
|
|
$array = $xmlparse->extract($postData); |
115
|
|
|
|
116
|
|
|
$ret = $array[0]; |
117
|
|
|
|
118
|
|
|
if ($ret != 0) { |
119
|
|
|
return $ret; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
if ($timestamp == null) { |
123
|
|
|
$timestamp = time(); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
$encrypt = $array[1]; |
127
|
|
|
$touser_name = $array[2]; |
|
|
|
|
128
|
|
|
|
129
|
|
|
//验证安全签名 |
130
|
|
|
$sha1 = new SHA1; |
131
|
|
|
$array = $sha1->getSHA1($this->token, $timestamp, $nonce, $encrypt); |
132
|
|
|
$ret = $array[0]; |
133
|
|
|
|
134
|
|
|
if ($ret != 0) { |
135
|
|
|
return $ret; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
$signature = $array[1]; |
139
|
|
|
|
140
|
|
|
if ($signature != $msgSignature) { |
141
|
|
|
return ErrorCode::$ValidateSignatureError; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
$result = $pc->decrypt($encrypt, $this->appId); |
145
|
|
|
if ($result[0] != 0) { |
146
|
|
|
return $result[0]; |
147
|
|
|
} |
148
|
|
|
$msg = $result[1]; |
149
|
|
|
|
150
|
|
|
return ErrorCode::$OK; |
151
|
|
|
} |
152
|
|
|
} |
153
|
|
|
|
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.