郭什么 發表於 2021-1-19 16:00:00

uni-app开发经验分享二十: 微信小程序 授权登录 获取详细信息 获取手机号

<h3>授权页面</h3>
<p>因为微信小程序提供的 权限弹窗 只能通用户确认授权 所以可以 写一个授权页面,让用户点击 来获取用户相关信息 然后再配合后台就可以完成登录</p>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">&lt;button class="btnInfo" open-type="getUserInfo"/&gt;</pre>
</div>
<p><img src="https://img2020.cnblogs.com/blog/2149129/202101/2149129-20210119155632425-261441140.png" alt="" loading="lazy"></p>
<p>&nbsp;素材</p>
<p><img src="https://img2020.cnblogs.com/blog/2149129/202101/2149129-20210119155645842-1630566619.png" alt="" loading="lazy"></p>
<p>&nbsp;页面代码示例<br>这个接口要在后端调用(https://api.weixin.qq.com无法加入白名单)</p>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&amp;secret="+secret+"&amp;js_code="+code+"&amp;grant_type=authorization_code</pre>
</div>
<p>&nbsp;</p>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">&lt;template&gt;
        &lt;view&gt;
                &lt;view&gt;
                  &lt;view&gt;
                        &lt;view class='header'&gt;
                          &lt;image src='../../static/wx_login.png'&gt;&lt;/image&gt;
                        &lt;/view&gt;
                        &lt;view class='content'&gt;
                          &lt;view&gt;申请获取以下权限&lt;/view&gt;
                          &lt;text&gt;获得你的公开信息(昵称,头像、地区等)&lt;/text&gt;
                        &lt;/view&gt;
                        &lt;!-- withCredentials=true获取到除用户基本信息之外的encryptedData以及iv等数据 --&gt;
                        &lt;button class='bottom' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo"&gt;
                          授权登录
                        &lt;/button&gt;
                       
                        &lt;!-- &lt;button class='bottom' type='primary' open-type="getPhoneNumber"@getphonenumber="getPhoneNumber"&gt;
                          授权登录
                        &lt;/button&gt; --&gt;
                  &lt;/view&gt;
                &lt;/view&gt;
        &lt;/view&gt;
&lt;/template&gt;

&lt;script&gt;
        import { htxcx } from "@/store/api.js"
        import { mapMutations } from 'vuex'
        export default {
                data() {
                        return {
                                code:"",
                                SessionKey: '',
                                encryptedData:"",
                                iv:"",
                                OpenId: '',
                                nickName: null,
                                avatarUrl: null,
                                isCanUse: uni.getStorageSync('isCanUse')//默认为true记录当前用户是否是第一次授权使用的
                        }
                },

                onLoad() {
                        this.login()
                },
                methods: {
                        ...mapMutations(["setName"]),
                        wxGetUserInfo(){ //第一授权获取用户信息===》按钮触发
                                let _this = this;
                                // 获取用户信息
                                uni.getUserInfo({
                                        provider: 'weixin',
                                        success: function (infoRes) {
                                                _this.encryptedData = infoRes.encryptedData
                                                _this.iv = infoRes.iv
                                                _this.nickName = infoRes.userInfo.nickName; //昵称
                                                _this.avatarUrl = infoRes.userInfo.avatarUrl; //头像
                                                uni.setStorageSync('isCanUse', false);//记录是否第一次授权 false:表示不是第一次授权
                                                _this.updateUserInfo();
                                        },fail:function (fail){console.log("fail:",fail)}
                                });
                        },
                        login(){
                                let _this = this;
                                uni.showLoading({
                                  title: '登录中...'
                                });
                               
                                // 1.wx获取登录用户code
                                uni.login({
                                        provider: 'weixin',
                                        success: function(loginRes) {
                                                _this.code = loginRes.code;
                                                if (!_this.isCanUse) {
                                                        //非第一次授权获取用户信息
                                                        uni.getUserInfo({
                                                                provider: 'weixin',
                                                                success: function(infoRes) {
                                                                        console.log('login用户信息:',infoRes);
                                          //获取用户信息后向调用信息更新方法
                                                                        _this.nickName = infoRes.userInfo.nickName; //昵称
                                                                        _this.avatarUrl = infoRes.userInfo.avatarUrl; //头像
                                                                        _this.updateUserInfo();//调用更新信息方法
                                                                }
                                                        });
                                                }
                                                // 将用户登录code传递到后台置换用户SessionKey、OpenId等信息
                                               
                                                uni.hideLoading();
                                        },
                                })
                                       
                        },
                        updateUserInfo(){ //向后台更新信息
                                this.setName(this.nickName,this.avatarUrl)
                                let _this = this;
                                var obj ={
                                        appid:"wx1*********0f06",
                                        secret:"07bd3*************096",
                                        code:this.code
                                }
                                // 这个接口要在后端调用(https://api.weixin.qq.com无法加入白名单)
                                // https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&amp;secret="+secret+"&amp;js_code="+code+"&amp;grant_type=authorization_code
                                // 请求微信端地址获取用户唯一标识的
                                htxcx(obj.appid,obj.secret,obj.code).then(res=&gt;{
                                        console.log("res:",res)
                                                                       
                                        res.data.openid // 唯一
                                        res.data.session_key
                                        this.encryptedData
                                        this.iv
                                       
                                       
                                       
                                       
                                        uni.reLaunch({//信息更新成功后跳转到小程序首页
                                                url: '/pages/index/index'
                                        });
                                },err=&gt;{
                                        console.log("err:",err)
                                })
                               
                               
                               
                               
                        }
                }
        }
&lt;/script&gt;

&lt;style scoped&gt;
        .header {
          margin: 90rpx 0 90rpx 50rpx;
          border-bottom: 1px solid #ccc;
          text-align: center;
          width: 650rpx;
          height: 300rpx;
          line-height: 450rpx;
          }
       
          .header image {
          width: 200rpx;
          height: 200rpx;
          }
       
          .content {
          margin-left: 50rpx;
          margin-bottom: 90rpx;
          }
       
          .content text {
          display: block;
          color: #9d9d9d;
          margin-top: 40rpx;
          }
       
          .bottom {
          border-radius: 80rpx;
          margin: 70rpx 50rpx;
          font-size: 35rpx;
          }
&lt;/style&gt;
</pre>
</div>
<h3>获取手机号</h3>
<p>微信文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html<br>前提条件 先要登录</p>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">onLoad() {
        this.login()
},
</pre>
</div>
<p>还是用上面的授权页面</p>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">&lt;button class='bottom' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo"&gt;授权登录&lt;/button&gt;
                       
