├── .gitignore ├── src ├── Decrypt │ ├── DecryptionException.php │ └── AppletDecrypt.php ├── Session.php └── Applet.php ├── composer.json ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | composer.lock 3 | .idea 4 | .DS_STORE -------------------------------------------------------------------------------- /src/Decrypt/DecryptionException.php: -------------------------------------------------------------------------------- 1 | =5.5", 9 | "yiisoft/yii2": "~2.0.11" 10 | }, 11 | "autoload": { 12 | "psr-4": { 13 | "Jtcczu\\Applet\\": "src" 14 | } 15 | }, 16 | "authors": [ 17 | { 18 | "name": "jiangtao", 19 | "email": "847837639@qq.com" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/Session.php: -------------------------------------------------------------------------------- 1 | data = $data; 12 | } 13 | 14 | public function get($key, $default=null) 15 | { 16 | return $this->has($key) ? $this->data[$key] : $default; 17 | } 18 | 19 | public function has($key) 20 | { 21 | return array_key_exists($key, $this->data); 22 | } 23 | 24 | public function getOpenid() 25 | { 26 | return $this->get('openid'); 27 | } 28 | 29 | public function getSessionKey() 30 | { 31 | return $this->get('session_key'); 32 | } 33 | 34 | public function getUnionid() 35 | { 36 | return $this->get('unionid'); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 jiangtao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yii2 Applet Extension 2 | 3 | Yii2小程序组件 获取用户信息和会话密钥 4 | 5 | 6 | ## 环境需求 7 | 8 | - PHP >= 5.5 9 | 10 | ## 安装 11 | 12 | ``` 13 | composer require jtcczu/yii2-applet 14 | ``` 15 | 16 | ## 配置 17 | 18 | ``` 19 | return [ 20 | //... 21 | 'components' => [ 22 | 'applet' => [ 23 | 'class' => 'Jtcczu\Applet\Applet', 24 | 'appid' => 'APPID', 25 | 'secret' => 'SECRET' 26 | ] 27 | ] 28 | ] 29 | 30 | ``` 31 | 32 | ## 使用 33 | 34 | ``` 35 | $applet = Yii::$app->applet->makeSession($code); 36 | $applet->getUser($encryptedData, $iv); //返回用户信息 37 | $applet->checkSignature($rawData, $signature); //数据签名校验 38 | 39 | $session = $applet->getSession(); 40 | $session->getOpenid(); //openid 41 | $session->getSessionKey(); //session_key 42 | $session->getUnionid(); //unionid 43 | ``` 44 | 45 | 微信小程序api文档 46 | https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject 47 | 48 | ## 快速开始 49 | 50 | 小程序代码 51 | ``` 52 | wx.login({ 53 | success: function (login) { 54 | wx.getUserInfo({ 55 | success: function (res) { 56 | wx.request({ 57 | url: 'xxx', 58 | method : 'post', 59 | data:{ 60 | code : login.code, 61 | rawData : res.rawData, 62 | signature : res.signature, 63 | encryptedData : res.encryptedData, 64 | iv : res.iv 65 | }, 66 | dataType : 'json', 67 | success : function(res){ 68 | } 69 | }) 70 | } 71 | }) 72 | } 73 | }) 74 | ``` 75 | 76 | 后端代码 77 | 78 | ``` 79 | public function actionTest(){ 80 | $contents = file_get_contents('php://input'); 81 | $data = json_decode($contents,true); 82 | $user = Yii::$app->applet 83 | ->makeSession($data['code']) 84 | ->getUser($data['encryptedData'],$data['iv']); 85 | } 86 | ``` 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /src/Decrypt/AppletDecrypt.php: -------------------------------------------------------------------------------- 1 | appid = $appid; 16 | $this->sessionKey = $sessionKey; 17 | } 18 | 19 | public function getUser($encryptedData, $iv) 20 | { 21 | if (strlen($this->sessionKey) != 24) { 22 | throw new DecryptionException('Illegal Aeskey', DecryptionException::ERROR_ILLEGAL_AESKEY); 23 | } 24 | 25 | if (strlen($iv) != 24) { 26 | throw new DecryptionException('Illegal Iv', DecryptionException::ERROR_ILLEGAL_IV); 27 | } 28 | 29 | list($aesKey, $aesIV, $aesCipher) = array_map('base64_decode', [$this->sessionKey, $iv, $encryptedData]); 30 | 31 | $result = self::decrypt($aesKey, $aesCipher, $aesIV); 32 | 33 | $userArray = Json::decode($result); 34 | 35 | if(is_null($userArray)) { 36 | throw new DecryptionException('Illegal Buffer', DecryptionException::ERROR_ILLEGAL_BUFFER); 37 | } 38 | 39 | if($userArray['watermark']['appid'] != $this->appid ) { 40 | throw new DecryptionException('Illegal Buffer', DecryptionException::ERROR_ILLEGAL_BUFFER); 41 | } 42 | 43 | return $userArray; 44 | } 45 | /** 46 | * check signature is equal 47 | * 48 | * @param $rawData 49 | * @param $signature 50 | * @return bool 51 | */ 52 | public function checkSignature($rawData, $signature) 53 | { 54 | return sha1($rawData.$this->sessionKey) === $signature; 55 | } 56 | 57 | /** 58 | * decode text 59 | * 60 | * @param $text 61 | * @return string 62 | */ 63 | public static function decode($text) 64 | { 65 | $pad = ord(substr($text, -1)); 66 | if ($pad < 1 || $pad > 32) { 67 | $pad = 0; 68 | } 69 | return substr($text, 0, (strlen($text) - $pad)); 70 | } 71 | 72 | /** 73 | * decrypt data 74 | * 75 | * @param $aesKey 76 | * @param $aesCipher 77 | * @param $aesIV 78 | * @return string 79 | * @throws DecryptionException 80 | */ 81 | public static function decrypt( $aesKey, $aesCipher, $aesIV ) 82 | { 83 | try{ 84 | $decrypted = openssl_decrypt($aesCipher, 'aes-128-cbc', $aesKey, OPENSSL_RAW_DATA, $aesIV); 85 | }catch (Exception $e){ 86 | throw new DecryptionException('Decode Base64 Error', DecryptionException::ERROR_DECODE_BASE64); 87 | } 88 | 89 | try { 90 | $result = self::decode($decrypted); 91 | } catch (Exception $e) { 92 | throw new DecryptionException('Illegal buffer', DecryptionException::ERROR_ILLEGAL_BUFFER); 93 | } 94 | 95 | return $result; 96 | } 97 | } -------------------------------------------------------------------------------- /src/Applet.php: -------------------------------------------------------------------------------- 1 | getClient()->get( 52 | $this->getSessionKeyUrl(), [ 53 | 'query' => [ 54 | 'appid' => $this->appid, 55 | 'secret' => $this->secret, 56 | 'js_code' => $code, 57 | 'grant_type' => 'authorization_code' 58 | ] 59 | ] 60 | ); 61 | $contents = $response->getBody()->getContents(); 62 | $result = Json::decode($contents); 63 | if (isset($result['errcode'])) { 64 | throw new HttpException(500, $result['errmsg']); 65 | } 66 | return $this->setSession($result); 67 | } 68 | 69 | protected function setSession($data) 70 | { 71 | $this->session = new Session($data); 72 | 73 | return $this; 74 | } 75 | 76 | public function getSession() 77 | { 78 | return $this->session; 79 | } 80 | 81 | /** 82 | * instance decrypt 83 | */ 84 | public function decrypt() 85 | { 86 | return new AppletDecrypt($this->appid, $this->session->getSessionKey()); 87 | } 88 | 89 | public function __call($method, $arguments) 90 | { 91 | $decrypt = $this->decrypt(); 92 | if(method_exists($decrypt, $method)){ 93 | return call_user_func_array([$decrypt, $method], $arguments); 94 | } 95 | 96 | throw new \BadMethodCallException("Method [$method] does not exist."); 97 | } 98 | 99 | /** 100 | * Get session_key server url 101 | * 102 | * @return string 103 | */ 104 | protected function getSessionKeyUrl() 105 | { 106 | return $this->baseUrl.'/jscode2session'; 107 | } 108 | 109 | /** 110 | * Get client instance 111 | * 112 | * @return Client 113 | */ 114 | protected function getClient() 115 | { 116 | return $this->client?:new Client(); 117 | } 118 | 119 | /** 120 | * Set client instance 121 | * 122 | * @param Client $client 123 | * @return $this 124 | */ 125 | public function setClient(Client $client) 126 | { 127 | $this->client = $client; 128 | 129 | return $this; 130 | } 131 | } 132 | 133 | 134 | --------------------------------------------------------------------------------