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