Java实现在小程序获取用户手机号码的功能


       获取用户手机号码包含了”获取用户的昵称、头像授权”、”获取用户的手机号授权”和”解密手机号”3个部分。在小程序获取了的手机号码是加密的密文,还需要经过解密才能获取明文手机号,解密的操作放在了服务器上。

1、获取用户的昵称、头像授权。
(1)小程序前端页面代码。

Open-type:微信开发能力,值为getUserInfo时获取用户信息,可以从bindgetuserinfo回调中获取到用户信息。

(2)弹出获取昵称、头像授权窗口。
用户点击登录,弹出微信授权窗口:

用户点击登录微信授权窗口

点击允许,调用onGetUserInfo方法,获取用户信息:

 // 通过按钮让微信用户授权以获取其信息
  onGetUserInfo: function (e) {
    var that = this;
    wx.getUserInfo({
      success(res) {
        console.log(res);
        if (res.errMsg == 'getUserInfo:ok') {
          //将信息放入缓存
          util.writeStorage(storage.WX_USER_Info, res.userInfo);
          that.setData({
            encrypted_UnionID: res.encryptedData,
            iv_UnionID: res.iv
          });
          // that.obtainAuthorizationInformation();
          that.setData({ showModal: true });  //显示授权手机号弹窗
        } else {
          wx.showToast({
            title: '授权用户信息失败,请重试',
            icon: 'none'
          })
        }
        // that.setData({
        //   encrypted_UnionID: res.encryptedData,
        //   iv_UnionID: res.iv
        // });
      },
      fail(res) {
        wx.showToast({
          title: '获取用户基本信息失败',
          icon: 'none'
        })
        console.log('获取用户基本信息失败!');
        util.writeStorage(storage.AUTHORISED, 0);
      }
    });
  }

2、获取用户手机号授权。
(1)获取用户信息之后,显示准备获取授权手机号弹窗 。

        if (res.errMsg == 'getUserInfo:ok') {
          //将信息放入缓存
          util.writeStorage(storage.WX_USER_Info, res.userInfo);
          that.setData({
            encrypted_UnionID: res.encryptedData,
            iv_UnionID: res.iv
          });
          // that.obtainAuthorizationInformation();
          that.setData({ showModal: true });  //显示授权手机号弹窗
        }

准备获取授权手机号弹窗

(2)获取手机号的前端页面代码。

<view class="toGetPhoneNumberShade" wx:if="{{ showModal }}" catchtap="closeModal"></view>
  <view class="toGetPhoneNumber" wx:if="{{ showModal }}">
    <view>
      <image src="../../images/points.png"></image>
      <text wx:if="{{ showShopName }}">商家名称</text>
      <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">微信用户快捷登录</button>
    </view>
  </view>

getPhoneNumber:
获取用户手机号,可以从bindgetphonenumber回调中获取到用户信息,具体说明 (小程序插件中不能使用)。
bindgetphonenumber: 获取用户手机号回调,open-type=getPhoneNumber时有效。
点击”微信用户快捷登录”,弹出获取手机号授权窗口:

获取手机号授权窗口

(3)获取手机号的js代码
点击允许,调用getPhoneNumber函数:

 // 绑定手机号
  getPhoneNumber: function (e) {
    console.log("xxxxxxxxxxxxxxxx");
    var that = this;
    that.setData({ showModal: false });  //隐藏获取手机号弹窗;
    wx.checkSession({
      success: function (res) { // session_key没有过期
        console.log(res);
        var loginParams = {
          'decryptSessionCode': that.data.decryptSessionCode, // 解密需要的参数
          'encryptedUnionID': that.data.encrypted_UnionID, // 加密的unionID
          'ivUnionID': that.data.iv_UnionID, // 解密需要的参数
          'encryptedPhone': e.detail.encryptedData, // 加密的手机号
          'ivPhone': e.detail.iv, // 解密需要的参数
          'mobile': "",
          'companySN': that.data.companySN
        };
        that.login(loginParams);
      },
      fail: function (res) { // session_key已过期,重新获取
        console.log(res);
        wx.login({
          success(res) {
            that.setData({ decryptSessionCode: res.code });
          },
          fail(res) { // 这里需要处理调用接口失败的情况
            console.log('调用wx.login失败');
          }
        });
        wx.showToast({
          title: '授权手机号失败,请重试',
          icon: 'none'
        })
      }
    });
  },