&lt;button class='bottom' type='primary' open-type="getPhoneNumber" @getphonenumber="getPhoneNumber"&gt;获取手机号&lt;/button&gt;

事件
getPhoneNumber(val){
        console.log(val)
},</pre>
</div>
<p>这个需要 真机测试 或 预览</p>
<p><img src="https://img2020.cnblogs.com/blog/2149129/202101/2149129-20210119155827321-2075372638.png" alt="" loading="lazy"></p>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">&lt;template&gt;
        &lt;view&gt;
                &lt;view&gt;
                  &lt;view&gt;
                        &lt;view class='header'&gt;
                          &lt;image src='../../static/wx_login.png'&gt;&lt;/image&gt;
                        &lt;/view&gt;
                        &lt;view class='content'&gt;
                          &lt;view&gt;申请获取以下权限&lt;/view&gt;
                          &lt;text&gt;获得你的公开信息(昵称,头像、地区等)&lt;/text&gt;
                        &lt;/view&gt;
                        &lt;!-- withCredentials=true获取到除用户基本信息之外的encryptedData以及iv等数据 --&gt;
                        &lt;!-- &lt;button class='bottom' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo"&gt;
                          授权登录
                        &lt;/button&gt; --&gt;
                       
                        &lt;button class='bottom' type='primary' open-type="getPhoneNumber"@getphonenumber="getPhoneNumber"&gt;
                          授权登录
                        &lt;/button&gt;
                  &lt;/view&gt;
                &lt;/view&gt;
        &lt;/view&gt;
&lt;/template&gt;

