微信开发获取头像

2019-05-24 18:21:27 iningwei 阅读数 2158

前言

微信小游戏接入微信登录还是很简单的,不像原生平台开发,还需要提供appid,appsecret等信息,并有一系列的和微信平台的交互,才能最终授权成功。
下面TS代码演示了,老的接入流程.

export default class WXSdk {
    private tempCode: string = "";//临时登录code
    private appid: string = "wx1926f6b28ac7dbb3";//小程序appid,需要从微信平台获取,并填写在这里
    private secret: string = "745c05d78619ba02a06a003963007299";//小程序appSecret,需要从微信平台获取,并填写在这里
    private grant_type: string = "authorization_code";//固定值
    private openId: string = "";//用户唯一id
    private session_key: string = "";//会话密钥


    public nickName: string = "";
    public avatarUrl: string = "";//头像url

    private loginSuccessCallback: any;
    private loginFailedCallback: any;
    public login(_successCallback: any, _failCallback: any): void {
        this.loginSuccessCallback = _successCallback;
        this.loginFailedCallback = _failCallback;
        this.checkSession();
    }

    private checkSession(): void {
        let obj: any = {
            success: () => {
                this.getUserInfo();
            },
            fail: () => {
                //登录状态过期,需要重新登录
                this.loginWX();
            }
        };
    }
    private loginWX(): void {
        let obj: any = {
            success: (code: string) => {
                this.tempCode = code;
                this.getAccessToken();
            },
            fail: () => {
                console.error("微信登录失败!");
                if (this.loginFailedCallback != null) {
                    this.loginFailedCallback();
                }
            }
        };
        wx.login(obj);
    }


    private getUserInfo(): void {
        let data: any =
        {
            withCredentials: false,
            lang: "zh_CN",
            success: (res: any) => {
                let userInfo: any = res.userInfo;
                this.nickName = userInfo.nickName; //用户昵称
                this.avatarUrl = userInfo.avatarUrl; //用户头像图片 url
                let gender: number = userInfo.gender //性别 0:未知、1:男、2:女
                let province: string = userInfo.province; //用户所在省份
                let city: string = userInfo.city; //用户所在城市
                let country: string = userInfo.country; // 用户所在国家
                console.log("获得用户信息成功,nickName:" + this.nickName + ",gender:" + gender + ",province:" + province + ",city:" + city + ",country:" + country);

                if (this.loginSuccessCallback != null) {
                    this.loginSuccessCallback();
                }
            },
            fail: () => {
                this.checkSession(); //获取用户信息失败之后 继续去获取
                console.error(">>>>获取用户信息失败:" + this.tempCode);
            }
        }
        wx.getUserInfo(data);
    }

    private getAccessToken(): void {
        let url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type={3}";
        url = StringExt.Format(url, this.appid, this.secret, this.tempCode, this.grant_type);
        let success = (res: any) => {
            let data = res.data;
            this.openId = data.openid; //用户唯一标识
            this.session_key = data.session_key; //会话密匙
            let errcode: number = data.errcode; //错误码
            let errMsg: string = data.errMsg; //错误信息
            if (errcode == -1) {
                console.error(">>>系统繁忙,此时请开发者稍候再试");
                Toast.ShowText("系统繁忙,此时请开发者稍候再试");
            } else if (errcode == 0) {
                //请求成功
                this.getUserInfo();
            } else if (errcode == 40029) {
                //code无效
                this.getUserInfo();
            }
        };
        let fail = () => {
            Toast.ShowText("获取登录凭证失败");
            console.error(">>>>>>>获取登录凭证失败");


        }
        this.request(url, success, fail);

    }

    private request(url: string, successCallBack: (res: any) => void, failBack: () => void): void {
        let requestData: any =
        {
            url: url,
            method: "GET",
            dataType: "json",
            success: (res: any) => {
                if (successCallBack != null) {
                    successCallBack(res);
                }
            },
            fail: () => {
                if (failBack != null) {
                    failBack();
                }
                console.error(">>>>>>请求url失败:" + requestData.url);
            }
        };
        let wxtem: any = wx;
        wxtem.request(requestData);
    }
}

目前微信小游戏貌似已经不支持这种方式了(反正我没有搞出来)。
PS:上述StringExt和Toast,请去我的github找代码。

如何接入

核心方法是调用wx.createUserInfoButton创建一个按钮,通过点击该按钮来获得授权信息。
示例代码如下:

