PHP快速实现微信小程序授权

小程序开发讲究的就是一个敏捷软件开发模式,作为微信小程序授权也有多个项目的积累,所以想贴出来代码,让需要用到的朋友拿来即用(当然前提是需要修改自己的小程序appid和秘钥)。

  1. 前端调用wx.login()获取code值。
  2. 前端通过调用wx.getUserInfo获取iv、rawData、signature、encryptedData等加密数据,传递给服务端。
  3. 服务器通过code请求api--auth.code2Session,换回session_key和openid(判断用户的openid是否在数据库中不在就提交,再给前端发送token(md5用户id+时间戳) )。
  4. 前端发送消息到服务器时带上token,即请求服务端接口时,token作为参数与其他参数一并传来。
  5. 服务器验证token(需要用户数据表创建一个token字段(char 64))。
appid&secret=$this->secret&js_code=$code&grant_type=authorization_code";
        //dump($url);
        $result = $this->getJson($url);
        if(isset($result['errcode'])){
            return \Response::echoError($result['errmsg']);
        }else{
            $session_key = $result['session_key'];
            $signature = $data['signature'];
            $raw = trim($data['rawData']);
            $encryptedData = $data['encryptedData'];
            $iv = $data['iv'];
            if(empty($signature) || empty($raw) || empty($encryptedData) || empty($iv)){
                return \Response::echoError('参数不完整!');
            }
            $signature2 = sha1($raw.$session_key);
            if($signature != $signature2){
                return \Response::echoError('签名错误!');
            }
            $user_info = new wxBizDataCrypt($this->appid, $session_key);
            $errCode = $user_info->decryptData($encryptedData, $iv, $info);
            if($errCode != 0){
                return \Response::echoError($errCode);
            }
            $info = json_decode($info,true);
            // 检查是否已存在该微信小程序的用户openid,存在表示之前已授权,直接更新token
            $res = Model('User')
                ->where([
                    'openId' => $info['openId']
                ])
                ->first();
            Model()->startTrans();
            if(!$res){
                $result_res = Model('User')
                    ->create([
                        'nickname' => $info['nickName'],
                        'openid' => $info['openId'],
                        'headimgurl' => $info['avatarUrl'],
                        'gender' => $info['gender'],
                        'create_time' => date('Y-m-d H:i:s'),
                        'update_at' => date('Y-m-d H:i:s'),
                    ]);
                if(!$result_res){
                    Model()->rollback();
                    return \Response::echoError('授权失败!');
                }else{
                    //保存当前用户登录信息(用户id等)到缓存
                    $loginLogic = new LoginLogic();
                    $loginLogic->save($result_res->id);
                    // 更新token
                    $token = md5($result.time());
                    Model('User')
                        ->where([
                            'id' => $result_res->id
                        ])
                        ->update([
                            'token' => $token
                        ]);
                    Model()->commit();
                    return \Response::echoSuccess($token, '授权成功!');
                }
            }else{
                // 更新token
                $token = md5($res['id'].time());
                Model('User')
                    ->where([
                        'id' => $res->id
                    ])
                    ->update([
                        'token' => $token
                    ]);
                Model()->commit();
                return \Response::echoSuccess($token, '已授权成功!');
            }
        }
    }

    /**
     * curl的get请求
     * @param $url
     * @return mixed
     */
    function getJson($url){
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($ch);
        curl_close($ch);
        return json_decode($output, true);
    }
}

对微信小程序用户加密数据的解密示例代码

sessionKey = $sessionKey;
	$this->appid = $appid;
    }

    /**
     * 检验数据的真实性,并且获取解密后的明文.
     * @param $encryptedData string 加密的用户数据
     * @param $iv string 与用户数据一同返回的初始向量
     * @param $data string 解密后的原文
     *
     * @return int 成功0,失败返回对应的错误码
     */
    public function decryptData( $encryptedData, $iv, &$data )
    {
	if (strlen($this->sessionKey) != 24) {
	    return ErrorCode::$IllegalAesKey;
	}
	$aesKey=base64_decode($this->sessionKey);
	if (strlen($iv) != 24) {
	    return ErrorCode::$IllegalIv;
	}
	$aesIV=base64_decode($iv);
	$aesCipher=base64_decode($encryptedData);
	$result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
	$dataObj=json_decode( $result );
	if( $dataObj  == NULL )
	{
	    return ErrorCode::$IllegalBuffer;
	}
	if( $dataObj->watermark->appid != $this->appid )
	{
	    return ErrorCode::$IllegalBuffer;
	}
	$data = $result;
	    return ErrorCode::$OK;
	}
    }
}

保存当前用户登录信息(用户id等)到缓存的LoginLogic.php

class LoginLogic{
    /**
     * 保存登录信息到缓存
     * @param $user_id
     */
    function save($user_id){
        // 用户信息
        $info = Model('User')
            ->where([
                'id' => $user_id
            ])
            ->first([
                'id',
                'openid',
            ]);
        if(empty($info)){
            return '账户信息不存在';
        }
        session([
            'user_id' => $info->id,
            'openid' => $info->openid,
            'is_login' => true
        ]);
        return true;
    }
}

接下来就是使用授权,创建一个公共的控制器,需要微信授权才能看到的信息都需要过这个公共的控制器。比如创建一个CommonController.php

// 判断是否小程序授权过
class CommonController
{
    // 登录验证openid
    public function __construct(){
    // 接收验证登录的参数
    $data = \Request::getData([
        'token',
    ]);
    if(empty($data['token'])){
	return \Response::echoError('请输入授权token参数!');
    }
    $res = Model('User')
        ->where([
            'token' => $data['token']
        ])
        ->select('id')
        ->first();
    if(!$res){
        return \Response::echoError('请先授权!');
    }else{
        //保存当前用户登录信息
        $loginLogic = new LoginLogic();
        $loginLogic->save($result_res->id);
    }
}

 

你可能感兴趣的:(PHP)