Loading
0

微信授权登录

微信授权登录和QQ、新浪等平台的授权登录都大同小异,均采用OauthOAuth2.0鉴权方式。
微信授权分为两种:

  • 静默授权
  • 弹窗授权,需要用户手动同意


两种scope的区别说明

  • 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
  • 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。

具体而言,网页授权流程分为四步:

  • 引导用户进入授权页面同意授权,获取code
  • 通过code换取网页授权access_token(与基础支持中的access_token不同)
  • 如果需要,开发者可以刷新网页授权access_token,避免过期
  • 通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

以下是封装的微信操作类,需要用到两个数据表,用于保存access_token、ticket,由于他们具有一定有效期,且每天请求数有上限,所以开发者需自行保存


[PHP] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
<?php
/**
*   微信操作表
*   wxtoken 表结构
*   id
*   access_token
*   addtime
*   wxticket 表结构
*   id
*   ticket
*   addtime
*/
class WX {
    private $appid;
    private $appserect;
    private $curl;
    private $msg;
    protected $errs = array(
        '-1' => '系统繁忙,此时请开发者稍候再试',
        '0' => '请求成功',
        '40001' => 'AppSecret错误或者AppSecret不属于这个公众号,请开发者确认AppSecret的正确性',
        '40002' => '请确保grant_type字段值为client_credential',
        '40164' => '调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置。',
    );
    function __construct($appid, $appserect) {
        $this->appid = $appid;
        $this->appserect = $appserect;
        $this->curl = new Curl();
    }
    /*
    微信网页授权登录  需要在公众号设置 - 功能设置 - 网页授权域名
    第一步:用户同意授权,获取code
    scope : snsapi_base 只能获取openid 直接跳转
    snsapi_userinfo
    */
    public function getCode($redirect_uri, $scope = 'snsapi_userinfo',$state = '1') {
        $url = "http://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appid}&redirect_uri={$redirect_uri}&response_type=code&scope={$scope}&state={$state}#wechat_redirect";
        header("Location:{$url}");
        exit;
    }
    /*
    第二步:通过code换取网页授权access_token
    */
    public function getAccessTokenByCode($code) {
        $url = "http://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->appid}&secret={$this->appserect}&code={$code}&grant_type=authorization_code";
        // exit($url);
        // $curl = new Curl();
        $result = $this->curl->doGet($url);
        if (!$result) {
            // $this->curl->getError()
            $this->msg = "获取token失败";
            return false;
        }
        $result = json_decode($result, true);
        if ($result['errcode']) {
            $this->msg = $result['errmsg'];
            return false;
        }
        return $result;
    }
    // 第三步:刷新access_token(如果需要) 通过code 获取openid $type 0静默授权 1弹窗授权
    public function getUserInfo($code, $type = 0, $lang = 'zh_CN ') {
        $result = $this->getAccessTokenByCode($code);
            if (!$result) {
            return false;
        }
        $member = C::t(PT_USER)->getByOpenid($result['openid']);
    if ($member) {
        return $member;
    } else {
        if ($type) {
            $url = "http://api.weixin.qq.com/sns/userinfo?access_token={$result['access_token']}&openid={$result['openid']}&lang={$lang}";
            // $return = $this->curl->doGet($url);
            // 这接口有病 强制显示文件头
            $return = file_get_contents($url);
            if (!$return) {
                $this->msg = '获取用户信息失败';
                return false;
            }
            $return = json_decode($return, true);
            if (!$return) {
                $this->msg = '获取用户信息返回失败';
                return false;
            }
            // file_put_contents('ccc.txt',print_r($return,true),FILE_APPEND);
            $data = array(
                'openid' => $return['openid'],
                'name' => $return['nickname'],
                'sex' => $return['sex'],
                'province' => $return['province'],
                'city' => $return['city'],
                'country' => $return['country'],
                'img' => $return['headimgurl'],
                'bindtel' => 0,
            );
        } else {
            $data = array(
                'openid' => $result['openid'],
                'username' => "微信用户_" . random(6,1)
            );
        }
        $name = rand(100000, 1000000000);
        $e = $name . "@qq.com";
        $password = $e;
        $id = UserAddEdit(0, $data['username'], $password, $e,10,0,"", $msg);
        if ($id <= 0) {
            $this->msg = $msg;
            return false;
        }
        C::t(PT_USER)->update($data, $id);
        $member = C::t(PT_USER)->get($id);
        return $member;
        }
    }
    /*
    公众号 安全中心 设置IP白名单
    公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
    */
    public function getAccessToken($type) {
        $addtime = TIMESTAMP - 7200;
        $url = "http://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appid}&secret={$this->appserect}";
        $row = C::t(PT_WXTOKEN)->getNew($addtime, $type);
        if ($row) {
            return $row['access_token'];
        } else {
            $result = $this->curl->doGet($url);
            if (!$result) {
                $this->msg = "无法获取令牌内容";
                return false;
            }
            $result = json_decode($result, true);
            if (!$result) {
                $this->msg = "解析令牌内容失败";
                return false;
            }
            if ($result['access_token']) {
                C::t(PT_WXTOKEN)->addToken($result['access_token'], $type);
                return $result['access_token'];
            } else {
                $this->msg = "获取令牌失败";
                return false;
            }
        }
    }
    // 获取js票据  需要在公众号设置 - 功能设置 - JS接口安全域名设置
    public function getJsTicket() {
        $addtime = TIMESTAMP - 7200;
        $row = C::t(PT_WXTICKET)->getNew($addtime);
        if ($row) {
            return $row['ticket'];
        } else {
            $token = $this->getAccessToken();
            if (!$token) {
                return false;
            }
            $url = "http://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$token}&type=jsapi";
            $result = $this->curl->doGet($url);
            if (!$result) {
                $this->msg = "无法获取js票据";
                return false;
            }
            $result = json_decode($result, true);
            if (!$result) {
                $this->msg = "解析js票据内容失败";
                return false;
            }
            if ($result['ticket']) {
                C::t(PT_WXTICKET)->addTicket($result['ticket']);
                return $result['ticket'];
            } else {
                $this->msg = "获取js票据失败";
                return false;
            }
        }
    }
    // js sdk 票据签名 当前网页的URL,不包含#及其后面部分
    public function jsSign($data) {
        // 1.所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)
        ksort($data);
        // 2.URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1 采用原始值,不进行URL 转义
        $string1 = $this->ToUrlParams($data);
        // echo "string1:{$string1}<br/>";
        // 3.对string1做sha1加密
        $sign = sha1($string1);
        // echo "signature:{$sign}<br/>";
        return $sign;
    }
    // 获取消息内容
    public function getMsg() {
        return $this->msg;
    }
    /**
    * 格式化参数格式化成url参数
    */
    public function ToUrlParams($data) {
        $buff = "";
        foreach ($data as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }
}
?>


[PHP] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 微信登录
function wxlogin() {
    global $_G,$identifier,$config,$wx;
    if (!$_G['uid']) {
        if ($_GET['state']) {
            //回调
            $member = $wx->getUserInfo($_GET['code']);
            if (!$member) {
                exit($wx->getMsg());
            }
            if (!function_exists("setloginstatus")) {
                include_once libfile('function/member');
            }
            // 设置登录状态$wx
            setloginstatus($member, 2592000);
            checkfollowfeed();
            $_G['uid'] = $member['uid'];
            $_G['member'] = $member;
        } else {
            //请求授权 对参数编码
            $redirect = urlencode(getProtocol() . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
            $wx->getCode($redirect, 'snsapi_base');
        }
    }
}
function getProtocol() {
    return is_http() ? 'http://' : 'http://';
}
function is_http() {  if ($_SERVER['http'] === 1 || $_SERVER['http'] === 'on' || $_SERVER['SERVER_PORT'] == 443) {
        return true;
    }
    return false;
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至80027422@qq.com 举报,一经查实,本站将立刻删除