php-微信小程序登录

微信小程序登录

<?php

/*start  登录  start*/
$code = "";
$iv = "";
$encryptedData = "";

$LoginWxXcx = new LoginWxXcx();
$LoginWxXcx->setCode($code);
$LoginWxXcx->setIv($iv);
$LoginWxXcx->encryptedData($encryptedData);
return $LoginWxXcx->initialization();
/*end  登录  end*/

/**
 * 微信小程序登录
 * Created by Sublime.
 * User: dongfh
 * Date: 2020/07/14
 */
class LoginWxXcx
{
/**
 * error code 微信解密错误说明.
 * <ul>
 *    <li>-41001: encodingAesKey 非法</li>
 *    <li>-41003: aes 解密失败</li>
 *    <li>-41004: 解密后得到的buffer非法</li>
 *    <li>-41005: base64加密失败</li>
 *    <li>-41016: base64解密失败</li>
 * </ul>
 */
    private static $OK = 0;
    private static $IllegalAesKey = -41001;
    private static $IllegalIv = -41002;
    private static $IllegalBuffer = -41003;
    private static $DecodeBase64Error = -41004;

/**
 * error code 业务错误说明.
 * <ul>
 *    <li>1000: 成功</li>
 *    <li>1004: 失败</li>
 *    <li>1005: 业务失败</li>
 * </ul>
 */
    private static $success = 1000;
    private static $fail = 1004;
    private static $business = 1005;

    private static $appid = "xxxx";
    private static $appsecret = "xxxx";
    private static $sessionKeyUri = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
    
    private $openid;
    private $sessionKey;
    
    private $member_id;
    private $UserToken;

    private $encryptedData;
    public function setEncryptedData($encryptedData){
        $this->encryptedData = $encryptedData;
    }

    private $iv;
    public function setIv($iv){
        $this->iv = $iv;
    }

    private $code;
    public function setCode($code){
        $this->code = $code;
    }

    /**
     * [initialization 初始化登录]
     * @return [type] [description]
     */
    public function initialization(){
        //获取openID
        $this->getOpenId();

        //获取用户ID
        $this->getMemberId();
        
        //获取User-Token
        $this->getUserToken();
        
        $info = [
            "user_token" => $this->UserToken
        ];

        return $this->JsonSuccess($info,"登录成功",self::$success);
    }

    /**
     * [getOpenId 获取openID]
     * @return [type] [description]
     */
    private function getOpenId(){
        //替换数据传输过程中的空格为+
        $this->encryptedData = str_replace(' ','+',$this->encryptedData);
        $this->iv = str_replace(' ','+',$this->iv);

        //格式化请求地址 请求接口
        $sessionKeyUri = sprintf(self::$sessionKeyUri,self::$appid,self::$appsecret,$this->code);
        $result = $this->https_request($sessionKeyUri);
        $result = json_decode($result, true);

        if(empty($result['openid']) || empty($result['session_key'])){
            return $this->JsonError("获取sessionKey失败",self::$business,["errmsg" => $result["errmsg"]]);
        }
        $this->openid = $result['openid'];
        $this->sessionKey = $result['session_key'];
    }

    /**
     * [getMemberId 获取用户ID]
     * @return [type] [description]
     */
    private function getMemberId(){
        //查询数据
        $userInfo_db = Db::name("member")->where("openid",$this->openid)->find();

        //用户不存在去注册
        if(empty($userInfo_db["id"])){
            //解密用户信息
            $errCode = $this->decryptData($data);
            if($errCode != 0){
                return $this->JsonError("信息解密失败",self::$business,["errCode" => $errCode]);
            }
            $userInfo = json_decode($data,true);

            //解密成功
            if(!empty($userInfo['openId'])){

                $Member_params = [
                    "nickname" => $userInfo["nickName"],
                    "avatar" => $userInfo["avatarUrl"],
                    "openid" => $userInfo["openId"],
                    "create_time" => time()
                ];
                $user_id = Db::name("member")->insert($Member_params);
                if(!$user_id){
                    return $this->JsonError("注册用户信息失败!",self::$fail,$Member_params);
                }

                $userInfo_db = Db::name("member")->where("member_id",$user_id)->find();
            }else{
                return $this->JsonError("解密用户信息失败!",self::$business,$userInfo);
            }
        }

        if(empty($userInfo_db["id"])){
            return $this->JsonError("获取用户信息失败!",self::$business,["openid" => $this->openid]);
        }

        $this->member_id = $userInfo_db["id"];
    }