&lt;script&gt;
       
        import { htxcx } from "@/store/api.js"
        import { mapMutations } from 'vuex'
        export default {
                data() {
                        return {
                                code:"",
                                SessionKey: '',
                                encryptedData:"",
                                iv:"",
                                OpenId: '',
                                nickName: null,
                                avatarUrl: null,
                                isCanUse: uni.getStorageSync('isCanUse')//默认为true记录当前用户是否是第一次授权使用的
                        }
                },

                onLoad() {
                        this.login()
                },
                methods: {
               
                        ...mapMutations(["setName"]),
                        wxGetUserInfo(){ //第一授权获取用户信息===》按钮触发
                                let _this = this;
                                // 获取用户信息
                                uni.getUserInfo({
                                        provider: 'weixin',
                                        success: function (infoRes) {
                                                _this.encryptedData = infoRes.encryptedData
                                                _this.iv = infoRes.iv
                                                _this.nickName = infoRes.userInfo.nickName; //昵称
                                                _this.avatarUrl = infoRes.userInfo.avatarUrl; //头像
                                                uni.setStorageSync('isCanUse', false);//记录是否第一次授权 false:表示不是第一次授权
                                                _this.updateUserInfo();
                                        },fail:function (fail){console.log("fail:",fail)}
                                });
                        },
                        getPhoneNumber:function(e){
                                this.encryptedData = e.detail.encryptedData
                                this.iv = e.detail.iv
                                uni.setStorageSync('isCanUse', false);
                                this.updateUserInfo()
                        },
                        login(){
                                let _this = this;
                                uni.showLoading({
                                  title: '登录中...'
                                });
                               
                                // 1.wx获取登录用户code
                                uni.login({
                                        provider: 'weixin',
                                        success: function(loginRes) {
                                                console.log("登录",loginRes.code)
                                                _this.code = loginRes.code;
                                                if (!_this.isCanUse) {
                                                        //非第一次授权获取用户信息
                                                        uni.getUserInfo({
                                                                provider: 'weixin',
                                                                success: function(infoRes) {
                                                                        console.log('login用户信息:',infoRes);
                                          //获取用户信息后向调用信息更新方法
                                                                        _this.nickName = infoRes.userInfo.nickName; //昵称
                                                                        _this.avatarUrl = infoRes.userInfo.avatarUrl; //头像
                                                                        _this.updateUserInfo();//调用更新信息方法
                                                                },
                                                                fail(err) {
                                                                        console.log(err)
                                                                }
                                                        });
                                                }
                                                // 将用户登录code传递到后台置换用户SessionKey、OpenId等信息
                                               
                                                uni.hideLoading();
                                        },
                                })
                                       
                        },
                        updateUserInfo(){ //向后台更新信息
                                this.setName(this.nickName,this.avatarUrl)
                                let _this = this;
                                var obj ={
                                        appid:"wx1b02a26b03110f06",
                                        secret:"07bd35d41e7fb6a9bff173c728d6a096",
                                        code:this.code
                                }
                               
                                // 这一步一般是在后台这里是为了测试
                                // 正常给 后台 5个测试 appId appsecret code(登录接口获取) encryptedData iv
                               
                                htxcx(obj.appid,obj.secret,obj.code).then(res=&gt;{
                                        console.log("res:",res)
                                                                       
                                        res.data.openid // 唯一
                                        res.data.session_key
                                        this.encryptedData
                                        this.iv
                                       
                                        // 把这些参数通过接口传给后台 解密 获取手机号
                                       
                                       
                                        return
                                        uni.reLaunch({//信息更新成功后跳转到小程序首页
                                                url: '/pages/index/index'
                                        });
                                },err=&gt;{
                                        console.log("err:",err)
                                })
                        }
                }
        }
&lt;/script&gt;
</pre>
</div>
<h3>至于后台解密</h3>
<p>我的项目后台解密</p>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">package jstfsn;

import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.sql.Connection;
import java.text.ParseException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.naming.NamingException;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

import GCcom.CommonValue;
import GCcom.DBOperation;
import StxsysBass.StxsysAdmin.CheckingLineService;
import com.alibaba.fastjson.JSONObject;
import com.justep.baas.action.ActionContext;


public class Login {
       
       
        /**
       * 查询历史线路未巡检的巡检点
       *
       * @param params
       * @param context
       * @return
       * @throws NamingException
       */
       