export default class WXSdk {
    public static data: any = null;

    public static getUserName(): string {
        if (WXSdk.data == null) {
            return "某高人";
        }
        else {
            return WXSdk.data.userInfo.nickName;
        }
    }
    public static getAvatarURL(): string {
        if (WXSdk.data == null) {
            return "";
        }
        else {
            return WXSdk.data.userInfo.avatarUrl;
        }
    }


    public static Login(): void {
        let sysInfo = wx.getSystemInfoSync();
        let width = sysInfo.screenWidth;
        let height = sysInfo.screenHeight;
        wx.getSetting({
            success(res) {
                console.log("res.authSetting:" + res.authSetting);
                if (res.authSetting["scope.userInfo"]) {
                    console.log("用户已授权");
                    wx.getUserInfo({
                        success(res) {
                            console.log(res);
                            WXSdk.data = res;
                            //TODO: others
                            console.log("nickName:" + WXSdk.getUserName());
                            console.log("avatarUrl:" + WXSdk.getAvatarURL());

                        }
                    });
                }
                else {
                    console.log("用户未授权");
                    //用户未授权的话,全屏覆盖一个按钮,用户点击任意地方都会触发onTap(),弹出授权界面
                    let button = wx.createUserInfoButton({
                        type: 'text',
                        text: '',//不显示文字
                        style: {
                            left: 0,
                            top: 0,
                            width: width,
                            height: height,
                            // lineHeight: 40,
                            backgroundColor: '#00000000',//设置按钮透明
                            color: '#ffffff',
                            textAlign: 'center',
                            fontSize: 16,
                            // borderRadius: 4
                        }
                    });
                    button.onTap(
                        (res) => {
                            if (res.userInfo) {
                                console.log("用户授权:" + res);
                                WXSdk.data = res;
                                //TODO:others
                                button.destroy();//此时删除按钮
                            }
                            else//说明用户点击 不允许授权的按钮
                            {
                                console.log("用户拒绝授权");
                                button.destroy();
                            }
                        }
                    );
                }
            }
        });
    }
}

上述代码中演示的是用户授权用户信息。授权用的是createUserInfoButton,获得用户信息使用到了scope.userInfo域。
另外还有还有诸如授权地理位置信息、授权运动信息、授权相册权限等。
更多详细信息参考 AuthSetting权限

2017-10-16 11:20:14 qq_31617637 阅读数 10556

前几天做的一个项目,微信助力活动,需要获取微信用户的头像,然后存表,在获取微信头像的时候,遇到了两个问题,可能很普通的问题,解决起来也很好解决!



  • 问题一Accesstoken 问题(获取信息接口的问题)

网页授权的 AccessToken 和获取用户信息的 AccessToken 不是一个东西。

也就是获取用户信息接口地址应是

https://api.weixin.qq.com/sns/userinfo

而不是

https://api.weixin.qq.com/cgi-bin/user/info

  • 问题二 48001错误问题

微信错误: 微信登录提示48001,{“errcode”:48001,”errmsg”:”api unauthorized, hints: [ req_id: 1QoCla0699ns81 ]”}
原因:
①:你的服务号必须是通过腾讯认证,每年是300元,如果没有认证而导致的错误提示,那就去认证,别往下看了!如果你已认证,本条原因排除,那么请继续往下看
②:你是否是第三方网页,第三方网页的话,那么你的url地址里面的scope这个参数要填写”snsapi_userinfo”,否则会报这个错!原因如下!
URL地址:https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope={2}&state=ok#wechat_redirect

scope参数对应值的解释:
snsapi_base 不需要用户点同意,直接跳转到授权后的页面,只能用于获取openid,不能获取用户基本信息
snsapi_userinfo 会征求用户同意,授权后,可以获取用户基本信息

需要snsapi_userinfo 的授权域,不然就会拿不到头像啦



  • 问题三 机械返回的问题

当微信回调地址拼上code参数之后,就会用code拿到头像,但是如果我们点进下一个链接,然后在通过手机返回之前拼接的code页面之时,那个连接的code 则会失效,则我们需要重新获取认证

           if(isset($wx_arr['errcode'])){  //当手机机械按钮返回的时候code已经使用过会出现报错  需要重新拿code <br>
            $return_url = '/wap/activityhelp-1.html?uid='.$_GET['uid'].'&amp;model='.$_GET['model']; <br>
            $return_url = 'http://'.$_SERVER['HTTP_HOST'].$return_url; <br>
            if($_GET['time']) { <br>
                $return_url = $return_url.'&amp;time='.$_GET['time']; <br>
            } <br>
            $appId_to_get_code = trim($wxpayjsapi_conf['setting']['appId']); <br>
            $wechat_object->get_code($appId_to_get_code, $return_url); <br>
        }</li>