设置请求登录变量loginParams,然后调用login函数。
(此时获取的手机号还是加密的手机号encryptedPhone,解密的操作放在了服务器端,需要把decryptSessionCode、encryptedPhone、ivPhone几个参数传到服务器端。)
3、解密用户的手机号。
解密手机号的操作在服务器端进行。
(1)请求服务器解密手机号码的js代码。

 // 第一次登录,非自动登录
  login: function (loginParams) {
    // let header = wx.getStorageSync('storageHeader'); // TODO 需要处理nbr会话失效的情况
    let that = this;
    wx.showLoading({
      title: '登录中,请稍等',
      mask: true
    })
    wx.request({
      url: api.login,
      method: api.POST,
      header: app.globalData.header,
      data: loginParams,
      success(res) {
        console.log(res);
        console.log(res.data.objectList2);
        util.writeStorage(storage.Company_Address, res.data.objectList2);
        that.onRequestSuccess(res)
         
      },
      fail(res) { // 这里需要处理调用接口失败的情况
        console.log(res);
        wx.hideLoading();
        wx.showToast({
          title: '登录失败,请重试',
          icon: 'none'
        })
        return null;
      }
    });
  },

(2)后端服务器解密手机号。
(2.1)向微信服务器获取sessionKey。
根据SessionAndOpenid_URL、appid、secret、decryptSessionCode向微信服务器发送请求,获取sessionKey(需要sessionKey才能解密手机号):

		// 向微信请求sessionKey
		String sessionAndOpenidURL = String.format(SessionAndOpenid_URL, MP_APPID, MP_SECRET, vip.getDecryptSessionCode());
		JSONObject jsonObject = WxUtils.getDataFromWxServer(sessionAndOpenidURL);
		if (jsonObject == null) {
			logger.error("获取openid和session_key失败!!!");
			params.put(JSON_ERROR_KEY, EnumErrorCode.EC_OtherError.toString());
			params.put(KEY_HTMLTable_Parameter_msg, "获取微信session_key失败!");
			return false;
		}
		String sessionKey = jsonObject.getString("session_key"); // ...
		if (StringUtils.isEmpty(sessionKey)) {
			logger.error("获取session_key失败!");
			params.put(KEY_HTMLTable_Parameter_msg, "获取session_key失败!");
			params.put(JSON_ERROR_KEY, EnumErrorCode.EC_OtherError.toString());
			return false;
		} else {
			logger.debug("获取的sessionKey:" + sessionKey);
		}

getDataFromWxServer方法代码:

	/** 通用函数。 向微信服务器发送Get请求,返回JSON数据。 */
	public static JSONObject getDataFromWxServer(String url) {
		HttpClient httpClient = HttpClientBuilder.create().build();

		try {
			HttpGet httpGet = new HttpGet(url);
			HttpResponse response = httpClient.execute(httpGet);// 接收client执行的结果
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String result = EntityUtils.toString(entity, "UTF-8");
				return JSONObject.fromObject(result);
			} else {
				logger.error("向微信服务器发送Get请求发生错误!");
				return null;
			}
		} catch (Exception e) {
			logger.error("向微信服务器发送Get请求发生错误:" + e.getMessage());
			return null;
		}
	}

(2.2)解密手机号。
根据sessionKey还有小程序传过来的密文手机号encryptedPhone、ivPhone进行解密:

	String mobile = decryptData(vip.getEncryptedPhone(), vip.getIvPhone(), sessionKey).getString("phoneNumber");
	if (StringUtils.isEmpty(mobile) || mobile.length() != FieldFormat.LENGTH_Mobile) {
		logger.error("解密手机号失败!");
		params.put(KEY_HTMLTable_Parameter_msg, "网络异常,请稍后再试!");
		params.put(JSON_ERROR_KEY, EnumErrorCode.EC_OtherError.toString());
		return false;
	}

这样就可以得到明文的手机号码 mobile 了。

decryptData方法代码:

	private JSONObject decryptData(String encryptedData, String ivData, String session_key) {
		byte[] encrypted = Base64.decodeBase64(encryptedData);
		byte[] iv = Base64.decodeBase64(ivData);
		byte[] key = Base64.decodeBase64(session_key);
		AESUtil aesUtil = new AESUtil(key, iv);
		return JSONObject.fromObject(aesUtil.decrypt(encrypted));
	}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM