2022-12-15 16:45:16.0
无极低码 :https://wheart.cn

我们在做小程序开发的过程中,经常会涉及到用户身份的问题,最普遍的就是我们要获取用户的手机号码,通过微信获取手机号码后可以减少很多操作,比如用户手机号码验证等,我们还可以给用户发送提示短信,那么本文主要讲解如何获取用户手机号码。

获取用户手机号码 分为以下几步:

第一点击页面获取授权按钮

第二获取用户授权参数

第三根据加解密算法解密手机号码

接下来我们来实现以上三步

先看前端页面

  1. <!--index.wxml-->
  2. <view class="container">
  3. <view >
  4. <button class="authbtn" type="primary" open-type="getUserInfo" lang="zh_CN"
  5. bindgetuserinfo="getUserProfile" bindtap="getUserProfile">获取用户信息</button>
  6. <button class="authbtn" open-type="getPhoneNumber" type="primary"
  7. bindgetphonenumber="onGetPhoneNumber">获取手机号码</button>
  8. <view class="userinfo">
  9. <block>
  10. <view class="userinfo-avatar" bindtap="bindViewTap">
  11. <image class="userinfo-avatar" type="userAvatarUrl" src="{{userInfo.avatarUrl}}" mode="cover" ></image>
  12. </view>
  13. <Text class="userinfo-nickname" >{{userInfo.nickName}}</Text>
  14. <text class="userinfo-phone" >{{userInfo.phone}}</text>
  15. <text class="userinfo-phone" wx:if="{{userInfo.gender==0}}"></text>
  16. <text class="userinfo-phone" wx:if="{{userInfo.gender==1}}"></text>
  17. <picker bindchange="bindPickerLingyuChange" value="{{index}}" range="{{array}}">
  18. <view wx:if="{{showLingyu==true}}" class="tips">选择职业 </view>
  19. <text class="tips"> {{array[index]}}</text>
  20. </picker>
  21. <picker bindchange="bindPickerAearaChange" value="{{i}}" range="{{items}}" range-key="name">
  22. <view wx:if="{{showAeara==true}}"class="tips">选择地区 </view>
  23. <text class="tips">{{items[i].name}}</text>
  24. </picker>
  25. <button class="authbtn" type="primary" bindtap="bindViewTap">注册</button>
  26. </block>
  27. </view>
  28. </view>
  29. </view>

大概长这样

获取用户头像的我就直接略过了,网上资料也比较多

接下来我们看关键代码

 此处定义

 getPhoneNumber是微信官方要求,获取用户手机号码授权

onGetPhoneNumber是回调函数,获取授权后会回调到该方法,也就是获取的电话号码就在这个函数的返回值里面。当然这个函数是自定义的,名字大家可以随便起,上面的getPhoneNumber可不能随便修改。

接下来我们通过服务器获取授权