</ul>
2018-07-13 15:17:58 weixin_42085115 阅读数 16976

在公众号开发中避免不了获取微信用户头像,昵称等登录信息。这里我总结了一下微信开发中从网页授权到获取到用户openid,nickname,headimgurl等信息。

微信开发手册

首先要在微信公众平台中配置好网页授权域名,建议设置为项目域名即可。

这里写图片描述

thinkPHP5的话建议在入口文档定义AppID和APPSecret,因为这两个参数会多次用到,如果以后有变更方便修改,也可在配置文件中定义。

define('APPID', 'wx8fc535aaa112dfb3');
define('SECRET', '97f96488de4911994dfc86f0e287a969');

接下来获取code

public function index()
    {
        //获取code
        $redirect_uri = urlencode('http://www.XXX.com/index/index/getAccesstoken');
        header('Location:https://open.weixin.qq.com/connect/oauth2/authorize?appid='.APPID.'&redirect_uri='.$redirect_uri.'&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect');
        exit;

    }

使用**urlencode()**函数来对回调地址进行加密,回调地址的域名和网页授权域名一致就好,回调地址控制器方法应为接下来获取access_token和openID的控制器和方法。

public function getAccesstoken(){
        //得到openID
        $code = $_GET['code'];
        //获取access_token值
        $get_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.APPID.'&secret='.SECRET.'&code='.$code.'&grant_type=authorization_code'; 
        $data = json_decode(httpRequest($get_token_url),true); 
        // 得到用户信息
        $get_user_info = 'https://api.weixin.qq.com/sns/userinfo?access_token='.$data["access_token"].'&openid='.$data["openid"].'&lang=zh_CN';
        $userinfo = json_decode(httpRequest($get_user_info),true); 
        var_dump($userinfo);
        // var_dump($data);
    }

通过回调链接,会将携带code的返回值返回到该方法中,发送获取access_token的请求,得到access_token,这里的access_token仅限于获取用户信息,具体建议查看手册。

拿到access_token和openID后发送获取用户信息的请求,得到的$userinfo就是包含用户昵称,性别,头像等信息的数组(通过json_decode将json格式转为数组,微信返回为json格式)。

这里的httpRequest()方法为发送curl请求的一个方法,如下:

function httpRequest($url, $postData=array()){
        // (1)初始化
        $ch = curl_init();
        // (2)设置选项
        // 设置请求的url
        curl_setopt($ch, CURLOPT_URL, $url);
        // 将curl_exec()获取的数据以字符串返回,而不是直接输出。
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        if(!empty($postData)){
            // 设置请求方式为post
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        }
        //curl注意事项,如果发送的请求是https,必须要禁止服务器端校检SSL证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        // (3)执行
        $result = curl_exec($ch); 
        // (4)关闭
        curl_close($ch);
        return $result;
}
2018-11-28 19:39:45 github_36673034 阅读数 3377

一、首先来认识一下所有ID

  1. appid 微信公众号唯一ID
  2. appsecret 公众号分配唯一表示
  3. access_token 公众号的全局唯一接口调用凭据 使用grant_type(client_credential),appid和secret获取,有效期两小时,但是老的失效5分钟以内可以用,中控服务器(redis)储存这个,每天限制2000次。
  4. openid 同一公众号下来标识用户的唯一性。
  5. UnionID 同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。

二、获取用户头像

一般情况

1、引导用户进入授权页面同意授权,获取code
配置一个地址
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
例如:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect
其中:
appid 公众号的唯一标识
redirect_uri 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
response_type 返回类型,请填写code
scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect 无论直接打开还是做页面302重定向时候,必须带此参数,这个为后端的302接口或者前端页面

后边三个都是后端做
2、通过code换取网页授权access_token(与基础支持中的access_token不同)

3、如果需要,开发者可以刷新网页授权access_token,避免过期

4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

参考https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
特殊情况
1.用户关注过公众号,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是scope为snsapi_userinfo,也是静默授权,用户无感知。
2.UnionID获取(开发者一个账号绑定了多个公众号) https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839