so_easy
so_easy
  • 发布:2019-01-09 22:47
  • 更新:2020-12-20 18:30
  • 阅读:22419

uni-app 编写小程序怎么获取微信手机号

分类:uni-app

<button>按钮已经绑定getPhoneNumber事件
<button type="primary" open-type="getPhoneNumber" @getPhoneNumber="getPhoneNumber">微信登录</button>

但是在小程序开发工具运行,点击【微信登录】按钮,页弹出获取手机号的弹出框,但是点击弹出框的按钮,没有任何反应。

2019-01-09 22:47 负责人:无 分享
已邀请:
skysowe

skysowe

荟萃了一下社区里的大家的代码,发现是可以取到微信小程序绑定的手机号的,完整代码如下:

这里面有几个知识点,做过微信公众号开发的同学肯定明白:

  1. 如何从微信后台获取jscode
  2. 通过APPID + SECRET + jscode 三个参数访问 https://api.weixin.qq.com/sns/jscode2session 换取session_key;
  3. getPhoneNumber函数,如果用户同意授权,得到encryptedData和iv;
  4. 通过微信官方的WXBizDataCrypt,用手中的APPID和session_key,解密encryptedData,得到手机号,拿到UserInfo和OpenId的方法类似

总结一下:首先得到jscode => 然后得到session_key => 拿到encryptedData和iv => 解密出 UserInfo或者手机号

<template>    
    <view>    
        <!-- bindgetphonenumber -->    
        <!-- <button type="primary" open-type="getUserInfo" @getuserinfo="getUserInfo" withCredentials="true">微信登录</button>  -->  
        <button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取电话号码</button>    

    </view>    
</template>    