    /**
     * [getUserToken 获取User-Token]
     * @return [type] [description]
     */
    private function getUserToken(){
        //生成用户User-Token
        $UserToken = $this->generateUserToken();
        $timestamp = time() + 2592000;

        //查询token
        $MemberToken = Db::name("MemberToken")->where("member_id",$this->member_id)->find();

        //不存在
        if(!$MemberToken){
            $Params = [
                "member_id" => $this->member_id , 
                "token" => $UserToken ,
                "create_time" => $timestamp
            ];
            $result = Db::name("MemberToken")->insert($Params);
            if(!$result){
                return $this->JsonError("添加token失败",self::$fail,$Params);
            }
        }else{
            $timeParams = [
                "token" => $UserToken , 
                "update_time" => $timestamp
            ];
            $result = Db::name("MemberToken")->where("member_id",$this->member_id)->update($timeParams);
            if(!$result){
                return $this->JsonError("更改过期时间失败",self::$fail,$timeParams);
            }
        }

        $this->UserToken = $UserToken."#".base64_encode($this->member_id);
    }

    /**
     * [generateUserToken 生成token]
     * @return [type]            [description]
     */
    private function generateUserToken(){
        $token = strtoupper(md5($this->member_id.'dongfh_'.mt_rand(100,999)));
        return $token;
    }

    /**
     * 检验数据的真实性,并且获取解密后的明文.
     * @param $data string 解密后的原文
     * @return int 成功0,失败返回对应的错误码
     */
    private function decryptData(&$data){
        if (strlen($this->sessionKey) != 24) {
            return self::$IllegalAesKey;
        }
        $aesKey = base64_decode($this->sessionKey);

        if (strlen($iv) != 24) {
            return self::$IllegalIv;
        }
        $aesIV = base64_decode($this->iv);

        $aesCipher = base64_decode($this->encryptedData);

        $result = openssl_decrypt($aesCipher,"AES-128-CBC",$aesKey,1,$aesIV);

        $dataObj = json_decode($result);
        if($dataObj == NULL){
            return self::$IllegalBuffer;
        }
        if($dataObj->watermark->appid != self::$appid){
            return self::$IllegalBuffer;
        }
        $data = $result;
        return self::$OK;
    }

    /**
     * [https_request 请求]
     * @param  [type] $url  [路径]
     * @param  [type] $data [参数]
     * @return [type]       [description]
     */
    private function https_request($url, $data = null) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        if(curl_errno($curl)){
            $output = curl_error($curl);
        }
        curl_close($curl);
        return $output;
    }

    /**
     * [JsonSuccess 返回数据]
     * @param [type]  $data [数据]
     * @param string  $msg  [信息]
     * @param integer $code [状态码]
     */
    private function JsonSuccess($data=[],$msg='成功',$code=1000){
        $data = [
            "code"  => $code,
            "msg"   => $msg,
            "data"  => $data
        ];
        return json_encode($data);
    }

    /**
     * [JsonError 返回数据]
     * @param integer $code [状态码]
     * @param string  $msg  [信息]
     * @param [type]  $data [数据]
     */
    private function JsonError($msg='失败',$code=1004,$data=[]){
        return $this->JsonSuccess($data,$msg,$code);
    }
}
 ?>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352