        /**
       * 日志
       */
        public static Logger logger = Logger.getLogger(CheckingLineService.class);
        /**
       * 数据库名
       */
//        public static String DATASOURCE = CommonValue.MYSQL_DATA_BASE_JSTFSN;
       
        /************************************************************************************
       * 函数名:        getWxUserInfo
       * 参数名:        JSONObject params: 参数集
       *                         ActionContext context : 上下文
       *
       * 功能:        通过用户授权加密信息解密获取用户信息
       *
       * 开发者:        Leechen8@gmail.com 20200317
       *
       * 修改者:
       *
       * @return
       * @throws ParseException
       *
       *
       ************************************************************************************/
        public static JSONObject getWxUserInfo(JSONObject params, ActionContext context) throws NamingException {
                // 获取参数
                String strCipher = "";
                String strEncrypdata = params.getString("encrypdata");
                String strIvdata = params.getString("ivdata");
                String strSessionkey= params.getString("sessionkey");
               
                byte[] byEncrypdata = Base64.decodeBase64(strEncrypdata);
                byte[] byIvdata = Base64.decodeBase64(strIvdata);
                byte[] bySessionkey = Base64.decodeBase64(strSessionkey);


                JSONObject jsData = new JSONObject();
       
                AlgorithmParameterSpec ivSpec = new IvParameterSpec(byIvdata);
                Cipher cipher;
                try {                
                        SecretKeySpec keySpec = new SecretKeySpec(bySessionkey, "AES");
                        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
                        strCipher = new String(cipher.doFinal(byEncrypdata),"UTF-8");
                        jsData.put("phone", strCipher);
                       
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                        jsData.put("error", e.getMessage());
                }
                             


                return jsData;
        }

}
</pre>
</div>
<p>可参考&nbsp;https://blog.csdn.net/qq_38194393/article/details/81382108</p>
<h3>获取详细信息 获取手机号 优化封装</h3>
<h4>页面</h4>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">&lt;template&gt;
        &lt;view&gt;
                &lt;view&gt;
                       &lt;view&gt;
                                &lt;view class='header'&gt;
                                        &lt;image src='../../static/wx_login.png'&gt;&lt;/image&gt;
                                &lt;/view&gt;
                                &lt;view class='content'&gt;
                                        &lt;view&gt;申请获取以下权限&lt;/view&gt;
                                        &lt;text&gt;获得你的公开信息(昵称,头像、地区等)&lt;/text&gt;
                                        &lt;text&gt;获得你微信绑定的手机号&lt;/text&gt;
                                &lt;/view&gt;
       
                                &lt;!-- &lt;picker class="view_input" @change="bindPickerMPChange" :value="type" :range="typeArr"&gt;
                                        &lt;view :class="typeArr?'uni-input':'uni-input options'"&gt;{{typeArr? typeArr:"请选择用户身份"}}&lt;/view&gt;
                                &lt;/picker&gt; --&gt;
                               
                                &lt;button class='bottom' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo"&gt;
                                        授权登录
                                &lt;/button&gt;
                               
                                &lt;button class='bottom' type='primary' open-type="getPhoneNumber"@getphonenumber="getPhoneNumber"&gt;
                                        手机号授权
                                &lt;/button&gt;
                        &lt;/view&gt;
                &lt;/view&gt;
        &lt;/view&gt;
&lt;/template&gt;