<script>    

    //微信提供的解密函数,请修改为你自己的路径  
    var WXBizDataCrypt = require('@/pages/login/WXBizDataCrypt.js');  

    export default {    
        data() {    
            return {    
                login_code : '',  
            };    
        },    
        onLoad: function() {  

            var that = this;  
            uni.login({    
                success: function(res) {    

                    // 获取code    
                    console.log(JSON.stringify(res));  
                    //{"errMsg":"login:ok","code":"071JIp1t1pv马赛克t1Ran1t1JIp1l"}  

                    that.login_code = res.code;  
                }  
            });  

        },  

        methods: {  

            getPhoneNumber: function(e) {    
                console.log(e);    
                if (e.detail.errMsg == 'getPhoneNumber:fail user deny') {    
                    console.log('用户拒绝提供手机号');  
                } else {    
                    console.log('用户同意提供手机号');  

                    console.log(JSON.stringify(e.detail.encryptedData));    
                    console.log(JSON.stringify(e.detail.iv));   

                    var encryptedData = e.detail.encryptedData;  
                    var iv = e.detail.iv;  

                    ////////////////////////////////////////////////////////////////////////////////  
                    //定义在根目录下的main.js里  
                    //Vue.prototype.APPID                           = 'wxb1a马赛克2bfc90a';  
                    //Vue.prototype.SECRET                          = 'b3ae36758马赛克dbe146d9acd81d';  
                    //Vue.prototype.WX_AUTH_URL                     = 'https://api.weixin.qq.com/sns/jscode2session';  

                    var JSCODE = this.login_code;  
                    var APPID = this.APPID;  
                    var SECRET = this.SECRET;  
                    var wx_author_url = this.WX_AUTH_URL + '?appid=' + APPID + '&secret=' + SECRET + '&js_code=' + JSCODE + '&grant_type=authorization_code';  

                    uni.request({  
                        url : wx_author_url,  
                        success(re){  
                            console.log( 'session_key:' + re.data.session_key );  

                            var appId = APPID;  
                            var sessionKey = re.data.session_key;  

                            var pc = new WXBizDataCrypt(appId, sessionKey);  
                            var data = pc.decryptData(encryptedData, iv);  

                            console.log('------------------->');  
                            console.log('解密后 data: ', data);  
                            // console.log('解密后 data: ', JSON.stringify(data));  
                            /*  
                                {  
                                    "phoneNumber": "139马赛克9490",  
                                    "purePhoneNumber": "139马赛克9490",  
                                    "countryCode": "86",  
                                    "watermark": {  
                                        "timestamp": 1560577589,  
                                        "appid": "wxb1a马赛克12bfc90a"  
                                    }  
                                }  
                            */  
                            console.log('------------------->');  

                        }  
                    });  
                    ////////////////////////////////////////////////////////////////////////////////  

                }    

            },  

            /*  
            getUserInfo: function(loginType, cb) {    
                var that = this    
                if (this.globalData.userInfo) {    
                    typeof cb == "function" && cb(this.globalData.userInfo, true);    
                } else {  

                    //1.调用登录接口    
                    wx.login({    
                        success: function() {    

                            wx.getUserInfo({    
                                success: function(res) {    
                                    that.globalData.userInfo = res.userInfo;    
                                    typeof cb == "function" && cb(that.globalData.userInfo, true);    
                                },    
                                fail: function() {    

                                    //2.第一次登陆不强制授权,直接返回    
                                    if (loginType == 0) {    
                                        typeof cb == "function" && cb(that.globalData.userInfo, false);    
                                    } else {    

                                        //3.授权友好提示    
                                        wx.showModal({    
                                            title: '提示',    
                                            content: "您还未授权登陆,部分功能将不能使用,是否重新授权?",    
                                            showCancel: true,    
                                            cancelText: "否",    
                                            confirmText: "是",    
                                            success: function(res) {    

                                                //4.确认授权调用wx.openSetting    
                                                if (res.confirm) {    
                                                    if (wx.openSetting) { //当前微信的版本 ,是否支持openSetting    
                                                        wx.openSetting({    
                                                            success: (res) => {    
                                                                if (res.authSetting["scope.userInfo"]) { //如果用户重新同意了授权登录    

                                                                    wx.getUserInfo({    
                                                                        success: function(res) {    
                                                                            that.globalData.userInfo = res.userInfo;    
                                                                            typeof cb == "function" && cb(that.globalData.userInfo, true);    
                                                                        }    
                                                                    })    
                                                                } else { //用户还是拒绝    
                                                                    typeof cb == "function" && cb(that.globalData.userInfo, false);    
                                                                }    
                                                            },    
                                                            fail: function() { //调用失败,授权登录不成功    
                                                                typeof cb == "function" && cb(that.globalData.userInfo, false);    
                                                            }    
                                                        })    
                                                    } else {    
                                                        typeof cb == "function" && cb(that.globalData.userInfo, false);    
                                                    }    
                                                } else {    
                                                    typeof cb == "function" && cb(that.globalData.userInfo, false);    
                                                }    
                                            },  

                                        })    
                                    }  

                                }    
                            })    
                        }    
                    })    
                }  

            }  
            */    
        }    
    }    
</script>    

<style>    

</style>  
  • skysowe

    以上实现,技术上是没问题的,确实获取到了手机号码和OpenId,但是只适合用于调试模式,,因为微信小程序有域名白名单机制,而微信自身的api.weixin.qq.com不在合法域名内,详见微信官方的文档:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html ;小程序作为客户端,确实存放AppId和SECRET是不合适的,有安全隐患,微信官方的建议是,这部分代码应该放在服务器端,首先在【客户端】得到jscode =>发送到【服务器端】 ,【服务器端】得到session_key发送给【客户端】 =>【客户端】 拿到encryptedData和iv => 解密出 UserInfo或者手机号

    2019-06-15 20:15

  • seho20001123

    回复 skysowe: 能否WXBizDataCrypt把这个js贴一下,我在微信官方没找到,谢谢啦,万分感谢

    2019-07-01 17:53

  • seho20001123

    回复 skysowe: 哎呀,我看到了

    2019-07-01 17:54

  • seho20001123

    请问这个app_id,是开发平台的id还是小程序的id;我这边请求错误了;参数都传的对的;{"errcode":40029,"errmsg":"invalid code, hints: [ req_id: bIadn_4ce-RbEJXa ]"}

    2019-07-01 18:04

  • skysowe

    回复 seho20001123: 这里的app_id当然是微信小程序后台的app_id

    2019-07-02 09:36

  • skysowe

    上面的代码仅供测试使用,开发版没有任何问题,弄懂了原理之后,在实际项目中,我是把访问https://api.weixin.qq.com/sns/jscode2session 通过jscode获取session_key的操作放在了后台,然后把session_key返回到手机端,再加上app_id,用WXBizDataCrypt获取了手机号或用户的完整信息

    2019-07-02 10:25

  • 1***@qq.com

    回复 skysowe: 复制您的代码没有弹窗出现,点击获取手机号码

    console.log(JSON.stringify(e.detail.encryptedData));

    console.log(JSON.stringify(e.detail.iv)); 取不到值

    2020-01-06 15:50

  • 2***@qq.com

    回复 seho20001123: 请问你在哪下载的WXBizDataCrypt.js呢?

    2020-08-14 14:20

  • skysowe

    回复 2***@qq.com: 社区的附件很不明显,就在代码下面第一行

    2020-08-15 11:41

