微信小程序:获取用户手机号

在某些业务情况下,微信小程序开发者需要获取到用户的手机号,微信小程序官方为我们提供了该方法。

    获取手机号的开发过程可以分为三部分:微信前端设置,微信js文件编写,服务器端程序开发.
    其中微信前端最为简单,在获取手机号的过程中我们必须经过用户授权,在wxml文件中加入如下代码:

//声明了一个按钮,当用户点击该按钮后将进入授权界面,用户允许系统获取手机号后,js的getPhoneNumber将接受到用户手机号的相关信。

    然后我们需要编写js文件,当用户允许获取手机号后调用相关逻辑,将手机号加密信息发送给用户服务器,以便进行进一步的解密操作获取用户真正的是手机号信息。

  getPhoneNumber(e) {
    console.log(e.detail.errMsg) // 错误信息,如果获取失败则返回该信息
    console.log(e.detail.iv) // iv用于解密操作
    console.log(e.detail.encryptedData) // 密文,解密后可以获取手机号
	//在真正的业务方向上应该将获取到的iv和encryptedData发送给用户服务器 
  },

服务器操作
    获取手机号的重点以及难点在于多加密数据的解密操作。微信的加密使用了对称加密算法AES。AES工具类如下

import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
 
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
/**
 * AES加密
 */
public class AES {
	public static boolean initialized = false;
	/**
	 * AES解密
	 * @param content
	 *            密文
	 * @return
	 * @throws InvalidAlgorithmParameterException
	 * @throws NoSuchProviderException
	 */
	public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
		initialize();
		try {
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
			Key sKeySpec = new SecretKeySpec(keyByte, "AES");
			cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
			byte[] result = cipher.doFinal(content);
			return result;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (NoSuchProviderException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
 
	public static void initialize() {
		if (initialized)
			return;
		Security.addProvider(new BouncyCastleProvider());
		initialized = true;
	}
 
	// 生成iv
	public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
		AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
		params.init(new IvParameterSpec(iv));
		return params;
	}
}

微信解密的直接接口如下:

import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
/**
 * 封装对外访问方法
 */
@Component
public class WXCore {
	
	private static final String WATERMARK = "watermark";
	private static final String APPID = "appid";
	/**
	 * 解密
	 * @param appId   --- 你的appId
	 * @param encryptedData --- 加密的数据
	 * @param sessionKey --- 密钥(session_key)
	 * @param iv 
	 * @return
	 */
	public static String decrypt(String appId, String encryptedData, String sessionKey, String iv){
		String result = "";
		try {
			AES aes = new AES();  
		    byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));  
		    if(null != resultByte && resultByte.length > 0){  
		        result = new String(WxPKCS7Encoder.decode(resultByte));  
		    	JSONObject jsonObject = JSONObject.parseObject(result);
		    	String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString(APPID);
		    	if(!appId.equals(decryptAppid)){
		    		result = "";
		    	}
	        }  
		} catch (Exception e) {
			result = "";
			e.printStackTrace();
		}
	    return result;
	}
}

    如果需要解密,将上面两个类直接添加到你的项目中,WXCore类需要调用AES类中的相关方法。获取手机号的解密可以直接调用WXCore.decrype(String appId, String encryptedData, String sessionKey, String iv)方法。注意这几个参数对应的值,需要注意的是sessionKey,还记得微信小程序的登录吗,登录获取到的其中一个参数是session_key这里就将使用到他。调用方法如下:

//解密获取结果
String result = WXCore.decrypt(appId, encryptedData, sessionKey, iv);
JSONObject jsonObject = JSONObject.parseObject(result);
//防止空指针异常
if(jsonObject!=null) {
	//获取的该手机号并不一定为非空,所以后面需要判断phone是否为null或者""
	String phone = jsonObject.getString("phoneNumber");
}

总结

  1. 前端编写
  2. js获取到iv和encryptedData两个参数发送给用户服务器
  3. 根据appId,encryptedData,登录时获取到的session_key,和iv进行解密获取json数据。
  4. 处理数据获取phone

你可能感兴趣的:(java,小程序,java)