上代码:这里是js调用我们自己的后台,我们的后台再调用微信服务端

  1. onGetPhoneNumber(e) {
  2. var that = this;
  3. wx.login({
  4. success (res) {
  5. if (res.code) {
  6. console.log('步骤2获检查用户登录状态,获取用户电话号码!', res)
  7. wx.request({
  8. url: '这里写自己的获取授权的服务器地址',
  9. data: {code: res.code},
  10. header: {'content-type': 'application/json'},
  11. success: function(res) {
  12. console.log("步骤三获取授权码,获取授权openid,session_key",res);
  13. var userphone=res.data.data;
  14. wx.setStorageSync('userphoneKey',userphone);
  15. //解密手机号
  16. var msg = e.detail.errMsg;
  17. var sessionID=wx.getStorageSync("userphoneKey").session_key;
  18. var encryptedData=e.detail.encryptedData;
  19. var iv=e.detail.iv;
  20. if (msg == 'getPhoneNumber:ok') {//这里表示获取授权成功
  21. wx.checkSession({
  22. success:function(){
  23. //这里进行请求服务端解密手机号
  24. that.deciyption(sessionID,encryptedData,iv);
  25. },
  26. fail:function(){
  27. // that.userlogin()
  28. }
  29. })
  30. }
  31. },fail:function(res){
  32. console.log("fail",res);
  33. }
  34. })
  35. } else {
  36. console.log('登录失败!' + res.errMsg)
  37. }
  38. }
  39. })

后台调用微信获取授权码

 下面是我通过自己写的框架调用的,不用关心注解内容,大家只关注自己的框架注解即可,不管是spring还是servlet只要请求能进到该方法即可,所以重点关注中间部分,把参数值传正确即可

  1. /**
  2. * 回调微信登录信息
  3. * @param request
  4. * @param response
  5. */
  6. @MethodAnnotation(method="miniGetAuth",methoddes="小程序授权",methodWay="ALL")
  7. public void miniGetAuth(HttpServletRequest request, HttpServletResponse response) throws Exception{
  8. String url="https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
  9. String code= request.getParameter("code");
  10. if(empty(code))return;
  11. url=url.replaceAll("APPID", PropertiesUtil.wx_appid)
  12. .replaceAll("SECRET", PropertiesUtil.wx_appsecret)
  13. .replaceAll("JSCODE", code);
  14. qury(request, response, WeixinUtil.doGetStr(url), false, 0);
  15. }

下面是工具类方法 WeixinUtil.doGetStr(url)

  1. /**
  2. * get请求
  3. * @param url
  4. * @return
  5. * @throws ParseException
  6. * @throws IOException
  7. */
  8. public static JSONObject doGetStr(String url) throws ParseException, IOException{
  9. DefaultHttpClient client = new DefaultHttpClient();
  10. HttpGet httpGet = new HttpGet(url);
  11. JSONObject jsonObject = null;
  12. HttpResponse httpResponse = client.execute(httpGet);
  13. HttpEntity entity = httpResponse.getEntity();
  14. if(entity != null){
  15. String result = EntityUtils.toString(entity,"UTF-8");
  16. jsonObject = JSONObject.fromObject(result);
  17. }
  18. return jsonObject;
  19. }

这个值可以返回给前端,前端可以收到如下参数

 接着我们通过授权之后,获取第三个参数iv,调用下面方法进行服务端解密

  that.deciyption(sessionID,encryptedData,iv);

  1. deciyption(sessionID,encryptedData,iv){
  2. var that = this;
  3. console.log("步骤4根据秘钥解密手机号码sessionID:",sessionID);
  4. wx.request({
  5. url: '解密地址',
  6. data: {
  7. sessionID: sessionID,
  8. encryptedData:encryptedData,
  9. iv: iv
  10. },
  11. header: {'content-type': 'application/json'},
  12. success: function(res) {
  13. console.log("79",(res.data.code==20001));
  14. if(res.data.code==20001){//这里不用管,可以删掉,我的框架里返回值20001是授权失败,可按照自己逻辑处理
  15. console.log("获取失败,重新获取",res);
  16. that.setData({
  17. showPhone:true,
  18. })
  19. }else{
  20. console.log("line 79", JSON.parse(res.data.data));
  21. var json= JSON.parse(res.data.data);
  22. wx.setStorageSync('userphone', JSON.parse(res.data.data).phoneNumber);
  23. console.log("步骤5解密成功",res.data.data);
  24. that.setData({
  25. showPhone:false,
  26. "userInfo.phone":wx.getStorageSync('userphone')
  27. })
  28. }
  29. },fail:function(res){
  30. console.log("fail",res);
  31. }
  32. })
  33. }

服务端解密代码

  1. /**
  2. *
  3. * @param request
  4. * @param response
  5. * @throws Exception
  6. */
  7. @MethodAnnotation(method="miniGetPhone",methoddes="小程序解密手机号",methodWay="ALL")
  8. public void miniGetPhone(HttpServletRequest request, HttpServletResponse response) throws Exception{
  9. String encrypdata= request.getParameter("encryptedData");
  10. String ivdata= request.getParameter("iv");
  11. String sessionkey= request.getParameter("sessionID");
  12. if(empty(encrypdata,ivdata,sessionkey))return;
  13. qury(request, response, deciphering(encrypdata, ivdata, sessionkey), false, 0);
  14. }

deciphering解密方法

  1.   public static String deciphering(String encrypdata,String ivdata, String sessionkey) {
  2.             byte[] encrypData = Base64.decode(encrypdata); 
  3.             byte[] ivData = Base64.decode(ivdata); 
  4.             byte[] sessionKey = Base64.decode(sessionkey); 
  5.             String str="";
  6.             try {
  7.             str = decrypt(sessionKey,ivData,encrypData);
  8.             } catch (Exception e) {
  9.             // TODO Auto-generated catch block
  10.             e.printStackTrace();
  11.             }
  12.             return str;
  13.             }
  14.     public static String decrypt(byte[] key, byte[] iv, byte[] encData) throws Exception {
  15.             AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv); 
  16.             Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
  17.             SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); 
  18.             cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); 
  19.             return new String(cipher.doFinal(encData),"UTF-8"); 
  20.     }

 最终效果

无极低码 :https://wheart.cn
最新文章