Neil_HL

Neil_HL

试试小程序的真机预览

  • so_easy (作者)

    真机预览也没有反应

    2019-01-10 11:27

  • so_easy (作者)

    我把@getPhoneNumber 换成 bindgetPhoneNumber 运行,就会提示没有方法来处理getPhoneNumber事件

    2019-01-10 11:29

  • so_easy (作者)

    @getPhoneNumber,下面写getPhoneNumber function(e){} 返回的参数e里面没有encryptedData、iv等有关的参数

    2019-01-10 11:32

大笨蛋

大笨蛋 - 打杂的

解决了吗

7***@qq.com

7***@qq.com - 愿您的代码可以改变世界

@getphonenumber="getPhoneNumber" ???

x***@163.com

x***@163.com

我的支付宝上写原生的方法调不起来

4***@qq.com

4***@qq.com

感觉屁用没有 完全看不到手机号

l***@outlook.com

l***@outlook.com

同问,这个什么原因

小米

小米

遇到了同样的问题,有人解决了吗

3***@qq.com

3***@qq.com

WXBizDataCrypt在哪里找到

1***@qq.com

1***@qq.com

我下载微信官方的的WXBizDataCrypt文件到项目中,WXBizDataCrypt文件编译到小程序有600多k,你们有遇到这种情况吗

1***@qq.com

1***@qq.com - 攻城狮

复制您的代码没有弹窗出现,
console.log(JSON.stringify(e.detail.encryptedData));
console.log(JSON.stringify(e.detail.iv)); 取不到值

  • 4***@qq.com

    你这个出错提示怎么解决的?

    2020-12-20 21:13

c***@qq.com

c***@qq.com - vuer

现在又遇到这种情况了,问一下各位怎么解决的

cydida

cydida

微信手机号快捷登录 第一次必定失败,第二次就好了,不管使用真机预览,还是发行模式。

cydida

cydida

微信手机号快捷登录 第一次必定失败,第二次就好了,不管使用真机预览,还是发行模式。

4***@qq.com

4***@qq.com - 暖水袋

如果后端采用uniCloud来完成的话,该如何做?我试着写了一个云函数,但执行后返回的不知道是啥,如下:

'use strict';  
exports.main = async (event, context) => {  
    //event为客户端上传的参数  
    //console.log('event : ', event)  
    const res=uniCloud.httpclient.request(  
        'https://api.weixin.qq.com/sns/jscode2session', {  
        method: 'GET',  
        data: {  
            appid:  "xxxxxxxxxx", //你的小程序的APPID    
            secret: "xxxxxxxxxx", //你的小程序的secret,    
            code:   "xxxxxxxxxx" //wx.login 登录成功后的code    
        }  
        })  
        console.log(res)      
};

执行上传并运行,返回的结果是:

Promise { <pending> }

发现获取微信相关信息原来这么不方便,有没有同学帮帮我?

该问题目前已经被锁定, 无法添加新回复