&lt;script&gt;
        import {wxlogin, getPhone, wxUserInfo} from "@/store/wxlogin.js"
        import {htxcx} from "@/store/api.js"
        export default {
                data() {
                        return {
                                appid:"wx1b02a26b03110f06",
                                secret:"07bd35d41e7fb6a9bff173c728d6a096",
                                type:0,
                                phone:"",
                                typeArr:["承运人","管理员"],
                                phoneParams:{
                                        sessionkey:"",
                                        ivdata:"",
                                        encrypdata:""
                                },
                                loginStatus:false,
                                phoneStatus:false
                        }
                },
                onLoad() {
                        try{
                                this.init()
                        }catch(e){
                                console.log("init错误信息:",e)
                        }
                },
                methods: {
                        async init(){
                                var code = await wxlogin()
                                // 获取sessionkey
                                var key = await htxcx(this.appid,this.secret,code)
                                this.phoneParams.sessionkey = key.data.session_key;
                        },
                        async getPhoneNumber(e){
                                this.phoneParams.encrypdata = e.detail.encryptedData
                                this.phoneParams.ivdata = e.detail.iv
                               
                                var phone = await getPhone(this.phoneParams)
                                this.phone = phone.purePhoneNumber
                                console.log("phone:",this.phone)
                               
                                if(this.phone){
                                        this.phoneStatus = true
                                        this.reLaunch()
                                }
                        },
                        async wxGetUserInfo(){
                                var info = await wxUserInfo()
                                this.loginStatus = true
                                this.reLaunch()
                        },
                        reLaunch(){
                                if(this.loginStatus &amp;&amp; this.phoneStatus){
                                        uni.setStorageSync("tongfang-phone",this.phone)
                                       
                                        // 后续业务代码
                                       
                                        // uni.reLaunch({//信息更新成功后跳转到小程序首页
                                        //         url: '/pages/index/index'
                                        // });
                                }
                        },
                       
                        bindPickerMPChange(e){
                                this.type =e.target.value
                        }       
                }
        }
&lt;/script&gt;

&lt;style&gt;
        .header {
          margin: 90rpx 0 50rpx 50rpx;
          border-bottom: 1px solid #ccc;
          text-align: center;
          width: 650rpx;
          height: 300rpx;
          line-height: 450rpx;
        }
        .header image {
          width: 200rpx;
          height: 200rpx;
        }
        .content {
          margin-left: 50rpx;
          margin-bottom: 50rpx;
        }
        .content text {
          display: block;
          color: #9d9d9d;
          margin-top: 40rpx;
        }
        .bottom {
          border-radius: 80rpx;
          margin: 35rpx 50rpx;
          font-size: 35rpx;
        }
        .bottom:first-child{
                margin-top: 50rpx;
        }
       
        .view_input{
                margin: 0 50rpx;
                background-color: white;
                padding: 10px;
                height: 1rem;
                line-height: 1rem;
        }
&lt;/style&gt;
</pre>
</div>
<h4>wxlogin.js</h4>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">import {getPhone as getphone} from '@/store/api.js'
/*
微信登录
        返回 code
*/
export const wxlogin = ()=&gt; {
        return new Promise((resolve, reject)=&gt;{
                uni.showLoading({
                  title: '登录中...'
                });
               
                uni.login({
                        provider: 'weixin',
                        success: function(loginRes) {
                                resolve(loginRes.code);
                                uni.hideLoading();
                        },
                        fail(err) {
                                reject(err)
                                uni.hideLoading();
                        }
                })
               
        })
}

/*
获取微信用户信息 要先调用登录接口
        返回用户信息
*/
export const wxUserInfo = ()=&gt;{
        return new Promise((resolve, reject)=&gt;{
                uni.getUserInfo({
                        provider: 'weixin',
                        success: function(res) {
                                resolve(res);
                        },
                        fail(err) {
                                reject(err)
                        }
                });
        })
}

/*
获取微信用户手机号 要先调用登录接口
        参数:obj{
                sessionkey,
                ivdata,
                encrypdata
        }
        返回手机号相关信息
       
*/
export const getPhone = (obj)=&gt;{
        return new Promise((resolve, reject)=&gt;{
                getphone(obj).then(res=&gt;{
                        resolve(JSON.parse(res.data.data.phone))
                },err=&gt;{
                        reject(err)
                })
        })
}
</pre>
</div>
<h4>api.js</h4>
<div class="cnblogs_Highlighter">
<pre class="brush:html;gutter:true;">// 接口获取 sessionkey
export const htxcx = (appid,secret,code)=&gt;uniAjax("https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&amp;secret="+secret+"&amp;js_code="+code+"&amp;grant_type=authorization_code")

// 解密手机号
export const getPhone = (obj)=&gt;uniAjax(BASE_URL_dev+"/getWxUserInfo",obj,"POST")
</pre>
</div>
<p>转载于:https://blog.csdn.net/weixin_42448623/article/details/104928750</p><br><br>
来源:https://www.cnblogs.com/smileZAZ/p/14298426.html
頁: [1]
查看完整版本: uni-app开发经验分享二十: 微信小程序 授权登录 获取详细信息 获取手机号